Skip to content

Commit 815e8cc

Browse files
authored
Merge pull request #63714 from ahoppen/ahoppen/ideinspectiontarget-charsourcerange
[IDE] Check whether an AST node contains the IDE inspection point based on `CharSourceRange`
2 parents 028596c + 8bdf68d commit 815e8cc

9 files changed

+64
-28
lines changed

include/swift/Basic/SourceManager.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,25 @@ class SourceManager {
214214
(isBeforeInBuffer(R.Start, Loc) && isBeforeInBuffer(Loc, R.End));
215215
}
216216

217+
/// Returns true if range \c R contains the location \c Loc. The location
218+
/// \c Loc should point at the beginning of the token.
219+
bool rangeContainsTokenLoc(CharSourceRange R, SourceLoc Loc) const {
220+
return Loc == R.getStart() || (isBeforeInBuffer(R.getStart(), Loc) &&
221+
isBeforeInBuffer(Loc, R.getEnd()));
222+
}
223+
217224
/// Returns true if range \c Enclosing contains the range \c Inner.
218225
bool rangeContains(SourceRange Enclosing, SourceRange Inner) const {
219226
return rangeContainsTokenLoc(Enclosing, Inner.Start) &&
220227
rangeContainsTokenLoc(Enclosing, Inner.End);
221228
}
222229

223230
/// Returns true if range \p R contains the code-completion location, if any.
224-
bool rangeContainsIDEInspectionTarget(SourceRange R) const {
225-
return IDEInspectionTargetBufferID
226-
? rangeContainsTokenLoc(R, getIDEInspectionTargetLoc())
227-
: false;
231+
bool rangeContainsIDEInspectionTarget(CharSourceRange R) const {
232+
if (!IDEInspectionTargetBufferID) {
233+
return false;
234+
}
235+
return rangeContainsTokenLoc(R, getIDEInspectionTargetLoc());
228236
}
229237

230238
/// Returns the buffer ID for the specified *valid* location.

include/swift/Sema/CompletionContextFinder.h

+8
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ class CompletionContextFinder : public ASTWalker {
126126
}
127127
};
128128

129+
130+
/// Returns \c true if \p range is valid and contains the IDE inspection
131+
/// target. This performs the underlying check based on \c CharSourceRange
132+
/// to make sure we correctly return \c true if the ide inspection target
133+
/// is inside a string literal that's the last token in \p range.
134+
bool containsIDEInspectionTarget(SourceRange range,
135+
const SourceManager &SourceMgr);
136+
129137
} // end namespace swift
130138

131139
#endif // SWIFT_SEMA_COMPLETIONCONTEXTFINDER_H

lib/AST/Decl.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -8175,8 +8175,15 @@ BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
81758175

81768176
// Don't allow getBody() to trigger parsing of an unparsed body containing the
81778177
// IDE inspection location.
8178+
// FIXME: We should be properly constructing the range of the the body as a
8179+
// CharSourceRange but we can't because we don't have access to the lexer
8180+
// here. Using the end location of the SourceRange works good enough here
8181+
// because the last token is a '}' and the IDE inspection point is not inside
8182+
// the closing brace.
81788183
if (getBodyKind() == BodyKind::Unparsed &&
8179-
ctx.SourceMgr.rangeContainsIDEInspectionTarget(getBodySourceRange())) {
8184+
ctx.SourceMgr.rangeContainsIDEInspectionTarget(
8185+
CharSourceRange(ctx.SourceMgr, getBodySourceRange().Start,
8186+
getBodySourceRange().End))) {
81808187
return nullptr;
81818188
}
81828189

