gopls: template suffix flags and documentation
Adds 'templateExtensions' (with default ["tmpl", "gotmpl"]) to control
which files gopls considers template files.
Adds template support documentation to features.md.
Fixes golang/go#36911
Change-Id: If0920912bf3748d1c231b3b29e7a008da186bede
Reviewed-on: https://go-review.googlesource.com/c/tools/+/363360
Run-TryBot: Peter Weinberger <pjw@google.com>
Trust: Peter Weinberger <pjw@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/gopls/doc/features.md b/gopls/doc/features.md
index 9cb6864..ccfe138 100644
--- a/gopls/doc/features.md
+++ b/gopls/doc/features.md
@@ -4,10 +4,10 @@
currently under construction, so, for a comprehensive list, see the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/).
-For now, only special features outside of the LSP are described below.
-
## Special features
+Here, only special features outside of the LSP are described.
+
### Symbol Queries
Gopls supports some extended syntax for `workspace/symbol` requests, when using
@@ -21,4 +21,26 @@
| `^` | `^printf` | exact prefix |
| `$` | `printf$` | exact suffix |
+## Template Files
+
+Gopls provides some support for Go template files, that is, files that
+are parsed by `text/template` or `html/template`.
+Gopls recognizes template files based on their file extension.
+By default it looks for files ending in `.tmpl` or `.gotmpl`,
+but this list may be configured by the
+[`templateExtensions`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#templateextensions-string) setting.
+Making this list empty turns off template support.
+
+In template files, template support works inside
+the default `{{` delimiters. (Go template parsing
+allows the user to specify other delimiters, but
+gopls does not know how to do that.)
+
+Gopls template support includes the following features:
++ **Diagnostics**: if template parsing returns an error,
+it is presented as a diagnostic. (Missing functions do not produce errors.)
++ **Syntax Highlighting**: syntax highlighting is provided for template files.
++ **Definitions**: gopls provides jump-to-definition inside templates, though it does not understand scoping (all templates are considered to be in one global scope).
++ **References**: gopls provides find-references, with the same scoping limitation as definitions.
++ **Completions**: gopls will attempt to suggest completions inside templates.
<!--TODO(rstambler): Automatically generate a list of supported features.-->
diff --git a/gopls/doc/settings.md b/gopls/doc/settings.md
index 375aab3..542eb16 100644
--- a/gopls/doc/settings.md
+++ b/gopls/doc/settings.md
@@ -72,12 +72,6 @@
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
diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go
index 51b00d5..53f97f4 100644
--- a/internal/lsp/cache/snapshot.go
+++ b/internal/lsp/cache/snapshot.go
@@ -159,7 +159,7 @@
}
func (s *snapshot) Templates() map[span.URI]source.VersionedFileHandle {
- if !s.view.Options().TemplateSupport {
+ if len(s.view.Options().TemplateExtensions) == 0 {
return nil
}
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index 881d7f1..b969573 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -347,7 +347,7 @@
}
func (s *snapshot) locateTemplateFiles(ctx context.Context) {
- if !s.view.Options().TemplateSupport {
+ if len(s.view.Options().TemplateExtensions) == 0 {
return
}
suffixes := s.view.Options().TemplateExtensions
diff --git a/internal/lsp/source/api_json.go b/internal/lsp/source/api_json.go
index b536df2..b7c5163 100755
--- a/internal/lsp/source/api_json.go
+++ b/internal/lsp/source/api_json.go
@@ -45,19 +45,6 @@
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",
diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go
index 41a0288..147bb9e 100644
--- a/internal/lsp/source/options.go
+++ b/internal/lsp/source/options.go
@@ -114,7 +114,6 @@
ExperimentalPackageCacheKey: true,
MemoryMode: ModeNormal,
DirectoryFilters: []string{"-node_modules"},
- TemplateSupport: true,
TemplateExtensions: []string{"tmpl", "gotmpl"},
},
UIOptions: UIOptions{
@@ -233,9 +232,6 @@
// 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.)
@@ -940,22 +936,23 @@
case "experimentalWorkspaceModule":
result.setBool(&o.ExperimentalWorkspaceModule)
- case "experimentalTemplateSupport", // remove after June 2022
- "templateSupport":
- if name == "experimentalTemplateSupport" {
- result.State = OptionDeprecated
- result.Replacement = "templateSupport"
- }
- result.setBool(&o.TemplateSupport)
+ case "experimentalTemplateSupport": // remove after June 2022
+ result.State = OptionDeprecated
case "templateExtensions":
- iexts, ok := value.([]string)
- if !ok {
- result.errorf("invalid type %T, expect []string", value)
+ if iexts, ok := value.([]interface{}); ok {
+ ans := []string{}
+ for _, x := range iexts {
+ ans = append(ans, fmt.Sprint(x))
+ }
+ o.TemplateExtensions = ans
break
}
- o.TemplateExtensions = iexts
-
+ if value == nil {
+ o.TemplateExtensions = nil
+ break
+ }
+ result.errorf(fmt.Sprintf("unexpected type %T not []string", value))
case "experimentalDiagnosticsDelay", "diagnosticsDelay":
if name == "experimentalDiagnosticsDelay" {
result.State = OptionDeprecated
diff --git a/internal/lsp/template/implementations.go b/internal/lsp/template/implementations.go
index 193b973..66dcc4b 100644
--- a/internal/lsp/template/implementations.go
+++ b/internal/lsp/template/implementations.go
@@ -66,7 +66,7 @@
}
func skipTemplates(s source.Snapshot) bool {
- return !s.View().Options().TemplateSupport
+ return len(s.View().Options().TemplateExtensions) == 0
}
// Definition finds the definitions of the symbol at loc. It