Skip to content

Commit 392339c

Browse files
committed
use isBefore
1 parent 6e1e183 commit 392339c

File tree

2 files changed

+49
-34
lines changed

2 files changed

+49
-34
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,12 +2462,26 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
24622462
return MacroWalking::ArgumentsAndExpansion;
24632463
}
24642464

2465+
/// Checks whether the given range, when treated as a character range,
2466+
/// contains the searched location.
2467+
bool charRangeContainsLoc(SourceRange range) {
2468+
if (SM.isBefore(Loc, range.Start))
2469+
return false;
2470+
2471+
// NOTE: We need to check the character loc here because the target
2472+
// loc can be inside the last token of the node. i.e. interpolated
2473+
// string.
2474+
return SM.isBefore(Loc, Lexer::getLocForEndOfToken(SM, range.End));
2475+
}
2476+
24652477
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
24662478
if (auto *brace = dyn_cast<BraceStmt>(S)) {
2467-
auto braceCharRange = Lexer::getCharSourceRangeFromSourceRange(
2468-
SM, brace->getSourceRange());
2479+
auto braceRange = brace->getSourceRange();
2480+
auto braceCharRange = SourceRange(
2481+
braceRange.Start, Lexer::getLocForEndOfToken(SM, braceRange.End));
2482+
24692483
// Unless this brace contains the loc, there's nothing to do.
2470-
if (!braceCharRange.contains(Loc))
2484+
if (!SM.containsLoc(braceCharRange, Loc))
24712485
return Action::SkipNode(S);
24722486

24732487
// Reset the node found in a parent context if it's not part of this
@@ -2477,22 +2491,22 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
24772491
// syntactically part of the brace stmt's range but won't be walked as
24782492
// a child of the brace stmt.
24792493
if (!brace->isImplicit() && FoundNode) {
2480-
auto foundNodeCharRange = Lexer::getCharSourceRangeFromSourceRange(
2481-
SM, FoundNode->getSourceRange());
2482-
if (!braceCharRange.contains(foundNodeCharRange)) {
2494+
auto foundRange = FoundNode->getSourceRange();
2495+
auto foundCharRange = SourceRange(
2496+
foundRange.Start, Lexer::getLocForEndOfToken(SM, foundRange.End));
2497+
if (!SM.encloses(braceCharRange, foundCharRange))
24832498
FoundNode = nullptr;
2484-
}
24852499
}
24862500

24872501
for (ASTNode &node : brace->getElements()) {
2488-
if (SM.isBeforeInBuffer(Loc, node.getStartLoc()))
2502+
auto range = node.getSourceRange();
2503+
if (SM.isBefore(Loc, range.Start))
24892504
break;
24902505

24912506
// NOTE: We need to check the character loc here because the target
24922507
// loc can be inside the last token of the node. i.e. interpolated
24932508
// string.
2494-
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, node.getEndLoc());
2495-
if (SM.isBeforeInBuffer(endLoc, Loc) || endLoc == Loc)
2509+
if (!SM.isBefore(Loc, Lexer::getLocForEndOfToken(SM, range.End)))
24962510
continue;
24972511

24982512
// 'node' may be the target node, except 'CaseStmt' which cannot be
@@ -2509,13 +2523,11 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
25092523
return Action::Stop();
25102524
} else if (auto Conditional = dyn_cast<LabeledConditionalStmt>(S)) {
25112525
for (StmtConditionElement &Cond : Conditional->getCond()) {
2512-
if (SM.isBeforeInBuffer(Loc, Cond.getStartLoc())) {
2526+
auto range = Cond.getSourceRange();
2527+
if (SM.isBefore(Loc, range.Start))
25132528
break;
2514-
}
2515-
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, Cond.getEndLoc());
2516-
if (SM.isBeforeInBuffer(endLoc, Loc) || endLoc == Loc) {
2529+
if (!SM.isBefore(Loc, Lexer::getLocForEndOfToken(SM, range.End)))
25172530
continue;
2518-
}
25192531

25202532
FoundNodeStorage = ASTNode(&Cond);
25212533
FoundNode = &FoundNodeStorage;
@@ -2527,11 +2539,7 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
25272539
}
25282540

25292541
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
2530-
if (SM.isBeforeInBuffer(Loc, E->getStartLoc()))
2531-
return Action::SkipNode(E);
2532-
2533-
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, E->getEndLoc());
2534-
if (SM.isBeforeInBuffer(endLoc, Loc))
2542+
if (!charRangeContainsLoc(E->getSourceRange()))
25352543
return Action::SkipNode(E);
25362544

25372545
// Don't walk into 'TapExpr'. They should be type checked with parent
@@ -2546,9 +2554,7 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
25462554
if (auto *SVE = dyn_cast<SingleValueStmtExpr>(E)) {
25472555
SmallVector<Expr *> scratch;
25482556
for (auto *result : SVE->getResultExprs(scratch)) {
2549-
auto resultCharRange = Lexer::getCharSourceRangeFromSourceRange(
2550-
SM, result->getSourceRange());
2551-
if (resultCharRange.contains(Loc)) {
2557+
if (charRangeContainsLoc(result->getSourceRange())) {
25522558
if (!result->walk(*this))
25532559
return Action::Stop();
25542560

@@ -2570,20 +2576,20 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
25702576
}
25712577

25722578
PreWalkAction walkToDeclPre(Decl *D) override {
2579+
// Ignore implicit decls with no source range.
2580+
auto range = D->getSourceRange();
2581+
if (!range)
2582+
return Action::Continue();
2583+
2584+
if (!charRangeContainsLoc(range))
2585+
return Action::SkipNode();
2586+
25732587
if (auto *newDC = dyn_cast<DeclContext>(D))
25742588
DC = newDC;
25752589

2576-
if (!SM.isBeforeInBuffer(Loc, D->getStartLoc())) {
2577-
// NOTE: We need to check the character loc here because the target
2578-
// loc can be inside the last token of the node. i.e. interpolated
2579-
// string.
2580-
SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, D->getEndLoc());
2581-
if (!(SM.isBeforeInBuffer(endLoc, Loc) || endLoc == Loc)) {
2582-
if (!isa<TopLevelCodeDecl>(D)) {
2583-
FoundNodeStorage = ASTNode(D);
2584-
FoundNode = &FoundNodeStorage;
2585-
}
2586-
}
2590+
if (!isa<TopLevelCodeDecl>(D)) {
2591+
FoundNodeStorage = ASTNode(D);
2592+
FoundNode = &FoundNodeStorage;
25872593
}
25882594
return Action::Continue();
25892595
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %batch-code-completion
2+
3+
// Make sure we don't crash.
4+
func foo(xs: [[Int]], ys: [Int]) {
5+
for x in ys {
6+
_ = xs.map{ $0.filter{ $0 == x } #^COMPLETE^# }
7+
// COMPLETE: Begin completions
8+
}
9+
}

0 commit comments

Comments
 (0)