Skip to content

Commit 6422c5c

Browse files
committed
internal/lsp/cache: invalidate metadata on magic comment changes
When a //go:embed or //go:build (//+build) line changes, we need to invalidate metadata. Do so. It might be preferable to only invalidate on save, but we don't currently have an approach for doing that. So for now we'll load on each keystroke in a magic comment. Fixes golang/go#38732, golang/go#44342. Change-Id: Id05fb84f44215ea6242a7cf8b2bca4e85f74680e Reviewed-on: https://go-review.googlesource.com/c/tools/+/296549 Trust: Heschi Kreinick <[email protected]> Run-TryBot: Heschi Kreinick <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Rebecca Stambler <[email protected]>
1 parent f9c628b commit 6422c5c

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

gopls/internal/regtest/diagnostics/diagnostics_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,3 +1789,30 @@ func main() {}
17891789
)
17901790
})
17911791
}
1792+
1793+
func TestBuildTagChange(t *testing.T) {
1794+
const files = `
1795+
-- go.mod --
1796+
module mod.com
1797+
1798+
go 1.12
1799+
-- foo.go --
1800+
// decoy comment
1801+
// +build hidden
1802+
// decoy comment
1803+
1804+
package foo
1805+
var Foo = 1
1806+
-- bar.go --
1807+
package foo
1808+
var Bar = Foo
1809+
`
1810+
1811+
Run(t, files, func(t *testing.T, env *Env) {
1812+
env.OpenFile("foo.go")
1813+
env.Await(env.DiagnosticAtRegexpWithMessage("bar.go", `Foo`, "undeclared name"))
1814+
env.RegexpReplace("foo.go", `\+build`, "")
1815+
env.Await(EmptyDiagnostics("bar.go"))
1816+
})
1817+
1818+
}

gopls/internal/regtest/misc/embed_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import (
2626
var foo string
2727
`
2828
Run(t, files, func(t *testing.T, env *Env) {
29+
env.OpenFile("x.go")
2930
env.Await(env.DiagnosticAtRegexpWithMessage("x.go", `NONEXISTENT`, "no matching files found"))
31+
env.RegexpReplace("x.go", `NONEXISTENT`, "x.go")
32+
env.Await(EmptyDiagnostics("x.go"))
3033
})
3134
}

internal/lsp/cache/snapshot.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"io/ioutil"
1616
"os"
1717
"path/filepath"
18+
"regexp"
1819
"sort"
1920
"strconv"
2021
"strings"
@@ -1680,9 +1681,38 @@ func (s *snapshot) shouldInvalidateMetadata(ctx context.Context, newSnapshot *sn
16801681
}
16811682
return true, false
16821683
}
1684+
1685+
// Re-evaluate build constraints and embed patterns. It would be preferable
1686+
// to only do this on save, but we don't have the prior versions accessible.
1687+
oldComments := extractMagicComments(original.File)
1688+
newComments := extractMagicComments(current.File)
1689+
if len(oldComments) != len(newComments) {
1690+
return true, false
1691+
}
1692+
for i := range oldComments {
1693+
if oldComments[i] != newComments[i] {
1694+
return true, false
1695+
}
1696+
}
1697+
16831698
return false, false
16841699
}
16851700

1701+
var buildConstraintOrEmbedRe = regexp.MustCompile(`^//(go:embed|go:build|\s*\+build).*`)
1702+
1703+
// extractMagicComments finds magic comments that affect metadata in f.
1704+
func extractMagicComments(f *ast.File) []string {
1705+
var results []string
1706+
for _, cg := range f.Comments {
1707+
for _, c := range cg.List {
1708+
if buildConstraintOrEmbedRe.MatchString(c.Text) {
1709+
results = append(results, c.Text)
1710+
}
1711+
}
1712+
}
1713+
return results
1714+
}
1715+
16861716
func (s *snapshot) BuiltinPackage(ctx context.Context) (*source.BuiltinPackage, error) {
16871717
s.AwaitInitialized(ctx)
16881718

0 commit comments

Comments
 (0)