Files
sourcekit-lsp/Sources/SourceKitLSP/Swift/RelatedIdentifiers.swift
Ben Barham a0a8f1eca4 Revert "Merge pull request #2094 from ahoppen/contextual-sourcekitd-request"
This reverts commit 188e174cde, reversing
changes made to be5ae8cf1c. Should be a
fairly harmless change, but it's also quite large. Skipping for 6.2.
2025-05-20 15:57:42 -07:00

104 lines
3.5 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 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 Csourcekitd
import LanguageServerProtocol
import SKLogging
import SourceKitD
struct RelatedIdentifier {
let range: Range<Position>
let usage: RenameLocation.Usage
}
extension RenameLocation.Usage {
fileprivate init?(_ uid: sourcekitd_api_uid_t?, _ values: sourcekitd_api_values) {
switch uid {
case values.definition:
self = .definition
case values.reference:
self = .reference
case values.call:
self = .call
case values.unknown:
self = .unknown
default:
return nil
}
}
func uid(values: sourcekitd_api_values) -> sourcekitd_api_uid_t {
switch self {
case .definition:
return values.definition
case .reference:
return values.reference
case .call:
return values.call
case .unknown:
return values.unknown
}
}
}
struct RelatedIdentifiersResponse {
let relatedIdentifiers: [RelatedIdentifier]
/// The compound decl name at the requested location. This can be used as `name` parameter to a
/// `find-syntactic-rename-ranges` request.
///
/// `nil` if `sourcekitd` is too old and doesn't return the `name` as part of the related identifiers request or
/// `relatedIdentifiers` is empty (eg. when performing a related identifiers request on `self`).
let name: String?
}
extension SwiftLanguageService {
func relatedIdentifiers(
at position: Position,
in snapshot: DocumentSnapshot,
includeNonEditableBaseNames: Bool
) async throws -> RelatedIdentifiersResponse {
let skreq = sourcekitd.dictionary([
keys.request: requests.relatedIdents,
keys.cancelOnSubsequentRequest: 0,
keys.offset: snapshot.utf8Offset(of: position),
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
keys.includeNonEditableBaseNames: includeNonEditableBaseNames ? 1 : 0,
keys.compilerArgs: await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: true)?.compilerArgs
as [SKDRequestValue]?,
])
let dict = try await sendSourcekitdRequest(skreq, fileContents: snapshot.text)
guard let results: SKDResponseArray = dict[self.keys.results] else {
throw ResponseError.internalError("sourcekitd response did not contain results")
}
let name: String? = dict[self.keys.name]
try Task.checkCancellation()
var relatedIdentifiers: [RelatedIdentifier] = []
results.forEach { _, value in
guard let offset: Int = value[keys.offset], let length: Int = value[keys.length] else {
return true // continue
}
let start = snapshot.positionOf(utf8Offset: offset)
let end = snapshot.positionOf(utf8Offset: offset + length)
let usage = RenameLocation.Usage(value[keys.nameType], values) ?? .unknown
relatedIdentifiers.append(RelatedIdentifier(range: start..<end, usage: usage))
return true // continue
}
return RelatedIdentifiersResponse(relatedIdentifiers: relatedIdentifiers, name: name)
}
}