Skip to content

Commit fbd2b8d

Browse files
authored
Merge pull request #81845 from hamishknight/range-expansion-6.2
[6.2] [SourceKit] Properly handle cursor info range for macro expansions
2 parents af18338 + 1d56f2e commit fbd2b8d

File tree

4 files changed

+79
-35
lines changed

4 files changed

+79
-35
lines changed

include/swift/AST/Module.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,10 +434,18 @@ class ModuleDecl
434434
/// \c nullptr if the source location isn't in this module.
435435
SourceFile *getSourceFileContainingLocation(SourceLoc loc);
436436

437+
// Retrieve the buffer ID and source range of the outermost node that
438+
// caused the generation of the buffer containing \p range. \p range and its
439+
// buffer if it isn't in a generated buffer or has no original range.
440+
std::pair<unsigned, SourceRange> getOriginalRange(SourceRange range) const;
441+
437442
// Retrieve the buffer ID and source location of the outermost location that
438443
// caused the generation of the buffer containing \p loc. \p loc and its
439444
// buffer if it isn't in a generated buffer or has no original location.
440-
std::pair<unsigned, SourceLoc> getOriginalLocation(SourceLoc loc) const;
445+
std::pair<unsigned, SourceLoc> getOriginalLocation(SourceLoc loc) const {
446+
auto [buffer, range] = getOriginalRange(loc);
447+
return std::make_pair(buffer, range.Start);
448+
}
441449

442450
/// Creates a map from \c #filePath strings to corresponding \c #fileID
443451
/// strings, diagnosing any conflicts.

lib/AST/Module.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -847,14 +847,14 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
847847
return nullptr;
848848
}
849849

850-
std::pair<unsigned, SourceLoc>
851-
ModuleDecl::getOriginalLocation(SourceLoc loc) const {
852-
assert(loc.isValid());
850+
std::pair<unsigned, SourceRange>
851+
ModuleDecl::getOriginalRange(SourceRange range) const {
852+
assert(range.isValid());
853853

854854
SourceManager &SM = getASTContext().SourceMgr;
855-
unsigned bufferID = SM.findBufferContainingLoc(loc);
855+
unsigned bufferID = SM.findBufferContainingLoc(range.Start);
856856

857-
SourceLoc startLoc = loc;
857+
auto startRange = range;
858858
unsigned startBufferID = bufferID;
859859
while (const GeneratedSourceInfo *info =
860860
SM.getGeneratedSourceInfo(bufferID)) {
@@ -866,12 +866,12 @@ ModuleDecl::getOriginalLocation(SourceLoc loc) const {
866866
// Location was within a macro expansion, return the expansion site, not
867867
// the insertion location.
868868
if (info->attachedMacroCustomAttr) {
869-
loc = info->attachedMacroCustomAttr->getLocation();
869+
range = info->attachedMacroCustomAttr->getRange();
870870
} else {
871871
ASTNode expansionNode = ASTNode::getFromOpaqueValue(info->astNode);
872-
loc = expansionNode.getStartLoc();
872+
range = expansionNode.getSourceRange();
873873
}
874-
bufferID = SM.findBufferContainingLoc(loc);
874+
bufferID = SM.findBufferContainingLoc(range.Start);
875875
break;
876876
}
877877
case GeneratedSourceInfo::DefaultArgument:
@@ -883,11 +883,11 @@ ModuleDecl::getOriginalLocation(SourceLoc loc) const {
883883
case GeneratedSourceInfo::PrettyPrinted:
884884
case GeneratedSourceInfo::AttributeFromClang:
885885
// No original location, return the original buffer/location
886-
return {startBufferID, startLoc};
886+
return {startBufferID, startRange};
887887
}
888888
}
889889

890-
return {bufferID, loc};
890+
return {bufferID, range};
891891
}
892892

893893
ArrayRef<SourceFile *>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// REQUIRES: swift_swift_parser
3+
4+
// RUN: split-file --leading-lines %s %t
5+
6+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %t/MacroDefinition.swift -g -no-toolchain-stdlib-rpath
7+
8+
//--- MacroDefinition.swift
9+
10+
import SwiftSyntax
11+
import SwiftSyntaxMacros
12+
13+
public struct AddFuncMacro: DeclarationMacro, PeerMacro {
14+
public static func expansion(
15+
of macro: some FreestandingMacroExpansionSyntax,
16+
in context: some MacroExpansionContext
17+
) -> [DeclSyntax] {
18+
["func foo(_ x: String) {}"]
19+
}
20+
public static func expansion(
21+
of node: AttributeSyntax,
22+
providingPeersOf declaration: some DeclSyntaxProtocol,
23+
in context: some MacroExpansionContext
24+
) throws -> [DeclSyntax] {
25+
["func foo(_ x: Int) {}"]
26+
}
27+
}
28+
29+
//--- main.swift
30+
31+
@attached(peer, names: named(foo))
32+
macro AddFuncPeer(x: Int) = #externalMacro(module: "MacroDefinition", type: "AddFuncMacro")
33+
34+
@freestanding(declaration, names: named(foo))
35+
macro AddFunc(x: Int) = #externalMacro(module: "MacroDefinition", type: "AddFuncMacro")
36+
37+
@AddFuncPeer(x: 0)
38+
#AddFunc(x: 0)
39+
40+
foo(0)
41+
// RUN: %sourcekitd-test -req=cursor %t/main.swift -pos=%(line-1):1 -- %t/main.swift -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser | %FileCheck --check-prefix PEER %s
42+
// PEER: source.lang.swift.ref.function.free ([[@LINE-5]]:1-[[@LINE-5]]:19)
43+
44+
foo("")
45+
// RUN: %sourcekitd-test -req=cursor %t/main.swift -pos=%(line-1):1 -- %t/main.swift -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser | %FileCheck --check-prefix FREESTANDING %s
46+
// FREESTANDING: source.lang.swift.ref.function.free ([[@LINE-8]]:1-[[@LINE-8]]:15)

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -877,11 +877,6 @@ static void setLocationInfoForClangNode(ClangNode ClangNode,
877877
}
878878
}
879879

