mirror of https://github.com/golang/go.git
internal/lsp: remove Mod handles
Continuing the massacre, remove ParseModHandle, and Mod*Handle, from the source API. Notably, having the snapshot available means we can simplify the go command invocation paths a lot. Change-Id: Ief4ef41e42f93d653f719a230004861e5e1ef70b Reviewed-on: https://go-review.googlesource.com/c/tools/+/244769 Run-TryBot: Heschi Kreinick <heschi@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
b47602a87a
commit
6467de6f59
|
|
@ -29,44 +29,31 @@ const (
|
|||
|
||||
type parseModHandle struct {
|
||||
handle *memoize.Handle
|
||||
|
||||
mod, sum source.FileHandle
|
||||
}
|
||||
|
||||
type parseModData struct {
|
||||
memoize.NoCopy
|
||||
|
||||
parsed *modfile.File
|
||||
m *protocol.ColumnMapper
|
||||
|
||||
// parseErrors refers to syntax errors found in the go.mod file.
|
||||
parseErrors []source.Error
|
||||
parsed *source.ParsedModule
|
||||
|
||||
// err is any error encountered while parsing the file.
|
||||
err error
|
||||
}
|
||||
|
||||
func (mh *parseModHandle) Mod() source.FileHandle {
|
||||
return mh.mod
|
||||
}
|
||||
|
||||
func (mh *parseModHandle) Sum() source.FileHandle {
|
||||
return mh.sum
|
||||
}
|
||||
|
||||
func (mh *parseModHandle) Parse(ctx context.Context, s source.Snapshot) (*modfile.File, *protocol.ColumnMapper, []source.Error, error) {
|
||||
func (mh *parseModHandle) parse(ctx context.Context, s source.Snapshot) (*source.ParsedModule, error) {
|
||||
v, err := mh.handle.Get(ctx, s.(*snapshot))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
data := v.(*parseModData)
|
||||
return data.parsed, data.m, data.parseErrors, data.err
|
||||
return data.parsed, data.err
|
||||
}
|
||||
|
||||
func (s *snapshot) ParseModHandle(ctx context.Context, modFH source.FileHandle) (source.ParseModHandle, error) {
|
||||
func (s *snapshot) ParseMod(ctx context.Context, modFH source.FileHandle) (*source.ParsedModule, error) {
|
||||
if handle := s.getModHandle(modFH.URI()); handle != nil {
|
||||
return handle, nil
|
||||
return handle.parse(ctx, s)
|
||||
}
|
||||
|
||||
h := s.view.session.cache.store.Bind(modFH.Identity().String(), func(ctx context.Context, _ memoize.Arg) interface{} {
|
||||
_, done := event.Start(ctx, "cache.ParseModHandle", tag.URI.Of(modFH.URI()))
|
||||
defer done()
|
||||
|
|
@ -80,55 +67,52 @@ func (s *snapshot) ParseModHandle(ctx context.Context, modFH source.FileHandle)
|
|||
Converter: span.NewContentConverter(modFH.URI().Filename(), contents),
|
||||
Content: contents,
|
||||
}
|
||||
parsed, err := modfile.Parse(modFH.URI().Filename(), contents, nil)
|
||||
if err != nil {
|
||||
parseErr, _ := extractModParseErrors(modFH.URI(), m, err, contents)
|
||||
var parseErrors []source.Error
|
||||
if parseErr != nil {
|
||||
parseErrors = append(parseErrors, *parseErr)
|
||||
}
|
||||
return &parseModData{
|
||||
parseErrors: parseErrors,
|
||||
err: err,
|
||||
data := &parseModData{
|
||||
parsed: &source.ParsedModule{
|
||||
Mapper: m,
|
||||
},
|
||||
}
|
||||
data.parsed.File, data.err = modfile.Parse(modFH.URI().Filename(), contents, nil)
|
||||
if data.err != nil {
|
||||
// Attempt to convert the error to a non-fatal parse error.
|
||||
if parseErr, extractErr := extractModParseErrors(modFH.URI(), m, data.err, contents); extractErr == nil {
|
||||
data.err = nil
|
||||
data.parsed.ParseErrors = []source.Error{*parseErr}
|
||||
}
|
||||
}
|
||||
return &parseModData{
|
||||
parsed: parsed,
|
||||
m: m,
|
||||
}
|
||||
return data
|
||||
})
|
||||
|
||||
pmh := &parseModHandle{handle: h}
|
||||
s.mu.Lock()
|
||||
s.parseModHandles[modFH.URI()] = pmh
|
||||
s.mu.Unlock()
|
||||
|
||||
return pmh.parse(ctx, s)
|
||||
}
|
||||
|
||||
func (s *snapshot) sumFH(ctx context.Context, modFH source.FileHandle) (source.FileHandle, error) {
|
||||
// Get the go.sum file, either from the snapshot or directly from the
|
||||
// cache. Avoid (*snapshot).GetFile here, as we don't want to add
|
||||
// nonexistent file handles to the snapshot if the file does not exist.
|
||||
sumURI := span.URIFromPath(sumFilename(modFH.URI()))
|
||||
sumFH := s.FindFile(sumURI)
|
||||
if sumFH == nil {
|
||||
fh, err := s.view.session.cache.getFile(ctx, sumURI)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
var err error
|
||||
sumFH, err = s.view.session.cache.getFile(ctx, sumURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fh.err != nil && !os.IsNotExist(fh.err) {
|
||||
return nil, fh.err
|
||||
}
|
||||
// If the file doesn't exist, we can just keep the go.sum nil.
|
||||
if err != nil || fh.err != nil {
|
||||
sumFH = nil
|
||||
} else {
|
||||
sumFH = fh
|
||||
}
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.parseModHandles[modFH.URI()] = &parseModHandle{
|
||||
handle: h,
|
||||
mod: modFH,
|
||||
sum: sumFH,
|
||||
_, err := sumFH.Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.parseModHandles[modFH.URI()], nil
|
||||
return sumFH, nil
|
||||
}
|
||||
|
||||
func sumFilename(modURI span.URI) string {
|
||||
return modURI.Filename()[:len(modURI.Filename())-len("mod")] + "sum"
|
||||
return strings.TrimSuffix(modURI.Filename(), ".mod") + ".sum"
|
||||
}
|
||||
|
||||
// extractModParseErrors processes the raw errors returned by modfile.Parse,
|
||||
|
|
@ -197,7 +181,7 @@ type modWhyData struct {
|
|||
err error
|
||||
}
|
||||
|
||||
func (mwh *modWhyHandle) Why(ctx context.Context, s source.Snapshot) (map[string]string, error) {
|
||||
func (mwh *modWhyHandle) why(ctx context.Context, s source.Snapshot) (map[string]string, error) {
|
||||
v, err := mwh.handle.Get(ctx, s.(*snapshot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -206,7 +190,7 @@ func (mwh *modWhyHandle) Why(ctx context.Context, s source.Snapshot) (map[string
|
|||
return data.why, data.err
|
||||
}
|
||||
|
||||
func (s *snapshot) ModWhyHandle(ctx context.Context) (source.ModWhyHandle, error) {
|
||||
func (s *snapshot) ModWhy(ctx context.Context) (map[string]string, error) {
|
||||
if err := s.awaitLoaded(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -214,7 +198,6 @@ func (s *snapshot) ModWhyHandle(ctx context.Context) (source.ModWhyHandle, error
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := s.config(ctx)
|
||||
key := modKey{
|
||||
sessionID: s.view.session.id,
|
||||
cfg: hashConfig(s.config(ctx)),
|
||||
|
|
@ -228,46 +211,42 @@ func (s *snapshot) ModWhyHandle(ctx context.Context) (source.ModWhyHandle, error
|
|||
|
||||
snapshot := arg.(*snapshot)
|
||||
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
if err != nil {
|
||||
return &modWhyData{err: err}
|
||||
}
|
||||
|
||||
parsed, _, _, err := pmh.Parse(ctx, snapshot)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return &modWhyData{err: err}
|
||||
}
|
||||
// No requires to explain.
|
||||
if len(parsed.Require) == 0 {
|
||||
if len(pm.File.Require) == 0 {
|
||||
return &modWhyData{}
|
||||
}
|
||||
// Run `go mod why` on all the dependencies.
|
||||
args := []string{"why", "-m"}
|
||||
for _, req := range parsed.Require {
|
||||
for _, req := range pm.File.Require {
|
||||
args = append(args, req.Mod.Path)
|
||||
}
|
||||
_, stdout, err := runGoCommand(ctx, cfg, pmh, snapshot.view.tmpMod, "mod", args)
|
||||
stdout, err := snapshot.RunGoCommand(ctx, "mod", args)
|
||||
if err != nil {
|
||||
return &modWhyData{err: err}
|
||||
}
|
||||
whyList := strings.Split(stdout.String(), "\n\n")
|
||||
if len(whyList) != len(parsed.Require) {
|
||||
if len(whyList) != len(pm.File.Require) {
|
||||
return &modWhyData{
|
||||
err: fmt.Errorf("mismatched number of results: got %v, want %v", len(whyList), len(parsed.Require)),
|
||||
err: fmt.Errorf("mismatched number of results: got %v, want %v", len(whyList), len(pm.File.Require)),
|
||||
}
|
||||
}
|
||||
why := make(map[string]string, len(parsed.Require))
|
||||
for i, req := range parsed.Require {
|
||||
why := make(map[string]string, len(pm.File.Require))
|
||||
for i, req := range pm.File.Require {
|
||||
why[req.Mod.Path] = whyList[i]
|
||||
}
|
||||
return &modWhyData{why: why}
|
||||
})
|
||||
|
||||
mwh := &modWhyHandle{handle: h}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.modWhyHandle = &modWhyHandle{
|
||||
handle: h,
|
||||
}
|
||||
return s.modWhyHandle, nil
|
||||
s.modWhyHandle = mwh
|
||||
s.mu.Unlock()
|
||||
|
||||
return s.modWhyHandle.why(ctx, s)
|
||||
}
|
||||
|
||||
type modUpgradeHandle struct {
|
||||
|
|
@ -290,7 +269,7 @@ func (muh *modUpgradeHandle) Upgrades(ctx context.Context, s source.Snapshot) (m
|
|||
return data.upgrades, data.err
|
||||
}
|
||||
|
||||
func (s *snapshot) ModUpgradeHandle(ctx context.Context) (source.ModUpgradeHandle, error) {
|
||||
func (s *snapshot) ModUpgrade(ctx context.Context) (map[string]string, error) {
|
||||
if err := s.awaitLoaded(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -312,28 +291,24 @@ func (s *snapshot) ModUpgradeHandle(ctx context.Context) (source.ModUpgradeHandl
|
|||
|
||||
snapshot := arg.(*snapshot)
|
||||
|
||||
pmh, err := s.ParseModHandle(ctx, fh)
|
||||
pm, err := s.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return &modUpgradeData{err: err}
|
||||
}
|
||||
|
||||
parsed, _, _, err := pmh.Parse(ctx, snapshot)
|
||||
if err != nil {
|
||||
return &modUpgradeData{err: err}
|
||||
}
|
||||
// No requires to upgrade.
|
||||
if len(parsed.Require) == 0 {
|
||||
if len(pm.File.Require) == 0 {
|
||||
return &modUpgradeData{}
|
||||
}
|
||||
// Run "go list -mod readonly -u -m all" to be able to see which deps can be
|
||||
// upgraded without modifying mod file.
|
||||
args := []string{"-u", "-m", "all"}
|
||||
if !snapshot.view.tmpMod || containsVendor(pmh.Mod().URI()) {
|
||||
if !snapshot.view.tmpMod || containsVendor(fh.URI()) {
|
||||
// Use -mod=readonly if the module contains a vendor directory
|
||||
// (see golang/go#38711).
|
||||
args = append([]string{"-mod", "readonly"}, args...)
|
||||
}
|
||||
_, stdout, err := runGoCommand(ctx, cfg, pmh, snapshot.view.tmpMod, "list", args)
|
||||
stdout, err := snapshot.RunGoCommand(ctx, "list", args)
|
||||
if err != nil {
|
||||
return &modUpgradeData{err: err}
|
||||
}
|
||||
|
|
@ -364,12 +339,12 @@ func (s *snapshot) ModUpgradeHandle(ctx context.Context) (source.ModUpgradeHandl
|
|||
upgrades: upgrades,
|
||||
}
|
||||
})
|
||||
muh := &modUpgradeHandle{handle: h}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.modUpgradeHandle = &modUpgradeHandle{
|
||||
handle: h,
|
||||
}
|
||||
return s.modUpgradeHandle, nil
|
||||
s.modUpgradeHandle = muh
|
||||
s.mu.Unlock()
|
||||
|
||||
return s.modUpgradeHandle.Upgrades(ctx, s)
|
||||
}
|
||||
|
||||
// containsVendor reports whether the module has a vendor folder.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/memoize"
|
||||
"golang.org/x/tools/internal/packagesinternal"
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
|
|
@ -34,57 +33,32 @@ type modTidyKey struct {
|
|||
|
||||
type modTidyHandle struct {
|
||||
handle *memoize.Handle
|
||||
|
||||
pmh source.ParseModHandle
|
||||
}
|
||||
|
||||
type modTidyData struct {
|
||||
memoize.NoCopy
|
||||
|
||||
// tidiedContent is the content of the tidied file.
|
||||
tidiedContent []byte
|
||||
|
||||
// diagnostics are any errors and associated suggested fixes for
|
||||
// the go.mod file.
|
||||
diagnostics []source.Error
|
||||
|
||||
err error
|
||||
tidied *source.TidiedModule
|
||||
err error
|
||||
}
|
||||
|
||||
func (mth *modTidyHandle) ParseModHandle() source.ParseModHandle {
|
||||
return mth.pmh
|
||||
}
|
||||
|
||||
func (mth *modTidyHandle) Tidy(ctx context.Context, s source.Snapshot) ([]source.Error, error) {
|
||||
func (mth *modTidyHandle) tidy(ctx context.Context, s source.Snapshot) (*source.TidiedModule, error) {
|
||||
v, err := mth.handle.Get(ctx, s.(*snapshot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := v.(*modTidyData)
|
||||
return data.diagnostics, data.err
|
||||
return data.tidied, data.err
|
||||
}
|
||||
|
||||
func (mth *modTidyHandle) TidiedContent(ctx context.Context, s source.Snapshot) ([]byte, error) {
|
||||
v, err := mth.handle.Get(ctx, s.(*snapshot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := v.(*modTidyData)
|
||||
return data.tidiedContent, data.err
|
||||
}
|
||||
|
||||
func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, error) {
|
||||
func (s *snapshot) ModTidy(ctx context.Context) (*source.TidiedModule, error) {
|
||||
if !s.view.tmpMod {
|
||||
return nil, source.ErrTmpModfileUnsupported
|
||||
}
|
||||
if handle := s.getModTidyHandle(); handle != nil {
|
||||
return handle, nil
|
||||
return handle.tidy(ctx, s)
|
||||
}
|
||||
fh, err := s.GetFile(ctx, s.view.modURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pmh, err := s.ParseModHandle(ctx, fh)
|
||||
modFH, err := s.GetFile(ctx, s.view.modURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -111,7 +85,7 @@ func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, err
|
|||
view: s.view.root.Filename(),
|
||||
imports: importHash,
|
||||
unsavedOverlays: overlayHash,
|
||||
gomod: pmh.Mod().Identity().String(),
|
||||
gomod: modFH.Identity().String(),
|
||||
cfg: hashConfig(cfg),
|
||||
}
|
||||
h := s.view.session.cache.store.Bind(key, func(ctx context.Context, arg memoize.Arg) interface{} {
|
||||
|
|
@ -119,21 +93,26 @@ func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, err
|
|||
defer done()
|
||||
|
||||
snapshot := arg.(*snapshot)
|
||||
original, m, parseErrors, err := pmh.Parse(ctx, snapshot)
|
||||
if err != nil || len(parseErrors) > 0 {
|
||||
pm, err := snapshot.ParseMod(ctx, modFH)
|
||||
if err != nil {
|
||||
return &modTidyData{err: err}
|
||||
}
|
||||
if len(pm.ParseErrors) > 0 {
|
||||
return &modTidyData{
|
||||
diagnostics: parseErrors,
|
||||
err: err,
|
||||
tidied: &source.TidiedModule{
|
||||
Parsed: pm,
|
||||
},
|
||||
err: fmt.Errorf("could not parse module to tidy: %v", pm.ParseErrors),
|
||||
}
|
||||
}
|
||||
tmpURI, inv, cleanup, err := goCommandInvocation(ctx, cfg, pmh, "mod", []string{"tidy"})
|
||||
tmpURI, runner, inv, cleanup, err := snapshot.goCommandInvocation(ctx, true, "mod", []string{"tidy"})
|
||||
if err != nil {
|
||||
return &modTidyData{err: err}
|
||||
}
|
||||
// Keep the temporary go.mod file around long enough to parse it.
|
||||
defer cleanup()
|
||||
|
||||
if _, err := packagesinternal.GetGoCmdRunner(cfg).Run(ctx, *inv); err != nil {
|
||||
if _, err := runner.Run(ctx, *inv); err != nil {
|
||||
return &modTidyData{err: err}
|
||||
}
|
||||
// Go directly to disk to get the temporary mod file, since it is
|
||||
|
|
@ -150,9 +129,9 @@ func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, err
|
|||
}
|
||||
// Get the dependencies that are different between the original and
|
||||
// ideal go.mod files.
|
||||
unusedDeps := make(map[string]*modfile.Require, len(original.Require))
|
||||
unusedDeps := make(map[string]*modfile.Require, len(pm.File.Require))
|
||||
missingDeps := make(map[string]*modfile.Require, len(ideal.Require))
|
||||
for _, req := range original.Require {
|
||||
for _, req := range pm.File.Require {
|
||||
unusedDeps[req.Mod.Path] = req
|
||||
}
|
||||
for _, req := range ideal.Require {
|
||||
|
|
@ -166,7 +145,7 @@ func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, err
|
|||
// First, compute any errors specific to the go.mod file. These include
|
||||
// unused dependencies and modules with incorrect // indirect comments.
|
||||
/// Both the diagnostic and the fix will appear on the go.mod file.
|
||||
modRequireErrs, err := modRequireErrors(m, missingDeps, unusedDeps, options)
|
||||
modRequireErrs, err := modRequireErrors(pm.Mapper, missingDeps, unusedDeps, options)
|
||||
if err != nil {
|
||||
return &modTidyData{err: err}
|
||||
}
|
||||
|
|
@ -179,22 +158,25 @@ func (s *snapshot) ModTidyHandle(ctx context.Context) (source.ModTidyHandle, err
|
|||
// go.mod file. The fixes will be for the go.mod file, but the
|
||||
// diagnostics should appear on the import statements in the Go or
|
||||
// go.mod files.
|
||||
missingModuleErrs, err := missingModuleErrors(ctx, snapshot, m, workspacePkgs, ideal.Require, missingDeps, original, options)
|
||||
missingModuleErrs, err := missingModuleErrors(ctx, snapshot, pm.Mapper, workspacePkgs, ideal.Require, missingDeps, pm.File, options)
|
||||
if err != nil {
|
||||
return &modTidyData{err: err}
|
||||
}
|
||||
return &modTidyData{
|
||||
tidiedContent: tempContents,
|
||||
diagnostics: append(modRequireErrs, missingModuleErrs...),
|
||||
tidied: &source.TidiedModule{
|
||||
Parsed: pm,
|
||||
TidiedContent: tempContents,
|
||||
Errors: append(modRequireErrs, missingModuleErrs...),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
mth := &modTidyHandle{handle: h}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.modTidyHandle = &modTidyHandle{
|
||||
handle: h,
|
||||
pmh: pmh,
|
||||
}
|
||||
return s.modTidyHandle, nil
|
||||
s.modTidyHandle = mth
|
||||
s.mu.Unlock()
|
||||
|
||||
return mth.tidy(ctx, s)
|
||||
}
|
||||
|
||||
func hashImports(ctx context.Context, wsPackages []source.Package) (string, error) {
|
||||
|
|
|
|||
|
|
@ -142,83 +142,55 @@ func (s *snapshot) config(ctx context.Context) *packages.Config {
|
|||
}
|
||||
|
||||
func (s *snapshot) RunGoCommandDirect(ctx context.Context, verb string, args []string) error {
|
||||
cfg := s.config(ctx)
|
||||
_, _, err := runGoCommand(ctx, cfg, nil, s.view.tmpMod, verb, args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *snapshot) RunGoCommand(ctx context.Context, verb string, args []string) (*bytes.Buffer, error) {
|
||||
cfg := s.config(ctx)
|
||||
var pmh source.ParseModHandle
|
||||
if s.view.tmpMod {
|
||||
modFH, err := s.GetFile(ctx, s.view.modURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pmh, err = s.ParseModHandle(ctx, modFH)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
_, stdout, err := runGoCommand(ctx, cfg, pmh, s.view.tmpMod, verb, args)
|
||||
return stdout, err
|
||||
}
|
||||
|
||||
func (s *snapshot) RunGoCommandPiped(ctx context.Context, verb string, args []string, stdout, stderr io.Writer) error {
|
||||
cfg := s.config(ctx)
|
||||
var pmh source.ParseModHandle
|
||||
if s.view.tmpMod {
|
||||
modFH, err := s.GetFile(ctx, s.view.modURI)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pmh, err = s.ParseModHandle(ctx, modFH)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, inv, cleanup, err := goCommandInvocation(ctx, cfg, pmh, verb, args)
|
||||
_, runner, inv, cleanup, err := s.goCommandInvocation(ctx, false, verb, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
runner := packagesinternal.GetGoCmdRunner(cfg)
|
||||
return runner.RunPiped(ctx, *inv, stdout, stderr)
|
||||
_, err = runner.Run(ctx, *inv)
|
||||
return err
|
||||
}
|
||||
|
||||
// runGoCommand runs the given go command with the given config.
|
||||
// The given go.mod file is used to construct the temporary go.mod file, which
|
||||
// is then passed to the go command via the BuildFlags.
|
||||
// It assumes that modURI is only provided when the -modfile flag is enabled.
|
||||
func runGoCommand(ctx context.Context, cfg *packages.Config, pmh source.ParseModHandle, tmpMod bool, verb string, args []string) (span.URI, *bytes.Buffer, error) {
|
||||
// Don't pass in the ParseModHandle if we are not using the -modfile flag.
|
||||
var tmpPMH source.ParseModHandle
|
||||
if tmpMod {
|
||||
tmpPMH = pmh
|
||||
}
|
||||
tmpURI, inv, cleanup, err := goCommandInvocation(ctx, cfg, tmpPMH, verb, args)
|
||||
func (s *snapshot) RunGoCommand(ctx context.Context, verb string, args []string) (*bytes.Buffer, error) {
|
||||
_, runner, inv, cleanup, err := s.goCommandInvocation(ctx, true, verb, args)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return nil, err
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
runner := packagesinternal.GetGoCmdRunner(cfg)
|
||||
stdout, err := runner.Run(ctx, *inv)
|
||||
return tmpURI, stdout, err
|
||||
return runner.Run(ctx, *inv)
|
||||
}
|
||||
|
||||
func (s *snapshot) RunGoCommandPiped(ctx context.Context, verb string, args []string, stdout, stderr io.Writer) error {
|
||||
_, runner, inv, cleanup, err := s.goCommandInvocation(ctx, true, verb, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup()
|
||||
return runner.RunPiped(ctx, *inv, stdout, stderr)
|
||||
}
|
||||
|
||||
// Assumes that modURI is only provided when the -modfile flag is enabled.
|
||||
func goCommandInvocation(ctx context.Context, cfg *packages.Config, pmh source.ParseModHandle, verb string, args []string) (tmpURI span.URI, inv *gocommand.Invocation, cleanup func(), err error) {
|
||||
func (s *snapshot) goCommandInvocation(ctx context.Context, allowTempModfile bool, verb string, args []string) (tmpURI span.URI, runner *gocommand.Runner, inv *gocommand.Invocation, cleanup func(), err error) {
|
||||
cleanup = func() {} // fallback
|
||||
if pmh != nil {
|
||||
tmpURI, cleanup, err = tempModFile(pmh.Mod(), pmh.Sum())
|
||||
cfg := s.config(ctx)
|
||||
if allowTempModfile && s.view.tmpMod {
|
||||
modFH, err := s.GetFile(ctx, s.view.modURI)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
return "", nil, nil, cleanup, err
|
||||
}
|
||||
// Use the go.sum if it happens to be available.
|
||||
sumFH, _ := s.sumFH(ctx, modFH)
|
||||
|
||||
tmpURI, cleanup, err = tempModFile(modFH, sumFH)
|
||||
if err != nil {
|
||||
return "", nil, nil, cleanup, err
|
||||
}
|
||||
cfg.BuildFlags = append(cfg.BuildFlags, fmt.Sprintf("-modfile=%s", tmpURI.Filename()))
|
||||
}
|
||||
return tmpURI, &gocommand.Invocation{
|
||||
runner = packagesinternal.GetGoCmdRunner(cfg)
|
||||
return tmpURI, runner, &gocommand.Invocation{
|
||||
Verb: verb,
|
||||
Args: args,
|
||||
Env: cfg.Env,
|
||||
|
|
|
|||
|
|
@ -562,15 +562,11 @@ func (v *View) WorkspaceDirectories(ctx context.Context) ([]string, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pmh, err := v.Snapshot().ParseModHandle(ctx, fh)
|
||||
pm, err := v.Snapshot().ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed, _, _, err := pmh.Parse(ctx, v.Snapshot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, replace := range parsed.Replace {
|
||||
for _, replace := range pm.File.Replace {
|
||||
dirs = append(dirs, replace.New.Path)
|
||||
}
|
||||
return dirs, nil
|
||||
|
|
|
|||
|
|
@ -454,20 +454,19 @@ func documentChanges(fh source.FileHandle, edits []protocol.TextEdit) []protocol
|
|||
}
|
||||
|
||||
func moduleQuickFixes(ctx context.Context, snapshot source.Snapshot, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
|
||||
mth, err := snapshot.ModTidyHandle(ctx)
|
||||
modFH, err := snapshot.GetFile(ctx, snapshot.View().ModFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tidied, err := snapshot.ModTidy(ctx)
|
||||
if err == source.ErrTmpModfileUnsupported {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errors, err := mth.Tidy(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pmh := mth.ParseModHandle()
|
||||
var quickFixes []protocol.CodeAction
|
||||
for _, e := range errors {
|
||||
for _, e := range tidied.Errors {
|
||||
var diag *protocol.Diagnostic
|
||||
for _, d := range diagnostics {
|
||||
if sameDiagnostic(d, e) {
|
||||
|
|
@ -486,14 +485,14 @@ func moduleQuickFixes(ctx context.Context, snapshot source.Snapshot, diagnostics
|
|||
Edit: protocol.WorkspaceEdit{},
|
||||
}
|
||||
for uri, edits := range fix.Edits {
|
||||
if uri != pmh.Mod().URI() {
|
||||
if uri != modFH.URI() {
|
||||
continue
|
||||
}
|
||||
action.Edit.DocumentChanges = append(action.Edit.DocumentChanges, protocol.TextDocumentEdit{
|
||||
TextDocument: protocol.VersionedTextDocumentIdentifier{
|
||||
Version: pmh.Mod().Version(),
|
||||
Version: modFH.Version(),
|
||||
TextDocumentIdentifier: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.URIFromSpanURI(pmh.Mod().URI()),
|
||||
URI: protocol.URIFromSpanURI(modFH.URI()),
|
||||
},
|
||||
},
|
||||
Edits: edits,
|
||||
|
|
@ -510,25 +509,21 @@ func sameDiagnostic(d protocol.Diagnostic, e source.Error) bool {
|
|||
}
|
||||
|
||||
func goModTidy(ctx context.Context, snapshot source.Snapshot) (*protocol.CodeAction, error) {
|
||||
mth, err := snapshot.ModTidyHandle(ctx)
|
||||
tidied, err := snapshot.ModTidy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uri := mth.ParseModHandle().Mod().URI()
|
||||
_, m, _, err := mth.ParseModHandle().Parse(ctx, snapshot)
|
||||
modFH, err := snapshot.GetFile(ctx, snapshot.View().ModFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
left, err := mth.ParseModHandle().Mod().Read()
|
||||
left, err := modFH.Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
right, err := mth.TidiedContent(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
edits := snapshot.View().Options().ComputeEdits(uri, string(left), string(right))
|
||||
protocolEdits, err := source.ToProtocolEdits(m, edits)
|
||||
right := tidied.TidiedContent
|
||||
edits := snapshot.View().Options().ComputeEdits(modFH.URI(), string(left), string(right))
|
||||
protocolEdits, err := source.ToProtocolEdits(tidied.Parsed.Mapper, edits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -538,9 +533,9 @@ func goModTidy(ctx context.Context, snapshot source.Snapshot) (*protocol.CodeAct
|
|||
Edit: protocol.WorkspaceEdit{
|
||||
DocumentChanges: []protocol.TextDocumentEdit{{
|
||||
TextDocument: protocol.VersionedTextDocumentIdentifier{
|
||||
Version: mth.ParseModHandle().Mod().Version(),
|
||||
Version: modFH.Version(),
|
||||
TextDocumentIdentifier: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.URIFromSpanURI(uri),
|
||||
URI: protocol.URIFromSpanURI(modFH.URI()),
|
||||
},
|
||||
},
|
||||
Edits: protocolEdits,
|
||||
|
|
|
|||
|
|
@ -46,16 +46,12 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
|
|||
func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.DocumentLink, error) {
|
||||
view := snapshot.View()
|
||||
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, m, _, err := pmh.Parse(ctx, snapshot)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var links []protocol.DocumentLink
|
||||
for _, req := range file.Require {
|
||||
for _, req := range pm.File.Require {
|
||||
if req.Syntax == nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -65,7 +61,7 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl
|
|||
}
|
||||
dep := []byte(req.Mod.Path)
|
||||
s, e := req.Syntax.Start.Byte, req.Syntax.End.Byte
|
||||
i := bytes.Index(m.Content[s:e], dep)
|
||||
i := bytes.Index(pm.Mapper.Content[s:e], dep)
|
||||
if i == -1 {
|
||||
continue
|
||||
}
|
||||
|
|
@ -73,25 +69,25 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl
|
|||
// dependency within the require statement.
|
||||
start, end := token.Pos(s+i), token.Pos(s+i+len(dep))
|
||||
target := fmt.Sprintf("https://%s/mod/%s", view.Options().LinkTarget, req.Mod.String())
|
||||
l, err := toProtocolLink(view, m, target, start, end, source.Mod)
|
||||
l, err := toProtocolLink(view, pm.Mapper, target, start, end, source.Mod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
links = append(links, l)
|
||||
}
|
||||
// TODO(ridersofrohan): handle links for replace and exclude directives.
|
||||
if syntax := file.Syntax; syntax == nil {
|
||||
if syntax := pm.File.Syntax; syntax == nil {
|
||||
return links, nil
|
||||
}
|
||||
// Get all the links that are contained in the comments of the file.
|
||||
for _, expr := range file.Syntax.Stmt {
|
||||
for _, expr := range pm.File.Syntax.Stmt {
|
||||
comments := expr.Comment()
|
||||
if comments == nil {
|
||||
continue
|
||||
}
|
||||
for _, section := range [][]modfile.Comment{comments.Before, comments.Suffix, comments.After} {
|
||||
for _, comment := range section {
|
||||
l, err := findLinksInString(ctx, view, comment.Token, token.Pos(comment.Start.Byte), m, source.Mod)
|
||||
l, err := findLinksInString(ctx, view, comment.Token, token.Pos(comment.Start.Byte), pm.Mapper, source.Mod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,19 +28,11 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, m, _, err := pmh.Parse(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
muh, err := snapshot.ModUpgradeHandle(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
upgrades, err := muh.Upgrades(ctx, snapshot)
|
||||
upgrades, err := snapshot.ModUpgrade(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -48,14 +40,14 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
|
|||
codelens []protocol.CodeLens
|
||||
allUpgrades []string
|
||||
)
|
||||
for _, req := range file.Require {
|
||||
for _, req := range pm.File.Require {
|
||||
dep := req.Mod.Path
|
||||
latest, ok := upgrades[dep]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Get the range of the require directive.
|
||||
rng, err := positionsToRange(uri, m, req.Syntax.Start, req.Syntax.End)
|
||||
rng, err := positionsToRange(uri, pm.Mapper, req.Syntax.Start, req.Syntax.End)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -74,9 +66,9 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
|
|||
allUpgrades = append(allUpgrades, dep)
|
||||
}
|
||||
// If there is at least 1 upgrade, add an "Upgrade all dependencies" to the module statement.
|
||||
if module := file.Module; len(allUpgrades) > 0 && module != nil && module.Syntax != nil {
|
||||
if module := pm.File.Module; len(allUpgrades) > 0 && module != nil && module.Syntax != nil {
|
||||
// Get the range of the module directive.
|
||||
rng, err := positionsToRange(uri, m, module.Syntax.Start, module.Syntax.End)
|
||||
rng, err := positionsToRange(uri, pm.Mapper, module.Syntax.Start, module.Syntax.End)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[source.File
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mth, err := snapshot.ModTidyHandle(ctx)
|
||||
tidied, err := snapshot.ModTidy(ctx)
|
||||
if err == source.ErrTmpModfileUnsupported {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -44,11 +44,7 @@ func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[source.File
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diagnostics, err := mth.Tidy(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, e := range diagnostics {
|
||||
for _, e := range tidied.Errors {
|
||||
diag := &source.Diagnostic{
|
||||
Message: e.Message,
|
||||
Range: e.Range,
|
||||
|
|
@ -98,16 +94,12 @@ func ExtractGoCommandError(ctx context.Context, snapshot source.Snapshot, fh sou
|
|||
break
|
||||
}
|
||||
}
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed, m, _, err := pmh.Parse(ctx, snapshot)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
toDiagnostic := func(line *modfile.Line) (*source.Diagnostic, error) {
|
||||
rng, err := rangeFromPositions(fh.URI(), m, line.Start, line.End)
|
||||
rng, err := rangeFromPositions(fh.URI(), pm.Mapper, line.Start, line.End)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -119,19 +111,19 @@ func ExtractGoCommandError(ctx context.Context, snapshot source.Snapshot, fh sou
|
|||
}
|
||||
// Check if there are any require, exclude, or replace statements that
|
||||
// match this module version.
|
||||
for _, req := range parsed.Require {
|
||||
for _, req := range pm.File.Require {
|
||||
if req.Mod != v {
|
||||
continue
|
||||
}
|
||||
return toDiagnostic(req.Syntax)
|
||||
}
|
||||
for _, ex := range parsed.Exclude {
|
||||
for _, ex := range pm.File.Exclude {
|
||||
if ex.Mod != v {
|
||||
continue
|
||||
}
|
||||
return toDiagnostic(ex.Syntax)
|
||||
}
|
||||
for _, rep := range parsed.Replace {
|
||||
for _, rep := range pm.File.Replace {
|
||||
if rep.New != v && rep.Old != v {
|
||||
continue
|
||||
}
|
||||
|
|
@ -139,7 +131,7 @@ func ExtractGoCommandError(ctx context.Context, snapshot source.Snapshot, fh sou
|
|||
}
|
||||
// No match for the module path was found in the go.mod file.
|
||||
// Show the error on the module declaration.
|
||||
return toDiagnostic(parsed.Module.Syntax)
|
||||
return toDiagnostic(pm.File.Module.Syntax)
|
||||
}
|
||||
|
||||
func rangeFromPositions(uri span.URI, m *protocol.ColumnMapper, s, e modfile.Position) (protocol.Range, error) {
|
||||
|
|
|
|||
|
|
@ -12,19 +12,15 @@ func Format(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle)
|
|||
ctx, done := event.Start(ctx, "mod.Format")
|
||||
defer done()
|
||||
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, m, _, err := pmh.Parse(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
formatted, err := file.Format()
|
||||
formatted, err := pm.File.Format()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Calculate the edits to be made due to the change.
|
||||
diff := snapshot.View().Options().ComputeEdits(fh.URI(), string(m.Content), string(formatted))
|
||||
return source.ToProtocolEdits(m, diff)
|
||||
diff := snapshot.View().Options().ComputeEdits(fh.URI(), string(pm.Mapper.Content), string(formatted))
|
||||
return source.ToProtocolEdits(pm.Mapper, diff)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,19 +26,15 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
|
|||
defer done()
|
||||
|
||||
// Get the position of the cursor.
|
||||
pmh, err := snapshot.ParseModHandle(ctx, fh)
|
||||
pm, err := snapshot.ParseMod(ctx, fh)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting modfile handle: %w", err)
|
||||
}
|
||||
file, m, _, err := pmh.Parse(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spn, err := m.PointSpan(position)
|
||||
spn, err := pm.Mapper.PointSpan(position)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("computing cursor position: %w", err)
|
||||
}
|
||||
hoverRng, err := spn.Range(m.Converter)
|
||||
hoverRng, err := spn.Range(pm.Mapper.Converter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("computing hover range: %w", err)
|
||||
}
|
||||
|
|
@ -46,10 +42,10 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
|
|||
// Confirm that the cursor is at the position of a require statement.
|
||||
var req *modfile.Require
|
||||
var startPos, endPos int
|
||||
for _, r := range file.Require {
|
||||
for _, r := range pm.File.Require {
|
||||
dep := []byte(r.Mod.Path)
|
||||
s, e := r.Syntax.Start.Byte, r.Syntax.End.Byte
|
||||
i := bytes.Index(m.Content[s:e], dep)
|
||||
i := bytes.Index(pm.Mapper.Content[s:e], dep)
|
||||
if i == -1 {
|
||||
continue
|
||||
}
|
||||
|
|
@ -68,37 +64,30 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
|
|||
}
|
||||
|
||||
// Get the `go mod why` results for the given file.
|
||||
mwh, err := snapshot.ModWhyHandle(ctx)
|
||||
why, err := snapshot.ModWhy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
why, err := mwh.Why(ctx, snapshot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("running go mod why: %w", err)
|
||||
}
|
||||
if why == nil {
|
||||
return nil, nil
|
||||
}
|
||||
explanation, ok := why[req.Mod.Path]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get the range to highlight for the hover.
|
||||
line, col, err := m.Converter.ToPosition(startPos)
|
||||
line, col, err := pm.Mapper.Converter.ToPosition(startPos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start := span.NewPoint(line, col, startPos)
|
||||
|
||||
line, col, err = m.Converter.ToPosition(endPos)
|
||||
line, col, err = pm.Mapper.Converter.ToPosition(endPos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
end := span.NewPoint(line, col, endPos)
|
||||
|
||||
spn = span.New(fh.URI(), start, end)
|
||||
rng, err := m.Range(spn)
|
||||
rng, err := pm.Mapper.Range(spn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,23 +74,17 @@ type Snapshot interface {
|
|||
// -modfile flag.
|
||||
RunGoCommandDirect(ctx context.Context, verb string, args []string) error
|
||||
|
||||
// ParseModHandle is used to parse go.mod files.
|
||||
ParseModHandle(ctx context.Context, fh FileHandle) (ParseModHandle, error)
|
||||
// ParseMod is used to parse go.mod files.
|
||||
ParseMod(ctx context.Context, fh FileHandle) (*ParsedModule, error)
|
||||
|
||||
// ModWhyHandle is used get the results of `go mod why` for a given module.
|
||||
// It only works for go.mod files that can be parsed, hence it takes a
|
||||
// ParseModHandle.
|
||||
ModWhyHandle(ctx context.Context) (ModWhyHandle, error)
|
||||
// ModWhy returns the results of `go mod why` for the snapshot's module.
|
||||
ModWhy(ctx context.Context) (map[string]string, error)
|
||||
|
||||
// ModWhyHandle is used get the possible upgrades for the dependencies of
|
||||
// a given module. It only works for go.mod files that can be parsed, hence
|
||||
// it takes a ParseModHandle.
|
||||
ModUpgradeHandle(ctx context.Context) (ModUpgradeHandle, error)
|
||||
// ModUpgrade returns the possible updates for the snapshot's module.
|
||||
ModUpgrade(ctx context.Context) (map[string]string, error)
|
||||
|
||||
// ModWhyHandle is used get the results of `go mod tidy` for a given
|
||||
// module. It only works for go.mod files that can be parsed, hence it
|
||||
// takes a ParseModHandle.
|
||||
ModTidyHandle(ctx context.Context) (ModTidyHandle, error)
|
||||
// ModTidy returns the results of `go mod tidy` for the snapshot's module.
|
||||
ModTidy(ctx context.Context) (*TidiedModule, error)
|
||||
|
||||
// PackagesForFile returns the packages that this file belongs to.
|
||||
PackagesForFile(ctx context.Context, uri span.URI) ([]Package, error)
|
||||
|
|
@ -183,6 +177,7 @@ type BuiltinPackage interface {
|
|||
ParsedFile() *ParsedGoFile
|
||||
}
|
||||
|
||||
// A ParsedGoFile contains the results of parsing a Go file.
|
||||
type ParsedGoFile struct {
|
||||
memoize.NoCopy
|
||||
|
||||
|
|
@ -197,6 +192,27 @@ type ParsedGoFile struct {
|
|||
ParseErr error
|
||||
}
|
||||
|
||||
// A ParsedModule contains the results of parsing a go.mod file.
|
||||
type ParsedModule struct {
|
||||
memoize.NoCopy
|
||||
|
||||
File *modfile.File
|
||||
Mapper *protocol.ColumnMapper
|
||||
ParseErrors []Error
|
||||
}
|
||||
|
||||
// A TidedModule contains the results of running `go mod tidy` on a module.
|
||||
type TidiedModule struct {
|
||||
memoize.NoCopy
|
||||
|
||||
// The parsed module, which is guaranteed to have parsed successfully.
|
||||
Parsed *ParsedModule
|
||||
// Diagnostics representing changes made by `go mod tidy`.
|
||||
Errors []Error
|
||||
// The bytes of the go.mod file after it was tidied.
|
||||
TidiedContent []byte
|
||||
}
|
||||
|
||||
// Session represents a single connection from a client.
|
||||
// This is the level at which things like open files are maintained on behalf
|
||||
// of the client.
|
||||
|
|
@ -319,41 +335,6 @@ type Cache interface {
|
|||
GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
|
||||
}
|
||||
|
||||
type ParseModHandle interface {
|
||||
// Mod returns the file handle for the go.mod file.
|
||||
Mod() FileHandle
|
||||
|
||||
// Sum returns the file handle for the analogous go.sum file. It may be nil.
|
||||
Sum() FileHandle
|
||||
|
||||
// Parse returns the parsed go.mod file, a column mapper, and a list of
|
||||
// parse for the go.mod file.
|
||||
Parse(ctx context.Context, snapshot Snapshot) (*modfile.File, *protocol.ColumnMapper, []Error, error)
|
||||
}
|
||||
|
||||
type ModUpgradeHandle interface {
|
||||
// Upgrades returns the latest versions for each of the module's
|
||||
// dependencies.
|
||||
Upgrades(ctx context.Context, snapshot Snapshot) (map[string]string, error)
|
||||
}
|
||||
|
||||
type ModWhyHandle interface {
|
||||
// Why returns the results of `go mod why` for every dependency of the
|
||||
// module.
|
||||
Why(ctx context.Context, snapshot Snapshot) (map[string]string, error)
|
||||
}
|
||||
|
||||
type ModTidyHandle interface {
|
||||
// Mod is the ParseModHandle associated with the go.mod file being tidied.
|
||||
ParseModHandle() ParseModHandle
|
||||
|
||||
// Tidy returns the results of `go mod tidy` for the module.
|
||||
Tidy(ctx context.Context, snapshot Snapshot) ([]Error, error)
|
||||
|
||||
// TidiedContent is the content of the tidied go.mod file.
|
||||
TidiedContent(ctx context.Context, snapshot Snapshot) ([]byte, error)
|
||||
}
|
||||
|
||||
var ErrTmpModfileUnsupported = errors.New("-modfile is unsupported for this Go version")
|
||||
|
||||
// ParseMode controls the content of the AST produced when parsing a source file.
|
||||
|
|
|
|||
Loading…
Reference in New Issue