Skip to content

Commit cfe92f8

Browse files
committed
[CodeComplete] Fix issue with completion in string literal as last token in case stmt
The last token in a case stmt can be a string literal token, which can *contain* its interpolation segments. If one of these interpolation segments is the reference point, we'd return false from `isReferencePointInRange` because the string literal token's start location is before the interpolation token. To fix this, adjust the range we are checking to range until the end of the string interpolation token. Fixes rdar://76330416 [SR-14455]
1 parent 5cf19e4 commit cfe92f8

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

lib/AST/NameLookup.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,7 +2842,19 @@ void FindLocalVal::visitBraceStmt(BraceStmt *S, bool isTopLevelCode) {
28422842
if (SM.isBeforeInBuffer(Loc, S->getStartLoc()))
28432843
return;
28442844
} else {
2845-
if (!isReferencePointInRange(S->getSourceRange()))
2845+
SourceRange CheckRange = S->getSourceRange();
2846+
if (S->isImplicit()) {
2847+
// If the brace statement is implicit, it doesn't have an explicit '}'
2848+
// token. Thus, the last token in the brace stmt could be a string
2849+
// literal token, which can *contain* its interpolation segments.
2850+
// If one of these interpolation segments is the reference point, we'd
2851+
// return false from `isReferencePointInRange` because the string
2852+
// literal token's start location is before the interpolation token.
2853+
// To fix this, adjust the range we are checking to range until the end of
2854+
// the potential string interpolation token.
2855+
CheckRange.End = Lexer::getLocForEndOfToken(SM, CheckRange.End);
2856+
}
2857+
if (!isReferencePointInRange(CheckRange))
28462858
return;
28472859
}
28482860

@@ -2867,7 +2879,16 @@ void FindLocalVal::visitSwitchStmt(SwitchStmt *S) {
28672879
}
28682880

28692881
void FindLocalVal::visitCaseStmt(CaseStmt *S) {
2870-
if (!isReferencePointInRange(S->getSourceRange()))
2882+
// The last token in a case stmt can be a string literal token, which can
2883+
// *contain* its interpolation segments. If one of these interpolation
2884+
// segments is the reference point, we'd return false from
2885+
// `isReferencePointInRange` because the string literal token's start location
2886+
// is before the interpolation token. To fix this, adjust the range we are
2887+
// checking to range until the end of the potential string interpolation
2888+
// token.
2889+
SourceRange CheckRange = {S->getStartLoc(),
2890+
Lexer::getLocForEndOfToken(SM, S->getEndLoc())};
2891+
if (!isReferencePointInRange(CheckRange))
28712892
return;
28722893
// Pattern names aren't visible in the patterns themselves,
28732894
// just in the body or in where guards.

test/IDE/complete_sr14455.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE | %FileCheck %s
2+
3+
public enum Endpoint {
4+
  case movieDetail
5+
6+
7+
  func path() -> String {
8+
    switch self {
9+
    case .movieDetail:
10+
      let myInt: Int = 2
11+
      return "\(#^COMPLETE^#)"
12+
    }
13+
  }
14+
}
15+
// CHECK: Begin completions
16+
// CHECK: Decl[LocalVar]/Local/TypeRelation[Convertible]: myInt[#Int#];
17+
// CHECK: End completions

0 commit comments

Comments
 (0)