Skip to content

Implement textDocument/typeDefinition request#2445

Merged
ahoppen merged 13 commits into
swiftlang:mainfrom
loveucifer:type-definition-request
Feb 11, 2026
Merged

Implement textDocument/typeDefinition request#2445
ahoppen merged 13 commits into
swiftlang:mainfrom
loveucifer:type-definition-request

Conversation

@loveucifer
Copy link
Copy Markdown
Member

follow up pr referenced from - comment
to be merged after #2436

  • Add TypeDefinition.swift with cursorInfo USR lookup
  • Add cursorInfoFromTypeUSR and convertMangledTypeToUSR helpers
  • Register typeDefinitionProvider capability and handler
  • Add typeDefinition to LanguageService protocol
  • Add tests for local and cross-module type definitions

@loveucifer
Copy link
Copy Markdown
Member Author

i might have missed something because i was going back and forth , lets see

@ahoppen
Copy link
Copy Markdown
Member

ahoppen commented Jan 11, 2026

I’ll start reviewing this after #2436 is merged and you can rebase this on top of main with all those changes in, so no need for you to keep this update until that time.

loveucifer added a commit to loveucifer/sourcekit-lsp that referenced this pull request Jan 12, 2026
@loveucifer loveucifer force-pushed the type-definition-request branch from 486f903 to df6ce2c Compare January 16, 2026 12:32
@loveucifer loveucifer force-pushed the type-definition-request branch 3 times, most recently from b5ed7e9 to d8b8d71 Compare January 16, 2026 12:54
@loveucifer loveucifer force-pushed the type-definition-request branch from c6ad839 to 94ad50d Compare January 16, 2026 13:00
Copy link
Copy Markdown
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice. I think the biggest thing will be to reconcile the resolving of the definition’s USR with indexBasedDefinition now.

return nil
}

// Try cursorInfo with USR lookup first - it knows the current in-memory state
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s no second here, so I think the comment no longer applies

