diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 1119aa3b86..97edbdf59f 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -36,7 +36,6 @@ func (l *LanguageService) ProvideCompletion( documentURI lsproto.DocumentUri, LSPPosition lsproto.Position, context *lsproto.CompletionContext, - clientOptions *lsproto.CompletionClientCapabilities, ) (lsproto.CompletionResponse, error) { _, file := l.getProgramAndFile(documentURI) var triggerCharacter *string @@ -49,7 +48,6 @@ func (l *LanguageService) ProvideCompletion( file, position, triggerCharacter, - clientOptions, ) completionList = ensureItemData(file.FileName(), position, completionList) return lsproto.CompletionItemsOrListOrNull{List: completionList}, nil @@ -342,7 +340,6 @@ func (l *LanguageService) getCompletionsAtPosition( file *ast.SourceFile, position int, triggerCharacter *string, - clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { _, previousToken := getRelevantTokens(position, file) if triggerCharacter != nil && !IsInString(file, position, previousToken) && !isValidTrigger(file, *triggerCharacter, previousToken, position) { @@ -369,7 +366,6 @@ func (l *LanguageService) getCompletionsAtPosition( position, previousToken, compilerOptions, - clientOptions, ) if stringCompletions != nil { return stringCompletions @@ -380,8 +376,8 @@ func (l *LanguageService) getCompletionsAtPosition( previousToken.Kind == ast.KindIdentifier) && ast.IsBreakOrContinueStatement(previousToken.Parent) { return l.getLabelCompletionsAtPosition( + ctx, previousToken.Parent, - clientOptions, file, position, l.getOptionalReplacementSpan(previousToken, file), @@ -406,7 +402,6 @@ func (l *LanguageService) getCompletionsAtPosition( compilerOptions, data, position, - clientOptions, optionalReplacementSpan, ) // !!! check if response is incomplete @@ -414,7 +409,7 @@ func (l *LanguageService) getCompletionsAtPosition( case *completionDataKeyword: optionalReplacementSpan := l.getOptionalReplacementSpan(previousToken, file) return l.specificKeywordCompletionInfo( - clientOptions, + ctx, position, file, data.keywordCompletions, @@ -425,7 +420,7 @@ func (l *LanguageService) getCompletionsAtPosition( // If the current position is a jsDoc tag name, only tag names should be provided for completion items := getJSDocTagNameCompletions() items = append(items, getJSDocParameterCompletions( - clientOptions, + ctx, file, position, checker, @@ -433,12 +428,12 @@ func (l *LanguageService) getCompletionsAtPosition( preferences, /*tagNameOnly*/ true, )...) - return l.jsDocCompletionInfo(clientOptions, position, file, items) + return l.jsDocCompletionInfo(ctx, position, file, items) case *completionDataJSDocTag: // If the current position is a jsDoc tag, only tags should be provided for completion items := getJSDocTagCompletions() items = append(items, getJSDocParameterCompletions( - clientOptions, + ctx, file, position, checker, @@ -446,9 +441,9 @@ func (l *LanguageService) getCompletionsAtPosition( preferences, /*tagNameOnly*/ false, )...) - return l.jsDocCompletionInfo(clientOptions, position, file, items) + return l.jsDocCompletionInfo(ctx, position, file, items) case *completionDataJSDocParameterName: - return l.jsDocCompletionInfo(clientOptions, position, file, getJSDocParameterNameCompletions(data.tag)) + return l.jsDocCompletionInfo(ctx, position, file, getJSDocParameterNameCompletions(data.tag)) default: panic("getCompletionData() returned unexpected type: " + fmt.Sprintf("%T", data)) } @@ -1818,7 +1813,6 @@ func (l *LanguageService) completionInfoFromData( compilerOptions *core.CompilerOptions, data *completionDataData, position int, - clientOptions *lsproto.CompletionClientCapabilities, optionalReplacementSpan *lsproto.Range, ) *lsproto.CompletionList { keywordFilters := data.keywordFilters @@ -1829,7 +1823,7 @@ func (l *LanguageService) completionInfoFromData( // Verify if the file is JSX language variant if file.LanguageVariant == core.LanguageVariantJSX { - list := l.getJsxClosingTagCompletion(data.location, file, position, clientOptions) + list := l.getJsxClosingTagCompletion(ctx, data.location, file, position) if list != nil { return list } @@ -1868,7 +1862,6 @@ func (l *LanguageService) completionInfoFromData( position, file, compilerOptions, - clientOptions, ) if data.keywordFilters != KeywordCompletionFiltersNone { @@ -1909,7 +1902,7 @@ func (l *LanguageService) completionInfoFromData( // !!! exhaustive case completions itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, sortedEntries, @@ -1931,7 +1924,6 @@ func (l *LanguageService) getCompletionEntriesFromSymbols( position int, file *ast.SourceFile, compilerOptions *core.CompilerOptions, - clientOptions *lsproto.CompletionClientCapabilities, ) (uniqueNames collections.Set[string], sortedEntries []*lsproto.CompletionItem) { closestSymbolDeclaration := getClosestSymbolDeclaration(data.contextToken, data.location) useSemicolons := lsutil.ProbablyUsesSemicolons(file) @@ -1988,7 +1980,6 @@ func (l *LanguageService) getCompletionEntriesFromSymbols( origin, useSemicolons, compilerOptions, - clientOptions, isMemberCompletion, ) if entry == nil { @@ -2054,9 +2045,9 @@ func (l *LanguageService) createCompletionItem( origin *symbolOriginInfo, useSemicolons bool, compilerOptions *core.CompilerOptions, - clientOptions *lsproto.CompletionClientCapabilities, isMemberCompletion bool, ) *lsproto.CompletionItem { + clientOptions := lsproto.GetClientCapabilities(ctx).TextDocument.Completion contextToken := data.contextToken var insertText string var filterText string @@ -2173,7 +2164,7 @@ func (l *LanguageService) createCompletionItem( if data.importStatementCompletion.isTopLevelTypeOnly { insertText += typeOnlyText } - tabStop := core.IfElse(ptrIsTrue(clientOptions.CompletionItem.SnippetSupport), "$1", "") + tabStop := core.IfElse(clientOptions.CompletionItem.SnippetSupport, "$1", "") importKind := getImportKind(file, exportKind, l.GetProgram(), true /*forceImportKeyword*/) escapedSnippet := escapeSnippetText(name) suffix := core.IfElse(useSemicolons, ";", "") @@ -2190,7 +2181,7 @@ func (l *LanguageService) createCompletionItem( } replacementSpan = data.importStatementCompletion.replacementSpan - isSnippet = ptrIsTrue(clientOptions.CompletionItem.SnippetSupport) + isSnippet = clientOptions.CompletionItem.SnippetSupport } } @@ -2234,7 +2225,7 @@ func (l *LanguageService) createCompletionItem( insertText = origin.asObjectLiteralMethod().insertText isSnippet = origin.asObjectLiteralMethod().isSnippet labelDetails = origin.asObjectLiteralMethod().labelDetails // !!! check if this can conflict with case above where we set label details - if !clientSupportsItemLabelDetails(clientOptions) { + if !clientSupportsItemLabelDetails(ctx) { name = name + *origin.asObjectLiteralMethod().labelDetails.Detail labelDetails = nil } @@ -2244,7 +2235,7 @@ func (l *LanguageService) createCompletionItem( if data.isJsxIdentifierExpected && !data.isRightOfOpenTag && - clientSupportsItemSnippet(clientOptions) && + clientSupportsItemSnippet(ctx) && preferences.JsxAttributeCompletionStyle != lsutil.JsxAttributeCompletionStyleNone && !(ast.IsJsxAttribute(data.location.Parent) && data.location.Parent.Initializer() != nil) { useBraces := preferences.JsxAttributeCompletionStyle == lsutil.JsxAttributeCompletionStyleBraces @@ -2311,10 +2302,10 @@ func (l *LanguageService) createCompletionItem( elementKind := getSymbolKind(typeChecker, symbol, data.location) var commitCharacters *[]string - if clientSupportsItemCommitCharacters(clientOptions) { + if clientSupportsItemCommitCharacters(ctx) { if elementKind == ScriptElementKindWarning || elementKind == ScriptElementKindString { commitCharacters = &[]string{} - } else if !clientSupportsDefaultCommitCharacters(clientOptions) { + } else if !clientSupportsDefaultCommitCharacters(ctx) { commitCharacters = ptrTo(data.defaultCommitCharacters) } // Otherwise use the completion list default. @@ -2324,6 +2315,7 @@ func (l *LanguageService) createCompletionItem( kindModifiers := getSymbolModifiers(typeChecker, symbol) return l.createLSPCompletionItem( + ctx, name, insertText, filterText, @@ -2335,7 +2327,6 @@ func (l *LanguageService) createCompletionItem( labelDetails, file, position, - clientOptions, isMemberCompletion, isSnippet, hasAction, @@ -4315,7 +4306,7 @@ func isTypeKeywordTokenOrIdentifier(node *ast.Node) bool { // Returns the item defaults for completion items, if that capability is supported. // Otherwise, if some item default is not supported by client, sets that property on each item. func (l *LanguageService) setItemDefaults( - clientOptions *lsproto.CompletionClientCapabilities, + ctx context.Context, position int, file *ast.SourceFile, items []*lsproto.CompletionItem, @@ -4324,8 +4315,8 @@ func (l *LanguageService) setItemDefaults( ) *lsproto.CompletionItemDefaults { var itemDefaults *lsproto.CompletionItemDefaults if defaultCommitCharacters != nil { - supportsItemCommitCharacters := clientSupportsItemCommitCharacters(clientOptions) - if clientSupportsDefaultCommitCharacters(clientOptions) && supportsItemCommitCharacters { + supportsItemCommitCharacters := clientSupportsItemCommitCharacters(ctx) + if clientSupportsDefaultCommitCharacters(ctx) && supportsItemCommitCharacters { itemDefaults = &lsproto.CompletionItemDefaults{ CommitCharacters: defaultCommitCharacters, } @@ -4343,7 +4334,7 @@ func (l *LanguageService) setItemDefaults( Start: optionalReplacementSpan.Start, End: l.createLspPosition(position, file), } - if clientSupportsDefaultEditRange(clientOptions) { + if clientSupportsDefaultEditRange(ctx) { itemDefaults = core.OrElse(itemDefaults, &lsproto.CompletionItemDefaults{}) itemDefaults.EditRange = &lsproto.RangeOrEditRangeWithInsertReplace{ EditRangeWithInsertReplace: &lsproto.EditRangeWithInsertReplace{ @@ -4365,7 +4356,7 @@ func (l *LanguageService) setItemDefaults( item.InsertText = nil } } - } else if clientSupportsItemInsertReplace(clientOptions) { + } else if clientSupportsItemInsertReplace(ctx) { for _, item := range items { if item.TextEdit == nil { item.TextEdit = &lsproto.TextEditOrInsertReplaceEdit{ @@ -4384,7 +4375,7 @@ func (l *LanguageService) setItemDefaults( } func (l *LanguageService) specificKeywordCompletionInfo( - clientOptions *lsproto.CompletionClientCapabilities, + ctx context.Context, position int, file *ast.SourceFile, items []*lsproto.CompletionItem, @@ -4393,7 +4384,7 @@ func (l *LanguageService) specificKeywordCompletionInfo( ) *lsproto.CompletionList { defaultCommitCharacters := getDefaultCommitCharacters(isNewIdentifierLocation) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -4408,10 +4399,10 @@ func (l *LanguageService) specificKeywordCompletionInfo( } func (l *LanguageService) getJsxClosingTagCompletion( + ctx context.Context, location *ast.Node, file *ast.SourceFile, position int, - clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { // We wanna walk up the tree till we find a JSX closing element. jsxClosingElement := ast.FindAncestorOrQuit(location, func(node *ast.Node) ast.FindAncestorResult { @@ -4449,6 +4440,7 @@ func (l *LanguageService) getJsxClosingTagCompletion( defaultCommitCharacters := getDefaultCommitCharacters(false /*isNewIdentifierLocation*/) item := l.createLSPCompletionItem( + ctx, fullClosingTag, /*name*/ "", /*insertText*/ "", /*filterText*/ @@ -4460,7 +4452,6 @@ func (l *LanguageService) getJsxClosingTagCompletion( nil, /*labelDetails*/ file, position, - clientOptions, true, /*isMemberCompletion*/ false, /*isSnippet*/ false, /*hasAction*/ @@ -4470,7 +4461,7 @@ func (l *LanguageService) getJsxClosingTagCompletion( ) items := []*lsproto.CompletionItem{item} itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -4486,6 +4477,7 @@ func (l *LanguageService) getJsxClosingTagCompletion( } func (l *LanguageService) createLSPCompletionItem( + ctx context.Context, name string, insertText string, filterText string, @@ -4497,7 +4489,6 @@ func (l *LanguageService) createLSPCompletionItem( labelDetails *lsproto.CompletionItemLabelDetails, file *ast.SourceFile, position int, - clientOptions *lsproto.CompletionClientCapabilities, isMemberCompletion bool, isSnippet bool, hasAction bool, @@ -4591,19 +4582,19 @@ func (l *LanguageService) createLSPCompletionItem( } func (l *LanguageService) getLabelCompletionsAtPosition( + ctx context.Context, node *ast.BreakOrContinueStatement, - clientOptions *lsproto.CompletionClientCapabilities, file *ast.SourceFile, position int, optionalReplacementSpan *lsproto.Range, ) *lsproto.CompletionList { - items := l.getLabelStatementCompletions(node, clientOptions, file, position) + items := l.getLabelStatementCompletions(ctx, node, file, position) if len(items) == 0 { return nil } defaultCommitCharacters := getDefaultCommitCharacters(false /*isNewIdentifierLocation*/) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -4618,8 +4609,8 @@ func (l *LanguageService) getLabelCompletionsAtPosition( } func (l *LanguageService) getLabelStatementCompletions( + ctx context.Context, node *ast.BreakOrContinueStatement, - clientOptions *lsproto.CompletionClientCapabilities, file *ast.SourceFile, position int, ) []*lsproto.CompletionItem { @@ -4635,6 +4626,7 @@ func (l *LanguageService) getLabelStatementCompletions( if !uniques.Has(name) { uniques.Add(name) items = append(items, l.createLSPCompletionItem( + ctx, name, "", /*insertText*/ "", /*filterText*/ @@ -4646,7 +4638,6 @@ func (l *LanguageService) getLabelStatementCompletions( nil, /*labelDetails*/ file, position, - clientOptions, false, /*isMemberCompletion*/ false, /*isSnippet*/ false, /*hasAction*/ @@ -4886,38 +4877,28 @@ func isInJsxText(contextToken *ast.Node, location *ast.Node) bool { return false } -func hasCompletionItem(clientOptions *lsproto.CompletionClientCapabilities) bool { - return clientOptions != nil && clientOptions.CompletionItem != nil -} - -func clientSupportsItemLabelDetails(clientOptions *lsproto.CompletionClientCapabilities) bool { - return hasCompletionItem(clientOptions) && ptrIsTrue(clientOptions.CompletionItem.LabelDetailsSupport) +func clientSupportsItemLabelDetails(ctx context.Context) bool { + return lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionItem.LabelDetailsSupport } -func clientSupportsItemSnippet(clientOptions *lsproto.CompletionClientCapabilities) bool { - return hasCompletionItem(clientOptions) && ptrIsTrue(clientOptions.CompletionItem.SnippetSupport) +func clientSupportsItemSnippet(ctx context.Context) bool { + return lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionItem.SnippetSupport } -func clientSupportsItemCommitCharacters(clientOptions *lsproto.CompletionClientCapabilities) bool { - return hasCompletionItem(clientOptions) && ptrIsTrue(clientOptions.CompletionItem.CommitCharactersSupport) +func clientSupportsItemCommitCharacters(ctx context.Context) bool { + return lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionItem.CommitCharactersSupport } -func clientSupportsItemInsertReplace(clientOptions *lsproto.CompletionClientCapabilities) bool { - return hasCompletionItem(clientOptions) && ptrIsTrue(clientOptions.CompletionItem.InsertReplaceSupport) +func clientSupportsItemInsertReplace(ctx context.Context) bool { + return lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionItem.InsertReplaceSupport } -func clientSupportsDefaultCommitCharacters(clientOptions *lsproto.CompletionClientCapabilities) bool { - if clientOptions == nil || clientOptions.CompletionList == nil || clientOptions.CompletionList.ItemDefaults == nil { - return false - } - return slices.Contains(*clientOptions.CompletionList.ItemDefaults, "commitCharacters") +func clientSupportsDefaultCommitCharacters(ctx context.Context) bool { + return slices.Contains(lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionList.ItemDefaults, "commitCharacters") } -func clientSupportsDefaultEditRange(clientOptions *lsproto.CompletionClientCapabilities) bool { - if clientOptions == nil || clientOptions.CompletionList == nil || clientOptions.CompletionList.ItemDefaults == nil { - return false - } - return slices.Contains(*clientOptions.CompletionList.ItemDefaults, "editRange") +func clientSupportsDefaultEditRange(ctx context.Context) bool { + return slices.Contains(lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionList.ItemDefaults, "editRange") } type argumentInfoForCompletions struct { @@ -5002,7 +4983,6 @@ func (l *LanguageService) ResolveCompletionItem( ctx context.Context, item *lsproto.CompletionItem, data *CompletionItemData, - clientOptions *lsproto.CompletionClientCapabilities, ) (*lsproto.CompletionItem, error) { if data == nil { return nil, errors.New("completion item data is nil") @@ -5013,7 +4993,7 @@ func (l *LanguageService) ResolveCompletionItem( return nil, fmt.Errorf("file not found: %s", data.FileName) } - return l.getCompletionItemDetails(ctx, program, data.Position, file, item, data, clientOptions), nil + return l.getCompletionItemDetails(ctx, program, data.Position, file, item, data), nil } func GetCompletionItemData(item *lsproto.CompletionItem) (*CompletionItemData, error) { @@ -5028,17 +5008,8 @@ func GetCompletionItemData(item *lsproto.CompletionItem) (*CompletionItemData, e return &itemData, nil } -func getCompletionDocumentationFormat(clientOptions *lsproto.CompletionClientCapabilities) lsproto.MarkupKind { - if clientOptions == nil || clientOptions.CompletionItem == nil || clientOptions.CompletionItem.DocumentationFormat == nil { - // Default to plaintext if no preference specified - return lsproto.MarkupKindPlainText - } - formats := *clientOptions.CompletionItem.DocumentationFormat - if len(formats) == 0 { - return lsproto.MarkupKindPlainText - } - // Return the first (most preferred) format - return formats[0] +func getCompletionDocumentationFormat(ctx context.Context) lsproto.MarkupKind { + return lsproto.PreferredMarkupKind(lsproto.GetClientCapabilities(ctx).TextDocument.Completion.CompletionItem.DocumentationFormat) } func (l *LanguageService) getCompletionItemDetails( @@ -5047,19 +5018,18 @@ func (l *LanguageService) getCompletionItemDetails( position int, file *ast.SourceFile, item *lsproto.CompletionItem, - itemData *CompletionItemData, - clientOptions *lsproto.CompletionClientCapabilities, + data *CompletionItemData, ) *lsproto.CompletionItem { checker, done := program.GetTypeCheckerForFile(ctx, file) defer done() - docFormat := getCompletionDocumentationFormat(clientOptions) + docFormat := getCompletionDocumentationFormat(ctx) contextToken, previousToken := getRelevantTokens(position, file) if IsInString(file, position, previousToken) { return l.getStringLiteralCompletionDetails( ctx, checker, item, - itemData.Name, + data.Name, file, position, contextToken, @@ -5073,8 +5043,7 @@ func (l *LanguageService) getCompletionItemDetails( checker, file, position, - itemData, - clientOptions, + data, ) preferences := l.UserPreferences() @@ -5083,16 +5052,16 @@ func (l *LanguageService) getCompletionItemDetails( request := *symbolCompletion.request switch request := request.(type) { case *completionDataJSDocTagName: - return createSimpleDetails(item, itemData.Name, docFormat) + return createSimpleDetails(item, data.Name, docFormat) case *completionDataJSDocTag: - return createSimpleDetails(item, itemData.Name, docFormat) + return createSimpleDetails(item, data.Name, docFormat) case *completionDataJSDocParameterName: - return createSimpleDetails(item, itemData.Name, docFormat) + return createSimpleDetails(item, data.Name, docFormat) case *completionDataKeyword: if core.Some(request.keywordCompletions, func(c *lsproto.CompletionItem) bool { - return c.Label == itemData.Name + return c.Label == data.Name }) { - return createSimpleDetails(item, itemData.Name, docFormat) + return createSimpleDetails(item, data.Name, docFormat) } return item default: @@ -5100,7 +5069,7 @@ func (l *LanguageService) getCompletionItemDetails( } case symbolCompletion.symbol != nil: symbolDetails := symbolCompletion.symbol - actions := l.getCompletionItemActions(ctx, checker, file, position, itemData, symbolDetails) + actions := l.getCompletionItemActions(ctx, checker, file, position, data, symbolDetails) return l.createCompletionDetailsForSymbol( item, symbolDetails.symbol, @@ -5118,9 +5087,9 @@ func (l *LanguageService) getCompletionItemDetails( default: // Didn't find a symbol with this name. See if we can find a keyword instead. if core.Some(allKeywordCompletions(), func(c *lsproto.CompletionItem) bool { - return c.Label == itemData.Name + return c.Label == data.Name }) { - return createSimpleDetails(item, itemData.Name, docFormat) + return createSimpleDetails(item, data.Name, docFormat) } return item } @@ -5149,7 +5118,6 @@ func (l *LanguageService) getSymbolCompletionFromItemData( file *ast.SourceFile, position int, itemData *CompletionItemData, - clientOptions *lsproto.CompletionClientCapabilities, ) detailsData { if itemData.Source == SourceSwitchCases { return detailsData{ @@ -5601,14 +5569,14 @@ func isTagWithTypeExpression(tag *ast.JSDocTag) bool { } func (l *LanguageService) jsDocCompletionInfo( - clientOptions *lsproto.CompletionClientCapabilities, + ctx context.Context, position int, file *ast.SourceFile, items []*lsproto.CompletionItem, ) *lsproto.CompletionList { defaultCommitCharacters := getDefaultCommitCharacters(false /*isNewIdentifierLocation*/) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -5744,7 +5712,7 @@ func getJSDocTagCompletions() []*lsproto.CompletionItem { } func getJSDocParameterCompletions( - clientOptions *lsproto.CompletionClientCapabilities, + ctx context.Context, file *ast.SourceFile, position int, typeChecker *checker.Checker, diff --git a/internal/ls/definition.go b/internal/ls/definition.go index 9f0d231fc7..fb9e8164a6 100644 --- a/internal/ls/definition.go +++ b/internal/ls/definition.go @@ -17,8 +17,10 @@ func (l *LanguageService) ProvideDefinition( ctx context.Context, documentURI lsproto.DocumentUri, position lsproto.Position, - clientSupportsLink bool, ) (lsproto.DefinitionResponse, error) { + caps := lsproto.GetClientCapabilities(ctx) + clientSupportsLink := caps.TextDocument.Definition.LinkSupport + program, file := l.getProgramAndFile(documentURI) node := astnav.GetTouchingPropertyName(file, int(l.converters.LineAndCharacterToPosition(file, position))) if node.Kind == ast.KindSourceFile { @@ -68,8 +70,10 @@ func (l *LanguageService) ProvideTypeDefinition( ctx context.Context, documentURI lsproto.DocumentUri, position lsproto.Position, - clientSupportsLink bool, -) (lsproto.DefinitionResponse, error) { +) (lsproto.TypeDefinitionResponse, error) { + caps := lsproto.GetClientCapabilities(ctx) + clientSupportsLink := caps.TextDocument.TypeDefinition.LinkSupport + program, file := l.getProgramAndFile(documentURI) node := astnav.GetTouchingPropertyName(file, int(l.converters.LineAndCharacterToPosition(file, position))) if node.Kind == ast.KindSourceFile { @@ -279,8 +283,3 @@ func getDeclarationsFromType(t *checker.Type) []*ast.Node { } return result } - -func clientSupportsLink(clientCapabilities *lsproto.DefinitionClientCapabilities) bool { - return clientCapabilities != nil && - ptrIsTrue(clientCapabilities.LinkSupport) -} diff --git a/internal/ls/diagnostics.go b/internal/ls/diagnostics.go index 28df9c80bb..59d34bb213 100644 --- a/internal/ls/diagnostics.go +++ b/internal/ls/diagnostics.go @@ -12,7 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/lsp/lsproto" ) -func (l *LanguageService) ProvideDiagnostics(ctx context.Context, uri lsproto.DocumentUri, clientOptions *lsproto.DiagnosticClientCapabilities) (lsproto.DocumentDiagnosticResponse, error) { +func (l *LanguageService) ProvideDiagnostics(ctx context.Context, uri lsproto.DocumentUri) (lsproto.DocumentDiagnosticResponse, error) { program, file := l.getProgramAndFile(uri) diagnostics := make([][]*ast.Diagnostic, 0, 4) @@ -28,12 +28,12 @@ func (l *LanguageService) ProvideDiagnostics(ctx context.Context, uri lsproto.Do return lsproto.RelatedFullDocumentDiagnosticReportOrUnchangedDocumentDiagnosticReport{ FullDocumentDiagnosticReport: &lsproto.RelatedFullDocumentDiagnosticReport{ - Items: l.toLSPDiagnostics(clientOptions, diagnostics...), + Items: l.toLSPDiagnostics(ctx, diagnostics...), }, }, nil } -func (l *LanguageService) toLSPDiagnostics(clientOptions *lsproto.DiagnosticClientCapabilities, diagnostics ...[]*ast.Diagnostic) []*lsproto.Diagnostic { +func (l *LanguageService) toLSPDiagnostics(ctx context.Context, diagnostics ...[]*ast.Diagnostic) []*lsproto.Diagnostic { size := 0 for _, diagSlice := range diagnostics { size += len(diagSlice) @@ -41,13 +41,14 @@ func (l *LanguageService) toLSPDiagnostics(clientOptions *lsproto.DiagnosticClie lspDiagnostics := make([]*lsproto.Diagnostic, 0, size) for _, diagSlice := range diagnostics { for _, diag := range diagSlice { - lspDiagnostics = append(lspDiagnostics, l.toLSPDiagnostic(clientOptions, diag)) + lspDiagnostics = append(lspDiagnostics, l.toLSPDiagnostic(ctx, diag)) } } return lspDiagnostics } -func (l *LanguageService) toLSPDiagnostic(clientOptions *lsproto.DiagnosticClientCapabilities, diagnostic *ast.Diagnostic) *lsproto.Diagnostic { +func (l *LanguageService) toLSPDiagnostic(ctx context.Context, diagnostic *ast.Diagnostic) *lsproto.Diagnostic { + clientOptions := lsproto.GetClientCapabilities(ctx).TextDocument.Diagnostic var severity lsproto.DiagnosticSeverity switch diagnostic.Category() { case diagnostics.CategorySuggestion: @@ -61,7 +62,7 @@ func (l *LanguageService) toLSPDiagnostic(clientOptions *lsproto.DiagnosticClien } var relatedInformation []*lsproto.DiagnosticRelatedInformation - if clientOptions != nil && ptrIsTrue(clientOptions.RelatedInformation) { + if clientOptions.RelatedInformation { relatedInformation = make([]*lsproto.DiagnosticRelatedInformation, 0, len(diagnostic.RelatedInformation())) for _, related := range diagnostic.RelatedInformation() { relatedInformation = append(relatedInformation, &lsproto.DiagnosticRelatedInformation{ @@ -75,7 +76,7 @@ func (l *LanguageService) toLSPDiagnostic(clientOptions *lsproto.DiagnosticClien } var tags []lsproto.DiagnosticTag - if clientOptions != nil && clientOptions.TagSupport != nil && (diagnostic.ReportsUnnecessary() || diagnostic.ReportsDeprecated()) { + if len(clientOptions.TagSupport.ValueSet) > 0 && (diagnostic.ReportsUnnecessary() || diagnostic.ReportsDeprecated()) { tags = make([]lsproto.DiagnosticTag, 0, 2) if diagnostic.ReportsUnnecessary() && slices.Contains(clientOptions.TagSupport.ValueSet, lsproto.DiagnosticTagUnnecessary) { tags = append(tags, lsproto.DiagnosticTagUnnecessary) diff --git a/internal/ls/findallreferences.go b/internal/ls/findallreferences.go index 545b274993..85d18cee0e 100644 --- a/internal/ls/findallreferences.go +++ b/internal/ls/findallreferences.go @@ -430,7 +430,7 @@ func (l *LanguageService) ProvideReferences(ctx context.Context, params *lsproto return lsproto.LocationsOrNull{Locations: &locations}, nil } -func (l *LanguageService) ProvideImplementations(ctx context.Context, params *lsproto.ImplementationParams, clientSupportsLink bool) (lsproto.ImplementationResponse, error) { +func (l *LanguageService) ProvideImplementations(ctx context.Context, params *lsproto.ImplementationParams) (lsproto.ImplementationResponse, error) { program, sourceFile := l.getProgramAndFile(params.TextDocument.Uri) position := int(l.converters.LineAndCharacterToPosition(sourceFile, params.Position)) node := astnav.GetTouchingPropertyName(sourceFile, position) @@ -452,7 +452,7 @@ func (l *LanguageService) ProvideImplementations(ctx context.Context, params *ls } } - if clientSupportsLink { + if lsproto.GetClientCapabilities(ctx).TextDocument.Implementation.LinkSupport { links := l.convertEntriesToLocationLinks(entries) return lsproto.LocationOrLocationsOrDefinitionLinksOrNull{DefinitionLinks: &links}, nil } diff --git a/internal/ls/hover.go b/internal/ls/hover.go index 808efe7dbf..736f4c31a9 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -18,7 +18,10 @@ const ( typeFormatFlags = checker.TypeFormatFlagsUseAliasDefinedOutsideCurrentScope ) -func (l *LanguageService) ProvideHover(ctx context.Context, documentURI lsproto.DocumentUri, position lsproto.Position, contentFormat lsproto.MarkupKind) (lsproto.HoverResponse, error) { +func (l *LanguageService) ProvideHover(ctx context.Context, documentURI lsproto.DocumentUri, position lsproto.Position) (lsproto.HoverResponse, error) { + caps := lsproto.GetClientCapabilities(ctx) + contentFormat := lsproto.PreferredMarkupKind(caps.TextDocument.Hover.ContentFormat) + program, file := l.getProgramAndFile(documentURI) node := astnav.GetTouchingPropertyName(file, int(l.converters.LineAndCharacterToPosition(file, position))) if node.Kind == ast.KindSourceFile { diff --git a/internal/ls/signaturehelp.go b/internal/ls/signaturehelp.go index 508c74877a..4369ef0bc8 100644 --- a/internal/ls/signaturehelp.go +++ b/internal/ls/signaturehelp.go @@ -43,8 +43,6 @@ func (l *LanguageService) ProvideSignatureHelp( documentURI lsproto.DocumentUri, position lsproto.Position, context *lsproto.SignatureHelpContext, - clientOptions *lsproto.SignatureHelpClientCapabilities, - docFormat lsproto.MarkupKind, ) (lsproto.SignatureHelpResponse, error) { program, sourceFile := l.getProgramAndFile(documentURI) items := l.GetSignatureHelpItems( @@ -52,9 +50,7 @@ func (l *LanguageService) ProvideSignatureHelp( int(l.converters.LineAndCharacterToPosition(sourceFile, position)), program, sourceFile, - context, - clientOptions, - docFormat) + context) return lsproto.SignatureHelpOrNull{SignatureHelp: items}, nil } @@ -64,8 +60,6 @@ func (l *LanguageService) GetSignatureHelpItems( program *compiler.Program, sourceFile *ast.SourceFile, context *lsproto.SignatureHelpContext, - clientOptions *lsproto.SignatureHelpClientCapabilities, - docFormat lsproto.MarkupKind, ) *lsproto.SignatureHelp { typeChecker, done := program.GetTypeCheckerForFile(ctx, sourceFile) defer done() @@ -143,12 +137,12 @@ func (l *LanguageService) GetSignatureHelpItems( // return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => if candidateInfo.candidateInfo != nil { - return l.createSignatureHelpItems(candidateInfo.candidateInfo.candidates, candidateInfo.candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker, onlyUseSyntacticOwners, clientOptions, docFormat) + return l.createSignatureHelpItems(ctx, candidateInfo.candidateInfo.candidates, candidateInfo.candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker, onlyUseSyntacticOwners) } - return createTypeHelpItems(candidateInfo.typeInfo, argumentInfo, sourceFile, clientOptions, typeChecker) + return createTypeHelpItems(candidateInfo.typeInfo, argumentInfo, sourceFile, typeChecker) } -func createTypeHelpItems(symbol *ast.Symbol, argumentInfo *argumentListInfo, sourceFile *ast.SourceFile, clientOptions *lsproto.SignatureHelpClientCapabilities, c *checker.Checker) *lsproto.SignatureHelp { +func createTypeHelpItems(symbol *ast.Symbol, argumentInfo *argumentListInfo, sourceFile *ast.SourceFile, c *checker.Checker) *lsproto.SignatureHelp { typeParameters := c.GetLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) if typeParameters == nil { return nil @@ -205,7 +199,10 @@ func getTypeHelpItem(symbol *ast.Symbol, typeParameter []*checker.Type, enclosin } } -func (l *LanguageService) createSignatureHelpItems(candidates []*checker.Signature, resolvedSignature *checker.Signature, argumentInfo *argumentListInfo, sourceFile *ast.SourceFile, c *checker.Checker, useFullPrefix bool, clientOptions *lsproto.SignatureHelpClientCapabilities, docFormat lsproto.MarkupKind) *lsproto.SignatureHelp { +func (l *LanguageService) createSignatureHelpItems(ctx context.Context, candidates []*checker.Signature, resolvedSignature *checker.Signature, argumentInfo *argumentListInfo, sourceFile *ast.SourceFile, c *checker.Checker, useFullPrefix bool) *lsproto.SignatureHelp { + caps := lsproto.GetClientCapabilities(ctx) + docFormat := lsproto.PreferredMarkupKind(caps.TextDocument.SignatureHelp.SignatureInformation.DocumentationFormat) + enclosingDeclaration := getEnclosingDeclarationFromInvocation(argumentInfo.invocation) if enclosingDeclaration == nil { return nil diff --git a/internal/ls/string_completions.go b/internal/ls/string_completions.go index 35d8b697da..a27b3768ef 100644 --- a/internal/ls/string_completions.go +++ b/internal/ls/string_completions.go @@ -46,7 +46,6 @@ func (l *LanguageService) getStringLiteralCompletions( position int, contextToken *ast.Node, compilerOptions *core.CompilerOptions, - clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { // !!! reference comment if IsInString(file, position, contextToken) { @@ -65,7 +64,6 @@ func (l *LanguageService) getStringLiteralCompletions( file, position, compilerOptions, - clientOptions, ) } return nil @@ -78,7 +76,6 @@ func (l *LanguageService) convertStringLiteralCompletions( file *ast.SourceFile, position int, options *core.CompilerOptions, - clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { if completion == nil { return nil @@ -88,7 +85,7 @@ func (l *LanguageService) convertStringLiteralCompletions( switch { case completion.fromPaths != nil: completion := completion.fromPaths - return l.convertPathCompletions(completion, file, position, clientOptions) + return l.convertPathCompletions(ctx, completion, file, position) case completion.fromProperties != nil: completion := completion.fromProperties data := &completionDataData{ @@ -105,11 +102,10 @@ func (l *LanguageService) convertStringLiteralCompletions( position, file, options, - clientOptions, ) defaultCommitCharacters := getDefaultCommitCharacters(completion.hasIndexSignature) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -134,6 +130,7 @@ func (l *LanguageService) convertStringLiteralCompletions( items := core.Map(completion.types, func(t *checker.StringLiteralType) *lsproto.CompletionItem { name := printer.EscapeString(t.AsLiteralType().Value().(string), quoteChar) return l.createLSPCompletionItem( + ctx, name, "", /*insertText*/ "", /*filterText*/ @@ -145,7 +142,6 @@ func (l *LanguageService) convertStringLiteralCompletions( nil, /*labelDetails*/ file, position, - clientOptions, false, /*isMemberCompletion*/ false, /*isSnippet*/ false, /*hasAction*/ @@ -156,7 +152,7 @@ func (l *LanguageService) convertStringLiteralCompletions( }) defaultCommitCharacters := getDefaultCommitCharacters(completion.isNewIdentifier) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, @@ -174,16 +170,17 @@ func (l *LanguageService) convertStringLiteralCompletions( } func (l *LanguageService) convertPathCompletions( + ctx context.Context, pathCompletions []*pathCompletion, file *ast.SourceFile, position int, - clientOptions *lsproto.CompletionClientCapabilities, ) *lsproto.CompletionList { isNewIdentifierLocation := true // The user may type in a path that doesn't yet exist, creating a "new identifier" with respect to the collection of identifiers the server is aware of. defaultCommitCharacters := getDefaultCommitCharacters(isNewIdentifierLocation) items := core.Map(pathCompletions, func(pathCompletion *pathCompletion) *lsproto.CompletionItem { replacementSpan := l.createLspRangeFromBounds(pathCompletion.textRange.Pos(), pathCompletion.textRange.End(), file) return l.createLSPCompletionItem( + ctx, pathCompletion.name, "", /*insertText*/ "", /*filterText*/ @@ -195,7 +192,6 @@ func (l *LanguageService) convertPathCompletions( nil, /*labelDetails*/ file, position, - clientOptions, false, /*isMemberCompletion*/ false, /*isSnippet*/ false, /*hasAction*/ @@ -205,7 +201,7 @@ func (l *LanguageService) convertPathCompletions( ) }) itemDefaults := l.setItemDefaults( - clientOptions, + ctx, position, file, items, diff --git a/internal/ls/symbols.go b/internal/ls/symbols.go index 98215dca31..5cab43634a 100644 --- a/internal/ls/symbols.go +++ b/internal/ls/symbols.go @@ -18,9 +18,9 @@ import ( "github.com/microsoft/typescript-go/internal/stringutil" ) -func (l *LanguageService) ProvideDocumentSymbols(ctx context.Context, documentURI lsproto.DocumentUri, hierarchicalSupport bool) (lsproto.DocumentSymbolResponse, error) { +func (l *LanguageService) ProvideDocumentSymbols(ctx context.Context, documentURI lsproto.DocumentUri) (lsproto.DocumentSymbolResponse, error) { _, file := l.getProgramAndFile(documentURI) - if hierarchicalSupport { + if lsproto.GetClientCapabilities(ctx).TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport { symbols := l.getDocumentSymbolsForChildren(ctx, file.AsNode()) return lsproto.SymbolInformationsOrDocumentSymbolsOrNull{DocumentSymbols: &symbols}, nil } diff --git a/internal/lsp/lsproto/_generate/generate.mts b/internal/lsp/lsproto/_generate/generate.mts index 1828abd62f..68bfb5778e 100644 --- a/internal/lsp/lsproto/_generate/generate.mts +++ b/internal/lsp/lsproto/_generate/generate.mts @@ -10,6 +10,7 @@ import type { Notification, OrType, Property, + ReferenceType, Request, Structure, Type, @@ -471,6 +472,107 @@ function generateCode() { parts.push(s + "\n"); } + function generateResolvedStruct(structure: Structure, indent: string = "\t"): string[] { + const lines: string[] = []; + + for (const prop of structure.properties) { + const type = resolveType(prop.type); + + // For reference types that are structures, use a named resolved type + if (prop.type.kind === "reference") { + const refStructure = model.structures.find(s => s.name === type.name); + if (refStructure) { + // Use a named type for the resolved version + lines.push(`${indent}${titleCase(prop.name)} Resolved${type.name} \`json:"${prop.name},omitzero"\``); + continue; + } + } + + // For other types (primitives, enums, arrays, etc.), use the type directly (no pointer) + const goType = type.name; + lines.push(`${indent}${titleCase(prop.name)} ${goType} \`json:"${prop.name},omitzero"\``); + } + + return lines; + } + + function generateResolveConversion(structure: Structure, varName: string, indent: string): string[] { + const lines: string[] = []; + + for (const prop of structure.properties) { + const type = resolveType(prop.type); + const fieldName = titleCase(prop.name); + const accessPath = `${varName}.${fieldName}`; + + // For reference types that are structures, call the resolve function + if (prop.type.kind === "reference") { + const refStructure = model.structures.find(s => s.name === type.name); + if (refStructure) { + // Use lowercase (unexported) function name for helper functions + lines.push(`${indent}${fieldName}: resolve${type.name}(${accessPath}),`); + continue; + } + } + + // For other types, dereference if pointer + if (prop.optional || type.needsPointer) { + lines.push(`${indent}${fieldName}: derefOr(${accessPath}),`); + } + else { + lines.push(`${indent}${fieldName}: ${accessPath},`); + } + } + + return lines; + } + + function collectStructureDependencies(structure: Structure, visited = new Set()): Structure[] { + if (visited.has(structure.name)) { + return []; + } + visited.add(structure.name); + + const deps: Structure[] = []; + + for (const prop of structure.properties) { + if (prop.type.kind === "reference") { + const refStructure = model.structures.find(s => s.name === (prop.type as ReferenceType).name); + if (refStructure) { + deps.push(...collectStructureDependencies(refStructure, new Set(visited))); + deps.push(refStructure); + } + } + } + + return deps; + } + + function generateResolvedTypeAndHelper(structure: Structure, isMain: boolean = false): string[] { + const lines: string[] = []; + const typeName = `Resolved${structure.name}`; + // Main function is exported, helpers are unexported + const funcName = isMain ? `Resolve${structure.name}` : `resolve${structure.name}`; + + // Generate the resolved type + lines.push(`type ${typeName} struct {`); + lines.push(...generateResolvedStruct(structure, "\t")); + lines.push(`}`); + lines.push(``); + + // Generate the conversion function + lines.push(`func ${funcName}(v *${structure.name}) ${typeName} {`); + lines.push(`\tif v == nil {`); + lines.push(`\t\treturn ${typeName}{}`); + lines.push(`\t}`); + lines.push(`\treturn ${typeName}{`); + lines.push(...generateResolveConversion(structure, "v", "\t\t")); + lines.push(`\t}`); + lines.push(`}`); + lines.push(``); + + return lines; + } + // File header writeLine("// Code generated by generate.mts; DO NOT EDIT."); writeLine(""); @@ -877,6 +979,40 @@ function generateCode() { writeLine(""); } + // Generate resolved capabilities + const clientCapsStructure = model.structures.find(s => s.name === "ClientCapabilities"); + if (clientCapsStructure) { + writeLine("// Helper function for dereferencing pointers with zero value fallback"); + writeLine("func derefOr[T any](v *T) T {"); + writeLine("\tif v != nil {"); + writeLine("\t\treturn *v"); + writeLine("\t}"); + writeLine("\tvar zero T"); + writeLine("\treturn zero"); + writeLine("}"); + writeLine(""); + + // Collect all dependent structures and generate their resolved types + const deps = collectStructureDependencies(clientCapsStructure); + const uniqueDeps = Array.from(new Map(deps.map(d => [d.name, d])).values()); + + for (const dep of uniqueDeps) { + const depLines = generateResolvedTypeAndHelper(dep, false); + for (const line of depLines) { + writeLine(line); + } + } + + // Generate the main ResolvedClientCapabilities type and function + writeLine("// ResolvedClientCapabilities is a version of ClientCapabilities where all nested"); + writeLine("// fields are values (not pointers), making it easier to access deeply nested capabilities."); + writeLine("// Use ResolveClientCapabilities to convert from ClientCapabilities."); + const mainLines = generateResolvedTypeAndHelper(clientCapsStructure, true); + for (const line of mainLines) { + writeLine(line); + } + } + return parts.join(""); } diff --git a/internal/lsp/lsproto/lsp.go b/internal/lsp/lsproto/lsp.go index dd172077c2..cc27437593 100644 --- a/internal/lsp/lsproto/lsp.go +++ b/internal/lsp/lsproto/lsp.go @@ -1,6 +1,7 @@ package lsproto import ( + "context" "fmt" "net/url" "strings" @@ -149,3 +150,25 @@ func (Null) UnmarshalJSONFrom(dec *jsontext.Decoder) error { func (Null) MarshalJSONTo(enc *jsontext.Encoder) error { return enc.WriteToken(jsontext.Null) } + +type clientCapabilitiesKey struct{} + +func WithClientCapabilities(ctx context.Context, caps *ResolvedClientCapabilities) context.Context { + return context.WithValue(ctx, clientCapabilitiesKey{}, caps) +} + +func GetClientCapabilities(ctx context.Context) *ResolvedClientCapabilities { + if caps, _ := ctx.Value(clientCapabilitiesKey{}).(*ResolvedClientCapabilities); caps != nil { + return caps + } + return &ResolvedClientCapabilities{} +} + +// PreferredMarkupKind returns the first (most preferred) markup kind from the given formats, +// or MarkupKindPlainText if the slice is empty. +func PreferredMarkupKind(formats []MarkupKind) MarkupKind { + if len(formats) > 0 { + return formats[0] + } + return MarkupKindPlainText +} diff --git a/internal/lsp/lsproto/lsp_generated.go b/internal/lsp/lsproto/lsp_generated.go index 04892d51b9..075d574c00 100644 --- a/internal/lsp/lsproto/lsp_generated.go +++ b/internal/lsp/lsproto/lsp_generated.go @@ -25725,3 +25725,1347 @@ func (o *StringLiteralSnippet) UnmarshalJSONFrom(dec *jsontext.Decoder) error { } return nil } + +// Helper function for dereferencing pointers with zero value fallback +func derefOr[T any](v *T) T { + if v != nil { + return *v + } + var zero T + return zero +} + +type ResolvedChangeAnnotationsSupportOptions struct { + GroupsOnLabel bool `json:"groupsOnLabel,omitzero"` +} + +func resolveChangeAnnotationsSupportOptions(v *ChangeAnnotationsSupportOptions) ResolvedChangeAnnotationsSupportOptions { + if v == nil { + return ResolvedChangeAnnotationsSupportOptions{} + } + return ResolvedChangeAnnotationsSupportOptions{ + GroupsOnLabel: derefOr(v.GroupsOnLabel), + } +} + +type ResolvedWorkspaceEditClientCapabilities struct { + DocumentChanges bool `json:"documentChanges,omitzero"` + ResourceOperations []ResourceOperationKind `json:"resourceOperations,omitzero"` + FailureHandling FailureHandlingKind `json:"failureHandling,omitzero"` + NormalizesLineEndings bool `json:"normalizesLineEndings,omitzero"` + ChangeAnnotationSupport ResolvedChangeAnnotationsSupportOptions `json:"changeAnnotationSupport,omitzero"` + MetadataSupport bool `json:"metadataSupport,omitzero"` + SnippetEditSupport bool `json:"snippetEditSupport,omitzero"` +} + +func resolveWorkspaceEditClientCapabilities(v *WorkspaceEditClientCapabilities) ResolvedWorkspaceEditClientCapabilities { + if v == nil { + return ResolvedWorkspaceEditClientCapabilities{} + } + return ResolvedWorkspaceEditClientCapabilities{ + DocumentChanges: derefOr(v.DocumentChanges), + ResourceOperations: derefOr(v.ResourceOperations), + FailureHandling: derefOr(v.FailureHandling), + NormalizesLineEndings: derefOr(v.NormalizesLineEndings), + ChangeAnnotationSupport: resolveChangeAnnotationsSupportOptions(v.ChangeAnnotationSupport), + MetadataSupport: derefOr(v.MetadataSupport), + SnippetEditSupport: derefOr(v.SnippetEditSupport), + } +} + +type ResolvedDidChangeConfigurationClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveDidChangeConfigurationClientCapabilities(v *DidChangeConfigurationClientCapabilities) ResolvedDidChangeConfigurationClientCapabilities { + if v == nil { + return ResolvedDidChangeConfigurationClientCapabilities{} + } + return ResolvedDidChangeConfigurationClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedDidChangeWatchedFilesClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + RelativePatternSupport bool `json:"relativePatternSupport,omitzero"` +} + +func resolveDidChangeWatchedFilesClientCapabilities(v *DidChangeWatchedFilesClientCapabilities) ResolvedDidChangeWatchedFilesClientCapabilities { + if v == nil { + return ResolvedDidChangeWatchedFilesClientCapabilities{} + } + return ResolvedDidChangeWatchedFilesClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + RelativePatternSupport: derefOr(v.RelativePatternSupport), + } +} + +type ResolvedClientSymbolKindOptions struct { + ValueSet []SymbolKind `json:"valueSet,omitzero"` +} + +func resolveClientSymbolKindOptions(v *ClientSymbolKindOptions) ResolvedClientSymbolKindOptions { + if v == nil { + return ResolvedClientSymbolKindOptions{} + } + return ResolvedClientSymbolKindOptions{ + ValueSet: derefOr(v.ValueSet), + } +} + +type ResolvedClientSymbolTagOptions struct { + ValueSet []SymbolTag `json:"valueSet,omitzero"` +} + +func resolveClientSymbolTagOptions(v *ClientSymbolTagOptions) ResolvedClientSymbolTagOptions { + if v == nil { + return ResolvedClientSymbolTagOptions{} + } + return ResolvedClientSymbolTagOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedClientSymbolResolveOptions struct { + Properties []string `json:"properties,omitzero"` +} + +func resolveClientSymbolResolveOptions(v *ClientSymbolResolveOptions) ResolvedClientSymbolResolveOptions { + if v == nil { + return ResolvedClientSymbolResolveOptions{} + } + return ResolvedClientSymbolResolveOptions{ + Properties: v.Properties, + } +} + +type ResolvedWorkspaceSymbolClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + SymbolKind ResolvedClientSymbolKindOptions `json:"symbolKind,omitzero"` + TagSupport ResolvedClientSymbolTagOptions `json:"tagSupport,omitzero"` + ResolveSupport ResolvedClientSymbolResolveOptions `json:"resolveSupport,omitzero"` +} + +func resolveWorkspaceSymbolClientCapabilities(v *WorkspaceSymbolClientCapabilities) ResolvedWorkspaceSymbolClientCapabilities { + if v == nil { + return ResolvedWorkspaceSymbolClientCapabilities{} + } + return ResolvedWorkspaceSymbolClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + SymbolKind: resolveClientSymbolKindOptions(v.SymbolKind), + TagSupport: resolveClientSymbolTagOptions(v.TagSupport), + ResolveSupport: resolveClientSymbolResolveOptions(v.ResolveSupport), + } +} + +type ResolvedExecuteCommandClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveExecuteCommandClientCapabilities(v *ExecuteCommandClientCapabilities) ResolvedExecuteCommandClientCapabilities { + if v == nil { + return ResolvedExecuteCommandClientCapabilities{} + } + return ResolvedExecuteCommandClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedSemanticTokensWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveSemanticTokensWorkspaceClientCapabilities(v *SemanticTokensWorkspaceClientCapabilities) ResolvedSemanticTokensWorkspaceClientCapabilities { + if v == nil { + return ResolvedSemanticTokensWorkspaceClientCapabilities{} + } + return ResolvedSemanticTokensWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedCodeLensWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveCodeLensWorkspaceClientCapabilities(v *CodeLensWorkspaceClientCapabilities) ResolvedCodeLensWorkspaceClientCapabilities { + if v == nil { + return ResolvedCodeLensWorkspaceClientCapabilities{} + } + return ResolvedCodeLensWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedFileOperationClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + DidCreate bool `json:"didCreate,omitzero"` + WillCreate bool `json:"willCreate,omitzero"` + DidRename bool `json:"didRename,omitzero"` + WillRename bool `json:"willRename,omitzero"` + DidDelete bool `json:"didDelete,omitzero"` + WillDelete bool `json:"willDelete,omitzero"` +} + +func resolveFileOperationClientCapabilities(v *FileOperationClientCapabilities) ResolvedFileOperationClientCapabilities { + if v == nil { + return ResolvedFileOperationClientCapabilities{} + } + return ResolvedFileOperationClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + DidCreate: derefOr(v.DidCreate), + WillCreate: derefOr(v.WillCreate), + DidRename: derefOr(v.DidRename), + WillRename: derefOr(v.WillRename), + DidDelete: derefOr(v.DidDelete), + WillDelete: derefOr(v.WillDelete), + } +} + +type ResolvedInlineValueWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveInlineValueWorkspaceClientCapabilities(v *InlineValueWorkspaceClientCapabilities) ResolvedInlineValueWorkspaceClientCapabilities { + if v == nil { + return ResolvedInlineValueWorkspaceClientCapabilities{} + } + return ResolvedInlineValueWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedInlayHintWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveInlayHintWorkspaceClientCapabilities(v *InlayHintWorkspaceClientCapabilities) ResolvedInlayHintWorkspaceClientCapabilities { + if v == nil { + return ResolvedInlayHintWorkspaceClientCapabilities{} + } + return ResolvedInlayHintWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedDiagnosticWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveDiagnosticWorkspaceClientCapabilities(v *DiagnosticWorkspaceClientCapabilities) ResolvedDiagnosticWorkspaceClientCapabilities { + if v == nil { + return ResolvedDiagnosticWorkspaceClientCapabilities{} + } + return ResolvedDiagnosticWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedFoldingRangeWorkspaceClientCapabilities struct { + RefreshSupport bool `json:"refreshSupport,omitzero"` +} + +func resolveFoldingRangeWorkspaceClientCapabilities(v *FoldingRangeWorkspaceClientCapabilities) ResolvedFoldingRangeWorkspaceClientCapabilities { + if v == nil { + return ResolvedFoldingRangeWorkspaceClientCapabilities{} + } + return ResolvedFoldingRangeWorkspaceClientCapabilities{ + RefreshSupport: derefOr(v.RefreshSupport), + } +} + +type ResolvedTextDocumentContentClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveTextDocumentContentClientCapabilities(v *TextDocumentContentClientCapabilities) ResolvedTextDocumentContentClientCapabilities { + if v == nil { + return ResolvedTextDocumentContentClientCapabilities{} + } + return ResolvedTextDocumentContentClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedWorkspaceClientCapabilities struct { + ApplyEdit bool `json:"applyEdit,omitzero"` + WorkspaceEdit ResolvedWorkspaceEditClientCapabilities `json:"workspaceEdit,omitzero"` + DidChangeConfiguration ResolvedDidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitzero"` + DidChangeWatchedFiles ResolvedDidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitzero"` + Symbol ResolvedWorkspaceSymbolClientCapabilities `json:"symbol,omitzero"` + ExecuteCommand ResolvedExecuteCommandClientCapabilities `json:"executeCommand,omitzero"` + WorkspaceFolders bool `json:"workspaceFolders,omitzero"` + Configuration bool `json:"configuration,omitzero"` + SemanticTokens ResolvedSemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitzero"` + CodeLens ResolvedCodeLensWorkspaceClientCapabilities `json:"codeLens,omitzero"` + FileOperations ResolvedFileOperationClientCapabilities `json:"fileOperations,omitzero"` + InlineValue ResolvedInlineValueWorkspaceClientCapabilities `json:"inlineValue,omitzero"` + InlayHint ResolvedInlayHintWorkspaceClientCapabilities `json:"inlayHint,omitzero"` + Diagnostics ResolvedDiagnosticWorkspaceClientCapabilities `json:"diagnostics,omitzero"` + FoldingRange ResolvedFoldingRangeWorkspaceClientCapabilities `json:"foldingRange,omitzero"` + TextDocumentContent ResolvedTextDocumentContentClientCapabilities `json:"textDocumentContent,omitzero"` +} + +func resolveWorkspaceClientCapabilities(v *WorkspaceClientCapabilities) ResolvedWorkspaceClientCapabilities { + if v == nil { + return ResolvedWorkspaceClientCapabilities{} + } + return ResolvedWorkspaceClientCapabilities{ + ApplyEdit: derefOr(v.ApplyEdit), + WorkspaceEdit: resolveWorkspaceEditClientCapabilities(v.WorkspaceEdit), + DidChangeConfiguration: resolveDidChangeConfigurationClientCapabilities(v.DidChangeConfiguration), + DidChangeWatchedFiles: resolveDidChangeWatchedFilesClientCapabilities(v.DidChangeWatchedFiles), + Symbol: resolveWorkspaceSymbolClientCapabilities(v.Symbol), + ExecuteCommand: resolveExecuteCommandClientCapabilities(v.ExecuteCommand), + WorkspaceFolders: derefOr(v.WorkspaceFolders), + Configuration: derefOr(v.Configuration), + SemanticTokens: resolveSemanticTokensWorkspaceClientCapabilities(v.SemanticTokens), + CodeLens: resolveCodeLensWorkspaceClientCapabilities(v.CodeLens), + FileOperations: resolveFileOperationClientCapabilities(v.FileOperations), + InlineValue: resolveInlineValueWorkspaceClientCapabilities(v.InlineValue), + InlayHint: resolveInlayHintWorkspaceClientCapabilities(v.InlayHint), + Diagnostics: resolveDiagnosticWorkspaceClientCapabilities(v.Diagnostics), + FoldingRange: resolveFoldingRangeWorkspaceClientCapabilities(v.FoldingRange), + TextDocumentContent: resolveTextDocumentContentClientCapabilities(v.TextDocumentContent), + } +} + +type ResolvedTextDocumentSyncClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + WillSave bool `json:"willSave,omitzero"` + WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitzero"` + DidSave bool `json:"didSave,omitzero"` +} + +func resolveTextDocumentSyncClientCapabilities(v *TextDocumentSyncClientCapabilities) ResolvedTextDocumentSyncClientCapabilities { + if v == nil { + return ResolvedTextDocumentSyncClientCapabilities{} + } + return ResolvedTextDocumentSyncClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + WillSave: derefOr(v.WillSave), + WillSaveWaitUntil: derefOr(v.WillSaveWaitUntil), + DidSave: derefOr(v.DidSave), + } +} + +type ResolvedTextDocumentFilterClientCapabilities struct { + RelativePatternSupport bool `json:"relativePatternSupport,omitzero"` +} + +func resolveTextDocumentFilterClientCapabilities(v *TextDocumentFilterClientCapabilities) ResolvedTextDocumentFilterClientCapabilities { + if v == nil { + return ResolvedTextDocumentFilterClientCapabilities{} + } + return ResolvedTextDocumentFilterClientCapabilities{ + RelativePatternSupport: derefOr(v.RelativePatternSupport), + } +} + +type ResolvedCompletionItemTagOptions struct { + ValueSet []CompletionItemTag `json:"valueSet,omitzero"` +} + +func resolveCompletionItemTagOptions(v *CompletionItemTagOptions) ResolvedCompletionItemTagOptions { + if v == nil { + return ResolvedCompletionItemTagOptions{} + } + return ResolvedCompletionItemTagOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedClientCompletionItemResolveOptions struct { + Properties []string `json:"properties,omitzero"` +} + +func resolveClientCompletionItemResolveOptions(v *ClientCompletionItemResolveOptions) ResolvedClientCompletionItemResolveOptions { + if v == nil { + return ResolvedClientCompletionItemResolveOptions{} + } + return ResolvedClientCompletionItemResolveOptions{ + Properties: v.Properties, + } +} + +type ResolvedClientCompletionItemInsertTextModeOptions struct { + ValueSet []InsertTextMode `json:"valueSet,omitzero"` +} + +func resolveClientCompletionItemInsertTextModeOptions(v *ClientCompletionItemInsertTextModeOptions) ResolvedClientCompletionItemInsertTextModeOptions { + if v == nil { + return ResolvedClientCompletionItemInsertTextModeOptions{} + } + return ResolvedClientCompletionItemInsertTextModeOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedClientCompletionItemOptions struct { + SnippetSupport bool `json:"snippetSupport,omitzero"` + CommitCharactersSupport bool `json:"commitCharactersSupport,omitzero"` + DocumentationFormat []MarkupKind `json:"documentationFormat,omitzero"` + DeprecatedSupport bool `json:"deprecatedSupport,omitzero"` + PreselectSupport bool `json:"preselectSupport,omitzero"` + TagSupport ResolvedCompletionItemTagOptions `json:"tagSupport,omitzero"` + InsertReplaceSupport bool `json:"insertReplaceSupport,omitzero"` + ResolveSupport ResolvedClientCompletionItemResolveOptions `json:"resolveSupport,omitzero"` + InsertTextModeSupport ResolvedClientCompletionItemInsertTextModeOptions `json:"insertTextModeSupport,omitzero"` + LabelDetailsSupport bool `json:"labelDetailsSupport,omitzero"` +} + +func resolveClientCompletionItemOptions(v *ClientCompletionItemOptions) ResolvedClientCompletionItemOptions { + if v == nil { + return ResolvedClientCompletionItemOptions{} + } + return ResolvedClientCompletionItemOptions{ + SnippetSupport: derefOr(v.SnippetSupport), + CommitCharactersSupport: derefOr(v.CommitCharactersSupport), + DocumentationFormat: derefOr(v.DocumentationFormat), + DeprecatedSupport: derefOr(v.DeprecatedSupport), + PreselectSupport: derefOr(v.PreselectSupport), + TagSupport: resolveCompletionItemTagOptions(v.TagSupport), + InsertReplaceSupport: derefOr(v.InsertReplaceSupport), + ResolveSupport: resolveClientCompletionItemResolveOptions(v.ResolveSupport), + InsertTextModeSupport: resolveClientCompletionItemInsertTextModeOptions(v.InsertTextModeSupport), + LabelDetailsSupport: derefOr(v.LabelDetailsSupport), + } +} + +type ResolvedClientCompletionItemOptionsKind struct { + ValueSet []CompletionItemKind `json:"valueSet,omitzero"` +} + +func resolveClientCompletionItemOptionsKind(v *ClientCompletionItemOptionsKind) ResolvedClientCompletionItemOptionsKind { + if v == nil { + return ResolvedClientCompletionItemOptionsKind{} + } + return ResolvedClientCompletionItemOptionsKind{ + ValueSet: derefOr(v.ValueSet), + } +} + +type ResolvedCompletionListCapabilities struct { + ItemDefaults []string `json:"itemDefaults,omitzero"` + ApplyKindSupport bool `json:"applyKindSupport,omitzero"` +} + +func resolveCompletionListCapabilities(v *CompletionListCapabilities) ResolvedCompletionListCapabilities { + if v == nil { + return ResolvedCompletionListCapabilities{} + } + return ResolvedCompletionListCapabilities{ + ItemDefaults: derefOr(v.ItemDefaults), + ApplyKindSupport: derefOr(v.ApplyKindSupport), + } +} + +type ResolvedCompletionClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + CompletionItem ResolvedClientCompletionItemOptions `json:"completionItem,omitzero"` + CompletionItemKind ResolvedClientCompletionItemOptionsKind `json:"completionItemKind,omitzero"` + InsertTextMode InsertTextMode `json:"insertTextMode,omitzero"` + ContextSupport bool `json:"contextSupport,omitzero"` + CompletionList ResolvedCompletionListCapabilities `json:"completionList,omitzero"` +} + +func resolveCompletionClientCapabilities(v *CompletionClientCapabilities) ResolvedCompletionClientCapabilities { + if v == nil { + return ResolvedCompletionClientCapabilities{} + } + return ResolvedCompletionClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + CompletionItem: resolveClientCompletionItemOptions(v.CompletionItem), + CompletionItemKind: resolveClientCompletionItemOptionsKind(v.CompletionItemKind), + InsertTextMode: derefOr(v.InsertTextMode), + ContextSupport: derefOr(v.ContextSupport), + CompletionList: resolveCompletionListCapabilities(v.CompletionList), + } +} + +type ResolvedHoverClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + ContentFormat []MarkupKind `json:"contentFormat,omitzero"` +} + +func resolveHoverClientCapabilities(v *HoverClientCapabilities) ResolvedHoverClientCapabilities { + if v == nil { + return ResolvedHoverClientCapabilities{} + } + return ResolvedHoverClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + ContentFormat: derefOr(v.ContentFormat), + } +} + +type ResolvedClientSignatureParameterInformationOptions struct { + LabelOffsetSupport bool `json:"labelOffsetSupport,omitzero"` +} + +func resolveClientSignatureParameterInformationOptions(v *ClientSignatureParameterInformationOptions) ResolvedClientSignatureParameterInformationOptions { + if v == nil { + return ResolvedClientSignatureParameterInformationOptions{} + } + return ResolvedClientSignatureParameterInformationOptions{ + LabelOffsetSupport: derefOr(v.LabelOffsetSupport), + } +} + +type ResolvedClientSignatureInformationOptions struct { + DocumentationFormat []MarkupKind `json:"documentationFormat,omitzero"` + ParameterInformation ResolvedClientSignatureParameterInformationOptions `json:"parameterInformation,omitzero"` + ActiveParameterSupport bool `json:"activeParameterSupport,omitzero"` + NoActiveParameterSupport bool `json:"noActiveParameterSupport,omitzero"` +} + +func resolveClientSignatureInformationOptions(v *ClientSignatureInformationOptions) ResolvedClientSignatureInformationOptions { + if v == nil { + return ResolvedClientSignatureInformationOptions{} + } + return ResolvedClientSignatureInformationOptions{ + DocumentationFormat: derefOr(v.DocumentationFormat), + ParameterInformation: resolveClientSignatureParameterInformationOptions(v.ParameterInformation), + ActiveParameterSupport: derefOr(v.ActiveParameterSupport), + NoActiveParameterSupport: derefOr(v.NoActiveParameterSupport), + } +} + +type ResolvedSignatureHelpClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + SignatureInformation ResolvedClientSignatureInformationOptions `json:"signatureInformation,omitzero"` + ContextSupport bool `json:"contextSupport,omitzero"` +} + +func resolveSignatureHelpClientCapabilities(v *SignatureHelpClientCapabilities) ResolvedSignatureHelpClientCapabilities { + if v == nil { + return ResolvedSignatureHelpClientCapabilities{} + } + return ResolvedSignatureHelpClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + SignatureInformation: resolveClientSignatureInformationOptions(v.SignatureInformation), + ContextSupport: derefOr(v.ContextSupport), + } +} + +type ResolvedDeclarationClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + LinkSupport bool `json:"linkSupport,omitzero"` +} + +func resolveDeclarationClientCapabilities(v *DeclarationClientCapabilities) ResolvedDeclarationClientCapabilities { + if v == nil { + return ResolvedDeclarationClientCapabilities{} + } + return ResolvedDeclarationClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + LinkSupport: derefOr(v.LinkSupport), + } +} + +type ResolvedDefinitionClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + LinkSupport bool `json:"linkSupport,omitzero"` +} + +func resolveDefinitionClientCapabilities(v *DefinitionClientCapabilities) ResolvedDefinitionClientCapabilities { + if v == nil { + return ResolvedDefinitionClientCapabilities{} + } + return ResolvedDefinitionClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + LinkSupport: derefOr(v.LinkSupport), + } +} + +type ResolvedTypeDefinitionClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + LinkSupport bool `json:"linkSupport,omitzero"` +} + +func resolveTypeDefinitionClientCapabilities(v *TypeDefinitionClientCapabilities) ResolvedTypeDefinitionClientCapabilities { + if v == nil { + return ResolvedTypeDefinitionClientCapabilities{} + } + return ResolvedTypeDefinitionClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + LinkSupport: derefOr(v.LinkSupport), + } +} + +type ResolvedImplementationClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + LinkSupport bool `json:"linkSupport,omitzero"` +} + +func resolveImplementationClientCapabilities(v *ImplementationClientCapabilities) ResolvedImplementationClientCapabilities { + if v == nil { + return ResolvedImplementationClientCapabilities{} + } + return ResolvedImplementationClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + LinkSupport: derefOr(v.LinkSupport), + } +} + +type ResolvedReferenceClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveReferenceClientCapabilities(v *ReferenceClientCapabilities) ResolvedReferenceClientCapabilities { + if v == nil { + return ResolvedReferenceClientCapabilities{} + } + return ResolvedReferenceClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedDocumentHighlightClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveDocumentHighlightClientCapabilities(v *DocumentHighlightClientCapabilities) ResolvedDocumentHighlightClientCapabilities { + if v == nil { + return ResolvedDocumentHighlightClientCapabilities{} + } + return ResolvedDocumentHighlightClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedDocumentSymbolClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + SymbolKind ResolvedClientSymbolKindOptions `json:"symbolKind,omitzero"` + HierarchicalDocumentSymbolSupport bool `json:"hierarchicalDocumentSymbolSupport,omitzero"` + TagSupport ResolvedClientSymbolTagOptions `json:"tagSupport,omitzero"` + LabelSupport bool `json:"labelSupport,omitzero"` +} + +func resolveDocumentSymbolClientCapabilities(v *DocumentSymbolClientCapabilities) ResolvedDocumentSymbolClientCapabilities { + if v == nil { + return ResolvedDocumentSymbolClientCapabilities{} + } + return ResolvedDocumentSymbolClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + SymbolKind: resolveClientSymbolKindOptions(v.SymbolKind), + HierarchicalDocumentSymbolSupport: derefOr(v.HierarchicalDocumentSymbolSupport), + TagSupport: resolveClientSymbolTagOptions(v.TagSupport), + LabelSupport: derefOr(v.LabelSupport), + } +} + +type ResolvedClientCodeActionKindOptions struct { + ValueSet []CodeActionKind `json:"valueSet,omitzero"` +} + +func resolveClientCodeActionKindOptions(v *ClientCodeActionKindOptions) ResolvedClientCodeActionKindOptions { + if v == nil { + return ResolvedClientCodeActionKindOptions{} + } + return ResolvedClientCodeActionKindOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedClientCodeActionLiteralOptions struct { + CodeActionKind ResolvedClientCodeActionKindOptions `json:"codeActionKind,omitzero"` +} + +func resolveClientCodeActionLiteralOptions(v *ClientCodeActionLiteralOptions) ResolvedClientCodeActionLiteralOptions { + if v == nil { + return ResolvedClientCodeActionLiteralOptions{} + } + return ResolvedClientCodeActionLiteralOptions{ + CodeActionKind: resolveClientCodeActionKindOptions(v.CodeActionKind), + } +} + +type ResolvedClientCodeActionResolveOptions struct { + Properties []string `json:"properties,omitzero"` +} + +func resolveClientCodeActionResolveOptions(v *ClientCodeActionResolveOptions) ResolvedClientCodeActionResolveOptions { + if v == nil { + return ResolvedClientCodeActionResolveOptions{} + } + return ResolvedClientCodeActionResolveOptions{ + Properties: v.Properties, + } +} + +type ResolvedCodeActionTagOptions struct { + ValueSet []CodeActionTag `json:"valueSet,omitzero"` +} + +func resolveCodeActionTagOptions(v *CodeActionTagOptions) ResolvedCodeActionTagOptions { + if v == nil { + return ResolvedCodeActionTagOptions{} + } + return ResolvedCodeActionTagOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedCodeActionClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + CodeActionLiteralSupport ResolvedClientCodeActionLiteralOptions `json:"codeActionLiteralSupport,omitzero"` + IsPreferredSupport bool `json:"isPreferredSupport,omitzero"` + DisabledSupport bool `json:"disabledSupport,omitzero"` + DataSupport bool `json:"dataSupport,omitzero"` + ResolveSupport ResolvedClientCodeActionResolveOptions `json:"resolveSupport,omitzero"` + HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitzero"` + DocumentationSupport bool `json:"documentationSupport,omitzero"` + TagSupport ResolvedCodeActionTagOptions `json:"tagSupport,omitzero"` +} + +func resolveCodeActionClientCapabilities(v *CodeActionClientCapabilities) ResolvedCodeActionClientCapabilities { + if v == nil { + return ResolvedCodeActionClientCapabilities{} + } + return ResolvedCodeActionClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + CodeActionLiteralSupport: resolveClientCodeActionLiteralOptions(v.CodeActionLiteralSupport), + IsPreferredSupport: derefOr(v.IsPreferredSupport), + DisabledSupport: derefOr(v.DisabledSupport), + DataSupport: derefOr(v.DataSupport), + ResolveSupport: resolveClientCodeActionResolveOptions(v.ResolveSupport), + HonorsChangeAnnotations: derefOr(v.HonorsChangeAnnotations), + DocumentationSupport: derefOr(v.DocumentationSupport), + TagSupport: resolveCodeActionTagOptions(v.TagSupport), + } +} + +type ResolvedClientCodeLensResolveOptions struct { + Properties []string `json:"properties,omitzero"` +} + +func resolveClientCodeLensResolveOptions(v *ClientCodeLensResolveOptions) ResolvedClientCodeLensResolveOptions { + if v == nil { + return ResolvedClientCodeLensResolveOptions{} + } + return ResolvedClientCodeLensResolveOptions{ + Properties: v.Properties, + } +} + +type ResolvedCodeLensClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + ResolveSupport ResolvedClientCodeLensResolveOptions `json:"resolveSupport,omitzero"` +} + +func resolveCodeLensClientCapabilities(v *CodeLensClientCapabilities) ResolvedCodeLensClientCapabilities { + if v == nil { + return ResolvedCodeLensClientCapabilities{} + } + return ResolvedCodeLensClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + ResolveSupport: resolveClientCodeLensResolveOptions(v.ResolveSupport), + } +} + +type ResolvedDocumentLinkClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + TooltipSupport bool `json:"tooltipSupport,omitzero"` +} + +func resolveDocumentLinkClientCapabilities(v *DocumentLinkClientCapabilities) ResolvedDocumentLinkClientCapabilities { + if v == nil { + return ResolvedDocumentLinkClientCapabilities{} + } + return ResolvedDocumentLinkClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + TooltipSupport: derefOr(v.TooltipSupport), + } +} + +type ResolvedDocumentColorClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveDocumentColorClientCapabilities(v *DocumentColorClientCapabilities) ResolvedDocumentColorClientCapabilities { + if v == nil { + return ResolvedDocumentColorClientCapabilities{} + } + return ResolvedDocumentColorClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedDocumentFormattingClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveDocumentFormattingClientCapabilities(v *DocumentFormattingClientCapabilities) ResolvedDocumentFormattingClientCapabilities { + if v == nil { + return ResolvedDocumentFormattingClientCapabilities{} + } + return ResolvedDocumentFormattingClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedDocumentRangeFormattingClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + RangesSupport bool `json:"rangesSupport,omitzero"` +} + +func resolveDocumentRangeFormattingClientCapabilities(v *DocumentRangeFormattingClientCapabilities) ResolvedDocumentRangeFormattingClientCapabilities { + if v == nil { + return ResolvedDocumentRangeFormattingClientCapabilities{} + } + return ResolvedDocumentRangeFormattingClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + RangesSupport: derefOr(v.RangesSupport), + } +} + +type ResolvedDocumentOnTypeFormattingClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveDocumentOnTypeFormattingClientCapabilities(v *DocumentOnTypeFormattingClientCapabilities) ResolvedDocumentOnTypeFormattingClientCapabilities { + if v == nil { + return ResolvedDocumentOnTypeFormattingClientCapabilities{} + } + return ResolvedDocumentOnTypeFormattingClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedRenameClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + PrepareSupport bool `json:"prepareSupport,omitzero"` + PrepareSupportDefaultBehavior PrepareSupportDefaultBehavior `json:"prepareSupportDefaultBehavior,omitzero"` + HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitzero"` +} + +func resolveRenameClientCapabilities(v *RenameClientCapabilities) ResolvedRenameClientCapabilities { + if v == nil { + return ResolvedRenameClientCapabilities{} + } + return ResolvedRenameClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + PrepareSupport: derefOr(v.PrepareSupport), + PrepareSupportDefaultBehavior: derefOr(v.PrepareSupportDefaultBehavior), + HonorsChangeAnnotations: derefOr(v.HonorsChangeAnnotations), + } +} + +type ResolvedClientFoldingRangeKindOptions struct { + ValueSet []FoldingRangeKind `json:"valueSet,omitzero"` +} + +func resolveClientFoldingRangeKindOptions(v *ClientFoldingRangeKindOptions) ResolvedClientFoldingRangeKindOptions { + if v == nil { + return ResolvedClientFoldingRangeKindOptions{} + } + return ResolvedClientFoldingRangeKindOptions{ + ValueSet: derefOr(v.ValueSet), + } +} + +type ResolvedClientFoldingRangeOptions struct { + CollapsedText bool `json:"collapsedText,omitzero"` +} + +func resolveClientFoldingRangeOptions(v *ClientFoldingRangeOptions) ResolvedClientFoldingRangeOptions { + if v == nil { + return ResolvedClientFoldingRangeOptions{} + } + return ResolvedClientFoldingRangeOptions{ + CollapsedText: derefOr(v.CollapsedText), + } +} + +type ResolvedFoldingRangeClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + RangeLimit uint32 `json:"rangeLimit,omitzero"` + LineFoldingOnly bool `json:"lineFoldingOnly,omitzero"` + FoldingRangeKind ResolvedClientFoldingRangeKindOptions `json:"foldingRangeKind,omitzero"` + FoldingRange ResolvedClientFoldingRangeOptions `json:"foldingRange,omitzero"` +} + +func resolveFoldingRangeClientCapabilities(v *FoldingRangeClientCapabilities) ResolvedFoldingRangeClientCapabilities { + if v == nil { + return ResolvedFoldingRangeClientCapabilities{} + } + return ResolvedFoldingRangeClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + RangeLimit: derefOr(v.RangeLimit), + LineFoldingOnly: derefOr(v.LineFoldingOnly), + FoldingRangeKind: resolveClientFoldingRangeKindOptions(v.FoldingRangeKind), + FoldingRange: resolveClientFoldingRangeOptions(v.FoldingRange), + } +} + +type ResolvedSelectionRangeClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveSelectionRangeClientCapabilities(v *SelectionRangeClientCapabilities) ResolvedSelectionRangeClientCapabilities { + if v == nil { + return ResolvedSelectionRangeClientCapabilities{} + } + return ResolvedSelectionRangeClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedClientDiagnosticsTagOptions struct { + ValueSet []DiagnosticTag `json:"valueSet,omitzero"` +} + +func resolveClientDiagnosticsTagOptions(v *ClientDiagnosticsTagOptions) ResolvedClientDiagnosticsTagOptions { + if v == nil { + return ResolvedClientDiagnosticsTagOptions{} + } + return ResolvedClientDiagnosticsTagOptions{ + ValueSet: v.ValueSet, + } +} + +type ResolvedPublishDiagnosticsClientCapabilities struct { + RelatedInformation bool `json:"relatedInformation,omitzero"` + TagSupport ResolvedClientDiagnosticsTagOptions `json:"tagSupport,omitzero"` + CodeDescriptionSupport bool `json:"codeDescriptionSupport,omitzero"` + DataSupport bool `json:"dataSupport,omitzero"` + VersionSupport bool `json:"versionSupport,omitzero"` +} + +func resolvePublishDiagnosticsClientCapabilities(v *PublishDiagnosticsClientCapabilities) ResolvedPublishDiagnosticsClientCapabilities { + if v == nil { + return ResolvedPublishDiagnosticsClientCapabilities{} + } + return ResolvedPublishDiagnosticsClientCapabilities{ + RelatedInformation: derefOr(v.RelatedInformation), + TagSupport: resolveClientDiagnosticsTagOptions(v.TagSupport), + CodeDescriptionSupport: derefOr(v.CodeDescriptionSupport), + DataSupport: derefOr(v.DataSupport), + VersionSupport: derefOr(v.VersionSupport), + } +} + +type ResolvedCallHierarchyClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveCallHierarchyClientCapabilities(v *CallHierarchyClientCapabilities) ResolvedCallHierarchyClientCapabilities { + if v == nil { + return ResolvedCallHierarchyClientCapabilities{} + } + return ResolvedCallHierarchyClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedClientSemanticTokensRequestOptions struct { + Range BooleanOrEmptyObject `json:"range,omitzero"` + Full BooleanOrClientSemanticTokensRequestFullDelta `json:"full,omitzero"` +} + +func resolveClientSemanticTokensRequestOptions(v *ClientSemanticTokensRequestOptions) ResolvedClientSemanticTokensRequestOptions { + if v == nil { + return ResolvedClientSemanticTokensRequestOptions{} + } + return ResolvedClientSemanticTokensRequestOptions{ + Range: derefOr(v.Range), + Full: derefOr(v.Full), + } +} + +type ResolvedSemanticTokensClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + Requests ResolvedClientSemanticTokensRequestOptions `json:"requests,omitzero"` + TokenTypes []string `json:"tokenTypes,omitzero"` + TokenModifiers []string `json:"tokenModifiers,omitzero"` + Formats []TokenFormat `json:"formats,omitzero"` + OverlappingTokenSupport bool `json:"overlappingTokenSupport,omitzero"` + MultilineTokenSupport bool `json:"multilineTokenSupport,omitzero"` + ServerCancelSupport bool `json:"serverCancelSupport,omitzero"` + AugmentsSyntaxTokens bool `json:"augmentsSyntaxTokens,omitzero"` +} + +func resolveSemanticTokensClientCapabilities(v *SemanticTokensClientCapabilities) ResolvedSemanticTokensClientCapabilities { + if v == nil { + return ResolvedSemanticTokensClientCapabilities{} + } + return ResolvedSemanticTokensClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + Requests: resolveClientSemanticTokensRequestOptions(v.Requests), + TokenTypes: v.TokenTypes, + TokenModifiers: v.TokenModifiers, + Formats: v.Formats, + OverlappingTokenSupport: derefOr(v.OverlappingTokenSupport), + MultilineTokenSupport: derefOr(v.MultilineTokenSupport), + ServerCancelSupport: derefOr(v.ServerCancelSupport), + AugmentsSyntaxTokens: derefOr(v.AugmentsSyntaxTokens), + } +} + +type ResolvedLinkedEditingRangeClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveLinkedEditingRangeClientCapabilities(v *LinkedEditingRangeClientCapabilities) ResolvedLinkedEditingRangeClientCapabilities { + if v == nil { + return ResolvedLinkedEditingRangeClientCapabilities{} + } + return ResolvedLinkedEditingRangeClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedMonikerClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveMonikerClientCapabilities(v *MonikerClientCapabilities) ResolvedMonikerClientCapabilities { + if v == nil { + return ResolvedMonikerClientCapabilities{} + } + return ResolvedMonikerClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedTypeHierarchyClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveTypeHierarchyClientCapabilities(v *TypeHierarchyClientCapabilities) ResolvedTypeHierarchyClientCapabilities { + if v == nil { + return ResolvedTypeHierarchyClientCapabilities{} + } + return ResolvedTypeHierarchyClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedInlineValueClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveInlineValueClientCapabilities(v *InlineValueClientCapabilities) ResolvedInlineValueClientCapabilities { + if v == nil { + return ResolvedInlineValueClientCapabilities{} + } + return ResolvedInlineValueClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedClientInlayHintResolveOptions struct { + Properties []string `json:"properties,omitzero"` +} + +func resolveClientInlayHintResolveOptions(v *ClientInlayHintResolveOptions) ResolvedClientInlayHintResolveOptions { + if v == nil { + return ResolvedClientInlayHintResolveOptions{} + } + return ResolvedClientInlayHintResolveOptions{ + Properties: v.Properties, + } +} + +type ResolvedInlayHintClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + ResolveSupport ResolvedClientInlayHintResolveOptions `json:"resolveSupport,omitzero"` +} + +func resolveInlayHintClientCapabilities(v *InlayHintClientCapabilities) ResolvedInlayHintClientCapabilities { + if v == nil { + return ResolvedInlayHintClientCapabilities{} + } + return ResolvedInlayHintClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + ResolveSupport: resolveClientInlayHintResolveOptions(v.ResolveSupport), + } +} + +type ResolvedDiagnosticClientCapabilities struct { + RelatedInformation bool `json:"relatedInformation,omitzero"` + TagSupport ResolvedClientDiagnosticsTagOptions `json:"tagSupport,omitzero"` + CodeDescriptionSupport bool `json:"codeDescriptionSupport,omitzero"` + DataSupport bool `json:"dataSupport,omitzero"` + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + RelatedDocumentSupport bool `json:"relatedDocumentSupport,omitzero"` +} + +func resolveDiagnosticClientCapabilities(v *DiagnosticClientCapabilities) ResolvedDiagnosticClientCapabilities { + if v == nil { + return ResolvedDiagnosticClientCapabilities{} + } + return ResolvedDiagnosticClientCapabilities{ + RelatedInformation: derefOr(v.RelatedInformation), + TagSupport: resolveClientDiagnosticsTagOptions(v.TagSupport), + CodeDescriptionSupport: derefOr(v.CodeDescriptionSupport), + DataSupport: derefOr(v.DataSupport), + DynamicRegistration: derefOr(v.DynamicRegistration), + RelatedDocumentSupport: derefOr(v.RelatedDocumentSupport), + } +} + +type ResolvedInlineCompletionClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` +} + +func resolveInlineCompletionClientCapabilities(v *InlineCompletionClientCapabilities) ResolvedInlineCompletionClientCapabilities { + if v == nil { + return ResolvedInlineCompletionClientCapabilities{} + } + return ResolvedInlineCompletionClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + } +} + +type ResolvedTextDocumentClientCapabilities struct { + Synchronization ResolvedTextDocumentSyncClientCapabilities `json:"synchronization,omitzero"` + Filters ResolvedTextDocumentFilterClientCapabilities `json:"filters,omitzero"` + Completion ResolvedCompletionClientCapabilities `json:"completion,omitzero"` + Hover ResolvedHoverClientCapabilities `json:"hover,omitzero"` + SignatureHelp ResolvedSignatureHelpClientCapabilities `json:"signatureHelp,omitzero"` + Declaration ResolvedDeclarationClientCapabilities `json:"declaration,omitzero"` + Definition ResolvedDefinitionClientCapabilities `json:"definition,omitzero"` + TypeDefinition ResolvedTypeDefinitionClientCapabilities `json:"typeDefinition,omitzero"` + Implementation ResolvedImplementationClientCapabilities `json:"implementation,omitzero"` + References ResolvedReferenceClientCapabilities `json:"references,omitzero"` + DocumentHighlight ResolvedDocumentHighlightClientCapabilities `json:"documentHighlight,omitzero"` + DocumentSymbol ResolvedDocumentSymbolClientCapabilities `json:"documentSymbol,omitzero"` + CodeAction ResolvedCodeActionClientCapabilities `json:"codeAction,omitzero"` + CodeLens ResolvedCodeLensClientCapabilities `json:"codeLens,omitzero"` + DocumentLink ResolvedDocumentLinkClientCapabilities `json:"documentLink,omitzero"` + ColorProvider ResolvedDocumentColorClientCapabilities `json:"colorProvider,omitzero"` + Formatting ResolvedDocumentFormattingClientCapabilities `json:"formatting,omitzero"` + RangeFormatting ResolvedDocumentRangeFormattingClientCapabilities `json:"rangeFormatting,omitzero"` + OnTypeFormatting ResolvedDocumentOnTypeFormattingClientCapabilities `json:"onTypeFormatting,omitzero"` + Rename ResolvedRenameClientCapabilities `json:"rename,omitzero"` + FoldingRange ResolvedFoldingRangeClientCapabilities `json:"foldingRange,omitzero"` + SelectionRange ResolvedSelectionRangeClientCapabilities `json:"selectionRange,omitzero"` + PublishDiagnostics ResolvedPublishDiagnosticsClientCapabilities `json:"publishDiagnostics,omitzero"` + CallHierarchy ResolvedCallHierarchyClientCapabilities `json:"callHierarchy,omitzero"` + SemanticTokens ResolvedSemanticTokensClientCapabilities `json:"semanticTokens,omitzero"` + LinkedEditingRange ResolvedLinkedEditingRangeClientCapabilities `json:"linkedEditingRange,omitzero"` + Moniker ResolvedMonikerClientCapabilities `json:"moniker,omitzero"` + TypeHierarchy ResolvedTypeHierarchyClientCapabilities `json:"typeHierarchy,omitzero"` + InlineValue ResolvedInlineValueClientCapabilities `json:"inlineValue,omitzero"` + InlayHint ResolvedInlayHintClientCapabilities `json:"inlayHint,omitzero"` + Diagnostic ResolvedDiagnosticClientCapabilities `json:"diagnostic,omitzero"` + InlineCompletion ResolvedInlineCompletionClientCapabilities `json:"inlineCompletion,omitzero"` +} + +func resolveTextDocumentClientCapabilities(v *TextDocumentClientCapabilities) ResolvedTextDocumentClientCapabilities { + if v == nil { + return ResolvedTextDocumentClientCapabilities{} + } + return ResolvedTextDocumentClientCapabilities{ + Synchronization: resolveTextDocumentSyncClientCapabilities(v.Synchronization), + Filters: resolveTextDocumentFilterClientCapabilities(v.Filters), + Completion: resolveCompletionClientCapabilities(v.Completion), + Hover: resolveHoverClientCapabilities(v.Hover), + SignatureHelp: resolveSignatureHelpClientCapabilities(v.SignatureHelp), + Declaration: resolveDeclarationClientCapabilities(v.Declaration), + Definition: resolveDefinitionClientCapabilities(v.Definition), + TypeDefinition: resolveTypeDefinitionClientCapabilities(v.TypeDefinition), + Implementation: resolveImplementationClientCapabilities(v.Implementation), + References: resolveReferenceClientCapabilities(v.References), + DocumentHighlight: resolveDocumentHighlightClientCapabilities(v.DocumentHighlight), + DocumentSymbol: resolveDocumentSymbolClientCapabilities(v.DocumentSymbol), + CodeAction: resolveCodeActionClientCapabilities(v.CodeAction), + CodeLens: resolveCodeLensClientCapabilities(v.CodeLens), + DocumentLink: resolveDocumentLinkClientCapabilities(v.DocumentLink), + ColorProvider: resolveDocumentColorClientCapabilities(v.ColorProvider), + Formatting: resolveDocumentFormattingClientCapabilities(v.Formatting), + RangeFormatting: resolveDocumentRangeFormattingClientCapabilities(v.RangeFormatting), + OnTypeFormatting: resolveDocumentOnTypeFormattingClientCapabilities(v.OnTypeFormatting), + Rename: resolveRenameClientCapabilities(v.Rename), + FoldingRange: resolveFoldingRangeClientCapabilities(v.FoldingRange), + SelectionRange: resolveSelectionRangeClientCapabilities(v.SelectionRange), + PublishDiagnostics: resolvePublishDiagnosticsClientCapabilities(v.PublishDiagnostics), + CallHierarchy: resolveCallHierarchyClientCapabilities(v.CallHierarchy), + SemanticTokens: resolveSemanticTokensClientCapabilities(v.SemanticTokens), + LinkedEditingRange: resolveLinkedEditingRangeClientCapabilities(v.LinkedEditingRange), + Moniker: resolveMonikerClientCapabilities(v.Moniker), + TypeHierarchy: resolveTypeHierarchyClientCapabilities(v.TypeHierarchy), + InlineValue: resolveInlineValueClientCapabilities(v.InlineValue), + InlayHint: resolveInlayHintClientCapabilities(v.InlayHint), + Diagnostic: resolveDiagnosticClientCapabilities(v.Diagnostic), + InlineCompletion: resolveInlineCompletionClientCapabilities(v.InlineCompletion), + } +} + +type ResolvedNotebookDocumentSyncClientCapabilities struct { + DynamicRegistration bool `json:"dynamicRegistration,omitzero"` + ExecutionSummarySupport bool `json:"executionSummarySupport,omitzero"` +} + +func resolveNotebookDocumentSyncClientCapabilities(v *NotebookDocumentSyncClientCapabilities) ResolvedNotebookDocumentSyncClientCapabilities { + if v == nil { + return ResolvedNotebookDocumentSyncClientCapabilities{} + } + return ResolvedNotebookDocumentSyncClientCapabilities{ + DynamicRegistration: derefOr(v.DynamicRegistration), + ExecutionSummarySupport: derefOr(v.ExecutionSummarySupport), + } +} + +type ResolvedNotebookDocumentClientCapabilities struct { + Synchronization ResolvedNotebookDocumentSyncClientCapabilities `json:"synchronization,omitzero"` +} + +func resolveNotebookDocumentClientCapabilities(v *NotebookDocumentClientCapabilities) ResolvedNotebookDocumentClientCapabilities { + if v == nil { + return ResolvedNotebookDocumentClientCapabilities{} + } + return ResolvedNotebookDocumentClientCapabilities{ + Synchronization: resolveNotebookDocumentSyncClientCapabilities(v.Synchronization), + } +} + +type ResolvedClientShowMessageActionItemOptions struct { + AdditionalPropertiesSupport bool `json:"additionalPropertiesSupport,omitzero"` +} + +func resolveClientShowMessageActionItemOptions(v *ClientShowMessageActionItemOptions) ResolvedClientShowMessageActionItemOptions { + if v == nil { + return ResolvedClientShowMessageActionItemOptions{} + } + return ResolvedClientShowMessageActionItemOptions{ + AdditionalPropertiesSupport: derefOr(v.AdditionalPropertiesSupport), + } +} + +type ResolvedShowMessageRequestClientCapabilities struct { + MessageActionItem ResolvedClientShowMessageActionItemOptions `json:"messageActionItem,omitzero"` +} + +func resolveShowMessageRequestClientCapabilities(v *ShowMessageRequestClientCapabilities) ResolvedShowMessageRequestClientCapabilities { + if v == nil { + return ResolvedShowMessageRequestClientCapabilities{} + } + return ResolvedShowMessageRequestClientCapabilities{ + MessageActionItem: resolveClientShowMessageActionItemOptions(v.MessageActionItem), + } +} + +type ResolvedShowDocumentClientCapabilities struct { + Support bool `json:"support,omitzero"` +} + +func resolveShowDocumentClientCapabilities(v *ShowDocumentClientCapabilities) ResolvedShowDocumentClientCapabilities { + if v == nil { + return ResolvedShowDocumentClientCapabilities{} + } + return ResolvedShowDocumentClientCapabilities{ + Support: v.Support, + } +} + +type ResolvedWindowClientCapabilities struct { + WorkDoneProgress bool `json:"workDoneProgress,omitzero"` + ShowMessage ResolvedShowMessageRequestClientCapabilities `json:"showMessage,omitzero"` + ShowDocument ResolvedShowDocumentClientCapabilities `json:"showDocument,omitzero"` +} + +func resolveWindowClientCapabilities(v *WindowClientCapabilities) ResolvedWindowClientCapabilities { + if v == nil { + return ResolvedWindowClientCapabilities{} + } + return ResolvedWindowClientCapabilities{ + WorkDoneProgress: derefOr(v.WorkDoneProgress), + ShowMessage: resolveShowMessageRequestClientCapabilities(v.ShowMessage), + ShowDocument: resolveShowDocumentClientCapabilities(v.ShowDocument), + } +} + +type ResolvedStaleRequestSupportOptions struct { + Cancel bool `json:"cancel,omitzero"` + RetryOnContentModified []string `json:"retryOnContentModified,omitzero"` +} + +func resolveStaleRequestSupportOptions(v *StaleRequestSupportOptions) ResolvedStaleRequestSupportOptions { + if v == nil { + return ResolvedStaleRequestSupportOptions{} + } + return ResolvedStaleRequestSupportOptions{ + Cancel: v.Cancel, + RetryOnContentModified: v.RetryOnContentModified, + } +} + +type ResolvedRegularExpressionsClientCapabilities struct { + Engine string `json:"engine,omitzero"` + Version string `json:"version,omitzero"` +} + +func resolveRegularExpressionsClientCapabilities(v *RegularExpressionsClientCapabilities) ResolvedRegularExpressionsClientCapabilities { + if v == nil { + return ResolvedRegularExpressionsClientCapabilities{} + } + return ResolvedRegularExpressionsClientCapabilities{ + Engine: v.Engine, + Version: derefOr(v.Version), + } +} + +type ResolvedMarkdownClientCapabilities struct { + Parser string `json:"parser,omitzero"` + Version string `json:"version,omitzero"` + AllowedTags []string `json:"allowedTags,omitzero"` +} + +func resolveMarkdownClientCapabilities(v *MarkdownClientCapabilities) ResolvedMarkdownClientCapabilities { + if v == nil { + return ResolvedMarkdownClientCapabilities{} + } + return ResolvedMarkdownClientCapabilities{ + Parser: v.Parser, + Version: derefOr(v.Version), + AllowedTags: derefOr(v.AllowedTags), + } +} + +type ResolvedGeneralClientCapabilities struct { + StaleRequestSupport ResolvedStaleRequestSupportOptions `json:"staleRequestSupport,omitzero"` + RegularExpressions ResolvedRegularExpressionsClientCapabilities `json:"regularExpressions,omitzero"` + Markdown ResolvedMarkdownClientCapabilities `json:"markdown,omitzero"` + PositionEncodings []PositionEncodingKind `json:"positionEncodings,omitzero"` +} + +func resolveGeneralClientCapabilities(v *GeneralClientCapabilities) ResolvedGeneralClientCapabilities { + if v == nil { + return ResolvedGeneralClientCapabilities{} + } + return ResolvedGeneralClientCapabilities{ + StaleRequestSupport: resolveStaleRequestSupportOptions(v.StaleRequestSupport), + RegularExpressions: resolveRegularExpressionsClientCapabilities(v.RegularExpressions), + Markdown: resolveMarkdownClientCapabilities(v.Markdown), + PositionEncodings: derefOr(v.PositionEncodings), + } +} + +// ResolvedClientCapabilities is a version of ClientCapabilities where all nested +// fields are values (not pointers), making it easier to access deeply nested capabilities. +// Use ResolveClientCapabilities to convert from ClientCapabilities. +type ResolvedClientCapabilities struct { + Workspace ResolvedWorkspaceClientCapabilities `json:"workspace,omitzero"` + TextDocument ResolvedTextDocumentClientCapabilities `json:"textDocument,omitzero"` + NotebookDocument ResolvedNotebookDocumentClientCapabilities `json:"notebookDocument,omitzero"` + Window ResolvedWindowClientCapabilities `json:"window,omitzero"` + General ResolvedGeneralClientCapabilities `json:"general,omitzero"` + Experimental any `json:"experimental,omitzero"` +} + +func ResolveClientCapabilities(v *ClientCapabilities) ResolvedClientCapabilities { + if v == nil { + return ResolvedClientCapabilities{} + } + return ResolvedClientCapabilities{ + Workspace: resolveWorkspaceClientCapabilities(v.Workspace), + TextDocument: resolveTextDocumentClientCapabilities(v.TextDocument), + NotebookDocument: resolveNotebookDocumentClientCapabilities(v.NotebookDocument), + Window: resolveWindowClientCapabilities(v.Window), + General: resolveGeneralClientCapabilities(v.General), + Experimental: derefOr(v.Experimental), + } +} diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 29037f6c74..0a65133a63 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -14,6 +14,7 @@ import ( "github.com/go-json-experiment/json" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/jsonutil" "github.com/microsoft/typescript-go/internal/ls" "github.com/microsoft/typescript-go/internal/ls/lsconv" "github.com/microsoft/typescript-go/internal/ls/lsutil" @@ -143,9 +144,10 @@ type Server struct { defaultLibraryPath string typingsLocation string - initializeParams *lsproto.InitializeParams - positionEncoding lsproto.PositionEncodingKind - locale language.Tag + initializeParams *lsproto.InitializeParams + clientCapabilities lsproto.ResolvedClientCapabilities + positionEncoding lsproto.PositionEncodingKind + locale language.Tag watchEnabled bool watcherID atomic.Uint32 @@ -206,10 +208,7 @@ func (s *Server) UnwatchFiles(ctx context.Context, id project.WatcherID) error { // RefreshDiagnostics implements project.Client. func (s *Server) RefreshDiagnostics(ctx context.Context) error { - if s.initializeParams.Capabilities == nil || - s.initializeParams.Capabilities.Workspace == nil || - s.initializeParams.Capabilities.Workspace.Diagnostics == nil || - !ptrIsTrue(s.initializeParams.Capabilities.Workspace.Diagnostics.RefreshSupport) { + if !s.clientCapabilities.Workspace.Diagnostics.RefreshSupport { return nil } @@ -221,8 +220,8 @@ func (s *Server) RefreshDiagnostics(ctx context.Context) error { } func (s *Server) RequestConfiguration(ctx context.Context) (*lsutil.UserPreferences, error) { - if s.initializeParams.Capabilities == nil || s.initializeParams.Capabilities.Workspace == nil || - !ptrIsTrue(s.initializeParams.Capabilities.Workspace.Configuration) { + caps := lsproto.GetClientCapabilities(ctx) + if !caps.Workspace.Configuration { // if no configuration request capapbility, return default preferences return s.session.NewUserPreferences(), nil } @@ -447,6 +446,8 @@ func (s *Server) sendResponse(resp *lsproto.ResponseMessage) { } func (s *Server) handleRequestOrNotification(ctx context.Context, req *lsproto.RequestMessage) error { + ctx = lsproto.WithClientCapabilities(ctx, &s.clientCapabilities) + if handler := handlers()[req.Method]; handler != nil { return handler(s, ctx, req) } @@ -585,12 +586,18 @@ func (s *Server) handleInitialize(ctx context.Context, params *lsproto.Initializ } s.initializeParams = params + s.clientCapabilities = resolveClientCapabilities(params.Capabilities) + + if _, err := fmt.Fprint(s.stderr, "Resolved client capabilities: "); err != nil { + return nil, err + } + if err := jsonutil.MarshalIndentWrite(s.stderr, &s.clientCapabilities, "", "\t"); err != nil { + return nil, err + } s.positionEncoding = lsproto.PositionEncodingKindUTF16 - if genCapabilities := s.initializeParams.Capabilities.General; genCapabilities != nil && genCapabilities.PositionEncodings != nil { - if slices.Contains(*genCapabilities.PositionEncodings, lsproto.PositionEncodingKindUTF8) { - s.positionEncoding = lsproto.PositionEncodingKindUTF8 - } + if slices.Contains(s.clientCapabilities.General.PositionEncodings, lsproto.PositionEncodingKindUTF8) { + s.positionEncoding = lsproto.PositionEncodingKindUTF8 } if s.initializeParams.Locale != nil { @@ -691,15 +698,12 @@ func (s *Server) handleInitialize(ctx context.Context, params *lsproto.Initializ } func (s *Server) handleInitialized(ctx context.Context, params *lsproto.InitializedParams) error { - if shouldEnableWatch(s.initializeParams) { + if s.clientCapabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration { s.watchEnabled = true } cwd := s.cwd - if s.initializeParams.Capabilities != nil && - s.initializeParams.Capabilities.Workspace != nil && - s.initializeParams.Capabilities.Workspace.WorkspaceFolders != nil && - ptrIsTrue(s.initializeParams.Capabilities.Workspace.WorkspaceFolders) && + if s.clientCapabilities.Workspace.WorkspaceFolders && s.initializeParams.WorkspaceFolders != nil && s.initializeParams.WorkspaceFolders.WorkspaceFolders != nil && len(*s.initializeParams.WorkspaceFolders.WorkspaceFolders) == 1 { @@ -812,11 +816,11 @@ func (s *Server) handleSetTrace(ctx context.Context, params *lsproto.SetTracePar } func (s *Server) handleDocumentDiagnostic(ctx context.Context, ls *ls.LanguageService, params *lsproto.DocumentDiagnosticParams) (lsproto.DocumentDiagnosticResponse, error) { - return ls.ProvideDiagnostics(ctx, params.TextDocument.Uri, getDiagnosticClientCapabilities(s.initializeParams)) + return ls.ProvideDiagnostics(ctx, params.TextDocument.Uri) } func (s *Server) handleHover(ctx context.Context, ls *ls.LanguageService, params *lsproto.HoverParams) (lsproto.HoverResponse, error) { - return ls.ProvideHover(ctx, params.TextDocument.Uri, params.Position, getHoverContentFormat(s.initializeParams)) + return ls.ProvideHover(ctx, params.TextDocument.Uri, params.Position) } func (s *Server) handleSignatureHelp(ctx context.Context, languageService *ls.LanguageService, params *lsproto.SignatureHelpParams) (lsproto.SignatureHelpResponse, error) { @@ -825,17 +829,15 @@ func (s *Server) handleSignatureHelp(ctx context.Context, languageService *ls.La params.TextDocument.Uri, params.Position, params.Context, - s.initializeParams.Capabilities.TextDocument.SignatureHelp, - getSignatureHelpDocumentationFormat(s.initializeParams), ) } func (s *Server) handleDefinition(ctx context.Context, ls *ls.LanguageService, params *lsproto.DefinitionParams) (lsproto.DefinitionResponse, error) { - return ls.ProvideDefinition(ctx, params.TextDocument.Uri, params.Position, getDefinitionClientSupportsLink(s.initializeParams)) + return ls.ProvideDefinition(ctx, params.TextDocument.Uri, params.Position) } func (s *Server) handleTypeDefinition(ctx context.Context, ls *ls.LanguageService, params *lsproto.TypeDefinitionParams) (lsproto.TypeDefinitionResponse, error) { - return ls.ProvideTypeDefinition(ctx, params.TextDocument.Uri, params.Position, getTypeDefinitionClientSupportsLink(s.initializeParams)) + return ls.ProvideTypeDefinition(ctx, params.TextDocument.Uri, params.Position) } func (s *Server) handleReferences(ctx context.Context, ls *ls.LanguageService, params *lsproto.ReferenceParams) (lsproto.ReferencesResponse, error) { @@ -845,7 +847,7 @@ func (s *Server) handleReferences(ctx context.Context, ls *ls.LanguageService, p func (s *Server) handleImplementations(ctx context.Context, ls *ls.LanguageService, params *lsproto.ImplementationParams) (lsproto.ImplementationResponse, error) { // goToImplementation - return ls.ProvideImplementations(ctx, params, getImplementationClientSupportsLink(s.initializeParams)) + return ls.ProvideImplementations(ctx, params) } func (s *Server) handleCompletion(ctx context.Context, languageService *ls.LanguageService, params *lsproto.CompletionParams) (lsproto.CompletionResponse, error) { @@ -854,7 +856,6 @@ func (s *Server) handleCompletion(ctx context.Context, languageService *ls.Langu params.TextDocument.Uri, params.Position, params.Context, - getCompletionClientCapabilities(s.initializeParams), ) } @@ -872,7 +873,6 @@ func (s *Server) handleCompletionItemResolve(ctx context.Context, params *lsprot ctx, params, data, - getCompletionClientCapabilities(s.initializeParams), ) } @@ -912,7 +912,7 @@ func (s *Server) handleWorkspaceSymbol(ctx context.Context, params *lsproto.Work } func (s *Server) handleDocumentSymbol(ctx context.Context, ls *ls.LanguageService, params *lsproto.DocumentSymbolParams) (lsproto.DocumentSymbolResponse, error) { - return ls.ProvideDocumentSymbols(ctx, params.TextDocument.Uri, getDocumentSymbolClientSupportsHierarchical(s.initializeParams)) + return ls.ProvideDocumentSymbols(ctx, params.TextDocument.Uri) } func (s *Server) handleRename(ctx context.Context, ls *ls.LanguageService, params *lsproto.RenameParams) (lsproto.RenameResponse, error) { @@ -931,6 +931,14 @@ func (s *Server) handleCodeAction(ctx context.Context, ls *ls.LanguageService, p return ls.ProvideCodeActions(ctx, params) } +func (s *Server) handleInlayHint( + ctx context.Context, + languageService *ls.LanguageService, + params *lsproto.InlayHintParams, +) (lsproto.InlayHintResponse, error) { + return languageService.ProvideInlayHint(ctx, params) +} + func (s *Server) Log(msg ...any) { fmt.Fprintln(s.stderr, msg...) } @@ -968,117 +976,28 @@ func ptrTo[T any](v T) *T { return &v } -func ptrIsTrue(v *bool) bool { - if v == nil { - return false - } - return *v -} - -func shouldEnableWatch(params *lsproto.InitializeParams) bool { - if params == nil || params.Capabilities == nil || params.Capabilities.Workspace == nil { - return false - } - return params.Capabilities.Workspace.DidChangeWatchedFiles != nil && - ptrIsTrue(params.Capabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration) -} - -func getCompletionClientCapabilities(params *lsproto.InitializeParams) *lsproto.CompletionClientCapabilities { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil { - return nil - } - return params.Capabilities.TextDocument.Completion -} - -func (s *Server) handleInlayHint( - ctx context.Context, - languageService *ls.LanguageService, - params *lsproto.InlayHintParams, -) (lsproto.InlayHintResponse, error) { - return languageService.ProvideInlayHint(ctx, params) -} - -func getDefinitionClientSupportsLink(params *lsproto.InitializeParams) bool { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || - params.Capabilities.TextDocument.Definition == nil { - return false - } - return ptrIsTrue(params.Capabilities.TextDocument.Definition.LinkSupport) -} - -func getTypeDefinitionClientSupportsLink(params *lsproto.InitializeParams) bool { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || - params.Capabilities.TextDocument.TypeDefinition == nil { - return false - } - return ptrIsTrue(params.Capabilities.TextDocument.TypeDefinition.LinkSupport) -} - -func getImplementationClientSupportsLink(params *lsproto.InitializeParams) bool { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || - params.Capabilities.TextDocument.Implementation == nil { - return false - } - return ptrIsTrue(params.Capabilities.TextDocument.Implementation.LinkSupport) -} - -func getDocumentSymbolClientSupportsHierarchical(params *lsproto.InitializeParams) bool { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || - params.Capabilities.TextDocument.DocumentSymbol == nil { - return false - } - return ptrIsTrue(params.Capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport) -} - -func getHoverContentFormat(params *lsproto.InitializeParams) lsproto.MarkupKind { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || params.Capabilities.TextDocument.Hover == nil || params.Capabilities.TextDocument.Hover.ContentFormat == nil { - // Default to plaintext if no preference specified - return lsproto.MarkupKindPlainText - } - formats := *params.Capabilities.TextDocument.Hover.ContentFormat - if len(formats) == 0 { - return lsproto.MarkupKindPlainText - } - // Return the first (most preferred) format - return formats[0] -} - -func getSignatureHelpDocumentationFormat(params *lsproto.InitializeParams) lsproto.MarkupKind { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil || params.Capabilities.TextDocument.SignatureHelp == nil || - params.Capabilities.TextDocument.SignatureHelp.SignatureInformation == nil || - params.Capabilities.TextDocument.SignatureHelp.SignatureInformation.DocumentationFormat == nil { - // Default to plaintext if no preference specified - return lsproto.MarkupKindPlainText - } - formats := *params.Capabilities.TextDocument.SignatureHelp.SignatureInformation.DocumentationFormat - if len(formats) == 0 { - return lsproto.MarkupKindPlainText - } - // Return the first (most preferred) format - return formats[0] -} - -func getDiagnosticClientCapabilities(params *lsproto.InitializeParams) *lsproto.DiagnosticClientCapabilities { - if params == nil || params.Capabilities == nil || params.Capabilities.TextDocument == nil { - return nil - } - - var caps lsproto.DiagnosticClientCapabilities - if params.Capabilities.TextDocument.Diagnostic != nil { - caps = *params.Capabilities.TextDocument.Diagnostic - } +func resolveClientCapabilities(caps *lsproto.ClientCapabilities) lsproto.ResolvedClientCapabilities { + resolved := lsproto.ResolveClientCapabilities(caps) // Some clients claim that push and pull diagnostics have different capabilities, // including vscode-languageclient v9. Work around this by defaulting any missing // pull diagnostic caps with the pull diagnostic equivalents. // // TODO: remove when we upgrade to vscode-languageclient v10, which fixes this issue. - if publish := params.Capabilities.TextDocument.PublishDiagnostics; publish != nil { - caps.RelatedInformation = core.Coalesce(caps.RelatedInformation, publish.RelatedInformation) - caps.TagSupport = core.Coalesce(caps.TagSupport, publish.TagSupport) - caps.CodeDescriptionSupport = core.Coalesce(caps.CodeDescriptionSupport, publish.CodeDescriptionSupport) - caps.DataSupport = core.Coalesce(caps.DataSupport, publish.DataSupport) + publish := resolved.TextDocument.PublishDiagnostics + diagnostic := &resolved.TextDocument.Diagnostic + if !diagnostic.RelatedInformation && publish.RelatedInformation { + diagnostic.RelatedInformation = true + } + if !diagnostic.CodeDescriptionSupport && publish.CodeDescriptionSupport { + diagnostic.CodeDescriptionSupport = true + } + if !diagnostic.DataSupport && publish.DataSupport { + diagnostic.DataSupport = true + } + if len(diagnostic.TagSupport.ValueSet) == 0 && len(publish.TagSupport.ValueSet) > 0 { + diagnostic.TagSupport.ValueSet = publish.TagSupport.ValueSet } - return &caps + return resolved } diff --git a/internal/project/untitled_test.go b/internal/project/untitled_test.go index 8eb0b93054..0291394040 100644 --- a/internal/project/untitled_test.go +++ b/internal/project/untitled_test.go @@ -87,7 +87,7 @@ x++;` assert.Assert(t, len(refs) == 3, "Expected 3 references, got %d", len(refs)) // Also test definition using ProvideDefinition - definition, err := languageService.ProvideDefinition(ctx, uri, lspPosition, false) + definition, err := languageService.ProvideDefinition(ctx, uri, lspPosition) assert.NilError(t, err) if definition.Locations != nil { t.Logf("Definition found: %d locations", len(*definition.Locations))