Skip to content

Commit 9cddf49

Browse files
committed
[Refactoring] Replace attributes when converting to an async function
The replacement range was `FunctionDecl::getRange`, which does not include attributes. This would cause attributes to be duplicated when converting a function to async. Override the start with the attribute start instead so that they are replaced as well. Resolves rdar://74063741
1 parent 9de5afd commit 9cddf49

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

lib/IDE/Refactoring.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4721,10 +4721,15 @@ class AsyncConversionStringBuilder : private SourceEntityWalker {
47214721
Placeholders.insert(TopHandler.Handler);
47224722
}
47234723

4724-
void replace(ASTNode Node, SourceEditConsumer &EditConsumer) {
4725-
CharSourceRange Range =
4726-
Lexer::getCharSourceRangeFromSourceRange(SM, Node.getSourceRange());
4727-
EditConsumer.accept(SM, Range, Buffer.str());
4724+
void replace(ASTNode Node, SourceEditConsumer &EditConsumer,
4725+
SourceLoc StartOverride = SourceLoc()) {
4726+
SourceRange Range = Node.getSourceRange();
4727+
if (StartOverride.isValid()) {
4728+
Range = SourceRange(StartOverride, Range.End);
4729+
}
4730+
CharSourceRange CharRange =
4731+
Lexer::getCharSourceRangeFromSourceRange(SM, Range);
4732+
EditConsumer.accept(SM, CharRange, Buffer.str());
47284733
Buffer.clear();
47294734
}
47304735

@@ -5285,7 +5290,7 @@ bool RefactoringActionConvertToAsync::performChange() {
52855290
if (DiagEngine.hadAnyError())
52865291
return true;
52875292

5288-
Builder.replace(FD, EditConsumer);
5293+
Builder.replace(FD, EditConsumer, FD->getSourceRangeIncludingAttrs().Start);
52895294
return false;
52905295
}
52915296

test/refactoring/ConvertAsync/convert_function.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ func nested() {
2222
// NESTED-NEXT: print(str2)
2323
// NESTED-NEXT: }
2424

25+
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+2):9 | %FileCheck -check-prefix=ATTRIBUTES %s
26+
@available(*, deprecated, message: "Deprecated")
27+
private func functionWithAttributes() {
28+
simple { str in
29+
print(str)
30+
}
31+
}
32+
// ATTRIBUTES: convert_function.swift [[# @LINE-6]]:1 -> [[# @LINE-1]]:2
33+
// ATTRIBUTES-NEXT: @available(*, deprecated, message: "Deprecated")
34+
// ATTRIBUTES-NEXT: private func functionWithAttributes() async {
35+
// ATTRIBUTES-NEXT: let str = await simple()
36+
// ATTRIBUTES-NEXT: print(str)
37+
// ATTRIBUTES-NEXT: }
38+
2539
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MANY-NESTED %s
2640
func manyNested() {
2741
simple { str1 in

0 commit comments

Comments
 (0)