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