@@ -1757,23 +1757,87 @@ extension SourceKitLSPServer {
17571757 position: req. position
17581758 )
17591759 )
1760- let locations = try await symbols. asyncMap { ( symbol) -> [ Location ] in
1761- if symbol. bestLocalDeclaration != nil && !( symbol. isDynamic ?? true )
1762- && symbol. usr? . hasPrefix ( " s: " ) ?? false /* Swift symbols have USRs starting with s: */
1760+
1761+ let canonicalOriginatorLocation = await languageService. canonicalDeclarationPosition (
1762+ of: req. position,
1763+ in: req. textDocument. uri
1764+ )
1765+
1766+ // Returns `true` if `location` points to the same declaration that the definition request was initiated from.
1767+ @Sendable func isAtCanonicalOriginatorLocation( _ location: Location ) async -> Bool {
1768+ guard location. uri == req. textDocument. uri, let canonicalOriginatorLocation else {
1769+ return false
1770+ }
1771+ return await languageService. canonicalDeclarationPosition ( of: location. range. lowerBound, in: location. uri)
1772+ == canonicalOriginatorLocation
1773+ }
1774+
1775+ var locations = try await symbols. asyncMap { ( symbol) -> [ Location ] in
1776+ var locations : [ Location ]
1777+ if let bestLocalDeclaration = symbol. bestLocalDeclaration,
1778+ !( symbol. isDynamic ?? true ) ,
1779+ symbol. usr? . hasPrefix ( " s: " ) ?? false /* Swift symbols have USRs starting with s: */
17631780 {
17641781 // If we have a known non-dynamic symbol within Swift, we don't need to do an index lookup.
17651782 // For non-Swift symbols, we need to perform an index lookup because the best local declaration will point to
1766- // a header file but jump-to-definition should prefer the implementation (there's the declaration request to jump
1767- // to the function's declaration).
1768- return [ symbol . bestLocalDeclaration ] . compactMap { $0 }
1783+ // a header file but jump-to-definition should prefer the implementation (there's the declaration request to
1784+ // jump to the function's declaration).
1785+ locations = [ bestLocalDeclaration]
1786+ } else {
1787+ locations = try await self . definitionLocations (
1788+ for: symbol,
1789+ in: req. textDocument. uri,
1790+ languageService: languageService
1791+ )
17691792 }
1770- return try await self . definitionLocations ( for: symbol, in: req. textDocument. uri, languageService: languageService)
1793+
1794+ // If the symbol's location is is where we initiated rename from, also show the declarations that the symbol
1795+ // overrides.
1796+ if let location = locations. only,
1797+ let usr = symbol. usr,
1798+ let index = workspace. index ( checkedFor: . deletedFiles) ,
1799+ await isAtCanonicalOriginatorLocation ( location)
1800+ {
1801+ let baseUSRs = index. occurrences ( ofUSR: usr, roles: . overrideOf) . flatMap {
1802+ $0. relations. filter { $0. roles. contains ( . overrideOf) } . map ( \. symbol. usr)
1803+ }
1804+ locations += baseUSRs. compactMap {
1805+ guard let baseDeclOccurrence = index. primaryDefinitionOrDeclarationOccurrence ( ofUSR: $0) else {
1806+ return nil
1807+ }
1808+ return indexToLSPLocation ( baseDeclOccurrence. location)
1809+ }
1810+ }
1811+
1812+ return locations
17711813 } . flatMap { $0 }
1814+
17721815 // Remove any duplicate locations. We might end up with duplicate locations when performing a definition request
17731816 // on eg. `MyStruct()` when no explicit initializer is declared. In this case we get two symbol infos, one for the
17741817 // declaration of the `MyStruct` type and one for the initializer, which is implicit and thus has the location of
17751818 // the `MyStruct` declaration itself.
1776- return locations. unique
1819+ locations = locations. unique
1820+
1821+ // Try removing any results that would point back to the location we are currently at. This ensures that eg. in the
1822+ // following case we only show line 2 when performing jump-to-definition on `TestImpl.doThing`.
1823+ //
1824+ // ```
1825+ // protocol TestProtocol {
1826+ // func doThing()
1827+ // }
1828+ // struct TestImpl: TestProtocol {
1829+ // func doThing() { }
1830+ // }
1831+ // ```
1832+ //
1833+ // If this would result in no locations, don't apply the filter. This way, performing jump-to-definition in the
1834+ // middle of a function's base name takes us to the base name start, indicating that jump-to-definition was able to
1835+ // resolve the location and didn't fail.
1836+ let nonOriginatorLocations = await locations. asyncFilter { await !isAtCanonicalOriginatorLocation( $0) }
1837+ if !nonOriginatorLocations. isEmpty {
1838+ locations = nonOriginatorLocations
1839+ }
1840+ return locations
17771841 }
17781842
17791843 func definition(
0 commit comments