Skip to content

Commit ba377d7

Browse files
authored
Merge pull request swiftlang#63765 from bnbarham/add-generated-name-to-expansions
[SourceKit] Add an optional path and name to refactoring edits
2 parents 9d5dd75 + f7aaf02 commit ba377d7

File tree

9 files changed

+137
-49
lines changed

9 files changed

+137
-49
lines changed

include/swift/IDE/Utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,15 @@ struct NoteRegion {
551551
};
552552

553553
struct Replacement {
554+
/// If the edit is outside of the originally request source file, the path
555+
/// to the file it is editing.
556+
StringRef Path;
557+
/// Range to apply the replacement to, zero-width if making an addition.
554558
CharSourceRange Range;
559+
/// If the edit is actually a file (which could be generated/from an
560+
/// expansion), the name (or path) of that buffer.
561+
StringRef BufferName;
562+
/// The text to replace \c Range with.
555563
StringRef Text;
556564
ArrayRef<NoteRegion> RegionsWorthNote;
557565
};

lib/IDE/Utils.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,8 @@ accept(SourceManager &SM, SourceLoc Loc, StringRef Text,
607607
void swift::ide::SourceEditConsumer::
608608
accept(SourceManager &SM, CharSourceRange Range, StringRef Text,
609609
ArrayRef<NoteRegion> SubRegions) {
610-
accept(SM, RegionType::ActiveCode, {{Range, Text, SubRegions}});
610+
accept(SM, RegionType::ActiveCode,
611+
{{/*Path=*/{}, Range, /*BufferName=*/{}, Text, SubRegions}});
611612
}
612613

613614
void swift::ide::SourceEditConsumer::
@@ -649,15 +650,27 @@ accept(SourceManager &SM, RegionType Type, ArrayRef<Replacement> Replacements) {
649650
void swift::ide::SourceEditTextConsumer::
650651
accept(SourceManager &SM, RegionType Type, ArrayRef<Replacement> Replacements) {
651652
for (const auto &Replacement: Replacements) {
652-
CharSourceRange Range = Replacement.Range;
653-
unsigned BufID = SM.findBufferContainingLoc(Range.getStart());
654-
auto Path(SM.getIdentifierForBuffer(BufID));
655-
auto Start = SM.getLineAndColumnInBuffer(Range.getStart());
656-
auto End = SM.getLineAndColumnInBuffer(Range.getEnd());
653+
OS << "// ";
654+
StringRef Path = Replacement.Path;
655+
if (Path.empty()) {
656+
unsigned BufID = SM.findBufferContainingLoc(Replacement.Range.getStart());
657+
Path = SM.getIdentifierForBuffer(BufID);
658+
} else {
659+
OS << "explicit ";
660+
}
661+
OS << Path.str() << " ";
657662

658-
OS << "// " << Path.str() << " ";
663+
auto Start = SM.getLineAndColumnInBuffer(Replacement.Range.getStart());
664+
auto End = SM.getLineAndColumnInBuffer(Replacement.Range.getEnd());
659665
OS << Start.first << ":" << Start.second << " -> ";
660-
OS << End.first << ":" << End.second << "\n";
666+
OS << End.first << ":" << End.second;
667+
668+
if (Replacement.BufferName.empty()) {
669+
OS << " (" << Replacement.BufferName << ")\n";
670+
} else {
671+
OS << "\n";
672+
}
673+
661674
OS << Replacement.Text << "\n";
662675
}
663676
}

lib/Refactoring/Refactoring.cpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ class RenameRangeDetailCollector : public Renamer {
477477

478478
class TextReplacementsRenamer : public Renamer {
479479
llvm::StringSet<> &ReplaceTextContext;
480-
std::vector<Replacement> Replacements;
480+
SmallVector<Replacement> Replacements;
481481

482482
public:
483483
const DeclNameViewer New;
@@ -571,7 +571,8 @@ class TextReplacementsRenamer : public Renamer {
571571
StringRef Text =
572572
getReplacementText(ExistingLabel, RangeKind, OldLabel, NewLabel);
573573
if (Text != ExistingLabel)
574-
Replacements.push_back({LabelRange, Text, {}});
574+
Replacements.push_back({/*Path=*/{}, LabelRange, /*BufferName=*/{}, Text,
575+
/*RegionsWorthNote=*/{}});
575576
}
576577

577578
void doRenameLabel(CharSourceRange Label, RefactoringRangeKind RangeKind,
@@ -582,7 +583,9 @@ class TextReplacementsRenamer : public Renamer {
582583

583584
void doRenameBase(CharSourceRange Range, RefactoringRangeKind) override {
584585
if (Old.base() != New.base())
585-
Replacements.push_back({Range, registerText(New.base()), {}});
586+
Replacements.push_back({/*Path=*/{}, Range, /*BufferName=*/{},
587+
registerText(New.base()),
588+
/*RegionsWorthNote=*/{}});
586589
}
587590

588591
public:
@@ -595,9 +598,7 @@ class TextReplacementsRenamer : public Renamer {
595598
assert(Old.partsCount() == New.partsCount());
596599
}
597600

598-
std::vector<Replacement> getReplacements() const {
599-
return std::move(Replacements);
600-
}
601+
ArrayRef<Replacement> getReplacements() const { return Replacements; }
601602
};
602603

603604
static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) {
@@ -8688,7 +8689,37 @@ bool RefactoringActionExpandMacro::performChange() {
86888689
rewrittenBuffer = adjustMacroExpansionWhitespace(
86898690
generatedInfo->kind, rewrittenBuffer, scratchBuffer);
86908691

8691-
EditConsumer.accept(SM, originalSourceRange, rewrittenBuffer);
8692+
// `TheFile` is the file of the actual expansion site, where as
8693+
// `OriginalFile` is the possibly enclosing buffer. Concretely:
8694+
// ```
8695+
// // m.swift
8696+
// @AddMemberAttributes
8697+
// struct Foo {
8698+
// // --- expanded from @AddMemberAttributes eg. @_someBufferName ---
8699+
// @AddedAttribute
8700+
// // ---
8701+
// let someMember: Int
8702+
// }
8703+
// ```
8704+
//
8705+
// When expanding `AddedAttribute`, the expansion actually applies to the
8706+
// original source (`m.swift`) rather than the buffer of the expansion
8707+
// site (`@_someBufferName`). Thus, we need to include the path to the
8708+
// original source as well. Note that this path could itself be another
8709+
// expansion.
8710+
SourceFile *originalFile =
8711+
MD->getSourceFileContainingLocation(originalSourceRange.getStart());
8712+
StringRef originalPath;
8713+
if (originalFile->getBufferID().hasValue() &&
8714+
TheFile->getBufferID() != originalFile->getBufferID()) {
8715+
originalPath = SM.getIdentifierForBuffer(*originalFile->getBufferID());
8716+
}
8717+
8718+
EditConsumer.accept(SM, {originalPath,
8719+
originalSourceRange,
8720+
SM.getIdentifierForBuffer(bufferID),
8721+
rewrittenBuffer,
8722+
{}});
86928723

86938724
if (generatedInfo->attachedMacroCustomAttr && !attachedMacroAttr)
86948725
attachedMacroAttr = generatedInfo->attachedMacroCustomAttr;
@@ -8780,7 +8811,8 @@ struct swift::ide::FindRenameRangesAnnotatingConsumer::Implementation {
87808811
if (Range.Index.has_value())
87818812
OS << " index=" << *Range.Index;
87828813
OS << ">" << Range.Range.str() << "</" << Tag << ">";
8783-
pRewriter->accept(SM, {Range.Range, OS.str(), {}});
8814+
pRewriter->accept(SM, {/*Path=*/{}, Range.Range, /*BufferName=*/{},
8815+
OS.str(), /*RegionsWorthNote=*/{}});
87848816
}
87858817
};
87868818

test/SourceKit/Macros/macro_basic.swift

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ struct S3 {
107107
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:8 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s
108108

109109
// EXPAND: source.edit.kind.active:
110-
// EXPAND-NEXT: 4:7-4:24 "(a + b, "a + b")"
110+
// EXPAND-NEXT: 4:7-4:24 (@__swiftmacro_9MacroUser13testStringify1a1bySi_SitF9stringifyfMf_.swift) "(a + b, "a + b")"
111111

112112
//##-- cursor-info at 'myTypeWrapper' position following @. We don't support
113113
// on the @ currently.
@@ -130,46 +130,51 @@ struct S3 {
130130
//##-- Refactoring expanding the attached macro
131131
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=21:2 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ATTACHED_EXPAND %s
132132
// ATTACHED_EXPAND: source.edit.kind.active:
133-
// ATTACHED_EXPAND: 23:3-23:3 "@accessViaStorage "
134-
// ATTACHED_EXPAND: source.edit.kind.active:
135-
// ATTACHED_EXPAND: 24:3-24:3 "@accessViaStorage "
136-
// ATTACHED_EXPAND: source.edit.kind.active:
137-
// ATTACHED_EXPAND: 22:11-22:11 "
138-
// ATTACHED_EXPAND: private var _storage = _Storage()
139-
// ATTACHED_EXPAND: source.edit.kind.active:
140-
// ATTACHED_EXPAND: 21:1-21:15 ""
133+
// ATTACHED_EXPAND-NEXT: 23:3-23:3 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMA_.swift) "@accessViaStorage "
134+
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
135+
// ATTACHED_EXPAND-NEXT: 24:3-24:3 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMA_.swift) "@accessViaStorage "
136+
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
137+
// ATTACHED_EXPAND-NEXT: 22:11-22:11 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMm_.swift) "
138+
// ATTACHED_EXPAND-NEXT: private var _storage = _Storage()
139+
// ATTACHED_EXPAND-NEXT: "
140+
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
141+
// ATTACHED_EXPAND-NEXT: 21:1-21:15 ""
141142

142143
//##-- Refactoring expanding the first accessor macro
143144
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=30:4 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ACCESSOR1_EXPAND %s
144145
// ACCESSOR1_EXPAND: source.edit.kind.active:
145-
// ACCESSOR1_EXPAND: 31:13-31:13 "{
146-
// ACCESSOR1_EXPAND: get { _storage.x }
147-
// ACCESSOR1_EXPAND: set { _storage.x = newValue }
148-
// ACCESSOR1_EXPAND: }"
149-
// ACCESSOR1_EXPAND: source.edit.kind.active:
150-
// ACCESSOR1_EXPAND: 30:3-30:20 ""
146+
// ACCESSOR1_EXPAND-NEXT: 31:13-31:13 (@__swiftmacro_9MacroUser2S2V1xSivp16accessViaStoragefMa_.swift) "{
147+
// ACCESSOR1_EXPAND-NEXT: get { _storage.x }
148+
// ACCESSOR1_EXPAND-EMPTY:
149+
// ACCESSOR1_EXPAND-NEXT: set { _storage.x = newValue }
150+
// ACCESSOR1_EXPAND-NEXT: }"
151+
// ACCESSOR1_EXPAND-NEXT: source.edit.kind.active:
152+
// ACCESSOR1_EXPAND-NEXT: 30:3-30:20 ""
151153

152154
//##-- Refactoring expanding the second accessor macro
153155
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=33:13 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ACCESSOR2_EXPAND %s
154156
// ACCESSOR2_EXPAND: source.edit.kind.active:
155-
// ACCESSOR2_EXPAND: 34:14-34:18 "{
156-
// ACCESSOR2_EXPAND: get { _storage.y }
157-
// ACCESSOR2_EXPAND: set { _storage.y = newValue }
158-
// ACCESSOR2_EXPAND: }"
159-
// ACCESSOR2_EXPAND: source.edit.kind.active:
160-
// ACCESSOR2_EXPAND: 33:3-33:20 ""
157+
// ACCESSOR2_EXPAND-NEXT: 34:14-34:18 (@__swiftmacro_9MacroUser2S2V1ySivp16accessViaStoragefMa_.swift) "{
158+
// ACCESSOR2_EXPAND-NEXT: get { _storage.y }
159+
// ACCESSOR2_EXPAND-EMPTY:
160+
// ACCESSOR2_EXPAND-NEXT: set { _storage.y = newValue }
161+
// ACCESSOR2_EXPAND-NEXT: }"
162+
// ACCESSOR2_EXPAND-NEXT: source.edit.kind.active:
163+
// ACCESSOR2_EXPAND-NEXT: 33:3-33:20 ""
161164

162165
//##-- Refactoring expanding the second accessor macro
163166
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=42:5 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=PEER_EXPAND %s
164167
// PEER_EXPAND: source.edit.kind.active:
165-
// PEER_EXPAND: 45:4-45:4 "
166-
// PEER_EXPAND: func f(a: Int, for b: String, _ value: Double, completionHandler: @escaping (String) -> Void) {
167-
// PEER_EXPAND: Task {
168-
// PEER_EXPAND: completionHandler(await f(a: a, for: b, value))
169-
// PEER_EXPAND: }
170-
// PEER_EXPAND: }
171-
// PEER_EXPAND: source.edit.kind.active:
172-
// PEER_EXPAND: 42:3-42:24 ""
168+
// PEER_EXPAND-NEXT: 45:4-45:4 (@__swiftmacro_9MacroUser2S3V1f1a3for_SSSi_SSSdtYaF20addCompletionHandlerfMp_.swift) "
169+
// PEER_EXPAND-EMPTY:
170+
// PEER_EXPAND-NEXT: func f(a: Int, for b: String, _ value: Double, completionHandler: @escaping (String) -> Void) {
171+
// PEER_EXPAND-NEXT: Task {
172+
// PEER_EXPAND-NEXT: completionHandler(await f(a: a, for: b, value))
173+
// PEER_EXPAND-NEXT: }
174+
// PEER_EXPAND-NEXT: }
175+
// PEER_EXPAND-NEXT: "
176+
// PEER_EXPAND-NEXT: source.edit.kind.active:
177+
// PEER_EXPAND-NEXT: 42:3-42:24 ""
173178

174179
//##-- Doc info, mostly just checking we don't crash because of the separate buffers
175180
// RUN: %sourcekitd-test -req=doc-info %s -- ${COMPILER_ARGS_WITHOUT_SOURCE[@]} | %FileCheck -check-prefix=DOCINFO %s

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,10 +708,16 @@ struct NoteRegion {
708708
};
709709

710710
struct Edit {
711+
/// If the edit is outside of the originally request source file, the path
712+
/// to the file it is editing.
713+
std::string Path;
711714
unsigned StartLine;
712715
unsigned StartColumn;
713716
unsigned EndLine;
714717
unsigned EndColumn;
718+
/// If the edit is actually a file (which could be generated/from an
719+
/// expansion), the name (or path) of that buffer.
720+
std::string BufferName;
715721
std::string NewText;
716722
SmallVector<NoteRegion, 2> RegionsWithNote;
717723
};

tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,8 +1287,9 @@ class RequestRefactoringEditConsumer::Implementation {
12871287
R.EndColumn,
12881288
R.ArgIndex};
12891289
});
1290-
return {Start.first, Start.second, End.first,
1291-
End.second, R.Text.str(), std::move(SubRanges)};
1290+
return {R.Path.str(), Start.first, Start.second,
1291+
End.first, End.second, R.BufferName.str(),
1292+
R.Text.str(), std::move(SubRanges)};
12921293
});
12931294
unsigned End = AllEdits.size();
12941295
StartEnds.emplace_back(Start, End);

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,14 +2223,30 @@ static void printSyntacticRenameEdits(sourcekitd_variant_t Info,
22232223
for(unsigned j = 0, je = sourcekitd_variant_array_get_count(Edits);
22242224
j != je; ++j) {
22252225
OS << " "; // indent
2226+
22262227
sourcekitd_variant_t Edit = sourcekitd_variant_array_get_value(Edits, j);
2228+
2229+
StringRef Path(
2230+
sourcekitd_variant_dictionary_get_string(Edit, KeyFilePath));
2231+
if (!Path.empty()) {
2232+
OS << Path << " ";
2233+
}
2234+
22272235
int64_t Line = sourcekitd_variant_dictionary_get_int64(Edit, KeyLine);
22282236
int64_t Column = sourcekitd_variant_dictionary_get_int64(Edit, KeyColumn);
22292237
int64_t EndLine = sourcekitd_variant_dictionary_get_int64(Edit, KeyEndLine);
22302238
int64_t EndColumn = sourcekitd_variant_dictionary_get_int64(Edit, KeyEndColumn);
2231-
OS << Line << ':' << Column << '-' << EndLine << ':' << EndColumn << " \"";
2239+
OS << Line << ':' << Column << '-' << EndLine << ':' << EndColumn << " ";
2240+
2241+
StringRef BufferName(
2242+
sourcekitd_variant_dictionary_get_string(Edit, KeyBufferName));
2243+
if (!BufferName.empty()) {
2244+
OS << "(" << BufferName << ") ";
2245+
}
2246+
22322247
StringRef Text(sourcekitd_variant_dictionary_get_string(Edit, KeyText));
2233-
OS << Text << "\"\n";
2248+
OS << "\"" << Text << "\"\n";
2249+
22342250
sourcekitd_variant_t NoteRanges =
22352251
sourcekitd_variant_dictionary_get_value(Edit, KeyRangesWorthNote);
22362252
if (unsigned e = sourcekitd_variant_array_get_count(NoteRanges)) {

tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3675,10 +3675,16 @@ createCategorizedEditsResponse(const RequestResult<ArrayRef<CategorizedEdits>> &
36753675
auto Edits = Entry.setArray(KeyEdits);
36763676
for(auto E: TheEdit.Edits) {
36773677
auto Edit = Edits.appendDictionary();
3678+
if (!E.Path.empty()) {
3679+
Edit.set(KeyFilePath, E.Path);
3680+
}
36783681
Edit.set(KeyLine, E.StartLine);
36793682
Edit.set(KeyColumn, E.StartColumn);
36803683
Edit.set(KeyEndLine, E.EndLine);
36813684
Edit.set(KeyEndColumn, E.EndColumn);
3685+
if (!E.BufferName.empty()) {
3686+
Edit.set(KeyBufferName, E.BufferName);
3687+
}
36823688
Edit.set(KeyText, E.NewText);
36833689
if (!E.RegionsWithNote.empty()) {
36843690
auto Notes = Edit.setArray(KeyRangesWorthNote);

utils/gyb_sourcekit_support/UIDs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def __init__(self, internal_name, external_name):
202202
# in this time. For cancellation testing purposes.
203203
KEY('SimulateLongRequest', 'key.simulate_long_request'),
204204
KEY('IsSynthesized', 'key.is_synthesized'),
205+
KEY('BufferName', 'key.buffer_name')
205206
]
206207

207208

0 commit comments

Comments
 (0)