@@ -1454,13 +1454,24 @@ extension SourceKitLSPServer {
14541454 range: Range ( symbolPosition)
14551455 )
14561456
1457+ let containerNames = index. containerNames ( of: symbolOccurrence)
1458+ let containerName : String ?
1459+ if containerNames. isEmpty {
1460+ containerName = nil
1461+ } else {
1462+ switch symbolOccurrence. symbol. language {
1463+ case . cxx, . c, . objc: containerName = containerNames. joined ( separator: " :: " )
1464+ case . swift: containerName = containerNames. joined ( separator: " . " )
1465+ }
1466+ }
1467+
14571468 return WorkspaceSymbolItem . symbolInformation (
14581469 SymbolInformation (
14591470 name: symbolOccurrence. symbol. name,
14601471 kind: symbolOccurrence. symbol. kind. asLspSymbolKind ( ) ,
14611472 deprecated: nil ,
14621473 location: symbolLocation,
1463- containerName: index . containerName ( of : symbolOccurrence )
1474+ containerName: containerName
14641475 )
14651476 )
14661477 }
@@ -1934,27 +1945,14 @@ extension SourceKitLSPServer {
19341945 }
19351946
19361947 private func indexToLSPCallHierarchyItem(
1937- symbol: Symbol ,
1938- containerName: String ? ,
1939- location: Location
1940- ) -> CallHierarchyItem {
1941- let name : String
1942- if let containerName {
1943- switch symbol. language {
1944- case . objc where symbol. kind == . instanceMethod || symbol. kind == . instanceProperty:
1945- name = " -[ \( containerName) \( symbol. name) ] "
1946- case . objc where symbol. kind == . classMethod || symbol. kind == . classProperty:
1947- name = " +[ \( containerName) \( symbol. name) ] "
1948- case . cxx, . c, . objc:
1949- // C shouldn't have container names for call hierarchy and Objective-C should be covered above.
1950- // Fall back to using the C++ notation using `::`.
1951- name = " \( containerName) :: \( symbol. name) "
1952- case . swift:
1953- name = " \( containerName) . \( symbol. name) "
1954- }
1955- } else {
1956- name = symbol. name
1948+ definition: SymbolOccurrence ,
1949+ index: CheckedIndex
1950+ ) -> CallHierarchyItem ? {
1951+ guard let location = indexToLSPLocation ( definition. location) else {
1952+ return nil
19571953 }
1954+ let name = index. fullyQualifiedName ( of: definition)
1955+ let symbol = definition. symbol
19581956 return CallHierarchyItem (
19591957 name: name,
19601958 kind: symbol. kind. asLspSymbolKind ( ) ,
@@ -1994,14 +1992,7 @@ extension SourceKitLSPServer {
19941992 guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) else {
19951993 return nil
19961994 }
1997- guard let location = indexToLSPLocation ( definition. location) else {
1998- return nil
1999- }
2000- return self . indexToLSPCallHierarchyItem (
2001- symbol: definition. symbol,
2002- containerName: index. containerName ( of: definition) ,
2003- location: location
2004- )
1995+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
20051996 } . sorted ( by: { Location ( uri: $0. uri, range: $0. range) < Location ( uri: $1. uri, range: $1. range) } )
20061997
20071998 // Ideally, we should show multiple symbols. But VS Code fails to display call hierarchies with multiple root items,
@@ -2063,38 +2054,27 @@ extension SourceKitLSPServer {
20632054
20642055 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
20652056 func indexToLSPCallHierarchyItem2(
2066- symbol: Symbol ,
2067- containerName: String ? ,
2068- location: Location
2069- ) -> CallHierarchyItem {
2070- return self . indexToLSPCallHierarchyItem ( symbol: symbol, containerName: containerName, location: location)
2057+ definition: SymbolOccurrence ,
2058+ index: CheckedIndex
2059+ ) -> CallHierarchyItem ? {
2060+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
20712061 }
20722062
20732063 let calls = callersToCalls. compactMap { ( caller: Symbol , calls: [ SymbolOccurrence ] ) -> CallHierarchyIncomingCall ? in
20742064 // Resolve the caller's definition to find its location
2075- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: caller. usr)
2076- let definitionSymbolLocation = definition? . location
2077- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2078- let containerName : String ? =
2079- if let definition {
2080- index. containerName ( of: definition)
2081- } else {
2082- nil
2083- }
2065+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: caller. usr) else {
2066+ return nil
2067+ }
20842068
20852069 let locations = calls. compactMap { indexToLSPLocation2 ( $0. location) } . sorted ( )
20862070 guard !locations. isEmpty else {
20872071 return nil
20882072 }
2073+ guard let item = indexToLSPCallHierarchyItem2 ( definition: definition, index: index) else {
2074+ return nil
2075+ }
20892076
2090- return CallHierarchyIncomingCall (
2091- from: indexToLSPCallHierarchyItem2 (
2092- symbol: caller,
2093- containerName: containerName,
2094- location: definitionLocation ?? locations. first!
2095- ) ,
2096- fromRanges: locations. map ( \. range)
2097- )
2077+ return CallHierarchyIncomingCall ( from: item, fromRanges: locations. map ( \. range) )
20982078 }
20992079 return calls. sorted ( by: { $0. from. name < $1. from. name } )
21002080 }
@@ -2113,11 +2093,10 @@ extension SourceKitLSPServer {
21132093
21142094 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
21152095 func indexToLSPCallHierarchyItem2(
2116- symbol: Symbol ,
2117- containerName: String ? ,
2118- location: Location
2119- ) -> CallHierarchyItem {
2120- return self . indexToLSPCallHierarchyItem ( symbol: symbol, containerName: containerName, location: location)
2096+ definition: SymbolOccurrence ,
2097+ index: CheckedIndex
2098+ ) -> CallHierarchyItem ? {
2099+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
21212100 }
21222101
21232102 let callableUsrs = [ data. usr] + index. occurrences ( relatedToUSR: data. usr, roles: . accessorOf) . map ( \. symbol. usr)
@@ -2131,37 +2110,32 @@ extension SourceKitLSPServer {
21312110 }
21322111
21332112 // Resolve the callee's definition to find its location
2134- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr)
2135- let definitionSymbolLocation = definition? . location
2136- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2137- let containerName : String ? =
2138- if let definition {
2139- index. containerName ( of: definition)
2140- } else {
2141- nil
2142- }
2113+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr) else {
2114+ return nil
2115+ }
21432116
2144- return CallHierarchyOutgoingCall (
2145- to: indexToLSPCallHierarchyItem2 (
2146- symbol: occurrence. symbol,
2147- containerName: containerName,
2148- location: definitionLocation ?? location // Use occurrence location as fallback
2149- ) ,
2150- fromRanges: [ location. range]
2151- )
2117+ guard let item = indexToLSPCallHierarchyItem2 ( definition: definition, index: index) else {
2118+ return nil
2119+ }
2120+
2121+ return CallHierarchyOutgoingCall ( to: item, fromRanges: [ location. range] )
21522122 }
21532123 return calls. sorted ( by: { $0. to. name < $1. to. name } )
21542124 }
21552125
21562126 private func indexToLSPTypeHierarchyItem(
2157- symbol : Symbol ,
2127+ definition : SymbolOccurrence ,
21582128 moduleName: String ? ,
2159- location: Location ,
21602129 index: CheckedIndex
2161- ) -> TypeHierarchyItem {
2130+ ) -> TypeHierarchyItem ? {
21622131 let name : String
21632132 let detail : String ?
21642133
2134+ guard let location = indexToLSPLocation ( definition. location) else {
2135+ return nil
2136+ }
2137+
2138+ let symbol = definition. symbol
21652139 switch symbol. kind {
21662140 case . extension:
21672141 // Query the conformance added by this extension
@@ -2182,7 +2156,7 @@ extension SourceKitLSPServer {
21822156 detail = " Extension "
21832157 }
21842158 default :
2185- name = symbol . name
2159+ name = index . fullyQualifiedName ( of : definition )
21862160 detail = moduleName
21872161 }
21882162
@@ -2231,16 +2205,12 @@ extension SourceKitLSPServer {
22312205 }
22322206 . compactMap ( \. usr)
22332207 let typeHierarchyItems = usrs. compactMap { ( usr) -> TypeHierarchyItem ? in
2234- guard
2235- let info = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) ,
2236- let location = indexToLSPLocation ( info. location)
2237- else {
2208+ guard let info = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) else {
22382209 return nil
22392210 }
22402211 return self . indexToLSPTypeHierarchyItem (
2241- symbol : info. symbol ,
2212+ definition : info,
22422213 moduleName: info. location. moduleName,
2243- location: location,
22442214 index: index
22452215 )
22462216 }
@@ -2305,30 +2275,28 @@ extension SourceKitLSPServer {
23052275
23062276 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
23072277 func indexToLSPTypeHierarchyItem2(
2308- symbol : Symbol ,
2278+ definition : SymbolOccurrence ,
23092279 moduleName: String ? ,
2310- location: Location ,
23112280 index: CheckedIndex
2312- ) -> TypeHierarchyItem {
2313- return self . indexToLSPTypeHierarchyItem ( symbol: symbol, moduleName: moduleName, location: location, index: index)
2281+ ) -> TypeHierarchyItem ? {
2282+ return self . indexToLSPTypeHierarchyItem (
2283+ definition: definition,
2284+ moduleName: moduleName,
2285+ index: index
2286+ )
23142287 }
23152288
23162289 // Convert occurrences to type hierarchy items
23172290 let occurs = baseOccurs + retroactiveConformanceOccurs
23182291 let types = occurs. compactMap { occurrence -> TypeHierarchyItem ? in
2319- guard let location = indexToLSPLocation2 ( occurrence. location) else {
2292+ // Resolve the supertype's definition to find its location
2293+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr) else {
23202294 return nil
23212295 }
23222296
2323- // Resolve the supertype's definition to find its location
2324- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr)
2325- let definitionSymbolLocation = definition? . location
2326- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2327-
23282297 return indexToLSPTypeHierarchyItem2 (
2329- symbol: occurrence. symbol,
2330- moduleName: definitionSymbolLocation? . moduleName,
2331- location: definitionLocation ?? location, // Use occurrence location as fallback
2298+ definition: definition,
2299+ moduleName: definition. location. moduleName,
23322300 index: index
23332301 )
23342302 }
@@ -2352,12 +2320,15 @@ extension SourceKitLSPServer {
23522320
23532321 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
23542322 func indexToLSPTypeHierarchyItem2(
2355- symbol : Symbol ,
2323+ definition : SymbolOccurrence ,
23562324 moduleName: String ? ,
2357- location: Location ,
23582325 index: CheckedIndex
2359- ) -> TypeHierarchyItem {
2360- return self . indexToLSPTypeHierarchyItem ( symbol: symbol, moduleName: moduleName, location: location, index: index)
2326+ ) -> TypeHierarchyItem ? {
2327+ return self . indexToLSPTypeHierarchyItem (
2328+ definition: definition,
2329+ moduleName: moduleName,
2330+ index: index
2331+ )
23612332 }
23622333
23632334 // Convert occurrences to type hierarchy items
@@ -2368,20 +2339,18 @@ extension SourceKitLSPServer {
23682339 // to.
23692340 logger. fault ( " Expected at most extendedBy or baseOf relation but got \( occurrence. relations. count) " )
23702341 }
2371- guard let related = occurrence. relations. sorted ( ) . first, let location = indexToLSPLocation2 ( occurrence. location)
2372- else {
2342+ guard let related = occurrence. relations. sorted ( ) . first else {
23732343 return nil
23742344 }
23752345
23762346 // Resolve the subtype's definition to find its location
2377- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: related. symbol. usr)
2378- let definitionSymbolLocation = definition . map ( \ . location )
2379- let definitionLocation = definitionSymbolLocation . flatMap ( indexToLSPLocation2 )
2347+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: related. symbol. usr) else {
2348+ return nil
2349+ }
23802350
23812351 return indexToLSPTypeHierarchyItem2 (
2382- symbol: related. symbol,
2383- moduleName: definitionSymbolLocation? . moduleName,
2384- location: definitionLocation ?? location, // Use occurrence location as fallback
2352+ definition: definition,
2353+ moduleName: definition. location. moduleName,
23852354 index: index
23862355 )
23872356 }
@@ -2426,24 +2395,23 @@ private let maxWorkspaceSymbolResults = 4096
24262395package typealias Diagnostic = LanguageServerProtocol . Diagnostic
24272396
24282397fileprivate extension CheckedIndex {
2429- /// Get the name of the symbol that is a parent of this symbol, if one exists
2430- func containerName( of symbol: SymbolOccurrence ) -> String ? {
2398+ func containerNames( of symbol: SymbolOccurrence ) -> [ String ] {
24312399 // The container name of accessors is the container of the surrounding variable.
24322400 let accessorOf = symbol. relations. filter { $0. roles. contains ( . accessorOf) }
24332401 if let primaryVariable = accessorOf. sorted ( ) . first {
24342402 if accessorOf. count > 1 {
24352403 logger. fault ( " Expected an occurrence to an accessor of at most one symbol, not multiple " )
24362404 }
24372405 if let primaryVariable = primaryDefinitionOrDeclarationOccurrence ( ofUSR: primaryVariable. symbol. usr) {
2438- return containerName ( of: primaryVariable)
2406+ return containerNames ( of: primaryVariable)
24392407 }
24402408 }
24412409
24422410 let containers = symbol. relations. filter { $0. roles. contains ( . childOf) }
24432411 if containers. count > 1 {
24442412 logger. fault ( " Expected an occurrence to a child of at most one symbol, not multiple " )
24452413 }
2446- return containers. filter {
2414+ let container = containers. filter {
24472415 switch $0. symbol. kind {
24482416 case . module, . namespace, . enum, . struct, . class, . protocol, . extension, . union:
24492417 return true
@@ -2452,7 +2420,39 @@ fileprivate extension CheckedIndex {
24522420 . destructor, . conversionFunction, . parameter, . using, . concept, . commentTag:
24532421 return false
24542422 }
2455- } . sorted ( ) . first? . symbol. name
2423+ } . sorted ( ) . first
2424+
2425+ if let container {
2426+ if let containerDefinition = primaryDefinitionOrDeclarationOccurrence ( ofUSR: container. symbol. usr) {
2427+ return self . containerNames ( of: containerDefinition) + [ container. symbol. name]
2428+ }
2429+ return [ container. symbol. name]
2430+ } else {
2431+ return [ ]
2432+ }
2433+ }
2434+
2435+ /// Take the name of containers into account to form a fully-qualified name for the given symbol.
2436+ /// This means that we will form names of nested types and type-qualify methods.
2437+ func fullyQualifiedName( of symbolOccurrence: SymbolOccurrence ) -> String {
2438+ let symbol = symbolOccurrence. symbol
2439+ let containerNames = containerNames ( of: symbolOccurrence)
2440+ guard let containerName = containerNames. last else {
2441+ // No containers, so nothing to do.
2442+ return symbol. name
2443+ }
2444+ switch symbol. language {
2445+ case . objc where symbol. kind == . instanceMethod || symbol. kind == . instanceProperty:
2446+ return " -[ \( containerName) \( symbol. name) ] "
2447+ case . objc where symbol. kind == . classMethod || symbol. kind == . classProperty:
2448+ return " +[ \( containerName) \( symbol. name) ] "
2449+ case . cxx, . c, . objc:
2450+ // C shouldn't have container names for call hierarchy and Objective-C should be covered above.
2451+ // Fall back to using the C++ notation using `::`.
2452+ return ( containerNames + [ symbol. name] ) . joined ( separator: " :: " )
2453+ case . swift:
2454+ return ( containerNames + [ symbol. name] ) . joined ( separator: " . " )
2455+ }
24562456 }
24572457}
24582458
0 commit comments