Skip to content

Commit 8666f40

Browse files
committed
Parse information from related identiers that is needed to perform local rename
1 parent ed077a3 commit 8666f40

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

Sources/SourceKitD/sourcekitd_uids.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ public struct sourcekitd_keys {
3737
public let endline: sourcekitd_uid_t
3838
public let expression_length: sourcekitd_uid_t
3939
public let expression_offset: sourcekitd_uid_t
40-
public let expression_type: sourcekitd_uid_t
4140
public let expression_type_list: sourcekitd_uid_t
41+
public let expression_type: sourcekitd_uid_t
4242
public let filepath: sourcekitd_uid_t
4343
public let fixits: sourcekitd_uid_t
4444
public let groupname: sourcekitd_uid_t
4545
public let id: sourcekitd_uid_t
46+
public let includeNonEditableBaseNames: sourcekitd_uid_t
4647
public let is_system: sourcekitd_uid_t
4748
public let isDynamic: sourcekitd_uid_t
4849
public let kind: sourcekitd_uid_t
@@ -52,6 +53,7 @@ public struct sourcekitd_keys {
5253
public let name: sourcekitd_uid_t
5354
public let namelength: sourcekitd_uid_t
5455
public let nameoffset: sourcekitd_uid_t
56+
public let nameType: sourcekitd_uid_t
5557
public let not_recommended: sourcekitd_uid_t
5658
public let notification: sourcekitd_uid_t
5759
public let num_bytes_to_erase: sourcekitd_uid_t
@@ -68,17 +70,21 @@ public struct sourcekitd_keys {
6870
public let sourcetext: sourcekitd_uid_t
6971
public let substructure: sourcekitd_uid_t
7072
public let syntactic_only: sourcekitd_uid_t
73+
public let syntacticRenameCall: sourcekitd_uid_t
74+
public let syntacticRenameDefinition: sourcekitd_uid_t
75+
public let syntacticRenameReference: sourcekitd_uid_t
76+
public let syntacticRenameUnknown: sourcekitd_uid_t
7177
public let syntaxmap: sourcekitd_uid_t
7278
public let synthesizedextensions: sourcekitd_uid_t
7379
public let enablesyntaxmap: sourcekitd_uid_t
7480
public let text: sourcekitd_uid_t
7581
public let typename: sourcekitd_uid_t
7682
public let usr: sourcekitd_uid_t
77-
public let variable_offset: sourcekitd_uid_t
7883
public let variable_length: sourcekitd_uid_t
79-
public let variable_type: sourcekitd_uid_t
84+
public let variable_offset: sourcekitd_uid_t
8085
public let variable_type_explicit: sourcekitd_uid_t
8186
public let variable_type_list: sourcekitd_uid_t
87+
public let variable_type: sourcekitd_uid_t
8288

8389
// Code Completion options.
8490
public let codecomplete_options: sourcekitd_uid_t
@@ -113,6 +119,7 @@ public struct sourcekitd_keys {
113119
doc_full_as_xml = api.uid_get_from_cstr("key.doc.full_as_xml")!
114120
edits = api.uid_get_from_cstr("key.edits")!
115121
educational_note_paths = api.uid_get_from_cstr("key.educational_note_paths")!
122+
enablesyntaxmap = api.uid_get_from_cstr("key.enablesyntaxmap")!
116123
endcolumn = api.uid_get_from_cstr("key.endcolumn")!
117124
endline = api.uid_get_from_cstr("key.endline")!
118125
expression_length = api.uid_get_from_cstr("key.expression_length")!
@@ -123,6 +130,7 @@ public struct sourcekitd_keys {
123130
fixits = api.uid_get_from_cstr("key.fixits")!
124131
groupname = api.uid_get_from_cstr("key.groupname")!
125132
id = api.uid_get_from_cstr("key.id")!
133+
includeNonEditableBaseNames = api.uid_get_from_cstr("key.include_non_editable_base_names")!
126134
is_system = api.uid_get_from_cstr("key.is_system")!
127135
isDynamic = api.uid_get_from_cstr("key.is_dynamic")!
128136
kind = api.uid_get_from_cstr("key.kind")!
@@ -132,6 +140,7 @@ public struct sourcekitd_keys {
132140
name = api.uid_get_from_cstr("key.name")!
133141
namelength = api.uid_get_from_cstr("key.namelength")!
134142
nameoffset = api.uid_get_from_cstr("key.nameoffset")!
143+
nameType = api.uid_get_from_cstr("key.nametype")!
135144
not_recommended = api.uid_get_from_cstr("key.not_recommended")!
136145
notification = api.uid_get_from_cstr("key.notification")!
137146
num_bytes_to_erase = api.uid_get_from_cstr("key.num_bytes_to_erase")!
@@ -148,14 +157,17 @@ public struct sourcekitd_keys {
148157
sourcetext = api.uid_get_from_cstr("key.sourcetext")!
149158
substructure = api.uid_get_from_cstr("key.substructure")!
150159
syntactic_only = api.uid_get_from_cstr("key.syntactic_only")!
160+
syntacticRenameCall = api.uid_get_from_cstr("source.syntacticrename.call")!
161+
syntacticRenameDefinition = api.uid_get_from_cstr("source.syntacticrename.definition")!
162+
syntacticRenameReference = api.uid_get_from_cstr("source.syntacticrename.reference")!
163+
syntacticRenameUnknown = api.uid_get_from_cstr("source.syntacticrename.unknown")!
151164
syntaxmap = api.uid_get_from_cstr("key.syntaxmap")!
152-
enablesyntaxmap = api.uid_get_from_cstr("key.enablesyntaxmap")!
153165
synthesizedextensions = api.uid_get_from_cstr("key.synthesizedextensions")!
154166
text = api.uid_get_from_cstr("key.text")!
155167
typename = api.uid_get_from_cstr("key.typename")!
156168
usr = api.uid_get_from_cstr("key.usr")!
157-
variable_offset = api.uid_get_from_cstr("key.variable_offset")!
158169
variable_length = api.uid_get_from_cstr("key.variable_length")!
170+
variable_offset = api.uid_get_from_cstr("key.variable_offset")!
159171
variable_type = api.uid_get_from_cstr("key.variable_type")!
160172
variable_type_explicit = api.uid_get_from_cstr("key.variable_type_explicit")!
161173
variable_type_list = api.uid_get_from_cstr("key.variable_type_list")!

Sources/SourceKitLSP/Swift/RelatedIdentifiers.swift

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,55 @@ import LanguageServerProtocol
1515
import SourceKitD
1616

1717
struct RelatedIdentifier {
18+
enum Usage {
19+
/// The definition of a function/subscript/variable/...
20+
case definition
21+
22+
/// The symbol is being referenced.
23+
///
24+
/// This includes
25+
/// - References to variables
26+
/// - Unapplied references to functions (`myStruct.memberFunc`)
27+
/// - Calls to subscripts (`myArray[1]`, location is `[` here, length 1)
28+
case reference
29+
30+
/// A function that is being called.
31+
case call
32+
33+
/// Unknown name usage occurs if we don't have an entry in the index that
34+
/// tells us whether the location is a call, reference or a definition. The
35+
/// most common reasons why this happens is if the editor is adding syntactic
36+
/// results (eg. from comments or string literals).
37+
case unknown
38+
}
1839
let range: Range<Position>
40+
let usage: Usage
41+
}
42+
43+
extension RelatedIdentifier.Usage {
44+
fileprivate init?(_ uid: sourcekitd_uid_t?, _ keys: sourcekitd_keys) {
45+
switch uid {
46+
case keys.syntacticRenameDefinition:
47+
self = .definition
48+
case keys.syntacticRenameReference:
49+
self = .reference
50+
case keys.syntacticRenameCall:
51+
self = .call
52+
case keys.syntacticRenameUnknown:
53+
self = .unknown
54+
default:
55+
return nil
56+
}
57+
}
1958
}
2059

2160
struct RelatedIdentifiersResponse {
2261
let relatedIdentifiers: [RelatedIdentifier]
62+
/// The compound decl name at the requested location. This can be used as `name` parameter to a
63+
/// `find-syntactic-rename-ranges` request.
64+
///
65+
/// `nil` if `sourcekitd` is too old and doesn't return the `name` as part of the related identifiers request.
66+
let name: String?
2367
}
2468

2569
extension SwiftLanguageServer {
@@ -35,6 +79,7 @@ extension SwiftLanguageServer {
3579
skreq[keys.cancelOnSubsequentRequest] = 0
3680
skreq[keys.offset] = offset
3781
skreq[keys.sourcefile] = snapshot.uri.pseudoPath
82+
skreq[keys.includeNonEditableBaseNames] = includeNonEditableBaseNames ? 1 : 0
3883

3984
// FIXME: SourceKit should probably cache this for us.
4085
if let compileCommand = await self.buildSettings(for: snapshot.uri) {
@@ -43,11 +88,10 @@ extension SwiftLanguageServer {
4388

4489
let dict = try await self.sourcekitd.send(skreq, fileContents: snapshot.text)
4590

46-
guard
47-
let results: SKDResponseArray = dict[self.keys.results]
48-
else {
49-
throw ResponseError.internalError("sourcekitd response did not contain results or name")
91+
guard let results: SKDResponseArray = dict[self.keys.results] else {
92+
throw ResponseError.internalError("sourcekitd response did not contain results")
5093
}
94+
let name: String? = dict[self.keys.name]
5195

5296
try Task.checkCancellation()
5397

@@ -59,10 +103,13 @@ extension SwiftLanguageServer {
59103
let length: Int = value[keys.length],
60104
let end: Position = snapshot.positionOf(utf8Offset: offset + length)
61105
{
62-
relatedIdentifiers.append(RelatedIdentifier(range: start..<end))
106+
let usage = RelatedIdentifier.Usage(value[keys.nameType], keys) ?? .unknown
107+
relatedIdentifiers.append(
108+
RelatedIdentifier(range: start..<end, usage: usage)
109+
)
63110
}
64111
return true
65112
}
66-
return RelatedIdentifiersResponse(relatedIdentifiers: relatedIdentifiers)
113+
return RelatedIdentifiersResponse(relatedIdentifiers: relatedIdentifiers, name: name)
67114
}
68115
}

0 commit comments

Comments
 (0)