internal/lsp: only linkify urls with http, https, and ftp schemes

Fixes golang/go#43990

Change-Id: I0ea26d521b2432238b05c26bfaccef6fc773dcf2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/393854
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Peter Weinberger <pjw@google.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/gopls/internal/regtest/misc/link_test.go b/gopls/internal/regtest/misc/link_test.go
index daea742..e84f637 100644
--- a/gopls/internal/regtest/misc/link_test.go
+++ b/gopls/internal/regtest/misc/link_test.go
@@ -15,6 +15,7 @@
 
 func TestHoverAndDocumentLink(t *testing.T) {
 	testenv.NeedsGo1Point(t, 13)
+
 	const program = `
 -- go.mod --
 module mod.test
@@ -31,6 +32,8 @@
 import "import.test/pkg"
 
 func main() {
+	// Issue 43990: this is not a link that most users can open from an LSP
+	// client: mongodb://not.a.link.com
 	println(pkg.Hello)
 }`
 
diff --git a/internal/lsp/link.go b/internal/lsp/link.go
index 2f9f006..dcb9217 100644
--- a/internal/lsp/link.go
+++ b/internal/lsp/link.go
@@ -185,6 +185,14 @@
 	return modpath, version, true
 }
 
+// acceptedSchemes controls the schemes that URLs must have to be shown to the
+// user. Other schemes can't be opened by LSP clients, so linkifying them is
+// distracting. See golang/go#43990.
+var acceptedSchemes = map[string]bool{
+	"http":  true,
+	"https": true,
+}
+
 func findLinksInString(ctx context.Context, snapshot source.Snapshot, src string, pos token.Pos, m *protocol.ColumnMapper, fileKind source.FileKind) ([]protocol.DocumentLink, error) {
 	var links []protocol.DocumentLink
 	for _, index := range snapshot.View().Options().URLRegexp.FindAllIndex([]byte(src), -1) {
@@ -205,6 +213,9 @@
 		if linkURL.Scheme == "" {
 			linkURL.Scheme = "https"
 		}
+		if !acceptedSchemes[linkURL.Scheme] {
+			continue
+		}
 		l, err := toProtocolLink(snapshot, m, linkURL.String(), startPos, endPos, fileKind)
 		if err != nil {
 			return nil, err
diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go
index 79628ee..123bbe1 100644
--- a/internal/lsp/source/options.go
+++ b/internal/lsp/source/options.go
@@ -475,7 +475,10 @@
 	// ComputeEdits is used to compute edits between file versions.
 	ComputeEdits diff.ComputeEdits
 
-	// URLRegexp is used to find urls in comments and strings.
+	// URLRegexp is used to find potential URLs in comments/strings.
+	//
+	// Not all matches are shown to the user: if the matched URL is not detected
+	// as valid, it will be skipped.
 	URLRegexp *regexp.Regexp
 
 	// GofumptFormat allows the gopls module to wire-in a call to