880-
static unsigned getCharLength(SourceManager &SM, SourceRange TokenRange) {
881-
SourceLoc CharEndLoc = Lexer::getLocForEndOfToken(SM, TokenRange.End);
882-
return SM.getByteDistance(TokenRange.Start, CharEndLoc);
883-
}
884-
885880
static void setLocationInfo(const ValueDecl *VD,
886881
LocationInfo &Location) {
887882
ASTContext &Ctx = VD->getASTContext();
@@ -891,29 +886,24 @@ static void setLocationInfo(const ValueDecl *VD,
891886

892887
auto Loc = VD->getLoc(/*SerializedOK=*/true);
893888
if (Loc.isValid()) {
894-
auto getParameterListRange =
895-
[&](const ValueDecl *VD) -> std::optional<unsigned> {
896-
if (auto FD = dyn_cast<AbstractFunctionDecl>(VD)) {
897-
SourceRange R = FD->getParameterListSourceRange();
898-
if (R.isValid())
899-
return getCharLength(SM, R);
900-
}
901-
return std::nullopt;
902-
};
903-
unsigned NameLen;
904-
if (auto SigLen = getParameterListRange(VD)) {
905-
NameLen = SigLen.value();
906-
} else if (VD->hasName()) {
907-
NameLen = VD->getBaseName().userFacingName().size();
908-
} else {
909-
NameLen = getCharLength(SM, Loc);
889+
// For most cases we just want the range of the name itself. One exception
890+
// is for functions, where we also want to include the parameter list.
891+
SourceRange Range = Loc;
892+
if (auto *FD = dyn_cast<AbstractFunctionDecl>(VD)) {
893+
if (auto R = FD->getParameterListSourceRange())
894+
Range = R;
910895
}
911896

912-
auto [DeclBufID, DeclLoc] =
913-
VD->getModuleContext()->getOriginalLocation(Loc);
897+
auto [DeclBufID, DeclRange] =
898+
VD->getModuleContext()->getOriginalRange(Range);
899+
900+
auto DeclCharRange =
901+
Lexer::getCharSourceRangeFromSourceRange(SM, DeclRange);
902+
auto DeclLoc = DeclCharRange.getStart();
903+
914904
Location.Filename = SM.getIdentifierForBuffer(DeclBufID);
915905
Location.Offset = SM.getLocOffsetInBuffer(DeclLoc, DeclBufID);
916-
Location.Length = NameLen;
906+
Location.Length = DeclCharRange.getByteLength();
917907
std::tie(Location.Line, Location.Column) =
918908
SM.getLineAndColumnInBuffer(DeclLoc, DeclBufID);
919909
if (auto GeneratedSourceInfo = SM.getGeneratedSourceInfo(DeclBufID)) {

0 commit comments

Comments
 (0)