internal/lsp: do not rename in compiler directive comments

Fixes golang/go#42331

Change-Id: I63599c961ac963b22dacd706b312807678c0a9d6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/267121
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Peter Weinberger <pjw@google.com>
diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go
index 7fdcc70..26c705a 100644
--- a/internal/lsp/source/rename.go
+++ b/internal/lsp/source/rename.go
@@ -216,6 +216,9 @@
 		// go/parser strips out \r\n returns from the comment text, so go
 		// line-by-line through the comment text to get the correct positions.
 		for _, comment := range doc.List {
+			if isDirective(comment.Text) {
+				continue
+			}
 			lines := strings.Split(comment.Text, "\n")
 			tok := r.fset.File(comment.Pos())
 			commentLine := tok.Position(comment.Pos()).Line
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index 1e0ac9a..4e01099 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -401,3 +401,43 @@
 		return p.Name()
 	}
 }
+
+// isDirective reports whether c is a comment directive.
+//
+// Copied and adapted from go/src/go/ast/ast.go.
+func isDirective(c string) bool {
+	if len(c) < 3 {
+		return false
+	}
+	if c[1] != '/' {
+		return false
+	}
+	//-style comment (no newline at the end)
+	c = c[2:]
+	if len(c) == 0 {
+		// empty line
+		return false
+	}
+	// "//line " is a line directive.
+	// (The // has been removed.)
+	if strings.HasPrefix(c, "line ") {
+		return true
+	}
+
+	// "//[a-z0-9]+:[a-z0-9]"
+	// (The // has been removed.)
+	colon := strings.Index(c, ":")
+	if colon <= 0 || colon+1 >= len(c) {
+		return false
+	}
+	for i := 0; i <= colon+1; i++ {
+		if i == colon {
+			continue
+		}
+		b := c[i]
+		if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {
+			return false
+		}
+	}
+	return true
+}
diff --git a/internal/lsp/testdata/rename/c/c2.go b/internal/lsp/testdata/rename/c/c2.go
new file mode 100644
index 0000000..4fc484a
--- /dev/null
+++ b/internal/lsp/testdata/rename/c/c2.go
@@ -0,0 +1,4 @@
+package c
+
+//go:embed Static/*
+var Static embed.FS //@rename("Static", "static")
\ No newline at end of file
diff --git a/internal/lsp/testdata/rename/c/c2.go.golden b/internal/lsp/testdata/rename/c/c2.go.golden
new file mode 100644
index 0000000..e509227
--- /dev/null
+++ b/internal/lsp/testdata/rename/c/c2.go.golden
@@ -0,0 +1,5 @@
+-- static-rename --
+package c
+
+//go:embed Static/*
+var static embed.FS //@rename("Static", "static")
diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden
index 6e2da0b..3771c85 100644
--- a/internal/lsp/testdata/summary.txt.golden
+++ b/internal/lsp/testdata/summary.txt.golden
@@ -19,7 +19,7 @@
 TypeDefinitionsCount = 2
 HighlightsCount = 69
 ReferencesCount = 25
-RenamesCount = 29
+RenamesCount = 30
 PrepareRenamesCount = 7
 SymbolsCount = 5
 WorkspaceSymbolsCount = 2