Files
swift-mirror/lib/IDE/SourceEntityWalker.cpp
Nathan Hawes bce68fa4e5 [IDE][Refactoring] Handle 'callAsFunction' specially in syntactic rename.
This change makes us treat it exactly as we do 'init'. We don't allow renaming the base name,
and don't fail if the basename doesn't match for calls.

Also:
  - explicit init calls/references like `MyType.init(42)` are now reported with
    'init' as a keywordBase range, rather than nothing.
  - cursor info no longer reports rename as available on init/callAsFunction
    calls without arguments, as there's nothing to rename in that case.
  - Improved detection of when a referenced function is a call (rather than
    reference) across syntactic rename, cursor-info, and indexing.

Resolves rdar://problem/60340429
2020-04-12 17:14:15 -07:00

843 lines
26 KiB
C++

//===--- SourceEntityWalker.cpp - Routines for semantic source info -------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Lexer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/Types.h"
#include "swift/Basic/SourceManager.h"
#include "clang/Basic/Module.h"
using namespace swift;
namespace {
class SemaAnnotator : public ASTWalker {
SourceEntityWalker &SEWalker;
SmallVector<ConstructorRefCallExpr *, 2> CtorRefs;
SmallVector<ExtensionDecl *, 2> ExtDecls;
llvm::SmallDenseMap<OpaqueValueExpr *, Expr *, 4> OpaqueValueMap;
llvm::SmallPtrSet<Expr *, 16> ExprsToSkip;
bool Cancelled = false;
Optional<AccessKind> OpAccess;
public:
explicit SemaAnnotator(SourceEntityWalker &SEWalker)
: SEWalker(SEWalker) { }
bool isDone() const { return Cancelled; }
private:
// FIXME: Remove this
bool shouldWalkAccessorsTheOldWay() override { return true; }
bool shouldWalkIntoGenericParams() override {
return SEWalker.shouldWalkIntoGenericParams();
}
bool walkToDeclPre(Decl *D) override;
std::pair<bool, Expr *> walkToExprPre(Expr *E) override;
bool walkToTypeReprPre(TypeRepr *T) override;
bool walkToDeclPost(Decl *D) override;
Expr *walkToExprPost(Expr *E) override;
bool walkToTypeReprPost(TypeRepr *T) override;
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override;
Stmt *walkToStmtPost(Stmt *S) override;
std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override;
bool handleImports(ImportDecl *Import);
bool handleCustomAttributes(Decl *D);
bool passModulePathElements(ArrayRef<ImportDecl::AccessPathElement> Path,
const clang::Module *ClangMod);
bool passReference(ValueDecl *D, Type Ty, SourceLoc Loc, SourceRange Range,
ReferenceMetaData Data);
bool passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data);
bool passReference(ModuleEntity Mod, Located<Identifier> IdLoc);
bool passSubscriptReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data, bool IsOpenBracket);
bool passCallAsFunctionReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data);
bool passCallArgNames(Expr *Fn, TupleExpr *TupleE);
bool shouldIgnore(Decl *D, bool &ShouldVisitChildren);
ValueDecl *extractDecl(Expr *Fn) const {
Fn = Fn->getSemanticsProvidingExpr();
if (auto *DRE = dyn_cast<DeclRefExpr>(Fn))
return DRE->getDecl();
if (auto ApplyE = dyn_cast<ApplyExpr>(Fn))
return extractDecl(ApplyE->getFn());
if (auto *ACE = dyn_cast<AutoClosureExpr>(Fn)) {
if (auto *Unwrapped = ACE->getUnwrappedCurryThunkExpr())
return extractDecl(Unwrapped);
}
return nullptr;
}
};
} // end anonymous namespace
bool SemaAnnotator::walkToDeclPre(Decl *D) {
if (isDone())
return false;
bool ShouldVisitChildren;
if (shouldIgnore(D, ShouldVisitChildren))
return ShouldVisitChildren;
if (!handleCustomAttributes(D)) {
Cancelled = true;
return false;
}
SourceLoc Loc = D->getLoc();
unsigned NameLen = 0;
bool IsExtension = false;
if (auto *VD = dyn_cast<ValueDecl>(D)) {
if (VD->hasName() && !VD->isImplicit())
NameLen = VD->getBaseName().userFacingName().size();
auto ReportParamList = [&](ParameterList *PL) {
for (auto *PD : *PL) {
auto Loc = PD->getArgumentNameLoc();
if (Loc.isInvalid())
continue;
if (!SEWalker.visitDeclarationArgumentName(PD->getArgumentName(), Loc,
VD)) {
Cancelled = true;
return true;
}
}
return false;
};
if (auto AF = dyn_cast<AbstractFunctionDecl>(VD)) {
if (ReportParamList(AF->getParameters()))
return false;
}
if (auto SD = dyn_cast<SubscriptDecl>(VD)) {
if (ReportParamList(SD->getIndices()))
return false;
}
} else if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
SourceRange SR = SourceRange();
if (auto *repr = ED->getExtendedTypeRepr())
SR = repr->getSourceRange();
Loc = SR.Start;
if (Loc.isValid())
NameLen = ED->getASTContext().SourceMgr.getByteDistance(SR.Start, SR.End);
IsExtension = true;
} else if (auto Import = dyn_cast<ImportDecl>(D)) {
if (!handleImports(Import))
return false;
} else if (auto OpD = dyn_cast<OperatorDecl>(D)) {
Loc = OpD->getLoc();
if (Loc.isValid())
NameLen = OpD->getName().getLength();
} else if (auto PrecD = dyn_cast<PrecedenceGroupDecl>(D)) {
Loc = PrecD->getLoc();
if (Loc.isValid())
NameLen = PrecD->getName().getLength();
} else if (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
if (SEWalker.shouldWalkInactiveConfigRegion()) {
for (auto Clause : ICD->getClauses()) {
for (auto Member : Clause.Elements) {
Member.walk(*this);
}
}
return false;
}
} else {
return true;
}
CharSourceRange Range = (Loc.isValid()) ? CharSourceRange(Loc, NameLen)
: CharSourceRange();
ShouldVisitChildren = SEWalker.walkToDeclPre(D, Range);
if (ShouldVisitChildren && IsExtension) {
ExtDecls.push_back(static_cast<ExtensionDecl*>(D));
}
return ShouldVisitChildren;
}
bool SemaAnnotator::walkToDeclPost(Decl *D) {
if (isDone())
return false;
bool ShouldVisitChildren;
if (shouldIgnore(D, ShouldVisitChildren))
return true;
if (isa<ExtensionDecl>(D)) {
assert(ExtDecls.back() == D);
ExtDecls.pop_back();
}
if (!isa<ValueDecl>(D) && !isa<ExtensionDecl>(D) && !isa<ImportDecl>(D) &&
!isa<IfConfigDecl>(D))
return true;
bool Continue = SEWalker.walkToDeclPost(D);
if (!Continue)
Cancelled = true;
return Continue;
}
std::pair<bool, Stmt *> SemaAnnotator::walkToStmtPre(Stmt *S) {
bool TraverseChildren = SEWalker.walkToStmtPre(S);
if (TraverseChildren) {
if (auto *DeferS = dyn_cast<DeferStmt>(S)) {
// Since 'DeferStmt::getTempDecl()' is marked as implicit, we manually
// walk into the body.
if (auto *FD = DeferS->getTempDecl()) {
auto *RetS = FD->getBody()->walk(*this);
if (!RetS)
return { false, nullptr };
assert(RetS == FD->getBody());
}
bool Continue = SEWalker.walkToStmtPost(DeferS);
if (!Continue)
Cancelled = true;
// Already walked children.
return { false, Continue ? DeferS : nullptr };
}
}
return { TraverseChildren, S };
}
Stmt *SemaAnnotator::walkToStmtPost(Stmt *S) {
bool Continue = SEWalker.walkToStmtPost(S);
if (!Continue)
Cancelled = true;
return Continue ? S : nullptr;
}
static SemaReferenceKind getReferenceKind(Expr *Parent, Expr *E) {
if (auto SA = dyn_cast_or_null<SelfApplyExpr>(Parent)) {
if (SA->getFn() == E)
return SemaReferenceKind::DeclMemberRef;
}
return SemaReferenceKind::DeclRef;
}
std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
assert(E);
std::pair<bool, Expr *> stopTraversal = { false, nullptr };
std::pair<bool, Expr *> skipChildren = { false, E };
auto doSkipChildren = [&]() -> std::pair<bool, Expr *> {
if (!SEWalker.walkToExprPost(E))
return stopTraversal;
return skipChildren;
};
if (isDone())
return stopTraversal;
if (ExprsToSkip.count(E) != 0)
return skipChildren;
if (!SEWalker.walkToExprPre(E))
return skipChildren;
if (auto *CtorRefE = dyn_cast<ConstructorRefCallExpr>(E))
CtorRefs.push_back(CtorRefE);
if (auto *ACE = dyn_cast<AutoClosureExpr>(E)) {
if (auto *SubExpr = ACE->getUnwrappedCurryThunkExpr()) {
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
if (!passReference(DRE->getDecl(), DRE->getType(),
DRE->getNameLoc(),
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
OpAccess)))
return stopTraversal;
return doSkipChildren();
}
}
return { true, E };
}
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
auto *FD = dyn_cast<FuncDecl>(DRE->getDecl());
// Handle implicit callAsFunction reference. An explicit reference will be
// handled by the usual DeclRefExpr case below.
if (DRE->isImplicit() && FD && FD->isCallAsFunctionMethod()) {
ReferenceMetaData data(SemaReferenceKind::DeclMemberRef, OpAccess);
if (!passCallAsFunctionReference(FD, DRE->getLoc(), data))
return {false, nullptr};
return {true, E};
}
}
if (!isa<InOutExpr>(E) &&
!isa<LoadExpr>(E) &&
!isa<OpenExistentialExpr>(E) &&
!isa<MakeTemporarilyEscapableExpr>(E) &&
!isa<CollectionUpcastConversionExpr>(E) &&
!isa<OpaqueValueExpr>(E) &&
!isa<SubscriptExpr>(E) &&
!isa<KeyPathExpr>(E) &&
E->isImplicit())
return { true, E };
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (auto *module = dyn_cast<ModuleDecl>(DRE->getDecl())) {
if (!passReference(ModuleEntity(module),
{module->getName(), E->getLoc()}))
return stopTraversal;
} else if (!passReference(DRE->getDecl(), DRE->getType(),
DRE->getNameLoc(),
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
OpAccess))) {
return stopTraversal;
}
} else if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
{
// This could be made more accurate if the member is nonmutating,
// or whatever.
Optional<AccessKind> NewOpAccess;
if (OpAccess) {
if (*OpAccess == AccessKind::Write)
NewOpAccess = AccessKind::ReadWrite;
else
NewOpAccess = OpAccess;
}
llvm::SaveAndRestore<Optional<AccessKind>>
C(this->OpAccess, NewOpAccess);
// Visit in source order.
if (!MRE->getBase()->walk(*this))
return stopTraversal;
}
if (!passReference(MRE->getMember().getDecl(), MRE->getType(),
MRE->getNameLoc(),
ReferenceMetaData(SemaReferenceKind::DeclMemberRef,
OpAccess)))
return stopTraversal;
// We already visited the children.
return doSkipChildren();
} else if (auto OtherCtorE = dyn_cast<OtherConstructorDeclRefExpr>(E)) {
if (!passReference(OtherCtorE->getDecl(), OtherCtorE->getType(),
OtherCtorE->getConstructorLoc(),
ReferenceMetaData(SemaReferenceKind::DeclConstructorRef,
OpAccess)))
return stopTraversal;
} else if (auto *SE = dyn_cast<SubscriptExpr>(E)) {
// Visit in source order.
if (!SE->getBase()->walk(*this))
return stopTraversal;
ValueDecl *SubscrD = nullptr;
if (SE->hasDecl())
SubscrD = SE->getDecl().getDecl();
ReferenceMetaData data(SemaReferenceKind::SubscriptRef, OpAccess,
SE->isImplicit());
if (SubscrD) {
if (!passSubscriptReference(SubscrD, E->getLoc(), data, true))
return stopTraversal;
}
if (!SE->getIndex()->walk(*this))
return stopTraversal;
if (SubscrD) {
if (!passSubscriptReference(SubscrD, E->getEndLoc(), data, false))
return stopTraversal;
}
// We already visited the children.
return doSkipChildren();
} else if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
for (auto &component : KPE->getComponents()) {
switch (component.getKind()) {
case KeyPathExpr::Component::Kind::Property:
case KeyPathExpr::Component::Kind::Subscript: {
auto *decl = component.getDeclRef().getDecl();
auto loc = component.getLoc();
SourceRange range(loc, loc);
passReference(decl, component.getComponentType(), loc, range,
ReferenceMetaData(
(isa<SubscriptDecl>(decl)
? SemaReferenceKind::SubscriptRef
: SemaReferenceKind::DeclMemberRef),
OpAccess));
break;
}
case KeyPathExpr::Component::Kind::TupleElement:
case KeyPathExpr::Component::Kind::Invalid:
case KeyPathExpr::Component::Kind::UnresolvedProperty:
case KeyPathExpr::Component::Kind::UnresolvedSubscript:
case KeyPathExpr::Component::Kind::OptionalChain:
case KeyPathExpr::Component::Kind::OptionalWrap:
case KeyPathExpr::Component::Kind::OptionalForce:
case KeyPathExpr::Component::Kind::Identity:
break;
}
}
} else if (auto *BinE = dyn_cast<BinaryExpr>(E)) {
// Visit in source order.
if (!BinE->getArg()->getElement(0)->walk(*this))
return stopTraversal;
if (!BinE->getFn()->walk(*this))
return stopTraversal;
if (!BinE->getArg()->getElement(1)->walk(*this))
return stopTraversal;
// We already visited the children.
return doSkipChildren();
} else if (auto TupleE = dyn_cast<TupleExpr>(E)) {
if (auto CallE = dyn_cast_or_null<CallExpr>(Parent.getAsExpr())) {
if (!passCallArgNames(CallE->getFn(), TupleE))
return stopTraversal;
}
} else if (auto IOE = dyn_cast<InOutExpr>(E)) {
llvm::SaveAndRestore<Optional<AccessKind>>
C(this->OpAccess, AccessKind::ReadWrite);
if (!IOE->getSubExpr()->walk(*this))
return stopTraversal;
// We already visited the children.
if (!walkToExprPost(E))
return stopTraversal;
return skipChildren;
} else if (auto LE = dyn_cast<LoadExpr>(E)) {
llvm::SaveAndRestore<Optional<AccessKind>>
C(this->OpAccess, AccessKind::Read);
if (!LE->getSubExpr()->walk(*this))
return stopTraversal;
// We already visited the children.
return doSkipChildren();
} else if (auto AE = dyn_cast<AssignExpr>(E)) {
{
llvm::SaveAndRestore<Optional<AccessKind>>
C(this->OpAccess, AccessKind::Write);
if (AE->getDest() && !AE->getDest()->walk(*this))
return stopTraversal;
}
if (AE->getSrc() && !AE->getSrc()->walk(*this))
return stopTraversal;
// We already visited the children.
return doSkipChildren();
} else if (auto OEE = dyn_cast<OpenExistentialExpr>(E)) {
// Record opaque value.
OpaqueValueMap[OEE->getOpaqueValue()] = OEE->getExistentialValue();
SWIFT_DEFER {
OpaqueValueMap.erase(OEE->getOpaqueValue());
};
if (!OEE->getSubExpr()->walk(*this))
return stopTraversal;
return doSkipChildren();
} else if (auto MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(E)) {
// Manually walk to original arguments in order. We don't handle
// OpaqueValueExpr here.
// Original non-escaping closure.
if (!MTEE->getNonescapingClosureValue()->walk(*this))
return stopTraversal;
// Body, which is called by synthesized CallExpr.
auto *callExpr = cast<CallExpr>(MTEE->getSubExpr());
if (!callExpr->getFn()->walk(*this))
return stopTraversal;
return doSkipChildren();
} else if (auto CUCE = dyn_cast<CollectionUpcastConversionExpr>(E)) {
// Ignore conversion expressions. We don't handle OpaqueValueExpr here
// because it's only in conversion expressions. Instead, just walk into
// sub expression.
if (!CUCE->getSubExpr()->walk(*this))
return stopTraversal;
return doSkipChildren();
} else if (auto OVE = dyn_cast<OpaqueValueExpr>(E)) {
// Walk into mapped value.
auto value = OpaqueValueMap.find(OVE);
if (value != OpaqueValueMap.end()) {
if (!value->second->walk(*this))
return stopTraversal;
return doSkipChildren();
}
}
return { true, E };
}
bool SemaAnnotator::walkToTypeReprPre(TypeRepr *T) {
if (isDone())
return false;
if (auto IdT = dyn_cast<ComponentIdentTypeRepr>(T)) {
if (ValueDecl *VD = IdT->getBoundDecl()) {
if (auto *ModD = dyn_cast<ModuleDecl>(VD)) {
auto ident = IdT->getNameRef().getBaseIdentifier();
return passReference(ModD, { ident, IdT->getLoc() });
}
return passReference(VD, Type(), IdT->getNameLoc(),
ReferenceMetaData(SemaReferenceKind::TypeRef, None));
}
}
return true;
}
Expr *SemaAnnotator::walkToExprPost(Expr *E) {
if (isa<ConstructorRefCallExpr>(E)) {
assert(CtorRefs.back() == E);
CtorRefs.pop_back();
}
bool Continue = SEWalker.walkToExprPost(E);
if (!Continue)
Cancelled = true;
return Continue ? E : nullptr;
}
bool SemaAnnotator::walkToTypeReprPost(TypeRepr *T) {
return !isDone();
}
std::pair<bool, Pattern *> SemaAnnotator::walkToPatternPre(Pattern *P) {
if (P->isImplicit())
return { true, P };
if (auto *EP = dyn_cast<EnumElementPattern>(P)) {
auto *Element = EP->getElementDecl();
if (!Element)
return { true, P };
Type T = EP->hasType() ? EP->getType() : Type();
return { passReference(Element, T, DeclNameLoc(EP->getLoc()),
ReferenceMetaData(SemaReferenceKind::EnumElementRef, None)), P };
}
auto *TP = dyn_cast<TypedPattern>(P);
if (!TP || !TP->isPropagatedType())
return { true, P };
// If the typed pattern was propagated from somewhere, just walk the
// subpattern. The type will be walked as a part of another TypedPattern.
TP->getSubPattern()->walk(*this);
return { false, P };
}
bool SemaAnnotator::handleCustomAttributes(Decl *D) {
// CustomAttrs of non-param VarDecls are handled when this method is called
// on their containing PatternBindingDecls (see below).
if (isa<VarDecl>(D) && !isa<ParamDecl>(D))
return true;
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
if (auto *SingleVar = PBD->getSingleVar()) {
D = SingleVar;
} else {
return true;
}
}
for (auto *customAttr : D->getAttrs().getAttributes<CustomAttr, true>()) {
if (auto *Repr = customAttr->getTypeLoc().getTypeRepr()) {
if (!Repr->walk(*this))
return false;
}
if (auto *SemaInit = customAttr->getSemanticInit()) {
if (!SemaInit->isImplicit()) {
assert(customAttr->getArg());
if (!SemaInit->walk(*this))
return false;
// Don't walk this again via the associated PatternBindingDecl's
// initializer
ExprsToSkip.insert(SemaInit);
}
} else if (auto *Arg = customAttr->getArg()) {
if (!Arg->walk(*this))
return false;
}
}
return true;
}
bool SemaAnnotator::handleImports(ImportDecl *Import) {
auto Mod = Import->getModule();
if (!Mod)
return true;
auto ClangMod = Mod->findUnderlyingClangModule();
if (ClangMod && ClangMod->isSubModule()) {
if (!passModulePathElements(Import->getModulePath(), ClangMod))
return false;
} else {
if (!passReference(Mod, Import->getModulePath().front()))
return false;
}
auto Decls = Import->getDecls();
if (Decls.size() == 1) {
// FIXME: ImportDecl should store a DeclNameLoc.
// FIXME: Handle overloaded funcs too by passing a reference for each?
if (!passReference(Decls.front(), Type(), DeclNameLoc(Import->getEndLoc()),
ReferenceMetaData(SemaReferenceKind::DeclRef, None)))
return false;
}
return true;
}
bool SemaAnnotator::passModulePathElements(
ArrayRef<ImportDecl::AccessPathElement> Path,
const clang::Module *ClangMod) {
if (Path.empty() || !ClangMod)
return true;
if (!passModulePathElements(Path.drop_back(1), ClangMod->Parent))
return false;
return passReference(ClangMod, Path.back());
}
bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data,
bool IsOpenBracket) {
CharSourceRange Range = Loc.isValid()
? CharSourceRange(Loc, 1)
: CharSourceRange();
bool Continue =
SEWalker.visitSubscriptReference(D, Range, Data, IsOpenBracket);
if (!Continue)
Cancelled = true;
return Continue;
}
bool SemaAnnotator::passCallAsFunctionReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data) {
CharSourceRange Range =
Loc.isValid() ? CharSourceRange(Loc, 1) : CharSourceRange();
bool Continue = SEWalker.visitCallAsFunctionReference(D, Range, Data);
if (!Continue)
Cancelled = true;
return Continue;
}
bool SemaAnnotator::
passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data) {
return passReference(D, Ty, Loc.getBaseNameLoc(), Loc.getSourceRange(), Data);
}
bool SemaAnnotator::
passReference(ValueDecl *D, Type Ty, SourceLoc BaseNameLoc, SourceRange Range,
ReferenceMetaData Data) {
TypeDecl *CtorTyRef = nullptr;
ExtensionDecl *ExtDecl = nullptr;
if (auto *TD = dyn_cast<TypeDecl>(D)) {
if (!CtorRefs.empty() && BaseNameLoc.isValid()) {
Expr *Fn = CtorRefs.back()->getFn();
if (Fn->getLoc() == BaseNameLoc) {
D = extractDecl(Fn);
CtorTyRef = TD;
}
}
if (!ExtDecls.empty() && BaseNameLoc.isValid()) {
SourceLoc ExtTyLoc = SourceLoc();
if (auto *repr = ExtDecls.back()->getExtendedTypeRepr())
ExtTyLoc = repr->getLoc();
if (ExtTyLoc.isValid() && ExtTyLoc == BaseNameLoc) {
ExtDecl = ExtDecls.back();
}
}
}
CharSourceRange CharRange =
Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr,
Range);
bool Continue = SEWalker.visitDeclReference(D, CharRange, CtorTyRef, ExtDecl,
Ty, Data);
if (!Continue)
Cancelled = true;
return Continue;
}
bool SemaAnnotator::passReference(ModuleEntity Mod,
Located<Identifier> IdLoc) {
if (IdLoc.Loc.isInvalid())
return true;
unsigned NameLen = IdLoc.Item.getLength();
CharSourceRange Range{ IdLoc.Loc, NameLen };
bool Continue = SEWalker.visitModuleReference(Mod, Range);
if (!Continue)
Cancelled = true;
return Continue;
}
bool SemaAnnotator::passCallArgNames(Expr *Fn, TupleExpr *TupleE) {
ValueDecl *D = extractDecl(Fn);
if (!D)
return true; // continue.
ArrayRef<Identifier> ArgNames = TupleE->getElementNames();
ArrayRef<SourceLoc> ArgLocs = TupleE->getElementNameLocs();
for (auto i : indices(ArgNames)) {
Identifier Name = ArgNames[i];
if (Name.empty())
continue;
SourceLoc Loc = ArgLocs[i];
if (Loc.isInvalid())
continue;
CharSourceRange Range{ Loc, Name.getLength() };
bool Continue = SEWalker.visitCallArgName(Name, Range, D);
if (!Continue) {
Cancelled = true;
return false;
}
}
return true;
}
bool SemaAnnotator::shouldIgnore(Decl *D, bool &ShouldVisitChildren) {
if (D->isImplicit() &&
!isa<PatternBindingDecl>(D) &&
!isa<ConstructorDecl>(D)) {
ShouldVisitChildren = false;
return true;
}
return false;
}
bool SourceEntityWalker::walk(SourceFile &SrcFile) {
SemaAnnotator Annotator(*this);
return SrcFile.walk(Annotator);
}
bool SourceEntityWalker::walk(ModuleDecl &Mod) {
SemaAnnotator Annotator(*this);
return Mod.walk(Annotator);
}
bool SourceEntityWalker::walk(Stmt *S) {
SemaAnnotator Annotator(*this);
return S->walk(Annotator);
}
bool SourceEntityWalker::walk(Expr *E) {
SemaAnnotator Annotator(*this);
return E->walk(Annotator);
}
bool SourceEntityWalker::walk(Decl *D) {
SemaAnnotator Annotator(*this);
return D->walk(Annotator);
}
bool SourceEntityWalker::walk(DeclContext *DC) {
SemaAnnotator Annotator(*this);
return DC->walkContext(Annotator);
}
bool SourceEntityWalker::walk(ASTNode N) {
if (auto *E = N.dyn_cast<Expr*>())
return walk(E);
if (auto *S = N.dyn_cast<Stmt*>())
return walk(S);
if (auto *D = N.dyn_cast<Decl*>())
return walk(D);
llvm_unreachable("unsupported AST node");
}
bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range,
TypeDecl *CtorTyRef,
ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) {
return true;
}
bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
CharSourceRange Range,
ReferenceMetaData Data,
bool IsOpenBracket) {
// Most of the clients treat subscript reference the same way as a
// regular reference when called on the open bracket and
// ignore the closing one.
return IsOpenBracket
? visitDeclReference(D, Range, nullptr, nullptr, Type(), Data)
: true;
}
bool SourceEntityWalker::visitCallAsFunctionReference(ValueDecl *D,
CharSourceRange Range,
ReferenceMetaData Data) {
return true;
}
bool SourceEntityWalker::visitCallArgName(Identifier Name,
CharSourceRange Range,
ValueDecl *D) {
return true;
}
bool SourceEntityWalker::
visitDeclarationArgumentName(Identifier Name, SourceLoc Start, ValueDecl *D) {
return true;
}
bool SourceEntityWalker::visitModuleReference(ModuleEntity Mod,
CharSourceRange Range) {
return true;
}
void SourceEntityWalker::anchor() {}