diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ab1013..d1385832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - LSP 的 textDocument/publishDiagnostics 添加了 DiagnosticTag 的支持; - 添加 core.Ranger 接口的定义; - 添加了对 textDocument/references 的支持; +- 添加了对 textDocument/definition 的支持; ## [v7.1.0] diff --git a/internal/ast/sanitize.go b/internal/ast/sanitize.go index ca36f475..13780d98 100644 --- a/internal/ast/sanitize.go +++ b/internal/ast/sanitize.go @@ -329,6 +329,11 @@ func (api *API) sanitizeTags() error { panic("api.doc 未获取正确的值") } + apiURI := api.URI + if apiURI == "" { + apiURI = api.doc.URI + } + for _, tag := range api.Tags { t := api.doc.findTag(tag.Content.Value) if t == nil { @@ -351,7 +356,7 @@ func (api *API) sanitizeTags() error { t.references = append(t.references, &Reference{ Location: core.Location{ Range: tag.R(), - URI: api.URI, + URI: apiURI, }, Target: tag, }) @@ -379,7 +384,7 @@ func (api *API) sanitizeTags() error { s.references = append(s.references, &Reference{ Location: core.Location{ Range: srv.R(), - URI: api.URI, + URI: apiURI, }, Target: srv, }) diff --git a/internal/lsp/initialize.go b/internal/lsp/initialize.go index b08e9ce4..e7604043 100644 --- a/internal/lsp/initialize.go +++ b/internal/lsp/initialize.go @@ -53,6 +53,10 @@ func (s *server) initialize(notify bool, in *protocol.InitializeParams, out *pro out.Capabilities.ReferencesProvider = true } + if in.Capabilities.TextDocument.Definition != nil { + out.Capabilities.DefinitionProvider = true + } + if in.Capabilities.TextDocument.SemanticTokens != nil { out.Capabilities.SemanticTokensProvider = &protocol.SemanticTokensOptions{ Legend: protocol.SemanticTokensLegend{ diff --git a/internal/lsp/lsp.go b/internal/lsp/lsp.go index da2d6bef..a77fafa1 100644 --- a/internal/lsp/lsp.go +++ b/internal/lsp/lsp.go @@ -106,6 +106,7 @@ func serve(t jsonrpc.Transport, infolog, errlog *log.Logger) error { "textDocument/completion": srv.textDocumentCompletion, "textDocument/semanticTokens": srv.textDocumentSemanticTokens, "textDocument/references": srv.textDocumentReferences, + "textDocument/definition": srv.textDocumentDefinition, }) jsonrpcServer.RegisterMatcher(func(method string) bool { diff --git a/internal/lsp/protocol/hover.go b/internal/lsp/protocol/hover.go index bedc4a57..7d762f99 100644 --- a/internal/lsp/protocol/hover.go +++ b/internal/lsp/protocol/hover.go @@ -27,7 +27,6 @@ type HoverParams struct { // Hover textDocument/hover 的返回结果 type Hover struct { // The hover's content - // contents MarkedString | MarkedString[] | MarkupContent; Contents MarkupContent `json:"contents"` // An optional range is a range inside a text document diff --git a/internal/lsp/protocol/reference.go b/internal/lsp/protocol/reference.go index c412efe0..a2130d8f 100644 --- a/internal/lsp/protocol/reference.go +++ b/internal/lsp/protocol/reference.go @@ -2,7 +2,7 @@ package protocol -// ReferenceClientCapabilities 客户端对与 textDocument/references 的支持情况 +// ReferenceClientCapabilities 客户端对 textDocument/references 的支持情况 type ReferenceClientCapabilities struct { // Whether references supports dynamic registration. DynamicRegistration bool `json:"dynamicRegistration,omitempty"` @@ -18,3 +18,21 @@ type ReferenceParams struct { IncludeDeclaration bool `json:"includeDeclaration"` } `json:"context"` } + +// DefinitionClientCapabilities 客户端对 textDocument/definition 的支持情况 +type DefinitionClientCapabilities struct { + // Whether definition supports dynamic registration. + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + // The client supports additional metadata in the form of definition links. + // + // @since 3.14.0 + LinkSupport bool `json:"linkSupport,omitempty"` +} + +// DefinitionParams textDocument/definition 服务的客户端请求参数 +type DefinitionParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} diff --git a/internal/lsp/protocol/server.go b/internal/lsp/protocol/server.go index ad3b63e6..1af902bc 100644 --- a/internal/lsp/protocol/server.go +++ b/internal/lsp/protocol/server.go @@ -15,18 +15,12 @@ type ServerCapabilities struct { CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"` // The server provides hover support. - // - // boolean | HoverOptions HoverProvider bool `json:"hoverProvider,omitempty"` // The server provides goto definition support. - // - // boolean | DefinitionOptions; DefinitionProvider bool `json:"definitionProvider,omitempty"` // The server provides find references support. - // - // boolean | ReferenceOptions; ReferencesProvider bool `json:"referencesProvider,omitempty"` // The server provides code actions. The `CodeActionOptions` return type is only @@ -51,8 +45,6 @@ type ServerCapabilities struct { // The server provides folding provider support. // // Since 3.10.0 - // - // boolean | FoldingRangeOptions | FoldingRangeRegistrationOptions; FoldingRangeProvider bool `json:"foldingRangeProvider,omitempty"` // The server provides folding provider support. diff --git a/internal/lsp/protocol/textdocument.go b/internal/lsp/protocol/textdocument.go index 3f175469..0fadc814 100644 --- a/internal/lsp/protocol/textdocument.go +++ b/internal/lsp/protocol/textdocument.go @@ -72,13 +72,7 @@ type TextDocumentClientCapabilities struct { // Capabilities specific to the `textDocument/definition`. // // Since 3.14.0 - Definition *struct { - // Whether definition supports dynamic registration. - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - - // The client supports additional metadata in the form of definition links. - LinkSupport bool `json:"linkSupport,omitempty"` - } `json:"definition,omitempty"` + Definition *DefinitionClientCapabilities `json:"definition,omitempty"` // Capabilities specific to the `textDocument/codeAction` CodeAction *struct { diff --git a/internal/lsp/search/reference.go b/internal/lsp/search/reference.go index fb53221e..223e189f 100644 --- a/internal/lsp/search/reference.go +++ b/internal/lsp/search/reference.go @@ -35,3 +35,13 @@ func References(doc *ast.APIDoc, uri core.URI, pos core.Position, include bool) return } + +// Definition 返回所在位置的定义内容 +func Definition(doc *ast.APIDoc, uri core.URI, pos core.Position) core.Location { + r := doc.Search(uri, pos, definitionerType) + if r == nil { + return core.Location{} + } + + return r.(ast.Definitioner).Definition().Location +} diff --git a/internal/lsp/textdocument.go b/internal/lsp/textdocument.go index dde4df1e..c4811318 100644 --- a/internal/lsp/textdocument.go +++ b/internal/lsp/textdocument.go @@ -149,3 +149,21 @@ func (s *server) textDocumentReferences(notify bool, in *protocol.ReferenceParam *out = search.References(f.doc, in.TextDocument.URI, in.Position, in.Context.IncludeDeclaration) return nil } + +// textDocumentDefinition +// +// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition +func (s *server) textDocumentDefinition(notify bool, in *protocol.DefinitionParams, out *core.Location) error { + f := s.findFolder(in.TextDocument.URI) + if f == nil { + return newError(ErrInvalidRequest, locale.ErrFileNotFound, in.TextDocument.URI) + } + + f.parsedMux.Lock() + defer f.parsedMux.Unlock() + + if r := search.Definition(f.doc, in.TextDocument.URI, in.Position); !r.Range.IsEmpty() { + *out = r + } + return nil +}