Merge pull request #63714 from ahoppen/ahoppen/ideinspectiontarget-charsourcerange

[IDE] Check whether an AST node contains the IDE inspection point based on `CharSourceRange`
This commit is contained in:
swift-ci
2023-02-20 10:20:45 -08:00
committed by GitHub
9 changed files with 64 additions and 28 deletions

View File

@@ -214,6 +214,13 @@ public:
(isBeforeInBuffer(R.Start, Loc) && isBeforeInBuffer(Loc, R.End)); (isBeforeInBuffer(R.Start, Loc) && isBeforeInBuffer(Loc, R.End));
} }
/// Returns true if range \c R contains the location \c Loc. The location
/// \c Loc should point at the beginning of the token.
bool rangeContainsTokenLoc(CharSourceRange R, SourceLoc Loc) const {
return Loc == R.getStart() || (isBeforeInBuffer(R.getStart(), Loc) &&
isBeforeInBuffer(Loc, R.getEnd()));
}
/// Returns true if range \c Enclosing contains the range \c Inner. /// Returns true if range \c Enclosing contains the range \c Inner.
bool rangeContains(SourceRange Enclosing, SourceRange Inner) const { bool rangeContains(SourceRange Enclosing, SourceRange Inner) const {
return rangeContainsTokenLoc(Enclosing, Inner.Start) && return rangeContainsTokenLoc(Enclosing, Inner.Start) &&
@@ -221,10 +228,11 @@ public:
} }
/// Returns true if range \p R contains the code-completion location, if any. /// Returns true if range \p R contains the code-completion location, if any.
bool rangeContainsIDEInspectionTarget(SourceRange R) const { bool rangeContainsIDEInspectionTarget(CharSourceRange R) const {
return IDEInspectionTargetBufferID if (!IDEInspectionTargetBufferID) {
? rangeContainsTokenLoc(R, getIDEInspectionTargetLoc()) return false;
: false; }
return rangeContainsTokenLoc(R, getIDEInspectionTargetLoc());
} }
/// Returns the buffer ID for the specified *valid* location. /// Returns the buffer ID for the specified *valid* location.

View File

@@ -126,6 +126,14 @@ private:
} }
}; };
/// Returns \c true if \p range is valid and contains the IDE inspection
/// target. This performs the underlying check based on \c CharSourceRange
/// to make sure we correctly return \c true if the ide inspection target
/// is inside a string literal that's the last token in \p range.
bool containsIDEInspectionTarget(SourceRange range,
const SourceManager &SourceMgr);
} // end namespace swift } // end namespace swift
#endif // SWIFT_SEMA_COMPLETIONCONTEXTFINDER_H #endif // SWIFT_SEMA_COMPLETIONCONTEXTFINDER_H

View File

@@ -8175,8 +8175,15 @@ BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
// Don't allow getBody() to trigger parsing of an unparsed body containing the // Don't allow getBody() to trigger parsing of an unparsed body containing the
// IDE inspection location. // IDE inspection location.
// FIXME: We should be properly constructing the range of the the body as a
// CharSourceRange but we can't because we don't have access to the lexer
// here. Using the end location of the SourceRange works good enough here
// because the last token is a '}' and the IDE inspection point is not inside
// the closing brace.
if (getBodyKind() == BodyKind::Unparsed && if (getBodyKind() == BodyKind::Unparsed &&
ctx.SourceMgr.rangeContainsIDEInspectionTarget(getBodySourceRange())) { ctx.SourceMgr.rangeContainsIDEInspectionTarget(
CharSourceRange(ctx.SourceMgr, getBodySourceRange().Start,
getBodySourceRange().End))) {
return nullptr; return nullptr;
} }

View File

