@@ -26,7 +26,6 @@ import (
2626 "golang.org/x/tools/go/internal/packagesdriver"
2727 "golang.org/x/tools/internal/gopathwalk"
2828 "golang.org/x/tools/internal/semver"
29- "golang.org/x/tools/internal/span"
3029)
3130
3231// debug controls verbose logging.
@@ -287,42 +286,43 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
287286 return fmt .Errorf ("could not determine absolute path of file= query path %q: %v" , query , err )
288287 }
289288 dirResponse , err := driver (cfg , pattern )
290- if err != nil {
289+ if err != nil || (len (dirResponse .Packages ) == 1 && len (dirResponse .Packages [0 ].Errors ) == 1 ) {
290+ // There was an error loading the package. Try to load the file as an ad-hoc package.
291+ // Usually the error will appear in a returned package, but may not if we're in modules mode
292+ // and the ad-hoc is located outside a module.
291293 var queryErr error
292- if dirResponse , queryErr = adHocPackage (cfg , driver , pattern , query ); queryErr != nil {
293- return err // return the original error
294+ dirResponse , queryErr = driver (cfg , query )
295+ if queryErr != nil {
296+ // Return the original error if the attempt to fall back failed.
297+ return err
294298 }
295- }
296- // `go list` can report errors for files that are not listed as part of a package's GoFiles.
297- // In the case of an invalid Go file, we should assume that it is part of package if only
298- // one package is in the response. The file may have valid contents in an overlay.
299- if len (dirResponse .Packages ) == 1 {
300- pkg := dirResponse .Packages [0 ]
301- for i , err := range pkg .Errors {
302- s := errorSpan (err )
303- if ! s .IsValid () {
304- break
305- }
306- if len (pkg .CompiledGoFiles ) == 0 {
307- break
308- }
309- dir := filepath .Dir (pkg .CompiledGoFiles [0 ])
310- filename := filepath .Join (dir , filepath .Base (s .URI ().Filename ()))
311- if info , err := os .Stat (filename ); err != nil || info .IsDir () {
312- break
313- }
314- if ! contains (pkg .CompiledGoFiles , filename ) {
315- pkg .CompiledGoFiles = append (pkg .CompiledGoFiles , filename )
316- pkg .GoFiles = append (pkg .GoFiles , filename )
317- pkg .Errors = append (pkg .Errors [:i ], pkg .Errors [i + 1 :]... )
318- }
299+ // If we get nothing back from `go list`, try to make this file into its own ad-hoc package.
300+ if len (dirResponse .Packages ) == 0 && queryErr == nil {
301+ dirResponse .Packages = append (dirResponse .Packages , & Package {
302+ ID : "command-line-arguments" ,
303+ PkgPath : query ,
304+ GoFiles : []string {query },
305+ CompiledGoFiles : []string {query },
306+ Imports : make (map [string ]* Package ),
307+ })
308+ dirResponse .Roots = append (dirResponse .Roots , "command-line-arguments" )
319309 }
320- }
321- // A final attempt to construct an ad-hoc package.
322- if len (dirResponse .Packages ) == 1 && len (dirResponse .Packages [0 ].Errors ) == 1 {
323- var queryErr error
324- if dirResponse , queryErr = adHocPackage (cfg , driver , pattern , query ); queryErr != nil {
325- return err // return the original error
310+ // Special case to handle issue #33482:
311+ // If this is a file= query for ad-hoc packages where the file only exists on an overlay,
312+ // and exists outside of a module, add the file in for the package.
313+ if len (dirResponse .Packages ) == 1 && (dirResponse .Packages [0 ].ID == "command-line-arguments" ||
314+ filepath .ToSlash (dirResponse .Packages [0 ].PkgPath ) == filepath .ToSlash (query )) {
315+ if len (dirResponse .Packages [0 ].GoFiles ) == 0 {
316+ filename := filepath .Join (pattern , filepath .Base (query )) // avoid recomputing abspath
317+ // TODO(matloob): check if the file is outside of a root dir?
318+ for path := range cfg .Overlay {
319+ if path == filename {
320+ dirResponse .Packages [0 ].Errors = nil
321+ dirResponse .Packages [0 ].GoFiles = []string {path }
322+ dirResponse .Packages [0 ].CompiledGoFiles = []string {path }
323+ }
324+ }
325+ }
326326 }
327327 }
328328 isRoot := make (map [string ]bool , len (dirResponse .Roots ))
@@ -350,74 +350,6 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
350350 return nil
351351}
352352
353- // adHocPackage attempts to construct an ad-hoc package given a query that failed.
354- func adHocPackage (cfg * Config , driver driver , pattern , query string ) (* driverResponse , error ) {
355- // There was an error loading the package. Try to load the file as an ad-hoc package.
356- // Usually the error will appear in a returned package, but may not if we're in modules mode
357- // and the ad-hoc is located outside a module.
358- dirResponse , err := driver (cfg , query )
359- if err != nil {
360- return nil , err
361- }
362- // If we get nothing back from `go list`, try to make this file into its own ad-hoc package.
363- if len (dirResponse .Packages ) == 0 && err == nil {
364- dirResponse .Packages = append (dirResponse .Packages , & Package {
365- ID : "command-line-arguments" ,
366- PkgPath : query ,
367- GoFiles : []string {query },
368- CompiledGoFiles : []string {query },
369- Imports : make (map [string ]* Package ),
370- })
371- dirResponse .Roots = append (dirResponse .Roots , "command-line-arguments" )
372- }
373- // Special case to handle issue #33482:
374- // If this is a file= query for ad-hoc packages where the file only exists on an overlay,
375- // and exists outside of a module, add the file in for the package.
376- if len (dirResponse .Packages ) == 1 && (dirResponse .Packages [0 ].ID == "command-line-arguments" || dirResponse .Packages [0 ].PkgPath == filepath .ToSlash (query )) {
377- if len (dirResponse .Packages [0 ].GoFiles ) == 0 {
378- filename := filepath .Join (pattern , filepath .Base (query )) // avoid recomputing abspath
379- // TODO(matloob): check if the file is outside of a root dir?
380- for path := range cfg .Overlay {
381- if path == filename {
382- dirResponse .Packages [0 ].Errors = nil
383- dirResponse .Packages [0 ].GoFiles = []string {path }
384- dirResponse .Packages [0 ].CompiledGoFiles = []string {path }
385- }
386- }
387- }
388- }
389- return dirResponse , nil
390- }
391-
392- func contains (files []string , filename string ) bool {
393- for _ , f := range files {
394- if f == filename {
395- return true
396- }
397- }
398- return false
399- }
400-
401- // errorSpan attempts to parse a standard `go list` error message
402- // by stripping off the trailing error message.
403- //
404- // It works only on errors whose message is prefixed by colon,
405- // followed by a space (": "). For example:
406- //
407- // attributes.go:13:1: expected 'package', found 'type'
408- //
409- func errorSpan (err Error ) span.Span {
410- if err .Pos == "" {
411- input := strings .TrimSpace (err .Msg )
412- msgIndex := strings .Index (input , ": " )
413- if msgIndex < 0 {
414- return span .Parse (input )
415- }
416- return span .Parse (input [:msgIndex ])
417- }
418- return span .Parse (err .Pos )
419- }
420-
421353// modCacheRegexp splits a path in a module cache into module, module version, and package.
422354var modCacheRegexp = regexp .MustCompile (`(.*)@([^/\\]*)(.*)` )
423355
0 commit comments