internal/lsp: handle language ID in didOpen calls

This change merely modifies session.DidOpen to accept the document's
language ID. It does not actually add any handling of the language ID.

Change-Id: I2582ae307d1ca062f37b4683907cdbcfdfc61809
Reviewed-on: https://go-review.googlesource.com/c/tools/+/184160
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/lsp/cache/session.go b/internal/lsp/cache/session.go
index 0b568b6..4775a9b 100644
--- a/internal/lsp/cache/session.go
+++ b/internal/lsp/cache/session.go
@@ -183,7 +183,8 @@
 	return s.log
 }
 
-func (s *session) DidOpen(ctx context.Context, uri span.URI, text []byte) {
+// TODO: Propagate the language ID through to the view.
+func (s *session) DidOpen(ctx context.Context, uri span.URI, _ source.FileKind, text []byte) {
 	// Mark the file as open.
 	s.openFiles.Store(uri, true)
 
diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go
index 837019d..03aa3d2 100644
--- a/internal/lsp/cmd/cmd.go
+++ b/internal/lsp/cmd/cmd.go
@@ -335,12 +335,14 @@
 func (c *connection) AddFile(ctx context.Context, uri span.URI) *cmdFile {
 	c.Client.filesMu.Lock()
 	defer c.Client.filesMu.Unlock()
+
 	file := c.Client.getFile(ctx, uri)
 	if !file.added {
 		file.added = true
 		p := &protocol.DidOpenTextDocumentParams{}
 		p.TextDocument.URI = string(uri)
 		p.TextDocument.Text = string(file.mapper.Content)
+		p.TextDocument.LanguageID = source.DetectLanguage("", file.uri.Filename()).String()
 		if err := c.Server.DidOpen(ctx, p); err != nil {
 			file.err = fmt.Errorf("%v: %v", uri, err)
 		}
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index cfacb46..38ca24e 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -9,9 +9,41 @@
 	"go/ast"
 	"go/token"
 	"go/types"
+	"path/filepath"
 	"strings"
 )
 
+func DetectLanguage(langID, filename string) FileKind {
+	switch langID {
+	case "go":
+		return Go
+	case "go.mod":
+		return Mod
+	case "go.sum":
+		return Sum
+	}
+	// Fallback to detecting the language based on the file extension.
+	switch filepath.Ext(filename) {
+	case ".mod":
+		return Mod
+	case ".sum":
+		return Sum
+	default: // fallback to Go
+		return Go
+	}
+}
+
+func (k FileKind) String() string {
+	switch k {
+	case Mod:
+		return "go.mod"
+	case Sum:
+		return "go.sum"
+	default:
+		return "go"
+	}
+}
+
 // indexExprAtPos returns the index of the expression containing pos.
 func indexExprAtPos(pos token.Pos, args []ast.Expr) int {
 	for i, expr := range args {
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index 2e99f49..996d659 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -154,7 +154,7 @@
 	FileSystem
 
 	// DidOpen is invoked each time a file is opened in the editor.
-	DidOpen(ctx context.Context, uri span.URI, text []byte)
+	DidOpen(ctx context.Context, uri span.URI, kind FileKind, text []byte)
 
 	// DidSave is invoked each time an open file is saved in the editor.
 	DidSave(uri span.URI)
diff --git a/internal/lsp/text_synchronization.go b/internal/lsp/text_synchronization.go
index 90ecce6..0f3e023 100644
--- a/internal/lsp/text_synchronization.go
+++ b/internal/lsp/text_synchronization.go
@@ -20,8 +20,11 @@
 	uri := span.NewURI(params.TextDocument.URI)
 	text := []byte(params.TextDocument.Text)
 
+	// Confirm that the file's language ID is related to Go.
+	fileKind := source.DetectLanguage(params.TextDocument.LanguageID, uri.Filename())
+
 	// Open the file.
-	s.session.DidOpen(ctx, uri, text)
+	s.session.DidOpen(ctx, uri, fileKind, text)
 
 	// Run diagnostics on the newly-changed file.
 	view := s.session.ViewOf(uri)