Files
sourcekit-lsp/Sources/SwiftLanguageService/TypeDefinition.swift
2026-02-08 23:25:25 +05:30

78 lines
2.8 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import IndexStoreDB
@_spi(SourceKitLSP) package import LanguageServerProtocol
import SemanticIndex
import SourceKitD
import SourceKitLSP
extension SwiftLanguageService {
/// Handles the textDocument/typeDefinition request.
package func typeDefinition(_ request: TypeDefinitionRequest) async throws -> LocationsOrLocationLinksResponse? {
let uri = request.textDocument.uri
let position = request.position
let snapshot = try await self.latestSnapshot(for: uri)
let compileCommand = await self.compileCommand(for: uri, fallbackAfterTimeout: false)
let skreq = sourcekitd.dictionary([
keys.cancelOnSubsequentRequest: 0,
keys.offset: snapshot.utf8Offset(of: position),
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
keys.compilerArgs: compileCommand?.compilerArgs as [any SKDRequestValue]?,
])
let dict = try await send(sourcekitdRequest: \.cursorInfo, skreq, snapshot: snapshot)
let documentManager = try self.documentManager
// If the cursor is on a type symbol itself, use its USR directly.
// Otherwise get the type of the symbol at this position.
let symbol: SymbolDetails
if let cursorInfo = CursorInfo(dict, snapshot: snapshot, documentManager: documentManager, sourcekitd: sourcekitd) {
switch cursorInfo.symbolInfo.kind {
case .class, .struct, .enum, .interface, .typeParameter:
symbol = cursorInfo.symbolInfo
default:
guard let typeUsr: String = dict[keys.typeUsr],
let typeSymbol = try await cursorInfoFromTypeUSR(typeUsr, in: snapshot)?.symbolInfo
else {
return nil
}
symbol = typeSymbol
}
} else {
guard let typeUsr: String = dict[keys.typeUsr],
let typeSymbol = try await cursorInfoFromTypeUSR(typeUsr, in: snapshot)?.symbolInfo
else {
return nil
}
symbol = typeSymbol
}
let index = await sourceKitLSPServer?.workspaceForDocument(uri: uri)?.index(checkedFor: .deletedFiles)
let locations = try await SourceKitLSP.definitionLocations(
for: symbol,
originatorUri: uri,
index: index,
languageService: self
).locations
if locations.isEmpty {
return nil
}
return .locations(locations)
}
}