1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
//===--- ExprContextAnalysis.cpp - Expession context analysis -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "ExprContextAnalysis.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/Basic/SourceManager.h"
#include "swift/IDE/CodeCompletionResult.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Subsystems.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/SmallSet.h"
using namespace swift;
using namespace ide;
//===----------------------------------------------------------------------===//
// typeCheckContextAt(DeclContext, SourceLoc)
//===----------------------------------------------------------------------===//
void swift::ide::typeCheckContextAt(TypeCheckASTNodeAtLocContext TypeCheckCtx,
SourceLoc Loc) {
// Make sure the extension has been bound.
auto DC = TypeCheckCtx.getDeclContext();
// Even if the extension is invalid (e.g. nested in a function or another
// type), we want to know the "intended nominal" of the extension so that
// we can know the type of 'Self'.
SmallVector<ExtensionDecl *, 1> extensions;
for (auto typeCtx = DC->getInnermostTypeContext(); typeCtx != nullptr;
typeCtx = typeCtx->getParent()->getInnermostTypeContext()) {
if (auto *ext = dyn_cast<ExtensionDecl>(typeCtx))
extensions.push_back(ext);
}
while (!extensions.empty()) {
extensions.back()->computeExtendedNominal();
extensions.pop_back();
}
// If the completion happens in the inheritance clause of the extension,
// 'DC' is the parent of the extension. We need to iterate the top level
// decls to find it. In theory, we don't need the extended nominal in the
// inheritance clause, but ASTScope lookup requires that. We don't care
// unless 'DC' is not 'SourceFile' because non-toplevel extensions are
// 'canNeverBeBound()' anyway.
if (auto *SF = dyn_cast<SourceFile>(DC)) {
auto &SM = DC->getASTContext().SourceMgr;
for (auto *decl : SF->getTopLevelDecls())
if (auto *ext = dyn_cast<ExtensionDecl>(decl))
if (SM.rangeContainsTokenLoc(ext->getSourceRange(), Loc))
ext->computeExtendedNominal();
}
swift::typeCheckASTNodeAtLoc(TypeCheckCtx, Loc);
}
//===----------------------------------------------------------------------===//
// findParsedExpr(DeclContext, Expr)
//===----------------------------------------------------------------------===//
namespace {
class ExprFinder : public ASTWalker {
SourceManager &SM;
SourceRange TargetRange;
Expr *FoundExpr = nullptr;
template <typename NodeType> bool isInterstingRange(NodeType *Node) {
return SM.rangeContains(Node->getSourceRange(), TargetRange);
}
bool shouldIgnore(Expr *E) {
// E.g. instanceOfDerived.methodInBaseReturningSelf().#^HERE^#'
// When calling a method in a base class returning 'Self', the call
// expression itself has the type of the base class. That is wrapped with
// CovariantReturnConversionExpr which downcasts it to the derived class.
if (isa<CovariantReturnConversionExpr>(E))
return false;
// E.g. TypeName(#^HERE^#
// In this case, we want the type expression instead of a reference to the
// initializer.
if (isa<ConstructorRefCallExpr>(E))
return true;
// Ignore other implicit expression.
if (E->isImplicit())
return true;
return false;
}
public:
ExprFinder(SourceManager &SM, SourceRange TargetRange)
: SM(SM), TargetRange(TargetRange) {}
Expr *get() const { return FoundExpr; }
MacroWalking getMacroWalkingBehavior() const override {
return MacroWalking::ArgumentsAndExpansion;
}
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
if (TargetRange == E->getSourceRange() && !shouldIgnore(E)) {
assert(!FoundExpr && "non-nullptr for found expr");
FoundExpr = E;
return Action::Stop();
}
return Action::VisitNodeIf(isInterstingRange(E), E);
}
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override {
return Action::VisitNodeIf(isInterstingRange(P), P);
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
return Action::VisitNodeIf(isInterstingRange(S), S);
}
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
return Action::SkipNode();
}
};
} // anonymous namespace
Expr *swift::ide::findParsedExpr(const DeclContext *DC,
SourceRange TargetRange) {
ExprFinder finder(DC->getASTContext().SourceMgr, TargetRange);
const_cast<DeclContext *>(DC)->walkContext(finder);
return finder.get();
}
|