@@ -1444,13 +1444,24 @@ extension SourceKitLSPServer {
14441444 range: Range ( symbolPosition)
14451445 )
14461446
1447+ let containerNames = index. containerNames ( of: symbolOccurrence)
1448+ let containerName : String ?
1449+ if containerNames. isEmpty {
1450+ containerName = nil
1451+ } else {
1452+ switch symbolOccurrence. symbol. language {
1453+ case . cxx, . c, . objc: containerName = containerNames. joined ( separator: " :: " )
1454+ case . swift: containerName = containerNames. joined ( separator: " . " )
1455+ }
1456+ }
1457+
14471458 return WorkspaceSymbolItem . symbolInformation (
14481459 SymbolInformation (
14491460 name: symbolOccurrence. symbol. name,
14501461 kind: symbolOccurrence. symbol. kind. asLspSymbolKind ( ) ,
14511462 deprecated: nil ,
14521463 location: symbolLocation,
1453- containerName: index . containerName ( of : symbolOccurrence )
1464+ containerName: containerName
14541465 )
14551466 )
14561467 }
@@ -1916,27 +1927,14 @@ extension SourceKitLSPServer {
19161927 }
19171928
19181929 private func indexToLSPCallHierarchyItem(
1919- symbol: Symbol ,
1920- containerName: String ? ,
1921- location: Location
1922- ) -> CallHierarchyItem {
1923- let name : String
1924- if let containerName {
1925- switch symbol. language {
1926- case . objc where symbol. kind == . instanceMethod || symbol. kind == . instanceProperty:
1927- name = " -[ \( containerName) \( symbol. name) ] "
1928- case . objc where symbol. kind == . classMethod || symbol. kind == . classProperty:
1929- name = " +[ \( containerName) \( symbol. name) ] "
1930- case . cxx, . c, . objc:
1931- // C shouldn't have container names for call hierarchy and Objective-C should be covered above.
1932- // Fall back to using the C++ notation using `::`.
1933- name = " \( containerName) :: \( symbol. name) "
1934- case . swift:
1935- name = " \( containerName) . \( symbol. name) "
1936- }
1937- } else {
1938- name = symbol. name
1930+ definition: SymbolOccurrence ,
1931+ index: CheckedIndex
1932+ ) -> CallHierarchyItem ? {
1933+ guard let location = indexToLSPLocation ( definition. location) else {
1934+ return nil
19391935 }
1936+ let name = index. fullyQualifiedName ( of: definition)
1937+ let symbol = definition. symbol
19401938 return CallHierarchyItem (
19411939 name: name,
19421940 kind: symbol. kind. asLspSymbolKind ( ) ,
@@ -1976,14 +1974,7 @@ extension SourceKitLSPServer {
19761974 guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) else {
19771975 return nil
19781976 }
1979- guard let location = indexToLSPLocation ( definition. location) else {
1980- return nil
1981- }
1982- return self . indexToLSPCallHierarchyItem (
1983- symbol: definition. symbol,
1984- containerName: index. containerName ( of: definition) ,
1985- location: location
1986- )
1977+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
19871978 } . sorted ( by: { Location ( uri: $0. uri, range: $0. range) < Location ( uri: $1. uri, range: $1. range) } )
19881979
19891980 // Ideally, we should show multiple symbols. But VS Code fails to display call hierarchies with multiple root items,
@@ -2045,38 +2036,27 @@ extension SourceKitLSPServer {
20452036
20462037 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
20472038 func indexToLSPCallHierarchyItem2(
2048- symbol: Symbol ,
2049- containerName: String ? ,
2050- location: Location
2051- ) -> CallHierarchyItem {
2052- return self . indexToLSPCallHierarchyItem ( symbol: symbol, containerName: containerName, location: location)
2039+ definition: SymbolOccurrence ,
2040+ index: CheckedIndex
2041+ ) -> CallHierarchyItem ? {
2042+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
20532043 }
20542044
20552045 let calls = callersToCalls. compactMap { ( caller: Symbol , calls: [ SymbolOccurrence ] ) -> CallHierarchyIncomingCall ? in
20562046 // Resolve the caller's definition to find its location
2057- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: caller. usr)
2058- let definitionSymbolLocation = definition? . location
2059- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2060- let containerName : String ? =
2061- if let definition {
2062- index. containerName ( of: definition)
2063- } else {
2064- nil
2065- }
2047+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: caller. usr) else {
2048+ return nil
2049+ }
20662050
20672051 let locations = calls. compactMap { indexToLSPLocation2 ( $0. location) } . sorted ( )
20682052 guard !locations. isEmpty else {
20692053 return nil
20702054 }
2055+ guard let item = indexToLSPCallHierarchyItem2 ( definition: definition, index: index) else {
2056+ return nil
2057+ }
20712058
2072- return CallHierarchyIncomingCall (
2073- from: indexToLSPCallHierarchyItem2 (
2074- symbol: caller,
2075- containerName: containerName,
2076- location: definitionLocation ?? locations. first!
2077- ) ,
2078- fromRanges: locations. map ( \. range)
2079- )
2059+ return CallHierarchyIncomingCall ( from: item, fromRanges: locations. map ( \. range) )
20802060 }
20812061 return calls. sorted ( by: { $0. from. name < $1. from. name } )
20822062 }
@@ -2095,11 +2075,10 @@ extension SourceKitLSPServer {
20952075
20962076 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
20972077 func indexToLSPCallHierarchyItem2(
2098- symbol: Symbol ,
2099- containerName: String ? ,
2100- location: Location
2101- ) -> CallHierarchyItem {
2102- return self . indexToLSPCallHierarchyItem ( symbol: symbol, containerName: containerName, location: location)
2078+ definition: SymbolOccurrence ,
2079+ index: CheckedIndex
2080+ ) -> CallHierarchyItem ? {
2081+ return self . indexToLSPCallHierarchyItem ( definition: definition, index: index)
21032082 }
21042083
21052084 let callableUsrs = [ data. usr] + index. occurrences ( relatedToUSR: data. usr, roles: . accessorOf) . map ( \. symbol. usr)
@@ -2113,37 +2092,32 @@ extension SourceKitLSPServer {
21132092 }
21142093
21152094 // Resolve the callee's definition to find its location
2116- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr)
2117- let definitionSymbolLocation = definition? . location
2118- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2119- let containerName : String ? =
2120- if let definition {
2121- index. containerName ( of: definition)
2122- } else {
2123- nil
2124- }
2095+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr) else {
2096+ return nil
2097+ }
21252098
2126- return CallHierarchyOutgoingCall (
2127- to: indexToLSPCallHierarchyItem2 (
2128- symbol: occurrence. symbol,
2129- containerName: containerName,
2130- location: definitionLocation ?? location // Use occurrence location as fallback
2131- ) ,
2132- fromRanges: [ location. range]
2133- )
2099+ guard let item = indexToLSPCallHierarchyItem2 ( definition: definition, index: index) else {
2100+ return nil
2101+ }
2102+
2103+ return CallHierarchyOutgoingCall ( to: item, fromRanges: [ location. range] )
21342104 }
21352105 return calls. sorted ( by: { $0. to. name < $1. to. name } )
21362106 }
21372107
21382108 private func indexToLSPTypeHierarchyItem(
2139- symbol : Symbol ,
2109+ definition : SymbolOccurrence ,
21402110 moduleName: String ? ,
2141- location: Location ,
21422111 index: CheckedIndex
2143- ) -> TypeHierarchyItem {
2112+ ) -> TypeHierarchyItem ? {
21442113 let name : String
21452114 let detail : String ?
21462115
2116+ guard let location = indexToLSPLocation ( definition. location) else {
2117+ return nil
2118+ }
2119+
2120+ let symbol = definition. symbol
21472121 switch symbol. kind {
21482122 case . extension:
21492123 // Query the conformance added by this extension
@@ -2164,7 +2138,7 @@ extension SourceKitLSPServer {
21642138 detail = " Extension "
21652139 }
21662140 default :
2167- name = symbol . name
2141+ name = index . fullyQualifiedName ( of : definition )
21682142 detail = moduleName
21692143 }
21702144
@@ -2213,16 +2187,12 @@ extension SourceKitLSPServer {
22132187 }
22142188 . compactMap ( \. usr)
22152189 let typeHierarchyItems = usrs. compactMap { ( usr) -> TypeHierarchyItem ? in
2216- guard
2217- let info = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) ,
2218- let location = indexToLSPLocation ( info. location)
2219- else {
2190+ guard let info = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: usr) else {
22202191 return nil
22212192 }
22222193 return self . indexToLSPTypeHierarchyItem (
2223- symbol : info. symbol ,
2194+ definition : info,
22242195 moduleName: info. location. moduleName,
2225- location: location,
22262196 index: index
22272197 )
22282198 }
@@ -2287,30 +2257,28 @@ extension SourceKitLSPServer {
22872257
22882258 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
22892259 func indexToLSPTypeHierarchyItem2(
2290- symbol : Symbol ,
2260+ definition : SymbolOccurrence ,
22912261 moduleName: String ? ,
2292- location: Location ,
22932262 index: CheckedIndex
2294- ) -> TypeHierarchyItem {
2295- return self . indexToLSPTypeHierarchyItem ( symbol: symbol, moduleName: moduleName, location: location, index: index)
2263+ ) -> TypeHierarchyItem ? {
2264+ return self . indexToLSPTypeHierarchyItem (
2265+ definition: definition,
2266+ moduleName: moduleName,
2267+ index: index
2268+ )
22962269 }
22972270
22982271 // Convert occurrences to type hierarchy items
22992272 let occurs = baseOccurs + retroactiveConformanceOccurs
23002273 let types = occurs. compactMap { occurrence -> TypeHierarchyItem ? in
2301- guard let location = indexToLSPLocation2 ( occurrence. location) else {
2274+ // Resolve the supertype's definition to find its location
2275+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr) else {
23022276 return nil
23032277 }
23042278
2305- // Resolve the supertype's definition to find its location
2306- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: occurrence. symbol. usr)
2307- let definitionSymbolLocation = definition? . location
2308- let definitionLocation = definitionSymbolLocation. flatMap ( indexToLSPLocation2)
2309-
23102279 return indexToLSPTypeHierarchyItem2 (
2311- symbol: occurrence. symbol,
2312- moduleName: definitionSymbolLocation? . moduleName,
2313- location: definitionLocation ?? location, // Use occurrence location as fallback
2280+ definition: definition,
2281+ moduleName: definition. location. moduleName,
23142282 index: index
23152283 )
23162284 }
@@ -2334,12 +2302,15 @@ extension SourceKitLSPServer {
23342302
23352303 // TODO: Remove this workaround once https://github.com/swiftlang/swift/issues/75600 is fixed
23362304 func indexToLSPTypeHierarchyItem2(
2337- symbol : Symbol ,
2305+ definition : SymbolOccurrence ,
23382306 moduleName: String ? ,
2339- location: Location ,
23402307 index: CheckedIndex
2341- ) -> TypeHierarchyItem {
2342- return self . indexToLSPTypeHierarchyItem ( symbol: symbol, moduleName: moduleName, location: location, index: index)
2308+ ) -> TypeHierarchyItem ? {
2309+ return self . indexToLSPTypeHierarchyItem (
2310+ definition: definition,
2311+ moduleName: moduleName,
2312+ index: index
2313+ )
23432314 }
23442315
23452316 // Convert occurrences to type hierarchy items
@@ -2350,20 +2321,18 @@ extension SourceKitLSPServer {
23502321 // to.
23512322 logger. fault ( " Expected at most extendedBy or baseOf relation but got \( occurrence. relations. count) " )
23522323 }
2353- guard let related = occurrence. relations. sorted ( ) . first, let location = indexToLSPLocation2 ( occurrence. location)
2354- else {
2324+ guard let related = occurrence. relations. sorted ( ) . first else {
23552325 return nil
23562326 }
23572327
23582328 // Resolve the subtype's definition to find its location
2359- let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: related. symbol. usr)
2360- let definitionSymbolLocation = definition . map ( \ . location )
2361- let definitionLocation = definitionSymbolLocation . flatMap ( indexToLSPLocation2 )
2329+ guard let definition = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: related. symbol. usr) else {
2330+ return nil
2331+ }
23622332
23632333 return indexToLSPTypeHierarchyItem2 (
2364- symbol: related. symbol,
2365- moduleName: definitionSymbolLocation? . moduleName,
2366- location: definitionLocation ?? location, // Use occurrence location as fallback
2334+ definition: definition,
2335+ moduleName: definition. location. moduleName,
23672336 index: index
23682337 )
23692338 }
@@ -2408,24 +2377,23 @@ private let maxWorkspaceSymbolResults = 4096
24082377package typealias Diagnostic = LanguageServerProtocol . Diagnostic
24092378
24102379fileprivate extension CheckedIndex {
2411- /// Get the name of the symbol that is a parent of this symbol, if one exists
2412- func containerName( of symbol: SymbolOccurrence ) -> String ? {
2380+ func containerNames( of symbol: SymbolOccurrence ) -> [ String ] {
24132381 // The container name of accessors is the container of the surrounding variable.
24142382 let accessorOf = symbol. relations. filter { $0. roles. contains ( . accessorOf) }
24152383 if let primaryVariable = accessorOf. sorted ( ) . first {
24162384 if accessorOf. count > 1 {
24172385 logger. fault ( " Expected an occurrence to an accessor of at most one symbol, not multiple " )
24182386 }
24192387 if let primaryVariable = primaryDefinitionOrDeclarationOccurrence ( ofUSR: primaryVariable. symbol. usr) {
2420- return containerName ( of: primaryVariable)
2388+ return containerNames ( of: primaryVariable)
24212389 }
24222390 }
24232391
24242392 let containers = symbol. relations. filter { $0. roles. contains ( . childOf) }
24252393 if containers. count > 1 {
24262394 logger. fault ( " Expected an occurrence to a child of at most one symbol, not multiple " )
24272395 }
2428- return containers. filter {
2396+ let container = containers. filter {
24292397 switch $0. symbol. kind {
24302398 case . module, . namespace, . enum, . struct, . class, . protocol, . extension, . union:
24312399 return true
@@ -2434,7 +2402,39 @@ fileprivate extension CheckedIndex {
24342402 . destructor, . conversionFunction, . parameter, . using, . concept, . commentTag:
24352403 return false
24362404 }
2437- } . sorted ( ) . first? . symbol. name
2405+ } . sorted ( ) . first
2406+
2407+ if let container {
2408+ if let containerDefinition = primaryDefinitionOrDeclarationOccurrence ( ofUSR: container. symbol. usr) {
2409+ return self . containerNames ( of: containerDefinition) + [ container. symbol. name]
2410+ }
2411+ return [ container. symbol. name]
2412+ } else {
2413+ return [ ]
2414+ }
2415+ }
2416+
2417+ /// Take the name of containers into account to form a fully-qualified name for the given symbol.
2418+ /// This means that we will form names of nested types and type-qualify methods.
2419+ func fullyQualifiedName( of symbolOccurrence: SymbolOccurrence ) -> String {
2420+ let symbol = symbolOccurrence. symbol
2421+ let containerNames = containerNames ( of: symbolOccurrence)
2422+ guard let containerName = containerNames. last else {
2423+ // No containers, so nothing to do.
2424+ return symbol. name
2425+ }
2426+ switch symbol. language {
2427+ case . objc where symbol. kind == . instanceMethod || symbol. kind == . instanceProperty:
2428+ return " -[ \( containerName) \( symbol. name) ] "
2429+ case . objc where symbol. kind == . classMethod || symbol. kind == . classProperty:
2430+ return " +[ \( containerName) \( symbol. name) ] "
2431+ case . cxx, . c, . objc:
2432+ // C shouldn't have container names for call hierarchy and Objective-C should be covered above.
2433+ // Fall back to using the C++ notation using `::`.
2434+ return ( containerNames + [ symbol. name] ) . joined ( separator: " :: " )
2435+ case . swift:
2436+ return ( containerNames + [ symbol. name] ) . joined ( separator: " . " )
2437+ }
24382438 }
24392439}
24402440
0 commit comments