@@ -733,8 +733,11 @@ func (s *snapshot) FindFile(uri span.URI) source.VersionedFileHandle {
733
733
return s .files [f .URI ()]
734
734
}
735
735
736
- // GetFile returns a File for the given URI. It will always succeed because it
737
- // adds the file to the managed set if needed.
736
+ // GetFile returns a File for the given URI. If the file is unknown it is added
737
+ // to the managed set.
738
+ //
739
+ // GetFile succeeds even if the file does not exist. A non-nil error return
740
+ // indicates some type of internal error, for example if ctx is cancelled.
738
741
func (s * snapshot ) GetFile (ctx context.Context , uri span.URI ) (source.VersionedFileHandle , error ) {
739
742
f , err := s .view .getFile (uri )
740
743
if err != nil {
@@ -1426,6 +1429,25 @@ func (s *snapshot) getWorkspaceModuleHandle(ctx context.Context) (*workspaceModu
1426
1429
}
1427
1430
fhs = append (fhs , fh )
1428
1431
}
1432
+ goplsModURI := span .URIFromPath (filepath .Join (s .view .Folder ().Filename (), "gopls.mod" ))
1433
+ goplsModFH , err := s .GetFile (ctx , goplsModURI )
1434
+ if err != nil {
1435
+ return nil , err
1436
+ }
1437
+ _ , err = goplsModFH .Read ()
1438
+ switch {
1439
+ case err == nil :
1440
+ // We have a gopls.mod. Our handle only depends on it.
1441
+ fhs = []source.FileHandle {goplsModFH }
1442
+ case os .IsNotExist (err ):
1443
+ // No gopls.mod, so we must build the workspace mod file automatically.
1444
+ // Defensively ensure that the goplsModFH is nil as this controls automatic
1445
+ // building of the workspace mod file.
1446
+ goplsModFH = nil
1447
+ default :
1448
+ return nil , errors .Errorf ("error getting gopls.mod: %w" , err )
1449
+ }
1450
+
1429
1451
sort .Slice (fhs , func (i , j int ) bool {
1430
1452
return fhs [i ].URI () < fhs [j ].URI ()
1431
1453
})
@@ -1435,6 +1457,13 @@ func (s *snapshot) getWorkspaceModuleHandle(ctx context.Context) (*workspaceModu
1435
1457
}
1436
1458
key := workspaceModuleKey (hashContents ([]byte (k )))
1437
1459
h := s .generation .Bind (key , func (ctx context.Context , arg memoize.Arg ) interface {} {
1460
+ if goplsModFH != nil {
1461
+ parsed , err := s .ParseMod (ctx , goplsModFH )
1462
+ if err != nil {
1463
+ return & workspaceModuleData {err : err }
1464
+ }
1465
+ return & workspaceModuleData {file : parsed .File }
1466
+ }
1438
1467
s := arg .(* snapshot )
1439
1468
data := & workspaceModuleData {}
1440
1469
data .file , data .err = s .BuildWorkspaceModFile (ctx )
@@ -1450,7 +1479,7 @@ func (s *snapshot) getWorkspaceModuleHandle(ctx context.Context) (*workspaceModu
1450
1479
}
1451
1480
1452
1481
// BuildWorkspaceModFile generates a workspace module given the modules in the
1453
- // the workspace.
1482
+ // the workspace. It does not read gopls.mod.
1454
1483
func (s * snapshot ) BuildWorkspaceModFile (ctx context.Context ) (* modfile.File , error ) {
1455
1484
file := & modfile.File {}
1456
1485
file .AddModuleStmt ("gopls-workspace" )
0 commit comments