diff --git a/gopmod/classfile.go b/gopmod/classfile.go index 49a6260..1721d5d 100644 --- a/gopmod/classfile.go +++ b/gopmod/classfile.go @@ -18,7 +18,6 @@ package gopmod import ( "errors" - "path" "syscall" "github.com/goplus/mod/modcache" @@ -47,7 +46,7 @@ var ( // ----------------------------------------------------------------------------- func (p *Module) ClassKind(fname string) (isProj, ok bool) { - ext := path.Ext(fname) + ext := modfile.ClassExt(fname) if c, ok := p.projects[ext]; ok { for _, w := range c.Works { if w.Ext == ext { diff --git a/modfile/ext.go b/modfile/ext.go new file mode 100644 index 0000000..dccd2db --- /dev/null +++ b/modfile/ext.go @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package modfile + +import ( + "fmt" + "path" + "strings" + + "github.com/qiniu/x/errors" +) + +// can be "_[class].gox" or ".[class]" +func isExt(s string) bool { + return len(s) > 1 && (s[0] == '_' || s[0] == '.') +} + +func parseExt(s *string) (t string, err error) { + t, err = parseString(s) + if err != nil { + goto failed + } + if isExt(t) { + return + } + err = errors.New("invalid ext format") +failed: + return "", &InvalidExtError{ + Ext: *s, + Err: err, + } +} + +type InvalidExtError struct { + Ext string + Err error +} + +func (e *InvalidExtError) Error() string { + return fmt.Sprintf("ext %s invalid: %s", e.Ext, e.Err) +} + +func (e *InvalidExtError) Unwrap() error { return e.Err } + +// SplitFname splits fname into (hasGoxExt, className, classExt). +func SplitFname(fname string) (hasGoxExt bool, className, classExt string) { + classExt = path.Ext(fname) + className = fname[:len(fname)-len(classExt)] + if hasGoxExt = (classExt == ".gox"); hasGoxExt { + if n := strings.LastIndexByte(className, '_'); n > 0 { + className, classExt = fname[:n], fname[n:] + } + } + return +} + +// ClassExt returns classExt of specified fname. +func ClassExt(fname string) string { + _, _, ext := SplitFname(fname) + return ext +} diff --git a/modfile/ext_test.go b/modfile/ext_test.go new file mode 100644 index 0000000..5b5fb53 --- /dev/null +++ b/modfile/ext_test.go @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package modfile + +import ( + "testing" +) + +func TestSplitFname(t *testing.T) { + type testCase struct { + fname string + ext string + } + cases := []testCase{ + {"foo.spx", ".spx"}, + {"foo_yap.gox", "_yap.gox"}, + {"foo.gox", ".gox"}, + } + for _, c := range cases { + if ext := ClassExt(c.fname); ext != c.ext { + t.Fatalf("ClassExt(%s): expect %s, got %s\n", c.fname, c.ext, ext) + } + } +} diff --git a/modfile/rule.go b/modfile/rule.go index 57c81ea..0e103a3 100644 --- a/modfile/rule.go +++ b/modfile/rule.go @@ -340,38 +340,6 @@ func isPkgPath(s string) bool { return s != "" && (s[0] != '.' && s[0] != '_') } -// can be "_[class].gox" or ".[class]" -func isExt(s string) bool { - return len(s) > 1 && (s[0] == '_' || s[0] == '.') -} - -func parseExt(s *string) (t string, err error) { - t, err = parseString(s) - if err != nil { - goto failed - } - if isExt(t) { - return - } - err = errors.New("invalid ext format") -failed: - return "", &InvalidExtError{ - Ext: *s, - Err: err, - } -} - -type InvalidExtError struct { - Ext string - Err error -} - -func (e *InvalidExtError) Error() string { - return fmt.Sprintf("ext %s invalid: %s", e.Ext, e.Err) -} - -func (e *InvalidExtError) Unwrap() error { return e.Err } - type InvalidSymbolError struct { Sym string Err error