mirror of https://github.com/golang/go.git
internal/lsp: enable template processing and add templateFiles option
Move template processing out of experimental and enable it. Users can set the option 'templateSupport' to false to disable it. Also, add a new flag 'templateExtensions', defaulting to ['tmpl','gotmpl'] to let the user provide a list of extensions of files to be considered as template files. Change-Id: I724387738c1632256999cda304d6cf9fa48ed91d Reviewed-on: https://go-review.googlesource.com/c/tools/+/362241 Run-TryBot: Peter Weinberger <pjw@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Peter Weinberger <pjw@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
e900012391
commit
fc3ed20887
|
|
@ -72,6 +72,20 @@ Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-pro
|
|||
|
||||
Default: `["-node_modules"]`.
|
||||
|
||||
#### **templateSupport** *bool*
|
||||
|
||||
templateSupport can be used to turn off support for template files.
|
||||
|
||||
Default: `true`.
|
||||
|
||||
#### **templateExtensions** *[]string*
|
||||
|
||||
templateExtensions gives the extensions of file names that are treateed
|
||||
as template files. (The extension
|
||||
is the part of the file name after the final dot.)
|
||||
|
||||
Default: `["tmpl","gotmpl"]`.
|
||||
|
||||
#### **memoryMode** *enum*
|
||||
|
||||
**This setting is experimental and may be deleted.**
|
||||
|
|
@ -112,15 +126,6 @@ for multi-module workspaces.
|
|||
|
||||
Default: `false`.
|
||||
|
||||
#### **experimentalTemplateSupport** *bool*
|
||||
|
||||
**This setting is experimental and may be deleted.**
|
||||
|
||||
experimentalTemplateSupport opts into the experimental support
|
||||
for template files.
|
||||
|
||||
Default: `false`.
|
||||
|
||||
#### **experimentalPackageCacheKey** *bool*
|
||||
|
||||
**This setting is experimental and may be deleted.**
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ func (s *snapshot) ModFiles() []span.URI {
|
|||
}
|
||||
|
||||
func (s *snapshot) Templates() map[span.URI]source.VersionedFileHandle {
|
||||
if !s.view.Options().ExperimentalTemplateSupport {
|
||||
if !s.view.Options().TemplateSupport {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -783,12 +783,15 @@ func (s *snapshot) getWorkspacePkgPath(id PackageID) PackagePath {
|
|||
const fileExtensions = "go,mod,sum,work,tmpl"
|
||||
|
||||
func (s *snapshot) fileWatchingGlobPatterns(ctx context.Context) map[string]struct{} {
|
||||
extensions := fileExtensions
|
||||
for _, ext := range s.View().Options().TemplateExtensions {
|
||||
extensions += "," + ext
|
||||
}
|
||||
// Work-around microsoft/vscode#100870 by making sure that we are,
|
||||
// at least, watching the user's entire workspace. This will still be
|
||||
// applied to every folder in the workspace.
|
||||
patterns := map[string]struct{}{
|
||||
fmt.Sprintf("**/*.{%s}", fileExtensions): {},
|
||||
"**/*.*tmpl": {},
|
||||
fmt.Sprintf("**/*.{%s}", extensions): {},
|
||||
}
|
||||
dirs := s.workspace.dirs(ctx, s)
|
||||
for _, dir := range dirs {
|
||||
|
|
@ -802,7 +805,7 @@ func (s *snapshot) fileWatchingGlobPatterns(ctx context.Context) map[string]stru
|
|||
// TODO(rstambler): If microsoft/vscode#3025 is resolved before
|
||||
// microsoft/vscode#101042, we will need a work-around for Windows
|
||||
// drive letter casing.
|
||||
patterns[fmt.Sprintf("%s/**/*.{%s}", dirName, fileExtensions)] = struct{}{}
|
||||
patterns[fmt.Sprintf("%s/**/*.{%s}", dirName, extensions)] = struct{}{}
|
||||
}
|
||||
|
||||
// Some clients do not send notifications for changes to directories that
|
||||
|
|
|
|||
|
|
@ -332,10 +332,25 @@ func (s *snapshot) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Optio
|
|||
return s.view.importsState.runProcessEnvFunc(ctx, s, fn)
|
||||
}
|
||||
|
||||
// separated out from its sole use in locateTemplatFiles for testability
|
||||
func fileHasExtension(path string, suffixes []string) bool {
|
||||
ext := filepath.Ext(path)
|
||||
if ext != "" && ext[0] == '.' {
|
||||
ext = ext[1:]
|
||||
}
|
||||
for _, s := range suffixes {
|
||||
if s != "" && ext == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *snapshot) locateTemplateFiles(ctx context.Context) {
|
||||
if !s.view.Options().ExperimentalTemplateSupport {
|
||||
if !s.view.Options().TemplateSupport {
|
||||
return
|
||||
}
|
||||
suffixes := s.view.Options().TemplateExtensions
|
||||
dir := s.workspace.root.Filename()
|
||||
searched := 0
|
||||
// Change to WalkDir when we move up to 1.16
|
||||
|
|
@ -343,7 +358,7 @@ func (s *snapshot) locateTemplateFiles(ctx context.Context) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(filepath.Ext(path), "tmpl") && !pathExcludedByFilter(path, dir, s.view.gomodcache, s.view.options) &&
|
||||
if fileHasExtension(path, suffixes) && !pathExcludedByFilter(path, dir, s.view.gomodcache, s.view.options) &&
|
||||
!fi.IsDir() {
|
||||
k := span.URIFromPath(path)
|
||||
fh, err := s.GetVersionedFile(ctx, k)
|
||||
|
|
|
|||
|
|
@ -172,3 +172,44 @@ func TestFilters(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuffixes(t *testing.T) {
|
||||
type file struct {
|
||||
path string
|
||||
want bool
|
||||
}
|
||||
type cases struct {
|
||||
option []string
|
||||
files []file
|
||||
}
|
||||
tests := []cases{
|
||||
{[]string{"tmpl", "gotmpl"}, []file{ // default
|
||||
{"foo", false},
|
||||
{"foo.tmpl", true},
|
||||
{"foo.gotmpl", true},
|
||||
{"tmpl", false},
|
||||
{"tmpl.go", false}},
|
||||
},
|
||||
{[]string{"tmpl", "gotmpl", "html", "gohtml"}, []file{
|
||||
{"foo.gotmpl", true},
|
||||
{"foo.html", true},
|
||||
{"foo.gohtml", true},
|
||||
{"html", false}},
|
||||
},
|
||||
{[]string{"tmpl", "gotmpl", ""}, []file{ // possible user mistake
|
||||
{"foo.gotmpl", true},
|
||||
{"foo.go", false},
|
||||
{"foo", false}},
|
||||
},
|
||||
}
|
||||
for _, a := range tests {
|
||||
suffixes := a.option
|
||||
for _, b := range a.files {
|
||||
got := fileHasExtension(b.path, suffixes)
|
||||
if got != b.want {
|
||||
t.Errorf("got %v, want %v, option %q, file %q (%+v)",
|
||||
got, b.want, a.option, b.path, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,32 @@ var GeneratedAPIJSON = &APIJSON{
|
|||
Status: "",
|
||||
Hierarchy: "build",
|
||||
},
|
||||
{
|
||||
Name: "templateSupport",
|
||||
Type: "bool",
|
||||
Doc: "templateSupport can be used to turn off support for template files.\n",
|
||||
EnumKeys: EnumKeys{
|
||||
ValueType: "",
|
||||
Keys: nil,
|
||||
},
|
||||
EnumValues: nil,
|
||||
Default: "true",
|
||||
Status: "",
|
||||
Hierarchy: "build",
|
||||
},
|
||||
{
|
||||
Name: "templateExtensions",
|
||||
Type: "[]string",
|
||||
Doc: "templateExtensions gives the extensions of file names that are treateed\nas template files. (The extension\nis the part of the file name after the final dot.)\n",
|
||||
EnumKeys: EnumKeys{
|
||||
ValueType: "",
|
||||
Keys: nil,
|
||||
},
|
||||
EnumValues: nil,
|
||||
Default: "[\"tmpl\",\"gotmpl\"]",
|
||||
Status: "",
|
||||
Hierarchy: "build",
|
||||
},
|
||||
{
|
||||
Name: "memoryMode",
|
||||
Type: "enum",
|
||||
|
|
@ -92,19 +118,6 @@ var GeneratedAPIJSON = &APIJSON{
|
|||
Status: "experimental",
|
||||
Hierarchy: "build",
|
||||
},
|
||||
{
|
||||
Name: "experimentalTemplateSupport",
|
||||
Type: "bool",
|
||||
Doc: "experimentalTemplateSupport opts into the experimental support\nfor template files.\n",
|
||||
EnumKeys: EnumKeys{
|
||||
ValueType: "",
|
||||
Keys: nil,
|
||||
},
|
||||
EnumValues: nil,
|
||||
Default: "false",
|
||||
Status: "experimental",
|
||||
Hierarchy: "build",
|
||||
},
|
||||
{
|
||||
Name: "experimentalPackageCacheKey",
|
||||
Type: "bool",
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ func DefaultOptions() *Options {
|
|||
ExperimentalPackageCacheKey: true,
|
||||
MemoryMode: ModeNormal,
|
||||
DirectoryFilters: []string{"-node_modules"},
|
||||
TemplateSupport: true,
|
||||
TemplateExtensions: []string{"tmpl", "gotmpl"},
|
||||
},
|
||||
UIOptions: UIOptions{
|
||||
DiagnosticOptions: DiagnosticOptions{
|
||||
|
|
@ -231,6 +233,14 @@ type BuildOptions struct {
|
|||
// Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`
|
||||
DirectoryFilters []string
|
||||
|
||||
// TemplateSupport can be used to turn off support for template files.
|
||||
TemplateSupport bool
|
||||
|
||||
// TemplateExtensions gives the extensions of file names that are treateed
|
||||
// as template files. (The extension
|
||||
// is the part of the file name after the final dot.)
|
||||
TemplateExtensions []string
|
||||
|
||||
// MemoryMode controls the tradeoff `gopls` makes between memory usage and
|
||||
// correctness.
|
||||
//
|
||||
|
|
@ -249,10 +259,6 @@ type BuildOptions struct {
|
|||
// for multi-module workspaces.
|
||||
ExperimentalWorkspaceModule bool `status:"experimental"`
|
||||
|
||||
// ExperimentalTemplateSupport opts into the experimental support
|
||||
// for template files.
|
||||
ExperimentalTemplateSupport bool `status:"experimental"`
|
||||
|
||||
// ExperimentalPackageCacheKey controls whether to use a coarser cache key
|
||||
// for package type information to increase cache hits. This setting removes
|
||||
// the user's environment, build flags, and working directory from the cache
|
||||
|
|
@ -747,7 +753,6 @@ func (o *Options) AddStaticcheckAnalyzer(a *analysis.Analyzer, enabled bool, sev
|
|||
func (o *Options) EnableAllExperiments() {
|
||||
o.SemanticTokens = true
|
||||
o.ExperimentalPostfixCompletions = true
|
||||
o.ExperimentalTemplateSupport = true
|
||||
o.ExperimentalUseInvalidMetadata = true
|
||||
o.ExperimentalWatchedFileDelay = 50 * time.Millisecond
|
||||
}
|
||||
|
|
@ -935,8 +940,21 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
|
|||
case "experimentalWorkspaceModule":
|
||||
result.setBool(&o.ExperimentalWorkspaceModule)
|
||||
|
||||
case "experimentalTemplateSupport":
|
||||
result.setBool(&o.ExperimentalTemplateSupport)
|
||||
case "experimentalTemplateSupport", // remove after June 2022
|
||||
"templateSupport":
|
||||
if name == "experimentalTemplateSupport" {
|
||||
result.State = OptionDeprecated
|
||||
result.Replacement = "templateSupport"
|
||||
}
|
||||
result.setBool(&o.TemplateSupport)
|
||||
|
||||
case "templateExtensions":
|
||||
iexts, ok := value.([]string)
|
||||
if !ok {
|
||||
result.errorf("invalid type %T, expect []string", value)
|
||||
break
|
||||
}
|
||||
o.TemplateExtensions = iexts
|
||||
|
||||
case "experimentalDiagnosticsDelay", "diagnosticsDelay":
|
||||
if name == "experimentalDiagnosticsDelay" {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func Diagnose(f source.VersionedFileHandle) []*source.Diagnostic {
|
|||
}
|
||||
|
||||
func skipTemplates(s source.Snapshot) bool {
|
||||
return !s.View().Options().ExperimentalTemplateSupport
|
||||
return !s.View().Options().TemplateSupport
|
||||
}
|
||||
|
||||
// Definition finds the definitions of the symbol at loc. It
|
||||
|
|
|
|||
Loading…
Reference in New Issue