mirror of https://github.com/golang/go.git
internal/template: identify template files by the templateExtensions option
Make the language id (sent from the client) 'gotmpl' equivalent to 'tmpl' Wherever a view is known, use its options to determine which files are template files. Whenever the client sends an explicit languageID, use that. Partially fixes golang/vscode-go#1957 Change-Id: I04cd630d6c6c80e0a78c2fafb6ddc1166ce86829 Reviewed-on: https://go-review.googlesource.com/c/tools/+/376854 Trust: Peter Weinberger <pjw@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
d7a4bb4f6a
commit
68b574acb9
|
|
@ -168,10 +168,6 @@ func (h *fileHandle) URI() span.URI {
|
|||
return h.uri
|
||||
}
|
||||
|
||||
func (h *fileHandle) Kind() source.FileKind {
|
||||
return source.DetectLanguage("", h.uri.Filename())
|
||||
}
|
||||
|
||||
func (h *fileHandle) Hash() string {
|
||||
return h.hash
|
||||
}
|
||||
|
|
@ -180,7 +176,6 @@ func (h *fileHandle) FileIdentity() source.FileIdentity {
|
|||
return source.FileIdentity{
|
||||
URI: h.uri,
|
||||
Hash: h.hash,
|
||||
Kind: h.Kind(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...interf
|
|||
uri := span.URI(scope)
|
||||
// Don't try to load a file that doesn't exist.
|
||||
fh := s.FindFile(uri)
|
||||
if fh == nil || fh.Kind() != source.Go {
|
||||
if fh == nil || s.View().FileKind(uri) != source.Go {
|
||||
continue
|
||||
}
|
||||
query = append(query, fmt.Sprintf("file=%s", uri.Filename()))
|
||||
|
|
@ -264,7 +264,7 @@ func (s *snapshot) applyCriticalErrorToFiles(ctx context.Context, msg string, fi
|
|||
for _, fh := range files {
|
||||
// Place the diagnostics on the package or module declarations.
|
||||
var rng protocol.Range
|
||||
switch fh.Kind() {
|
||||
switch s.view.FileKind(fh.URI()) {
|
||||
case source.Go:
|
||||
if pgf, err := s.ParseGo(ctx, fh, source.ParseHeader); err == nil {
|
||||
pkgDecl := span.NewRange(s.FileSet(), pgf.File.Package, pgf.File.Name.End())
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func (mwh *modWhyHandle) why(ctx context.Context, snapshot *snapshot) (map[strin
|
|||
}
|
||||
|
||||
func (s *snapshot) ModWhy(ctx context.Context, fh source.FileHandle) (map[string]string, error) {
|
||||
if fh.Kind() != source.Mod {
|
||||
if s.View().FileKind(fh.URI()) != source.Mod {
|
||||
return nil, fmt.Errorf("%s is not a go.mod file", fh.URI())
|
||||
}
|
||||
if handle := s.getModWhyHandle(fh.URI()); handle != nil {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"go/scanner"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -246,7 +247,8 @@ func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mod
|
|||
ctx, done := event.Start(ctx, "cache.parseGo", tag.File.Of(fh.URI().Filename()))
|
||||
defer done()
|
||||
|
||||
if fh.Kind() != source.Go {
|
||||
ext := filepath.Ext(fh.URI().Filename())
|
||||
if ext != ".go" && ext != "" { // files generated by cgo have no extension
|
||||
return &parseGoData{err: errors.Errorf("cannot parse non-Go file %s", fh.URI())}
|
||||
}
|
||||
src, err := fh.Read()
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ func (o *overlay) FileIdentity() source.FileIdentity {
|
|||
return source.FileIdentity{
|
||||
URI: o.uri,
|
||||
Hash: o.hash,
|
||||
Kind: o.kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ func (s *snapshot) ModFiles() []span.URI {
|
|||
}
|
||||
|
||||
func (s *snapshot) Templates() map[span.URI]source.VersionedFileHandle {
|
||||
if len(s.view.Options().TemplateExtensions) == 0 {
|
||||
opts := s.view.Options().TemplateExtensions
|
||||
if len(opts) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -168,8 +169,18 @@ func (s *snapshot) Templates() map[span.URI]source.VersionedFileHandle {
|
|||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
isin := func(s string, a []string) bool {
|
||||
for _, x := range a {
|
||||
if x == s || "."+x == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for k, x := range s.files {
|
||||
if strings.HasSuffix(filepath.Ext(k.Filename()), "tmpl") {
|
||||
suffix := filepath.Ext(k.Filename())
|
||||
if isin(suffix, opts) {
|
||||
ans[k] = x
|
||||
}
|
||||
}
|
||||
|
|
@ -516,8 +527,8 @@ func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fh.Kind() != source.Go {
|
||||
return nil, fmt.Errorf("no packages for non-Go file %s", uri)
|
||||
if kind := s.view.FileKind(fh.FileIdentity().URI); kind != source.Go {
|
||||
return nil, fmt.Errorf("no packages for non-Go file %s (%v)", uri, kind)
|
||||
}
|
||||
knownIDs, err := s.getOrLoadIDsForURI(ctx, uri)
|
||||
if err != nil {
|
||||
|
|
@ -780,7 +791,7 @@ func (s *snapshot) getWorkspacePkgPath(id PackageID) PackagePath {
|
|||
return s.workspacePackages[id]
|
||||
}
|
||||
|
||||
const fileExtensions = "go,mod,sum,work,tmpl"
|
||||
const fileExtensions = "go,mod,sum,work"
|
||||
|
||||
func (s *snapshot) fileWatchingGlobPatterns(ctx context.Context) map[string]struct{} {
|
||||
extensions := fileExtensions
|
||||
|
|
@ -1574,7 +1585,7 @@ func (s *snapshot) orphanedFiles() []source.VersionedFileHandle {
|
|||
var files []source.VersionedFileHandle
|
||||
for uri, fh := range s.files {
|
||||
// Don't try to reload metadata for go.mod files.
|
||||
if fh.Kind() != source.Go {
|
||||
if s.view.FileKind(uri) != source.Go {
|
||||
continue
|
||||
}
|
||||
// If the URI doesn't belong to this view, then it's not in a workspace
|
||||
|
|
|
|||
|
|
@ -241,6 +241,26 @@ func (v *View) Options() *source.Options {
|
|||
return v.options
|
||||
}
|
||||
|
||||
func (v *View) FileKind(URI span.URI) source.FileKind {
|
||||
got := filepath.Ext(URI.Filename())
|
||||
switch got {
|
||||
case ".go":
|
||||
return source.Go
|
||||
case ".mod":
|
||||
return source.Mod
|
||||
case ".sum":
|
||||
return source.Sum
|
||||
}
|
||||
exts := v.Options().TemplateExtensions
|
||||
for _, ext := range exts {
|
||||
if got == ext || got == "."+ext {
|
||||
return source.Tmpl
|
||||
}
|
||||
}
|
||||
// and now what? This should never happen, but it does for cgo before go1.15
|
||||
return source.Go
|
||||
}
|
||||
|
||||
func minorOptionsChange(a, b *source.Options) bool {
|
||||
// Check if any of the settings that modify our understanding of files have been changed
|
||||
if !reflect.DeepEqual(a.Env, b.Env) {
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ func (c *connection) AddFile(ctx context.Context, uri span.URI) *cmdFile {
|
|||
p := &protocol.DidOpenTextDocumentParams{
|
||||
TextDocument: protocol.TextDocumentItem{
|
||||
URI: protocol.URIFromSpanURI(uri),
|
||||
LanguageID: source.DetectLanguage("", file.uri.Filename()).String(),
|
||||
LanguageID: "go",
|
||||
Version: 1,
|
||||
Text: string(file.mapper.Content),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
|
|||
uri := fh.URI()
|
||||
|
||||
// Determine the supported actions for this file kind.
|
||||
supportedCodeActions, ok := snapshot.View().Options().SupportedCodeActions[fh.Kind()]
|
||||
kind := snapshot.View().FileKind(uri)
|
||||
supportedCodeActions, ok := snapshot.View().Options().SupportedCodeActions[kind]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no supported code actions for %v file kind", fh.Kind())
|
||||
return nil, fmt.Errorf("no supported code actions for %v file kind", kind)
|
||||
}
|
||||
|
||||
// The Only field of the context specifies which code actions the client wants.
|
||||
|
|
@ -67,7 +68,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
|
|||
}
|
||||
|
||||
var codeActions []protocol.CodeAction
|
||||
switch fh.Kind() {
|
||||
switch kind {
|
||||
case source.Mod:
|
||||
if diagnostics := params.Context.Diagnostics; len(diagnostics) > 0 {
|
||||
diags, err := mod.DiagnosticsForMod(ctx, snapshot, fh)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func (s *Server) codeLens(ctx context.Context, params *protocol.CodeLensParams)
|
|||
return nil, err
|
||||
}
|
||||
var lenses map[command.Command]source.LensFunc
|
||||
switch fh.Kind() {
|
||||
switch snapshot.View().FileKind(fh.URI()) {
|
||||
case source.Mod:
|
||||
lenses = mod.LensFuncs()
|
||||
case source.Go:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara
|
|||
}
|
||||
var candidates []completion.CompletionItem
|
||||
var surrounding *completion.Selection
|
||||
switch fh.Kind() {
|
||||
switch snapshot.View().FileKind(fh.URI()) {
|
||||
case source.Go:
|
||||
candidates, surrounding, err = completion.Completion(ctx, snapshot, fh, params.Position, params.Context)
|
||||
case source.Mod:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func (s *Server) definition(ctx context.Context, params *protocol.DefinitionPara
|
|||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
if fh.Kind() == source.Tmpl {
|
||||
if snapshot.View().FileKind(fh.URI()) == source.Tmpl {
|
||||
return template.Definition(snapshot, fh, params.Position)
|
||||
}
|
||||
ident, err := source.Identifier(ctx, snapshot, fh, params.Position)
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ func (s *Server) showCriticalErrorStatus(ctx context.Context, snapshot source.Sn
|
|||
// If they cannot and the workspace is not otherwise unloaded, it also surfaces
|
||||
// a warning, suggesting that the user check the file for build tags.
|
||||
func (s *Server) checkForOrphanedFile(ctx context.Context, snapshot source.Snapshot, fh source.VersionedFileHandle) *source.Diagnostic {
|
||||
if fh.Kind() != source.Go {
|
||||
if snapshot.View().FileKind(fh.URI()) != source.Go {
|
||||
return nil
|
||||
}
|
||||
// builtin files won't have a package, but they are never orphaned.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func (s *Server) formatting(ctx context.Context, params *protocol.DocumentFormat
|
|||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
switch fh.Kind() {
|
||||
switch snapshot.View().FileKind(fh.URI()) {
|
||||
case source.Mod:
|
||||
return mod.Format(ctx, snapshot, fh)
|
||||
case source.Go:
|
||||
|
|
|
|||
|
|
@ -466,7 +466,8 @@ func (s *Server) beginFileRequest(ctx context.Context, pURI protocol.DocumentURI
|
|||
release()
|
||||
return nil, nil, false, func() {}, err
|
||||
}
|
||||
if expectKind != source.UnknownKind && fh.Kind() != expectKind {
|
||||
kind := snapshot.View().FileKind(fh.URI())
|
||||
if expectKind != source.UnknownKind && kind != expectKind {
|
||||
// Wrong kind of file. Nothing to do.
|
||||
release()
|
||||
return nil, nil, false, func() {}, nil
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func (s *Server) documentHighlight(ctx context.Context, params *protocol.Documen
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if fh.Kind() == source.Tmpl {
|
||||
if snapshot.View().FileKind(fh.URI()) == source.Tmpl {
|
||||
return template.Highlight(ctx, snapshot, fh, params.Position)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*prot
|
|||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
switch fh.Kind() {
|
||||
switch snapshot.View().FileKind(fh.URI()) {
|
||||
case source.Mod:
|
||||
return mod.Hover(ctx, snapshot, fh, params.Position)
|
||||
case source.Go:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
|
|||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
switch fh.Kind() {
|
||||
switch snapshot.View().FileKind(fh.URI()) {
|
||||
case source.Mod:
|
||||
links, err = modLinks(ctx, snapshot, fh)
|
||||
case source.Go:
|
||||
|
|
|
|||
|
|
@ -71,8 +71,7 @@ func testLSP(t *testing.T, datum *tests.Data) {
|
|||
|
||||
var modifications []source.FileModification
|
||||
for filename, content := range datum.Config.Overlay {
|
||||
kind := source.DetectLanguage("", filename)
|
||||
if kind != source.Go {
|
||||
if filepath.Ext(filename) != ".go" {
|
||||
continue
|
||||
}
|
||||
modifications = append(modifications, source.FileModification{
|
||||
|
|
@ -187,7 +186,7 @@ func (r *runner) CallHierarchy(t *testing.T, spn span.Span, expectedCalls *tests
|
|||
}
|
||||
|
||||
func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
|
||||
if source.DetectLanguage("", uri.Filename()) != source.Mod {
|
||||
if !strings.HasSuffix(uri.Filename(), "go.mod") {
|
||||
return
|
||||
}
|
||||
got, err := r.server.codeLens(r.ctx, &protocol.CodeLensParams{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func (s *Server) references(ctx context.Context, params *protocol.ReferenceParam
|
|||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
if fh.Kind() == source.Tmpl {
|
||||
if snapshot.View().FileKind(fh.URI()) == source.Tmpl {
|
||||
return template.References(ctx, snapshot, fh, params)
|
||||
}
|
||||
references, err := source.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
|
|||
// the client won't remember the wrong answer
|
||||
return nil, errors.Errorf("semantictokens are disabled")
|
||||
}
|
||||
if fh.Kind() == source.Tmpl {
|
||||
kind := snapshot.View().FileKind(fh.URI())
|
||||
if kind == source.Tmpl {
|
||||
// this is a little cumbersome to avoid both exporting 'encoded' and its methods
|
||||
// and to avoid import cycles
|
||||
e := &encoded{
|
||||
|
|
@ -87,7 +88,7 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
|
|||
}
|
||||
return template.SemanticTokens(ctx, snapshot, fh.URI(), add, data)
|
||||
}
|
||||
if fh.Kind() != source.Go {
|
||||
if kind != source.Go {
|
||||
return nil, nil
|
||||
}
|
||||
pkg, err := snapshot.PackageForFile(ctx, fh.URI(), source.TypecheckFull, source.WidestPackage)
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ func testSource(t *testing.T, datum *tests.Data) {
|
|||
|
||||
var modifications []source.FileModification
|
||||
for filename, content := range datum.Config.Overlay {
|
||||
kind := source.DetectLanguage("", filename)
|
||||
if kind != source.Go {
|
||||
if filepath.Ext(filename) != ".go" {
|
||||
continue
|
||||
}
|
||||
modifications = append(modifications, source.FileModification{
|
||||
|
|
|
|||
|
|
@ -162,34 +162,39 @@ func posToMappedRange(snapshot Snapshot, pkg Package, pos, end token.Pos) (Mappe
|
|||
var generatedRx = regexp.MustCompile(`// .*DO NOT EDIT\.?`)
|
||||
|
||||
func DetectLanguage(langID, filename string) FileKind {
|
||||
switch langID {
|
||||
case "go":
|
||||
return Go
|
||||
case "go.mod":
|
||||
return Mod
|
||||
case "go.sum":
|
||||
return Sum
|
||||
case "tmpl":
|
||||
return Tmpl
|
||||
// use the langID if the client sent it
|
||||
if langID != "" {
|
||||
switch langID {
|
||||
case "go":
|
||||
return Go
|
||||
case "go.mod":
|
||||
return Mod
|
||||
case "go.sum":
|
||||
return Sum
|
||||
case "tmpl", "gotmpl":
|
||||
return Tmpl
|
||||
default:
|
||||
return UnknownKind
|
||||
}
|
||||
}
|
||||
// Fallback to detecting the language based on the file extension.
|
||||
// Detect the language based on the file extension.
|
||||
switch ext := filepath.Ext(filename); ext {
|
||||
case ".mod":
|
||||
return Mod
|
||||
case ".sum":
|
||||
return Sum
|
||||
case ".go":
|
||||
return Go
|
||||
default:
|
||||
if strings.HasSuffix(ext, "tmpl") {
|
||||
// .tmpl, .gotmpl, etc
|
||||
return Tmpl
|
||||
}
|
||||
// It's a Go file, or we shouldn't be seeing it
|
||||
// (for instance, before go1.15 cgo files had no extension)
|
||||
return Go
|
||||
}
|
||||
}
|
||||
|
||||
func (k FileKind) String() string {
|
||||
switch k {
|
||||
case Go:
|
||||
return "go"
|
||||
case Mod:
|
||||
return "go.mod"
|
||||
case Sum:
|
||||
|
|
@ -197,7 +202,7 @@ func (k FileKind) String() string {
|
|||
case Tmpl:
|
||||
return "tmpl"
|
||||
default:
|
||||
return "go"
|
||||
return fmt.Sprintf("unk%d", k)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,9 @@ type View interface {
|
|||
|
||||
// RegisterModuleUpgrades registers that upgrades exist for the given modules.
|
||||
RegisterModuleUpgrades(upgrades map[string]string)
|
||||
|
||||
// FileKind returns the type of a file
|
||||
FileKind(uri span.URI) FileKind
|
||||
}
|
||||
|
||||
// A FileSource maps uris to FileHandles. This abstraction exists both for
|
||||
|
|
@ -498,7 +501,6 @@ type VersionedFileIdentity struct {
|
|||
// FileHandle represents a handle to a specific version of a single file.
|
||||
type FileHandle interface {
|
||||
URI() span.URI
|
||||
Kind() FileKind
|
||||
|
||||
// FileIdentity returns a FileIdentity for the file, even if there was an
|
||||
// error reading it.
|
||||
|
|
@ -516,17 +518,14 @@ type FileIdentity struct {
|
|||
|
||||
// Identifier represents a unique identifier for the file's content.
|
||||
Hash string
|
||||
|
||||
// Kind is the file's kind.
|
||||
Kind FileKind
|
||||
}
|
||||
|
||||
func (id FileIdentity) String() string {
|
||||
return fmt.Sprintf("%s%s%s", id.URI, id.Hash, id.Kind)
|
||||
return fmt.Sprintf("%s%s", id.URI, id.Hash)
|
||||
}
|
||||
|
||||
// FileKind describes the kind of the file in question.
|
||||
// It can be one of Go, mod, or sum.
|
||||
// It can be one of Go,mod, Sum, or Tmpl.
|
||||
type FileKind int
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func (s *Server) documentSymbol(ctx context.Context, params *protocol.DocumentSy
|
|||
return []interface{}{}, err
|
||||
}
|
||||
var docSymbols []protocol.DocumentSymbol
|
||||
if fh.Kind() == source.Tmpl {
|
||||
if snapshot.View().FileKind(fh.URI()) == source.Tmpl {
|
||||
docSymbols, err = template.DocumentSymbols(snapshot, fh)
|
||||
} else {
|
||||
docSymbols, err = source.DocumentSymbols(ctx, snapshot, fh)
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ func (s *Server) didChangeConfiguration(ctx context.Context, _ *protocol.DidChan
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshot, release := view.Snapshot(ctx)
|
||||
go func() {
|
||||
snapshot, release := view.Snapshot(ctx)
|
||||
defer release()
|
||||
s.diagnoseDetached(snapshot)
|
||||
}()
|
||||
|
|
|
|||
Loading…
Reference in New Issue