diff --git a/gopls/internal/goxls/parserutil/parser_util.go b/gopls/internal/goxls/parserutil/parser_util.go index 5999139f0ea..a3cc6b093c5 100644 --- a/gopls/internal/goxls/parserutil/parser_util.go +++ b/gopls/internal/goxls/parserutil/parser_util.go @@ -5,10 +5,8 @@ package parserutil import ( - "strings" - + "github.com/goplus/gop" "github.com/goplus/gop/ast" - "github.com/goplus/gop/cl" "github.com/goplus/gop/parser" "github.com/goplus/gop/token" "github.com/goplus/mod/gopmod" @@ -50,25 +48,14 @@ func ParseFileEx(mod *gopmod.Module, fset *token.FileSet, filename string, src i return } -const ( - casePrefix = "case" -) - -func testNameSuffix(testType string) string { - if c := testType[0]; c >= 'A' && c <= 'Z' { - return testType - } - return "_" + testType -} - -// GetClassType is get class type from ast.File and filename -func GetClassType(file *ast.File, filename string) (classType string, ok bool) { - if file.IsClass { - ok = true - classType, _, _ = cl.ClassNameAndExt(filename) - if strings.HasSuffix(filename, "test.gox") && !file.IsProj { - classType = casePrefix + testNameSuffix(classType) +func GetClassType(file *ast.File, filename string, getMod func() (*gopmod.Module, error)) (classType string, isTest bool, err error) { + var mod *gopmod.Module + if file.IsProj { + mod, err = getMod() + if err != nil { + return } } + classType, isTest = gop.GetFileClassType(mod, file, filename) return } diff --git a/gopls/internal/lsp/source/completion/completion_gox.go b/gopls/internal/lsp/source/completion/completion_gox.go index f137be3478c..8899238ebc5 100644 --- a/gopls/internal/lsp/source/completion/completion_gox.go +++ b/gopls/internal/lsp/source/completion/completion_gox.go @@ -24,6 +24,7 @@ import ( "github.com/goplus/gop/scanner" "github.com/goplus/gop/token" "github.com/goplus/gop/x/typesutil" + "github.com/goplus/mod/gopmod" "golang.org/x/sync/errgroup" "golang.org/x/tools/gop/ast/astutil" "golang.org/x/tools/gopls/internal/goxls" @@ -1431,7 +1432,12 @@ func (c *gopCompleter) lexical(ctx context.Context) error { // position or embedded in interface declarations). // builtinComparable = types.Universe.Lookup("comparable") ) - classType, isClass := parserutil.GetClassType(c.file, c.filename) + classType, _, err := parserutil.GetClassType(c.file, c.filename, func() (*gopmod.Module, error) { + return c.snapshot.GopModForFile(ctx, c.fh.URI()) + }) + if err != nil { + return fmt.Errorf("getting classType for gopCompleter: %w", err) + } // Track seen variables to avoid showing completions for shadowed variables. // This works since we look at scopes from innermost to outermost. seen := make(map[string]struct{}) @@ -1446,7 +1452,7 @@ func (c *gopCompleter) lexical(ctx context.Context) error { for _, name := range scope.Names() { declScope, obj := scope.LookupParent(name, c.pos) // Go+ class - if isClass && name == classType { + if c.file.IsClass && name == classType { c.methodsAndFields(obj.Type(), true, nil, c.deepState.enqueue) continue } diff --git a/gopls/internal/lsp/source/symbols_gox.go b/gopls/internal/lsp/source/symbols_gox.go index 6e83dd37426..025f4f23891 100644 --- a/gopls/internal/lsp/source/symbols_gox.go +++ b/gopls/internal/lsp/source/symbols_gox.go @@ -11,6 +11,7 @@ import ( "github.com/goplus/gop/ast" "github.com/goplus/gop/token" "github.com/goplus/gop/x/typesutil" + "github.com/goplus/mod/gopmod" "golang.org/x/tools/gopls/internal/goxls/parserutil" "golang.org/x/tools/gopls/internal/lsp/protocol" "golang.org/x/tools/internal/event" @@ -25,7 +26,13 @@ func GopDocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ( return nil, fmt.Errorf("getting file for GopDocumentSymbols: %w", err) } file := pgf.File - classType, _ := parserutil.GetClassType(file, fh.URI().Filename()) + + classType, _, err := parserutil.GetClassType(file, fh.URI().Filename(), func() (*gopmod.Module, error) { + return snapshot.GopModForFile(ctx, fh.URI()) + }) + if err != nil { + return nil, fmt.Errorf("getting classType for GopDocumentSymbols: %w", err) + } // Build symbols for file declarations. When encountering a declaration with // errors (typically because positions are invalid), we skip the declaration // entirely. VS Code fails to show any symbols if one of the top-level