@@ -7986,8 +7986,10 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
auto BodyPreviousLoc = PreviousLoc; auto BodyPreviousLoc = PreviousLoc;
SourceRange BodyRange(Tok.getLoc()); SourceRange BodyRange(Tok.getLoc());
auto setIDEInspectionDelayedDeclStateIfNeeded = [&] { auto setIDEInspectionDelayedDeclStateIfNeeded = [&] {
auto CharBodyRange =
Lexer::getCharSourceRangeFromSourceRange(SourceMgr, BodyRange);
if (!isIDEInspectionFirstPass() || if (!isIDEInspectionFirstPass() ||
!SourceMgr.rangeContainsIDEInspectionTarget(BodyRange)) { !SourceMgr.rangeContainsIDEInspectionTarget(CharBodyRange)) {
return; return;
} }
if (State->hasIDEInspectionDelayedDeclState()) if (State->hasIDEInspectionDelayedDeclState())

View File

@@ -1433,7 +1433,9 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
assert(activeElements.size() == 1 && activeElements[0].is<Expr *>()); assert(activeElements.size() == 1 && activeElements[0].is<Expr *>());
auto expr = activeElements[0].get<Expr *>(); auto expr = activeElements[0].get<Expr *>();
ParserStatus status(ICD); ParserStatus status(ICD);
if (SourceMgr.rangeContainsIDEInspectionTarget(expr->getSourceRange()) && auto charRange = Lexer::getCharSourceRangeFromSourceRange(
SourceMgr, expr->getSourceRange());
if (SourceMgr.rangeContainsIDEInspectionTarget(charRange) &&
L->isCodeCompletion()) L->isCodeCompletion())
status.setHasCodeCompletion(); status.setHasCodeCompletion();
hasBindOptional |= exprsWithBindOptional.contains(expr); hasBindOptional |= exprsWithBindOptional.contains(expr);
@@ -2826,7 +2828,9 @@ ParserResult<Expr> Parser::parseExprClosure() {
SmallVector<ASTNode, 4> bodyElements; SmallVector<ASTNode, 4> bodyElements;
Status |= parseBraceItems(bodyElements, BraceItemListKind::Brace); Status |= parseBraceItems(bodyElements, BraceItemListKind::Brace);
if (SourceMgr.rangeContainsIDEInspectionTarget({leftBrace, PreviousLoc})) { if (SourceMgr.rangeContainsIDEInspectionTarget(
Lexer::getCharSourceRangeFromSourceRange(SourceMgr,
{leftBrace, PreviousLoc}))) {
// Ignore 'IDEInspectionDelayedDeclState' inside closures. // Ignore 'IDEInspectionDelayedDeclState' inside closures.
// Completions inside functions body inside closures at top level should // Completions inside functions body inside closures at top level should
// be considered top-level completions. // be considered top-level completions.

View File

@@ -16,9 +16,8 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "MiscDiagnostics.h" #include "MiscDiagnostics.h"
#include "TypeChecker.h"
#include "TypeCheckAvailability.h" #include "TypeCheckAvailability.h"
#include "swift/Sema/IDETypeChecking.h" #include "TypeChecker.h"
#include "swift/AST/ASTPrinter.h" #include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h" #include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h" #include "swift/AST/ASTWalker.h"
@@ -27,14 +26,15 @@
#include "swift/AST/ParameterList.h" #include "swift/AST/ParameterList.h"
#include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeCheckRequests.h"
#include "swift/Sema/ConstraintSystem.h" #include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Sema/SolutionResult.h" #include "swift/Sema/SolutionResult.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include <iterator> #include <iterator>
#include <map> #include <map>
#include <memory> #include <memory>
#include <utility>
#include <tuple> #include <tuple>
#include <utility>
using namespace swift; using namespace swift;
using namespace constraints; using namespace constraints;

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "swift/Sema/CompletionContextFinder.h" #include "swift/Sema/CompletionContextFinder.h"
#include "swift/Parse/Lexer.h"
using namespace swift; using namespace swift;
using Fallback = CompletionContextFinder::Fallback; using Fallback = CompletionContextFinder::Fallback;
@@ -132,3 +133,11 @@ Optional<Fallback> CompletionContextFinder::getFallbackCompletionExpr() const {
return Fallback{getCompletionExpr(), fallbackDC, separatePrecheck}; return Fallback{getCompletionExpr(), fallbackDC, separatePrecheck};
return None; return None;
} }
bool swift::containsIDEInspectionTarget(SourceRange range,
const SourceManager &SourceMgr) {
if (range.isInvalid())
return false;
auto charRange = Lexer::getCharSourceRangeFromSourceRange(SourceMgr, range);
return SourceMgr.rangeContainsIDEInspectionTarget(charRange);
}

View File

@@ -31,6 +31,7 @@
#include "swift/Basic/Statistic.h" #include "swift/Basic/Statistic.h"
#include "swift/Sema/CSFix.h" #include "swift/Sema/CSFix.h"
#include "swift/Sema/ConstraintGraph.h" #include "swift/Sema/ConstraintGraph.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Sema/SolutionResult.h" #include "swift/Sema/SolutionResult.h"
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
@@ -353,18 +354,14 @@ ConstraintSystem::getAlternativeLiteralTypes(KnownProtocolKind kind,
} }
bool ConstraintSystem::containsIDEInspectionTarget(ASTNode node) const { bool ConstraintSystem::containsIDEInspectionTarget(ASTNode node) const {
SourceRange range = node.getSourceRange(); return swift::containsIDEInspectionTarget(node.getSourceRange(),
if (range.isInvalid()) Context.SourceMgr);
return false;
return Context.SourceMgr.rangeContainsIDEInspectionTarget(range);
} }
bool ConstraintSystem::containsIDEInspectionTarget( bool ConstraintSystem::containsIDEInspectionTarget(
const ArgumentList *args) const { const ArgumentList *args) const {
SourceRange range = args->getSourceRange(); return swift::containsIDEInspectionTarget(args->getSourceRange(),
if (range.isInvalid()) Context.SourceMgr);
return false;
return Context.SourceMgr.rangeContainsIDEInspectionTarget(range);
} }
ConstraintLocator *ConstraintSystem::getConstraintLocator( ConstraintLocator *ConstraintSystem::getConstraintLocator(

View File

@@ -14,14 +14,13 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "swift/Subsystems.h"
#include "TypeChecker.h"
#include "TypeCheckObjC.h"
#include "TypeCheckType.h"
#include "CodeSynthesis.h" #include "CodeSynthesis.h"
#include "MiscDiagnostics.h" #include "MiscDiagnostics.h"
#include "swift/AST/ASTWalker.h" #include "TypeCheckObjC.h"
#include "TypeCheckType.h"
#include "TypeChecker.h"
#include "swift/AST/ASTVisitor.h" #include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.h" #include "swift/AST/Attr.h"
#include "swift/AST/DiagnosticSuppression.h" #include "swift/AST/DiagnosticSuppression.h"
#include "swift/AST/ExistentialLayout.h" #include "swift/AST/ExistentialLayout.h"
@@ -37,13 +36,15 @@
#include "swift/AST/Type.h" #include "swift/AST/Type.h"
#include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h" #include "swift/Basic/Defer.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/STLExtras.h" #include "swift/Basic/STLExtras.h"
#include "swift/Basic/Statistic.h"
#include "swift/Parse/IDEInspectionCallbacks.h"
#include "swift/Parse/Lexer.h" #include "swift/Parse/Lexer.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/CompletionContextFinder.h" #include "swift/Sema/CompletionContextFinder.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Strings.h" #include "swift/Strings.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
@@ -565,7 +566,7 @@ bool TypeChecker::typeCheckForCodeCompletion(
{ {
auto range = target.getSourceRange(); auto range = target.getSourceRange();
if (range.isInvalid() || if (range.isInvalid() ||
!Context.SourceMgr.rangeContainsIDEInspectionTarget(range)) !containsIDEInspectionTarget(range, Context.SourceMgr))
return false; return false;
} }