let location = typeInfo.symbolInfo.bestLocalDeclaration
{
return .locations([location])
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my comments in the inlay type hints PR, this doesn’t handle jumping to generated interfaces. Instead of doing another ad-hoc fix like you did in the inlay hints PR, I’d really like to see this unified with the logic in indexBasedJumpToDefinition. Could you look into how we can best re-use code between both that function, inlay hints resolve and the type definition request?

Comment on lines +203 to +231
func testTypeDefinitionClassType() async throws {
let testClient = try await TestSourceKitLSPClient()
let uri = DocumentURI(for: .swift)

let positions = testClient.openDocument(
"""
class 1️⃣MyClass {}
let 2️⃣instance = MyClass()
""",
uri: uri
)

let response = try await testClient.send(
TypeDefinitionRequest(
textDocument: TextDocumentIdentifier(uri),
position: positions["2️⃣"]
)
)

guard case .locations(let locations) = response, let location = locations.first else {
XCTFail("Expected location response")
return
}

XCTAssertEqual(location.uri, uri)
XCTAssertEqual(location.range, Range(positions["1️⃣"]))
}

func testTypeDefinitionEnumType() async throws {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Classes and enums are just the same as a struct in the type system, so these two tests don’t really provide much value and I think we can delete them.

completionProvider: completionOptions,
signatureHelpProvider: signatureHelpOptions,
definitionProvider: .bool(true),
typeDefinitionProvider: .bool(true),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also advertise the typeDefinitionProvider here?

Comment on lines +442 to +445
func typeDefinition(_ request: TypeDefinitionRequest) async throws -> LocationsOrLocationLinksResponse? {
throw ResponseError.requestNotImplemented(TypeDefinitionRequest.self)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also forward the request to clangd in the ClangLanguageService? Not sure if clangd supports the request right now but if it does in the future, we’ll pick it up that way.

Comment on lines +793 to +794
case let request as RequestAndReply<TypeDefinitionRequest>:
await self.handleRequest(for: request, requestHandler: self.typeDefinition)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list is ordered alphabetically? Could insert this at t?

@ahoppen
Copy link
Copy Markdown
Member

ahoppen commented Jan 18, 2026

Instead of adding a new requirement to LanguageService like you did, which also doesn’t unify the implementation for the inlay type resolve, I was thinking to pull definitionLocations and definitionInInterface out to top-level functions (or maybe their own type if it makes sense, probably not but not sure) and then call it from indexBasedDefinition in SourceKitLSPServer, the type definition request in SwiftLanguageService and also the inlay hint resolve. I just checked and indexBasedDefinition mostly deals with logic to jump to definitions instead of declarations (only really applicable to the C family of languages), so I don’t think we need to generalize any of that except for potentially uniquing the results, which we can just copy to all three locations.

Comment thread Sources/SourceKitLSP/DefinitionLocations.swift
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift Outdated
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift Outdated
Comment thread Sources/SwiftLanguageService/InlayHintResolve.swift Outdated
Comment thread Sources/SwiftLanguageService/InlayHintResolve.swift Outdated
Comment thread Sources/SwiftLanguageService/TypeDefinition.swift Outdated
Comment thread Sources/SwiftLanguageService/TypeDefinition.swift Outdated
Comment thread Tests/SourceKitLSPTests/TypeDefinitionTests.swift
- Add DefinitionLocations.swift to CMakeLists.txt
- Add proper documentation comments to functions in DefinitionLocations.swift
- Make indexToLSPLocation private since it's only used within the file
- Revert unrelated comment changes in InlayHintResolve.swift
- Use .only instead of .first in InlayHintResolve to avoid ambiguous types
- Refactor TypeDefinition.swift to use cleaner control flow with guard/else
- Add test for jumping to generated interface (String)
Copy link
Copy Markdown
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delayed review.

I left a few comments inline but there are also quite a few comments from my previous review outstanding. Please address those and then I can take another look at this.

Comment thread Sources/SourceKitLSP/DefinitionLocations.swift
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift Outdated
Comment thread Sources/SourceKitLSP/DefinitionLocations.swift
@loveucifer loveucifer force-pushed the type-definition-request branch from e4bc7d7 to 5ee63b7 Compare January 29, 2026 16:50
@loveucifer
Copy link
Copy Markdown
Member Author

Regarding the isDynamic check - your comment said that "indexBasedDefinition mostly deals with logic to jump to definitions instead of declarations (only really applicable to the C family of languages)", so I left tout the isDynamic handling out of the shared definitionLocations function since:
Type definition and inlay hint resolve don't need dynamic symbol handling afaik they just need to find the type's location
Only indexBasedDefinition in SourceKitLSPServer needs the isDynamic logic for proper jump-to-definition behavior

What i thought was to do is this
keep the shared definitionLocations simple (for type definition + inlay hints)
keep indexBasedDefinition in SourceKitLSPServer with its own isDynamic handling
Is this the right way or should the shared function also include the isDynamic logic?

@ahoppen
Copy link
Copy Markdown
Member

ahoppen commented Jan 31, 2026

Oh, sorry, you‘re right about isDynamic. I think I was partially confused because the old definitionLocations still exists and I would have expected the isDynamic check to show up somewhere in the diff where it stuck around but it didn’t. That being said, could you still address all comments from my previous review? Eg. #2445 (comment) but all of them really.

@loveucifer
Copy link
Copy Markdown
Member Author

okie got it

Copy link
Copy Markdown
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I only have a few small things left, otherwise this looks good to me. Looking forward to using this request 😄

Comment thread Sources/SourceKitLSP/SourceKitLSPServer.swift Outdated
Comment thread Sources/SwiftLanguageService/InlayHintResolve.swift Outdated
Comment thread Sources/SwiftLanguageService/TypeDefinition.swift Outdated
Comment thread Sources/SwiftLanguageService/TypeDefinition.swift Outdated
Copy link
Copy Markdown
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s 🚢 it

@ahoppen
Copy link
Copy Markdown
Member

ahoppen commented Feb 9, 2026

@swift-ci Please test

@loveucifer
Copy link
Copy Markdown
Member Author

@swift-ci please test windows

Comment thread Sources/SwiftLanguageService/TypeDefinition.swift
@loveucifer
Copy link
Copy Markdown
Member Author

@swift-ci please test

@loveucifer
Copy link
Copy Markdown
Member Author

@swift-ci please test windows

@ahoppen
Copy link
Copy Markdown
Member

ahoppen commented Feb 10, 2026

@swift-ci Please test Windows

@loveucifer
Copy link
Copy Markdown
Member Author

yaay 🎊

@ahoppen ahoppen merged commit 0ad0ac4 into swiftlang:main Feb 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants