mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Refactoring] Fix local rename missing occurrences in string interpolations
NameMatcher checked if a StringLiteralExpr was a string segment in an interpolated string by checking if the parent expression was an InterpolatedStringLiteralExpr. That's only true pre-type-checking, and unlike global rename, local rename uses the type-checked AST.
This commit is contained in:
@@ -564,35 +564,21 @@ void NameMatcher::skipLocsBefore(SourceLoc Start) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool NameMatcher::shouldSkip(Expr *E) {
|
bool NameMatcher::shouldSkip(Expr *E) {
|
||||||
if (!isa<StringLiteralExpr>(E) || !Parent.getAsExpr() ||
|
if (isa<StringLiteralExpr>(E) && Parent.getAsExpr()) {
|
||||||
!isa<InterpolatedStringLiteralExpr>(Parent.getAsExpr()))
|
// Attempting to get the CharSourceRange from the SourceRange of a
|
||||||
return shouldSkip(E->getSourceRange());
|
// StringLiteralExpr that is a segment of an interpolated string gives
|
||||||
|
// incorrect ranges. Use the CharSourceRange of the corresponding token
|
||||||
|
// instead.
|
||||||
|
|
||||||
// The lexer treats interpolated strings as a single token when computing the
|
auto ExprStart = E->getStartLoc();
|
||||||
// CharSourceRange, so when we try to get the CharSourceRange of its first
|
auto RemaingTokens = TokensToCheck.drop_while([&](const Token &tok) -> bool {
|
||||||
// child StringLiteralExpr (at the same SourceLoc) it goes beyond any
|
return getSourceMgr().isBeforeInBuffer(tok.getRange().getStart(), ExprStart);
|
||||||
// interpolated values. Use the StartLoc of the next sibling to bound it.
|
});
|
||||||
|
|
||||||
StringLiteralExpr *SL = cast<StringLiteralExpr>(E);
|
if (!RemaingTokens.empty() && RemaingTokens.front().getLoc() == ExprStart)
|
||||||
InterpolatedStringLiteralExpr *ISL =
|
return shouldSkip(RemaingTokens.front().getRange());
|
||||||
cast<InterpolatedStringLiteralExpr>(Parent.getAsExpr());
|
|
||||||
|
|
||||||
SourceLoc Start = SL->getStartLoc();
|
|
||||||
ArrayRef<Expr*> Segments = ISL->getSegments();
|
|
||||||
Segments = Segments.drop_until([&](Expr *Item){ return Item == SL; })
|
|
||||||
.drop_front();
|
|
||||||
|
|
||||||
CharSourceRange Range;
|
|
||||||
if (Segments.empty()) {
|
|
||||||
Range = Lexer::getCharSourceRangeFromSourceRange(getSourceMgr(),
|
|
||||||
SourceRange(Start));
|
|
||||||
} else {
|
|
||||||
SourceLoc NextSiblingLoc = Segments.front()->getStartLoc();
|
|
||||||
unsigned Length = getSourceMgr().getByteDistance(Start, NextSiblingLoc);
|
|
||||||
Range = CharSourceRange(Start, Length);
|
|
||||||
}
|
}
|
||||||
|
return shouldSkip(E->getSourceRange());
|
||||||
return shouldSkip(Range);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NameMatcher::shouldSkip(SourceRange Range) {
|
bool NameMatcher::shouldSkip(SourceRange Range) {
|
||||||
|
|||||||
@@ -25,3 +25,5 @@ source.edit.kind.active:
|
|||||||
26:28-26:29 source.refactoring.range.kind.call-argument-colon arg-index=0
|
26:28-26:29 source.refactoring.range.kind.call-argument-colon arg-index=0
|
||||||
source.edit.kind.string:
|
source.edit.kind.string:
|
||||||
26:33-26:36 source.refactoring.range.kind.basename
|
26:33-26:36 source.refactoring.range.kind.basename
|
||||||
|
source.edit.kind.string:
|
||||||
|
26:43-26:46 source.refactoring.range.kind.basename
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ source.edit.kind.active:
|
|||||||
3:3-3:5 source.refactoring.range.kind.basename
|
3:3-3:5 source.refactoring.range.kind.basename
|
||||||
source.edit.kind.active:
|
source.edit.kind.active:
|
||||||
3:8-3:10 source.refactoring.range.kind.basename
|
3:8-3:10 source.refactoring.range.kind.basename
|
||||||
|
source.edit.kind.active:
|
||||||
|
4:17-4:19 source.refactoring.range.kind.basename
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
func foo() {
|
func foo() {
|
||||||
var aa = 3
|
var aa = 3
|
||||||
aa = aa + 1
|
aa = aa + 1
|
||||||
|
_ = "before \(aa) after"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ source.edit.kind.active:
|
|||||||
3:3-3:5 "new_name"
|
3:3-3:5 "new_name"
|
||||||
source.edit.kind.active:
|
source.edit.kind.active:
|
||||||
3:8-3:10 "new_name"
|
3:8-3:10 "new_name"
|
||||||
|
source.edit.kind.active:
|
||||||
|
4:17-4:19 "new_name"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ let s = "a foo is here"
|
|||||||
#selector(AStruct.foo(a:))
|
#selector(AStruct.foo(a:))
|
||||||
#selector(AStruct.foo())
|
#selector(AStruct.foo())
|
||||||
#selector(AStruct.foo)
|
#selector(AStruct.foo)
|
||||||
let y = "before foo \(foo(a:1)) foo after"
|
let y = "before foo \(foo(a:1)) foo after foo"
|
||||||
|
|
||||||
func bar(a/* a comment */: Int, b c: Int, _: Int, _ d: Int) {}
|
func bar(a/* a comment */: Int, b c: Int, _: Int, _ d: Int) {}
|
||||||
bar(a: 1, b: 2, 3, 4)
|
bar(a: 1, b: 2, 3, 4)
|
||||||
|
|||||||
@@ -54,6 +54,11 @@
|
|||||||
"key.line": 26,
|
"key.line": 26,
|
||||||
"key.column": 33,
|
"key.column": 33,
|
||||||
"key.nametype": source.syntacticrename.unknown
|
"key.nametype": source.syntacticrename.unknown
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key.line": 26,
|
||||||
|
"key.column": 43,
|
||||||
|
"key.nametype": source.syntacticrename.unknown
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,3 +22,5 @@ source.edit.kind.active:
|
|||||||
26:27-26:28 "first"
|
26:27-26:28 "first"
|
||||||
source.edit.kind.string:
|
source.edit.kind.string:
|
||||||
26:33-26:36 "bar"
|
26:33-26:36 "bar"
|
||||||
|
source.edit.kind.string:
|
||||||
|
26:43-26:46 "bar"
|
||||||
|
|||||||
Reference in New Issue
Block a user