diff --git a/gopls/doc/generate.go b/gopls/doc/generate.go index 34034fb4e58..e43eeb16e3f 100644 --- a/gopls/doc/generate.go +++ b/gopls/doc/generate.go @@ -31,7 +31,7 @@ import ( "github.com/jba/printsrc" "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/command" "golang.org/x/tools/gopls/internal/lsp/command/commandmeta" "golang.org/x/tools/gopls/internal/lsp/mod" diff --git a/gopls/internal/astutil/purge_test.go b/gopls/internal/astutil/purge_test.go index 97c04072f75..b840e919c01 100644 --- a/gopls/internal/astutil/purge_test.go +++ b/gopls/internal/astutil/purge_test.go @@ -12,8 +12,8 @@ import ( "reflect" "testing" - "golang.org/x/tools/go/packages" "golang.org/x/tools/gopls/internal/astutil" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/internal/testenv" ) diff --git a/gopls/internal/goxls/packages/packages.go b/gopls/internal/goxls/packages/packages.go new file mode 100644 index 00000000000..d4770f00cf4 --- /dev/null +++ b/gopls/internal/goxls/packages/packages.go @@ -0,0 +1,213 @@ +// Copyright 2023 The GoPlus Authors (goplus.org). All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packages + +import ( + "sort" + + "golang.org/x/tools/go/packages" + internal "golang.org/x/tools/internal/packagesinternal" + + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" +) + +// An Error describes a problem with a package's metadata, syntax, or types. +type Error = packages.Error + +// ErrorKind describes the source of the error, allowing the user to +// differentiate between errors generated by the driver, the parser, or the +// type-checker. +type ErrorKind = packages.ErrorKind + +const ( + UnknownError = packages.UnknownError + ListError = packages.ListError + ParseError = packages.ParseError + TypeError = packages.TypeError +) + +// A LoadMode controls the amount of detail to return when loading. +// The bits below can be combined to specify which fields should be +// filled in the result packages. +// The zero value is a special case, equivalent to combining +// the NeedName, NeedFiles, and NeedCompiledGoFiles bits. +// ID and Errors (if present) will always be filled. +// Load may return more information than requested. +type LoadMode = packages.LoadMode + +const ( + // NeedName adds Name and PkgPath. + NeedName = packages.NeedName + + // NeedFiles adds GoFiles, GopFiles and OtherFiles. + NeedFiles = packages.NeedFiles + + // NeedCompiledGoFiles adds CompiledGoFiles/CompiledGopFiles. + NeedCompiledGoFiles = packages.NeedCompiledGoFiles + + // NeedCompiledGopFiles adds CompiledGoFiles/CompiledGopFiles. + NeedCompiledGopFiles = packages.NeedCompiledGoFiles + + // NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain + // "placeholder" Packages with only the ID set. + NeedImports = packages.NeedImports + + // NeedDeps adds the fields requested by the LoadMode in the packages in Imports. + NeedDeps = packages.NeedDeps + + // NeedExportFile adds ExportFile. + NeedExportFile = packages.NeedExportFile + + // NeedTypes adds Types, Fset, and IllTyped. + NeedTypes = packages.NeedTypes + + // NeedSyntax adds Syntax. + NeedSyntax = packages.NeedSyntax + + // NeedTypesInfo adds TypesInfo. + NeedTypesInfo = packages.NeedTypesInfo + + // NeedTypesSizes adds TypesSizes. + NeedTypesSizes = packages.NeedTypesSizes + + // NeedModule adds Module. + NeedModule = packages.NeedModule + + // NeedEmbedFiles adds EmbedFiles. + NeedEmbedFiles = packages.NeedEmbedFiles + + // NeedEmbedPatterns adds EmbedPatterns. + NeedEmbedPatterns = packages.NeedEmbedPatterns +) + +// A Config specifies details about how packages should be loaded. +// The zero value is a valid configuration. +// Calls to Load do not modify this struct. +type Config = packages.Config + +type Package = packages.Package + +/* +// A Package describes a loaded Go+ package. +type Package struct { + *packages.Package + + // GopFiles lists the absolute file paths of the package's Go source files. + // It may include files that should not be compiled, for example because + // they contain non-matching build tags, are documentary pseudo-files such as + // unsafe/unsafe.go or builtin/builtin.go, or are subject to cgo preprocessing. + GopFiles []string + + // CompiledGopFiles lists the absolute file paths of the package's source + // files that are suitable for type checking. + // This may differ from GoFiles if files are processed before compilation. + CompiledGopFiles []string + + // Imports maps import paths appearing in the package's Go source files + // to corresponding loaded Packages. + Imports map[string]*Package + + // TypesInfo provides type information about the package's syntax trees. + // It is set only when Syntax is set. + GopTypesInfo *typesutil.Info +} +*/ + +// Module provides module information for a package. +type Module = packages.Module + +// Load loads and returns the Go packages named by the given patterns. +// +// Config specifies loading options; +// nil behaves the same as an empty Config. +// +// Load returns an error if any of the patterns was invalid +// as defined by the underlying build system. +// It may return an empty list of packages without an error, +// for instance for an empty expansion of a valid wildcard. +// Errors associated with a particular package are recorded in the +// corresponding Package's Errors list, and do not cause Load to +// return an error. Clients may need to handle such errors before +// proceeding with further analysis. The PrintErrors function is +// provided for convenient display of all errors. +func Load(cfg *Config, patterns ...string) ([]*Package, error) { + return packages.Load(cfg, patterns...) +} + +/* + pkgs, err := packages.Load(cfg, patterns...) + if err != nil { + return nil, err + } + ret := make([]*Package, len(pkgs)) + for i, pkg := range pkgs { + ret[i] = &Package{Package: pkg, Imports: importPkgs(pkg.Imports)} + } + return ret, nil +} + +func importPkgs(pkgs map[string]*packages.Package) map[string]*Package { + if len(pkgs) == 0 { + return nil + } + ret := make(map[string]*Package, len(pkgs)) + for path, pkg := range pkgs { + ret[path] = &Package{Package: pkg} + } + return ret +} +*/ + +// Visit visits all the packages in the import graph whose roots are +// pkgs, calling the optional pre function the first time each package +// is encountered (preorder), and the optional post function after a +// package's dependencies have been visited (postorder). +// The boolean result of pre(pkg) determines whether +// the imports of package pkg are visited. +func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) { + seen := make(map[*Package]bool) + var visit func(*Package) + visit = func(pkg *Package) { + if !seen[pkg] { + seen[pkg] = true + + if pre == nil || pre(pkg) { + paths := make([]string, 0, len(pkg.Imports)) + for path := range pkg.Imports { + paths = append(paths, path) + } + sort.Strings(paths) // Imports is a map, this makes visit stable + for _, path := range paths { + visit(pkg.Imports[path]) + } + } + + if post != nil { + post(pkg) + } + } + } + for _, pkg := range pkgs { + visit(pkg) + } +} + +func init() { + packagesinternal.GetForTest = func(p interface{}) string { + return internal.GetForTest(p.(*Package)) + // return internal.GetForTest(p.(*Package).Package) + } + packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError { + return internal.GetDepsErrors(p.(*Package)) + // return internal.GetDepsErrors(p.(*Package).Package) + } + packagesinternal.GetGoCmdRunner = internal.GetGoCmdRunner + packagesinternal.SetGoCmdRunner = internal.SetGoCmdRunner + packagesinternal.SetModFile = internal.SetModFile + packagesinternal.SetModFlag = internal.SetModFlag + packagesinternal.TypecheckCgo = internal.TypecheckCgo + packagesinternal.DepsErrors = internal.DepsErrors + packagesinternal.ForTest = internal.ForTest +} diff --git a/gopls/internal/goxls/packagesinternal/pkgs.go b/gopls/internal/goxls/packagesinternal/pkgs.go new file mode 100644 index 00000000000..f531e57522e --- /dev/null +++ b/gopls/internal/goxls/packagesinternal/pkgs.go @@ -0,0 +1,27 @@ +// Copyright 2023 The GoPlus Authors (goplus.org). All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package packagesinternal exposes internal-only fields from goxls/packages. +package packagesinternal + +import ( + "golang.org/x/tools/internal/gocommand" + "golang.org/x/tools/internal/packagesinternal" +) + +var GetForTest = func(p interface{}) string { return "" } +var GetDepsErrors = func(p interface{}) []*PackageError { return nil } + +type PackageError = packagesinternal.PackageError + +var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil } + +var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {} + +var TypecheckCgo int +var DepsErrors int // must be set as a LoadMode to call GetDepsErrors +var ForTest int // must be set as a LoadMode to call GetForTest + +var SetModFlag = func(config interface{}, value string) {} +var SetModFile = func(config interface{}, value string) {} diff --git a/gopls/internal/lsp/cache/check.go b/gopls/internal/lsp/cache/check.go index bdfc922c147..9a71e61d7bc 100644 --- a/gopls/internal/lsp/cache/check.go +++ b/gopls/internal/lsp/cache/check.go @@ -23,6 +23,7 @@ import ( "golang.org/x/sync/errgroup" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/gopls/internal/bug" + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" "golang.org/x/tools/gopls/internal/goxls/parserutil" "golang.org/x/tools/gopls/internal/lsp/filecache" "golang.org/x/tools/gopls/internal/lsp/protocol" @@ -32,7 +33,6 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/tag" "golang.org/x/tools/internal/gcimporter" - "golang.org/x/tools/internal/packagesinternal" "golang.org/x/tools/internal/tokeninternal" "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/typesinternal" diff --git a/gopls/internal/lsp/cache/errors.go b/gopls/internal/lsp/cache/errors.go index e252ee2930c..437a7bb6016 100644 --- a/gopls/internal/lsp/cache/errors.go +++ b/gopls/internal/lsp/cache/errors.go @@ -20,8 +20,8 @@ import ( "strconv" "strings" - "golang.org/x/tools/go/packages" "golang.org/x/tools/gopls/internal/bug" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/command" "golang.org/x/tools/gopls/internal/lsp/protocol" "golang.org/x/tools/gopls/internal/lsp/safetoken" diff --git a/gopls/internal/lsp/cache/graph.go b/gopls/internal/lsp/cache/graph.go index 684bdab957f..2ed2b1e811c 100644 --- a/gopls/internal/lsp/cache/graph.go +++ b/gopls/internal/lsp/cache/graph.go @@ -7,8 +7,8 @@ package cache import ( "sort" - "golang.org/x/tools/go/packages" "golang.org/x/tools/gopls/internal/bug" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/source" "golang.org/x/tools/gopls/internal/span" ) diff --git a/gopls/internal/lsp/cache/load.go b/gopls/internal/lsp/cache/load.go index 0abdfb373de..b02378e94fe 100644 --- a/gopls/internal/lsp/cache/load.go +++ b/gopls/internal/lsp/cache/load.go @@ -15,16 +15,15 @@ import ( "sync/atomic" "time" - "golang.org/x/tools/go/packages" "golang.org/x/tools/gopls/internal/bug" - "golang.org/x/tools/gopls/internal/goxls/goputil" + "golang.org/x/tools/gopls/internal/goxls/packages" // goxls: replace golang.org/x/tools/go/packages + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" // goxls: replace golang.org/x/tools/internal/packagesinternal "golang.org/x/tools/gopls/internal/lsp/protocol" "golang.org/x/tools/gopls/internal/lsp/source" "golang.org/x/tools/gopls/internal/span" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/tag" "golang.org/x/tools/internal/gocommand" - "golang.org/x/tools/internal/packagesinternal" ) var loadID uint64 // atomic identifier for loads @@ -438,14 +437,18 @@ func buildMetadata(updates map[PackageID]*source.Metadata, pkg *packages.Package uri := span.URIFromPath(filename) m.GoFiles = append(m.GoFiles, uri) } - // goxls: Go+ files: we don't change codes out of gopls - for _, filename := range pkg.OtherFiles { - fext := filepath.Ext(filename) - if goputil.FileKind(fext) != 0 { // Go+ file - uri := span.URIFromPath(filename) - m.GopFiles = append(m.GopFiles, uri) + /* + if true { // goxls: Go+ files + for _, filename := range pkg.GopFiles { + uri := span.URIFromPath(filename) + m.GopFiles = append(m.GopFiles, uri) + } + for _, filename := range pkg.CompiledGopFiles { + uri := span.URIFromPath(filename) + m.CompiledGopFiles = append(m.CompiledGopFiles, uri) + } } - } + */ for _, filename := range pkg.IgnoredFiles { uri := span.URIFromPath(filename) m.IgnoredFiles = append(m.IgnoredFiles, uri) diff --git a/gopls/internal/lsp/cache/mod_tidy.go b/gopls/internal/lsp/cache/mod_tidy.go index b806edb7499..8afabbac9c6 100644 --- a/gopls/internal/lsp/cache/mod_tidy.go +++ b/gopls/internal/lsp/cache/mod_tidy.go @@ -260,7 +260,7 @@ func missingModuleDiagnostics(ctx context.Context, snapshot *snapshot, pm *sourc // // import ( // "golang.org/x/tools/go/expect" - // "golang.org/x/tools/go/packages" + // "golang.org/x/tools/gopls/internal/goxls/packages" // ) // They both are related to the same module: "golang.org/x/tools". var match string diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go index 691cd4d03f0..837a5f29b50 100644 --- a/gopls/internal/lsp/cache/snapshot.go +++ b/gopls/internal/lsp/cache/snapshot.go @@ -27,9 +27,10 @@ import ( "unsafe" "golang.org/x/sync/errgroup" - "golang.org/x/tools/go/packages" "golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/gopls/internal/bug" + "golang.org/x/tools/gopls/internal/goxls/packages" + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" "golang.org/x/tools/gopls/internal/lsp/command" "golang.org/x/tools/gopls/internal/lsp/filecache" "golang.org/x/tools/gopls/internal/lsp/protocol" @@ -42,7 +43,6 @@ import ( "golang.org/x/tools/internal/event/tag" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/memoize" - "golang.org/x/tools/internal/packagesinternal" "golang.org/x/tools/internal/persistent" "golang.org/x/tools/internal/typesinternal" ) diff --git a/gopls/internal/lsp/command/commandmeta/meta.go b/gopls/internal/lsp/command/commandmeta/meta.go index bf85c4faa9b..08e39c0063b 100644 --- a/gopls/internal/lsp/command/commandmeta/meta.go +++ b/gopls/internal/lsp/command/commandmeta/meta.go @@ -16,7 +16,7 @@ import ( "unicode" "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/command" ) diff --git a/gopls/internal/lsp/safetoken/safetoken_test.go b/gopls/internal/lsp/safetoken/safetoken_test.go index 83a50fbec10..adccae7b615 100644 --- a/gopls/internal/lsp/safetoken/safetoken_test.go +++ b/gopls/internal/lsp/safetoken/safetoken_test.go @@ -12,7 +12,7 @@ import ( "os" "testing" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/safetoken" "golang.org/x/tools/internal/testenv" ) diff --git a/gopls/internal/lsp/source/typerefs/pkgrefs_test.go b/gopls/internal/lsp/source/typerefs/pkgrefs_test.go index d75205581af..07a71f985b3 100644 --- a/gopls/internal/lsp/source/typerefs/pkgrefs_test.go +++ b/gopls/internal/lsp/source/typerefs/pkgrefs_test.go @@ -19,13 +19,13 @@ import ( "time" "golang.org/x/tools/go/gcexportdata" - "golang.org/x/tools/go/packages" "golang.org/x/tools/gopls/internal/astutil" + "golang.org/x/tools/gopls/internal/goxls/packages" + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" "golang.org/x/tools/gopls/internal/lsp/cache" "golang.org/x/tools/gopls/internal/lsp/source" "golang.org/x/tools/gopls/internal/lsp/source/typerefs" "golang.org/x/tools/gopls/internal/span" - "golang.org/x/tools/internal/packagesinternal" "golang.org/x/tools/internal/testenv" ) diff --git a/gopls/internal/lsp/source/view.go b/gopls/internal/lsp/source/view.go index 6cd03a50331..059e019e8db 100644 --- a/gopls/internal/lsp/source/view.go +++ b/gopls/internal/lsp/source/view.go @@ -22,8 +22,9 @@ import ( "golang.org/x/mod/modfile" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/packages" "golang.org/x/tools/go/types/objectpath" + "golang.org/x/tools/gopls/internal/goxls/packages" + "golang.org/x/tools/gopls/internal/goxls/packagesinternal" "golang.org/x/tools/gopls/internal/goxls/typesutil" "golang.org/x/tools/gopls/internal/lsp/progress" "golang.org/x/tools/gopls/internal/lsp/protocol" @@ -35,7 +36,6 @@ import ( "golang.org/x/tools/internal/event/tag" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/imports" - "golang.org/x/tools/internal/packagesinternal" ) // A GlobalSnapshotID uniquely identifies a snapshot within this process and @@ -562,7 +562,8 @@ type Metadata struct { IgnoredFiles []span.URI // goxls: Go+ files - GopFiles []span.URI + GopFiles []span.URI + CompiledGopFiles []span.URI ForTest PackagePath // q in a "p [q.test]" package, else "" TypesSizes types.Sizes @@ -972,7 +973,7 @@ type Package interface { // goxls: Go+ files GopFile(uri span.URI) (*ParsedGopFile, error) - GopTypesInfo() *typesutil.Info // use GopTypesInfo() instead of GetTypesInfo() in a Go+ package + GopTypesInfo() *typesutil.Info // use GopTypesInfo() in a Go+ file // Results of type checking: GetTypes() *types.Package diff --git a/gopls/internal/lsp/tests/tests.go b/gopls/internal/lsp/tests/tests.go index 5b7074fe6fa..7e894ce97c4 100644 --- a/gopls/internal/lsp/tests/tests.go +++ b/gopls/internal/lsp/tests/tests.go @@ -24,8 +24,8 @@ import ( "time" "golang.org/x/tools/go/expect" - "golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages/packagestest" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/protocol" "golang.org/x/tools/gopls/internal/lsp/safetoken" "golang.org/x/tools/gopls/internal/lsp/source" @@ -195,6 +195,14 @@ func DefaultOptions(o *source.Options) { protocol.RefactorExtract: true, protocol.SourceFixAll: true, }, + source.Gop: { // goxls: DefaultOptions is same as Go + protocol.SourceOrganizeImports: true, + protocol.QuickFix: true, + protocol.RefactorRewrite: true, + protocol.RefactorInline: true, + protocol.RefactorExtract: true, + protocol.SourceFixAll: true, + }, source.Mod: { protocol.SourceOrganizeImports: true, }, diff --git a/gopls/internal/vulncheck/scan/command.go b/gopls/internal/vulncheck/scan/command.go index 89d24e08b71..b240e39a94b 100644 --- a/gopls/internal/vulncheck/scan/command.go +++ b/gopls/internal/vulncheck/scan/command.go @@ -21,7 +21,7 @@ import ( "golang.org/x/mod/semver" "golang.org/x/sync/errgroup" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/source" "golang.org/x/tools/gopls/internal/vulncheck" "golang.org/x/tools/gopls/internal/vulncheck/govulncheck" diff --git a/gopls/release/release.go b/gopls/release/release.go index b2e0b3ca847..61ae9f76a8a 100644 --- a/gopls/release/release.go +++ b/gopls/release/release.go @@ -25,7 +25,7 @@ import ( "golang.org/x/mod/modfile" "golang.org/x/mod/semver" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" ) var versionFlag = flag.String("version", "", "version to tag") diff --git a/gopls/test/debug/debug_test.go b/gopls/test/debug/debug_test.go index dfe8a3e6edf..1babae8c543 100644 --- a/gopls/test/debug/debug_test.go +++ b/gopls/test/debug/debug_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/jba/templatecheck" - "golang.org/x/tools/go/packages" + "golang.org/x/tools/gopls/internal/goxls/packages" "golang.org/x/tools/gopls/internal/lsp/cache" "golang.org/x/tools/gopls/internal/lsp/debug" "golang.org/x/tools/internal/testenv"