internal/lsp: run gopls as long as there is one folder with a file URI

Fixes golang/vscode-go#585

Change-Id: Icb4295f1cab5c0fe60c86dd5f911023f70d2dd62
Reviewed-on: https://go-review.googlesource.com/c/tools/+/252123
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/general.go b/internal/lsp/general.go
index 53424de..397e6b6 100644
--- a/internal/lsp/general.go
+++ b/internal/lsp/general.go
@@ -44,31 +44,27 @@
 	}
 	options.ForClientCapabilities(params.Capabilities)
 
-	// gopls only supports URIs with a file:// scheme. Any other URIs will not
-	// work, so fail to initialize. See golang/go#40272.
-	if params.RootURI != "" && !params.RootURI.SpanURI().IsFile() {
-		return nil, fmt.Errorf("unsupported URI scheme: %v (gopls only supports file URIs)", params.RootURI)
-	}
-	if params.RootURI != "" {
-		s.rootURI = params.RootURI.SpanURI()
-	}
-
-	for _, folder := range params.WorkspaceFolders {
-		uri := span.URIFromURI(folder.URI)
-		if !uri.IsFile() {
-			return nil, fmt.Errorf("unsupported URI scheme: %q (gopls only supports file URIs)", folder.URI)
-		}
-	}
-
-	s.pendingFolders = params.WorkspaceFolders
-	if len(s.pendingFolders) == 0 {
+	folders := params.WorkspaceFolders
+	if len(folders) == 0 {
 		if params.RootURI != "" {
-			s.pendingFolders = []protocol.WorkspaceFolder{{
+			folders = []protocol.WorkspaceFolder{{
 				URI:  string(params.RootURI),
 				Name: path.Base(params.RootURI.SpanURI().Filename()),
 			}}
 		}
 	}
+	for _, folder := range folders {
+		uri := span.URIFromURI(folder.URI)
+		if !uri.IsFile() {
+			continue
+		}
+		s.pendingFolders = append(s.pendingFolders, folder)
+	}
+	// gopls only supports URIs with a file:// scheme, so if we have no
+	// workspace folders with a supported scheme, fail to initialize.
+	if len(folders) > 0 && len(s.pendingFolders) == 0 {
+		return nil, fmt.Errorf("unsupported URI schemes: %v (gopls only supports file URIs)", folders)
+	}
 
 	var codeActionProvider interface{} = true
 	if ca := params.Capabilities.TextDocument.CodeAction; len(ca.CodeActionLiteralSupport.CodeActionKind.ValueSet) > 0 {
@@ -198,6 +194,10 @@
 	dirsToWatch := map[span.URI]struct{}{}
 	for _, folder := range folders {
 		uri := span.URIFromURI(folder.URI)
+		// Ignore non-file URIs.
+		if !uri.IsFile() {
+			continue
+		}
 		work := s.progress.start(ctx, "Setting up workspace", "Loading packages...", nil, nil)
 		view, snapshot, release, err := s.addView(ctx, folder.Name, uri)
 		if err != nil {
@@ -340,10 +340,12 @@
 	}}
 	for dir := range dirs {
 		filename := dir.Filename()
-		// If the directory is within the root URI, we're already watching it
-		// via the relative path above.
-		if isSubdirectory(s.rootURI.Filename(), filename) {
-			continue
+		// If the directory is within a workspace folder, we're already
+		// watching it via the relative path above.
+		for _, view := range s.session.Views() {
+			if isSubdirectory(view.Folder().Filename(), filename) {
+				continue
+			}
 		}
 		// If microsoft/vscode#100870 is resolved before
 		// microsoft/vscode#104387, we will need a work-around for Windows
diff --git a/internal/lsp/server.go b/internal/lsp/server.go
index 52403f5..c135b34 100644
--- a/internal/lsp/server.go
+++ b/internal/lsp/server.go
@@ -65,9 +65,6 @@
 
 	session source.Session
 
-	// rootURI is the root of the workspace opened in the editor (if any).
-	rootURI span.URI
-
 	// changedFiles tracks files for which there has been a textDocument/didChange.
 	changedFilesMu sync.Mutex
 	changedFiles   map[span.URI]struct{}