@@ -1654,46 +1654,6 @@ extension SourceKitServer {
1654
1654
)
1655
1655
}
1656
1656
1657
- /// Extracts the locations of an indexed symbol's occurrences,
1658
- /// e.g. for definition or reference lookups.
1659
- ///
1660
- /// - Parameters:
1661
- /// - result: The symbol to look up
1662
- /// - index: The index in which the occurrences will be looked up
1663
- /// - useLocalFallback: Whether to consider the best known local declaration if no other locations are found
1664
- /// - extractOccurrences: A function fetching the occurrences by the desired roles given a usr from the index
1665
- /// - Returns: The resolved symbol locations
1666
- private func extractIndexedOccurrences(
1667
- symbols: [ SymbolDetails ] ,
1668
- index: IndexStoreDB ? ,
1669
- useLocalFallback: Bool = false ,
1670
- extractOccurrences: ( SymbolDetails , IndexStoreDB ) -> [ SymbolOccurrence ]
1671
- ) -> [ ( occurrence: SymbolOccurrence ? , location: Location ) ] {
1672
- guard let symbol = symbols. first else {
1673
- return [ ]
1674
- }
1675
-
1676
- let fallback : [ ( occurrence: SymbolOccurrence ? , location: Location ) ]
1677
- if useLocalFallback, let bestLocalDeclaration = symbol. bestLocalDeclaration {
1678
- fallback = [ ( occurrence: nil , location: bestLocalDeclaration) ]
1679
- } else {
1680
- fallback = [ ]
1681
- }
1682
-
1683
- guard let index = index else {
1684
- return fallback
1685
- }
1686
-
1687
- let occurs = extractOccurrences ( symbol, index)
1688
- let resolved = occurs. compactMap { occur in
1689
- indexToLSPLocation ( occur. location) . map {
1690
- ( occurrence: occur, location: $0)
1691
- }
1692
- }
1693
-
1694
- return resolved. isEmpty ? fallback : resolved
1695
- }
1696
-
1697
1657
func declaration(
1698
1658
_ req: DeclarationRequest ,
1699
1659
workspace: Workspace ,
@@ -1702,85 +1662,102 @@ extension SourceKitServer {
1702
1662
return try await languageService. declaration ( req)
1703
1663
}
1704
1664
1705
- func definition(
1665
+ /// Returns the result of a `DefinitionRequest` by running a `SymbolInfoRequest`, inspecting
1666
+ /// its result and doing index lookups, if necessary.
1667
+ ///
1668
+ /// In contrast to `definition`, this does not fall back to sending a `DefinitionRequest` to the
1669
+ /// toolchain language server.
1670
+ private func indexBasedDefinition(
1706
1671
_ req: DefinitionRequest ,
1707
1672
workspace: Workspace ,
1708
1673
languageService: ToolchainLanguageServer
1709
- ) async throws -> LocationsOrLocationLinksResponse ? {
1674
+ ) async throws -> [ Location ] {
1710
1675
let symbols = try await languageService. symbolInfo (
1711
1676
SymbolInfoRequest (
1712
1677
textDocument: req. textDocument,
1713
1678
position: req. position
1714
1679
)
1715
1680
)
1716
- let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1681
+ guard let symbol = symbols. first else {
1682
+ return [ ]
1683
+ }
1684
+
1685
+ if let symbol = symbols. first, let bestLocalDeclaration = symbol. bestLocalDeclaration, !( symbol. isDynamic ?? false )
1686
+ {
1687
+ // If we have a non-dynamic symbol, we don't need to do an index lookup
1688
+ return [ bestLocalDeclaration]
1689
+ }
1690
+
1717
1691
// If this symbol is a module then generate a textual interface
1718
- if let symbol = symbols . first , symbol. kind == . module, let name = symbol. name {
1719
- return try await self . definitionInInterface (
1692
+ if symbol. kind == . module, let name = symbol. name {
1693
+ let interfaceLocation = try await self . definitionInInterface (
1720
1694
req,
1721
1695
moduleName: name,
1722
1696
symbolUSR: nil ,
1723
1697
languageService: languageService
1724
1698
)
1699
+ return [ interfaceLocation]
1725
1700
}
1726
1701
1727
- let resolved = self . extractIndexedOccurrences ( symbols: symbols, index: index, useLocalFallback: true ) {
1728
- ( symbolDetails, index) in
1729
- guard symbolDetails. isDynamic ?? false else {
1730
- // If the symbol isn't dynamic, we won't get more information from the index compared to what we already have
1731
- // in the symbolDetails response. Return an empty array so that `extractIndexedOccurrences` falls back to the
1732
- // location in the symbol details response.
1733
- return [ ]
1734
- }
1735
- guard let usr = symbolDetails. usr else { return [ ] }
1736
- logger. info ( " performing indexed jump-to-def with usr \( usr) " )
1737
- var occurs = index. occurrences ( ofUSR: usr, roles: [ . definition] )
1738
- if occurs. isEmpty {
1739
- occurs = index. occurrences ( ofUSR: usr, roles: [ . declaration] )
1740
- }
1741
- if symbolDetails. isDynamic ?? false {
1742
- occurs += occurs. flatMap {
1743
- index. occurrences ( relatedToUSR: $0. symbol. usr, roles: . overrideOf)
1744
- }
1702
+ guard let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index else {
1703
+ return [ ]
1704
+ }
1705
+ guard let usr = symbol. usr else { return [ ] }
1706
+ logger. info ( " performing indexed jump-to-def with usr \( usr) " )
1707
+ var occurances = index. occurrences ( ofUSR: usr, roles: [ . definition] )
1708
+ if occurances. isEmpty {
1709
+ occurances = index. occurrences ( ofUSR: usr, roles: [ . declaration] )
1710
+ }
1711
+ if symbol. isDynamic ?? false {
1712
+ occurances += occurances. flatMap {
1713
+ index. occurrences ( relatedToUSR: $0. symbol. usr, roles: . overrideOf)
1745
1714
}
1746
- return occurs
1747
1715
}
1748
1716
1749
- // if first resolved location is in `.swiftinterface` file. Use moduleName to return
1750
- // textual interface
1751
- if let firstResolved = resolved. first ,
1752
- let moduleName = firstResolved . occurrence ? . location . moduleName ,
1753
- firstResolved . location . uri . fileURL ? . pathExtension == " swiftinterface "
1754
- {
1755
- return try await self . definitionInInterface (
1756
- req ,
1757
- moduleName : moduleName ,
1758
- symbolUSR : firstResolved . occurrence ? . symbol . usr ,
1759
- languageService : languageService
1760
- )
1717
+ return try await occurances . asyncCompactMap { occurance in
1718
+ if URL ( fileURLWithPath : occurance . location . path ) . pathExtension == " swiftinterface " {
1719
+ // if first resolved location is in `.swiftinterface` file. Use moduleName to return
1720
+ // textual interface
1721
+ return try await self . definitionInInterface (
1722
+ req ,
1723
+ moduleName : occurance . location . moduleName ,
1724
+ symbolUSR : occurance . symbol . usr ,
1725
+ languageService : languageService
1726
+ )
1727
+ }
1728
+ return indexToLSPLocation ( occurance . location )
1761
1729
}
1762
- let locs = resolved. map ( \. location)
1730
+ }
1731
+
1732
+ func definition(
1733
+ _ req: DefinitionRequest ,
1734
+ workspace: Workspace ,
1735
+ languageService: ToolchainLanguageServer
1736
+ ) async throws -> LocationsOrLocationLinksResponse ? {
1737
+ let indexBasedResponse = try await indexBasedDefinition ( req, workspace: workspace, languageService: languageService)
1763
1738
// If we're unable to handle the definition request using our index, see if the
1764
1739
// language service can handle it (e.g. clangd can provide AST based definitions).
1765
- if locs. isEmpty {
1766
- return try await languageService. definition ( req)
1740
+ if indexBasedResponse. isEmpty {
1741
+ do {
1742
+ return try await languageService. definition ( req)
1743
+ } catch { }
1767
1744
}
1768
- return . locations( locs )
1745
+ return . locations( indexBasedResponse )
1769
1746
}
1770
1747
1771
1748
func definitionInInterface(
1772
1749
_ req: DefinitionRequest ,
1773
1750
moduleName: String ,
1774
1751
symbolUSR: String ? ,
1775
1752
languageService: ToolchainLanguageServer
1776
- ) async throws -> LocationsOrLocationLinksResponse ? {
1753
+ ) async throws -> Location {
1777
1754
let openInterface = OpenInterfaceRequest ( textDocument: req. textDocument, name: moduleName, symbolUSR: symbolUSR)
1778
1755
guard let interfaceDetails = try await languageService. openInterface ( openInterface) else {
1779
1756
throw ResponseError . unknown ( " Could not generate Swift Interface for \( moduleName) " )
1780
1757
}
1781
1758
let position = interfaceDetails. position ?? Position ( line: 0 , utf16index: 0 )
1782
1759
let loc = Location ( uri: interfaceDetails. uri, range: Range ( position) )
1783
- return . locations ( [ loc] )
1760
+ return loc
1784
1761
}
1785
1762
1786
1763
func implementation(
@@ -1794,17 +1771,18 @@ extension SourceKitServer {
1794
1771
position: req. position
1795
1772
)
1796
1773
)
1797
- let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1798
- let extractedResult = self . extractIndexedOccurrences ( symbols: symbols, index: index) { ( symbolDetails, index) in
1799
- guard let usr = symbolDetails. usr else { return [ ] }
1800
- var occurs = index. occurrences ( ofUSR: usr, roles: . baseOf)
1801
- if occurs. isEmpty {
1802
- occurs = index. occurrences ( relatedToUSR: usr, roles: . overrideOf)
1803
- }
1804
- return occurs
1774
+ guard let symbol = symbols. first,
1775
+ let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1776
+ else {
1777
+ return nil
1778
+ }
1779
+ guard let usr = symbol. usr else { return nil }
1780
+ var occurrances = index. occurrences ( ofUSR: usr, roles: . baseOf)
1781
+ if occurrances. isEmpty {
1782
+ occurrances = index. occurrences ( relatedToUSR: usr, roles: . overrideOf)
1805
1783
}
1806
1784
1807
- return . locations( extractedResult . map ( \ . location) )
1785
+ return . locations( occurrances . compactMap { indexToLSPLocation ( $0 . location) } )
1808
1786
}
1809
1787
1810
1788
func references(
@@ -1818,18 +1796,17 @@ extension SourceKitServer {
1818
1796
position: req. position
1819
1797
)
1820
1798
)
1821
- let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1822
- let extractedResult = self . extractIndexedOccurrences ( symbols: symbols, index: index) { ( symbolDetails, index) in
1823
- guard let usr = symbolDetails. usr else { return [ ] }
1824
- logger. info ( " performing indexed jump-to-def with usr \( usr) " )
1825
- var roles : SymbolRole = [ . reference]
1826
- if req. context. includeDeclaration {
1827
- roles. formUnion ( [ . declaration, . definition] )
1828
- }
1829
- return index. occurrences ( ofUSR: usr, roles: roles)
1799
+ guard let symbol = symbols. first, let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1800
+ else {
1801
+ return [ ]
1830
1802
}
1831
-
1832
- return extractedResult. map ( \. location)
1803
+ guard let usr = symbol. usr else { return [ ] }
1804
+ logger. info ( " performing indexed jump-to-def with usr \( usr) " )
1805
+ var roles : SymbolRole = [ . reference]
1806
+ if req. context. includeDeclaration {
1807
+ roles. formUnion ( [ . declaration, . definition] )
1808
+ }
1809
+ return index. occurrences ( ofUSR: usr, roles: roles) . compactMap { indexToLSPLocation ( $0. location) }
1833
1810
}
1834
1811
1835
1812
private func indexToLSPCallHierarchyItem(
@@ -1864,23 +1841,23 @@ extension SourceKitServer {
1864
1841
position: req. position
1865
1842
)
1866
1843
)
1867
- let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1868
- // For call hierarchy preparation we only locate the definition
1869
- let extractedResult = self . extractIndexedOccurrences ( symbols: symbols, index: index) { ( symbolDetails, index) in
1870
- guard let usr = symbolDetails. usr else { return [ ] }
1871
- return index. occurrences ( ofUSR: usr, roles: [ . definition, . declaration] )
1844
+ guard let symbol = symbols. first, let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index
1845
+ else {
1846
+ return nil
1872
1847
}
1873
- return extractedResult. compactMap { info -> CallHierarchyItem ? in
1874
- guard let occurrence = info. occurrence else {
1875
- return nil
1848
+ // For call hierarchy preparation we only locate the definition
1849
+ guard let usr = symbol. usr else { return nil }
1850
+ return index. occurrences ( ofUSR: usr, roles: [ . definition, . declaration] )
1851
+ . compactMap { info -> CallHierarchyItem ? in
1852
+ guard let location = indexToLSPLocation ( info. location) else {
1853
+ return nil
1854
+ }
1855
+ return self . indexToLSPCallHierarchyItem (
1856
+ symbol: info. symbol,
1857
+ moduleName: info. location. moduleName,
1858
+ location: location
1859
+ )
1876
1860
}
1877
- let symbol = occurrence. symbol
1878
- return self . indexToLSPCallHierarchyItem (
1879
- symbol: symbol,
1880
- moduleName: occurrence. location. moduleName,
1881
- location: info. location
1882
- )
1883
- }
1884
1861
}
1885
1862
1886
1863
/// Extracts our implementation-specific data about a call hierarchy
@@ -2021,25 +1998,25 @@ extension SourceKitServer {
2021
1998
position: req. position
2022
1999
)
2023
2000
)
2024
- guard let index = await self . workspaceForDocument ( uri : req . textDocument . uri ) ? . index else {
2025
- return [ ]
2001
+ guard let symbol = symbols . first else {
2002
+ return nil
2026
2003
}
2027
- let extractedResult = self . extractIndexedOccurrences ( symbols: symbols, index: index) { ( symbolDetails, index) in
2028
- guard let usr = symbolDetails. usr else { return [ ] }
2029
- return index. occurrences ( ofUSR: usr, roles: [ . definition, . declaration] )
2004
+ guard let index = await self . workspaceForDocument ( uri: req. textDocument. uri) ? . index else {
2005
+ return nil
2030
2006
}
2031
- return extractedResult. compactMap { info -> TypeHierarchyItem ? in
2032
- guard let occurrence = info. occurrence else {
2033
- return nil
2007
+ guard let usr = symbol. usr else { return nil }
2008
+ return index. occurrences ( ofUSR: usr, roles: [ . definition, . declaration] )
2009
+ . compactMap { info -> TypeHierarchyItem ? in
2010
+ guard let location = indexToLSPLocation ( info. location) else {
2011
+ return nil
2012
+ }
2013
+ return self . indexToLSPTypeHierarchyItem (
2014
+ symbol: info. symbol,
2015
+ moduleName: info. location. moduleName,
2016
+ location: location,
2017
+ index: index
2018
+ )
2034
2019
}
2035
- let symbol = occurrence. symbol
2036
- return self . indexToLSPTypeHierarchyItem (
2037
- symbol: symbol,
2038
- moduleName: occurrence. location. moduleName,
2039
- location: info. location,
2040
- index: index
2041
- )
2042
- }
2043
2020
}
2044
2021
2045
2022
/// Extracts our implementation-specific data about a type hierarchy
0 commit comments