lib/Parse/ParseDecl.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -7986,8 +7986,10 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
79867986
auto BodyPreviousLoc = PreviousLoc;
79877987
SourceRange BodyRange(Tok.getLoc());
79887988
auto setIDEInspectionDelayedDeclStateIfNeeded = [&] {
7989+
auto CharBodyRange =
7990+
Lexer::getCharSourceRangeFromSourceRange(SourceMgr, BodyRange);
79897991
if (!isIDEInspectionFirstPass() ||
7990-
!SourceMgr.rangeContainsIDEInspectionTarget(BodyRange)) {
7992+
!SourceMgr.rangeContainsIDEInspectionTarget(CharBodyRange)) {
79917993
return;
79927994
}
79937995
if (State->hasIDEInspectionDelayedDeclState())

lib/Parse/ParseExpr.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,9 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
14331433
assert(activeElements.size() == 1 && activeElements[0].is<Expr *>());
14341434
auto expr = activeElements[0].get<Expr *>();
14351435
ParserStatus status(ICD);
1436-
if (SourceMgr.rangeContainsIDEInspectionTarget(expr->getSourceRange()) &&
1436+
auto charRange = Lexer::getCharSourceRangeFromSourceRange(
1437+
SourceMgr, expr->getSourceRange());
1438+
if (SourceMgr.rangeContainsIDEInspectionTarget(charRange) &&
14371439
L->isCodeCompletion())
14381440
status.setHasCodeCompletion();
14391441
hasBindOptional |= exprsWithBindOptional.contains(expr);
@@ -2826,7 +2828,9 @@ ParserResult<Expr> Parser::parseExprClosure() {
28262828
SmallVector<ASTNode, 4> bodyElements;
28272829
Status |= parseBraceItems(bodyElements, BraceItemListKind::Brace);
28282830

2829-
if (SourceMgr.rangeContainsIDEInspectionTarget({leftBrace, PreviousLoc})) {
2831+
if (SourceMgr.rangeContainsIDEInspectionTarget(
2832+
Lexer::getCharSourceRangeFromSourceRange(SourceMgr,
2833+
{leftBrace, PreviousLoc}))) {
28302834
// Ignore 'IDEInspectionDelayedDeclState' inside closures.
28312835
// Completions inside functions body inside closures at top level should
28322836
// be considered top-level completions.

lib/Sema/BuilderTransform.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "MiscDiagnostics.h"
19-
#include "TypeChecker.h"
2019
#include "TypeCheckAvailability.h"
21-
#include "swift/Sema/IDETypeChecking.h"
20+
#include "TypeChecker.h"
2221
#include "swift/AST/ASTPrinter.h"
2322
#include "swift/AST/ASTVisitor.h"
2423
#include "swift/AST/ASTWalker.h"
@@ -27,14 +26,15 @@
2726
#include "swift/AST/ParameterList.h"
2827
#include "swift/AST/TypeCheckRequests.h"
2928
#include "swift/Sema/ConstraintSystem.h"
29+
#include "swift/Sema/IDETypeChecking.h"
3030
#include "swift/Sema/SolutionResult.h"
3131
#include "llvm/ADT/DenseMap.h"
3232
#include "llvm/ADT/SmallVector.h"
3333
#include <iterator>
3434
#include <map>
3535
#include <memory>
36-
#include <utility>
3736
#include <tuple>
37+
#include <utility>
3838

3939
using namespace swift;
4040
using namespace constraints;

lib/Sema/CompletionContextFinder.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Sema/CompletionContextFinder.h"
14+
#include "swift/Parse/Lexer.h"
1415

1516
using namespace swift;
1617
using Fallback = CompletionContextFinder::Fallback;
@@ -132,3 +133,11 @@ Optional<Fallback> CompletionContextFinder::getFallbackCompletionExpr() const {
132133
return Fallback{getCompletionExpr(), fallbackDC, separatePrecheck};
133134
return None;
134135
}
136+
137+
bool swift::containsIDEInspectionTarget(SourceRange range,
138+
const SourceManager &SourceMgr) {
139+
if (range.isInvalid())
140+
return false;
141+
auto charRange = Lexer::getCharSourceRangeFromSourceRange(SourceMgr, range);
142+
return SourceMgr.rangeContainsIDEInspectionTarget(charRange);
143+
}

lib/Sema/ConstraintSystem.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/Basic/Statistic.h"
3232
#include "swift/Sema/CSFix.h"
3333
#include "swift/Sema/ConstraintGraph.h"
34+
#include "swift/Sema/IDETypeChecking.h"
3435
#include "swift/Sema/SolutionResult.h"
3536
#include "llvm/ADT/SetVector.h"
3637
#include "llvm/ADT/SmallSet.h"
@@ -353,18 +354,14 @@ ConstraintSystem::getAlternativeLiteralTypes(KnownProtocolKind kind,
353354
}
354355

355356
bool ConstraintSystem::containsIDEInspectionTarget(ASTNode node) const {
356-
SourceRange range = node.getSourceRange();
357-
if (range.isInvalid())
358-
return false;
359-
return Context.SourceMgr.rangeContainsIDEInspectionTarget(range);
357+
return swift::containsIDEInspectionTarget(node.getSourceRange(),
358+
Context.SourceMgr);
360359
}
361360

362361
bool ConstraintSystem::containsIDEInspectionTarget(
363362
const ArgumentList *args) const {
364-
SourceRange range = args->getSourceRange();
365-
if (range.isInvalid())
366-
return false;
367-
return Context.SourceMgr.rangeContainsIDEInspectionTarget(range);
363+
return swift::containsIDEInspectionTarget(args->getSourceRange(),
364+
Context.SourceMgr);
368365
}
369366

370367
ConstraintLocator *ConstraintSystem::getConstraintLocator(

lib/Sema/TypeCheckCodeCompletion.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#include "swift/Subsystems.h"
18-
#include "TypeChecker.h"
19-
#include "TypeCheckObjC.h"
20-
#include "TypeCheckType.h"
2117
#include "CodeSynthesis.h"
2218
#include "MiscDiagnostics.h"
23-
#include "swift/AST/ASTWalker.h"
19+
#include "TypeCheckObjC.h"
20+
#include "TypeCheckType.h"
21+
#include "TypeChecker.h"
2422
#include "swift/AST/ASTVisitor.h"
23+
#include "swift/AST/ASTWalker.h"
2524
#include "swift/AST/Attr.h"
2625
#include "swift/AST/DiagnosticSuppression.h"
2726
#include "swift/AST/ExistentialLayout.h"
@@ -37,13 +36,15 @@
3736
#include "swift/AST/Type.h"
3837
#include "swift/AST/TypeCheckRequests.h"
3938
#include "swift/Basic/Defer.h"
40-
#include "swift/Basic/Statistic.h"
4139
#include "swift/Basic/STLExtras.h"
40+
#include "swift/Basic/Statistic.h"
41+
#include "swift/Parse/IDEInspectionCallbacks.h"
4242
#include "swift/Parse/Lexer.h"
43-
#include "swift/Sema/IDETypeChecking.h"
44-
#include "swift/Sema/ConstraintSystem.h"
4543
#include "swift/Sema/CompletionContextFinder.h"
44+
#include "swift/Sema/ConstraintSystem.h"
45+
#include "swift/Sema/IDETypeChecking.h"
4646
#include "swift/Strings.h"
47+
#include "swift/Subsystems.h"
4748
#include "llvm/ADT/DenseMap.h"
4849
#include "llvm/ADT/PointerUnion.h"
4950
#include "llvm/ADT/SmallSet.h"
@@ -565,7 +566,7 @@ bool TypeChecker::typeCheckForCodeCompletion(
565566
{
566567
auto range = target.getSourceRange();
567568
if (range.isInvalid() ||
568-
!Context.SourceMgr.rangeContainsIDEInspectionTarget(range))
569+
!containsIDEInspectionTarget(range, Context.SourceMgr))
569570
return false;
570571
}
571572

0 commit comments

Comments
 (0)