mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #6677 from nathawes/swift-indexing
Add roles and relations for Swift indexing
This commit is contained in:
@@ -190,8 +190,8 @@ public:
|
||||
virtual bool walkToTypeReprPost(TypeRepr *T) { return true; }
|
||||
|
||||
/// This method configures whether the walker should explore into the generic
|
||||
/// params in an AbstractFunctionDecl.
|
||||
virtual bool shouldWalkIntoFunctionGenericParams() { return false; }
|
||||
/// params in AbstractFunctionDecl and NominalTypeDecl.
|
||||
virtual bool shouldWalkIntoGenericParams() { return false; }
|
||||
|
||||
/// walkToParameterListPre - This method is called when first visiting a
|
||||
/// ParameterList, before walking into its parameters. If it returns false,
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
/// Whether walk into the inactive region in a #if config statement.
|
||||
virtual bool shouldWalkInactiveConfigRegion() { return false; }
|
||||
|
||||
virtual bool shouldWalkIntoFunctionGenericParams() { return true; }
|
||||
virtual bool shouldWalkIntoGenericParams() { return true; }
|
||||
|
||||
protected:
|
||||
SourceEntityWalker() = default;
|
||||
|
||||
@@ -22,6 +22,8 @@ class IndexDataConsumer {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
enum Action {Skip, Abort, Continue};
|
||||
|
||||
virtual ~IndexDataConsumer() {}
|
||||
|
||||
virtual void failed(StringRef error) = 0;
|
||||
@@ -32,8 +34,7 @@ public:
|
||||
virtual bool startDependency(SymbolKind kind, StringRef name, StringRef path,
|
||||
bool isSystem, StringRef hash) = 0;
|
||||
virtual bool finishDependency(SymbolKind kind) = 0;
|
||||
virtual bool startSourceEntity(const IndexSymbol &symbol) = 0;
|
||||
virtual bool recordRelatedEntity(const IndexSymbol &symbol) = 0;
|
||||
virtual Action startSourceEntity(const IndexSymbol &symbol) = 0;
|
||||
virtual bool finishSourceEntity(SymbolKind kind, SymbolSubKindSet subKinds,
|
||||
SymbolRoleSet roles) = 0;
|
||||
|
||||
|
||||
@@ -92,25 +92,48 @@ inline SymbolSubKindSet &operator|=(SymbolSubKindSet &SKSet, SymbolSubKind SK) {
|
||||
using SymbolRole = clang::index::SymbolRole;
|
||||
using SymbolRoleSet = clang::index::SymbolRoleSet;
|
||||
|
||||
struct IndexSymbol {
|
||||
struct IndexRelation {
|
||||
const ValueDecl *decl;
|
||||
SymbolKind kind;
|
||||
SymbolSubKindSet subKinds = SymbolSubKindSet(0);
|
||||
SymbolRoleSet roles = SymbolRoleSet(0);
|
||||
|
||||
// The following strings are guaranteed to live at least as long as the
|
||||
// current indexing action.
|
||||
StringRef name;
|
||||
StringRef USR; // USR may be safely compared by pointer.
|
||||
StringRef group;
|
||||
StringRef receiverUSR;
|
||||
|
||||
IndexRelation(SymbolRoleSet Roles, const ValueDecl *Sym, SymbolKind Kind, SymbolSubKindSet SubKinds, StringRef Name, StringRef USR)
|
||||
: decl(Sym), kind(Kind), subKinds(SubKinds), roles(Roles), name(Name), USR(USR) {}
|
||||
|
||||
IndexRelation() = default;
|
||||
};
|
||||
|
||||
struct IndexSymbol : IndexRelation {
|
||||
SmallVector<IndexRelation, 3> Relations;
|
||||
unsigned line = 0;
|
||||
unsigned column = 0;
|
||||
|
||||
IndexSymbol() = default;
|
||||
|
||||
StringRef getReceiverUSR() const {
|
||||
for(auto Relation: Relations) {
|
||||
if (Relation.roles & (SymbolRoleSet) SymbolRole::RelationReceivedBy)
|
||||
return Relation.USR;
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
};
|
||||
|
||||
SymbolKind getSymbolKindForDecl(const Decl *D);
|
||||
|
||||
StringRef getSymbolKindString(SymbolKind K);
|
||||
|
||||
void applyForEachSymbolSubKind(SymbolSubKindSet SubKinds,
|
||||
llvm::function_ref<void(SymbolSubKind)> Fn);
|
||||
void printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS);
|
||||
|
||||
} // end namespace index
|
||||
} // end namespace swift
|
||||
|
||||
|
||||
@@ -201,10 +201,29 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
|
||||
}
|
||||
|
||||
bool visitNominalTypeDecl(NominalTypeDecl *NTD) {
|
||||
if (auto GPS = NTD->getGenericParams()) {
|
||||
for (auto GP : GPS->getParams()) {
|
||||
if (NTD->getGenericParams() &&
|
||||
Walker.shouldWalkIntoGenericParams()) {
|
||||
// Visit generic params
|
||||
for (auto GP : NTD->getGenericParams()->getParams()) {
|
||||
if (doIt(GP))
|
||||
return true;
|
||||
for(auto Inherit: GP->getInherited()) {
|
||||
if (doIt(Inherit))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Visit param conformance
|
||||
for (auto &Req : NTD->getGenericParams()->getRequirements()) {
|
||||
switch (Req.getKind()) {
|
||||
case RequirementReprKind::SameType:
|
||||
if (doIt(Req.getFirstTypeLoc()) || doIt(Req.getSecondTypeLoc()))
|
||||
return true;
|
||||
break;
|
||||
case RequirementReprKind::TypeConstraint:
|
||||
if (doIt(Req.getSubjectLoc()) || doIt(Req.getConstraintLoc()))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +256,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
|
||||
PrettyStackTraceDecl debugStack("walking into body of", AFD);
|
||||
#endif
|
||||
if (AFD->getGenericParams() &&
|
||||
Walker.shouldWalkIntoFunctionGenericParams()) {
|
||||
Walker.shouldWalkIntoGenericParams()) {
|
||||
|
||||
// Visit generic params
|
||||
for (auto &P : AFD->getGenericParams()->getParams()) {
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
bool isDone() const { return Cancelled; }
|
||||
|
||||
private:
|
||||
bool shouldWalkIntoFunctionGenericParams() override {
|
||||
return SEWalker.shouldWalkIntoFunctionGenericParams();
|
||||
bool shouldWalkIntoGenericParams() override {
|
||||
return SEWalker.shouldWalkIntoGenericParams();
|
||||
}
|
||||
bool walkToDeclPre(Decl *D) override;
|
||||
std::pair<bool, Expr *> walkToExprPre(Expr *E) override;
|
||||
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
bool walkToDeclPost(Decl *D) override;
|
||||
bool walkToTypeReprPre(TypeRepr *T) override;
|
||||
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override;
|
||||
bool shouldWalkIntoFunctionGenericParams() override { return true; }
|
||||
bool shouldWalkIntoGenericParams() override { return true; }
|
||||
|
||||
private:
|
||||
static bool findUrlStartingLoc(StringRef Text, unsigned &Start,
|
||||
|
||||
@@ -18,29 +18,43 @@
|
||||
#include "swift/Basic/SourceManager.h"
|
||||
#include "swift/Basic/StringExtras.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::index;
|
||||
|
||||
static SymbolSubKind getSubKindForAccessor(AccessorKind AK) {
|
||||
switch (AK) {
|
||||
case AccessorKind::NotAccessor: return SymbolSubKind::None;
|
||||
case AccessorKind::IsGetter: return SymbolSubKind::AccessorGetter;
|
||||
case AccessorKind::IsSetter: return SymbolSubKind::AccessorSetter;
|
||||
case AccessorKind::IsWillSet: return SymbolSubKind::AccessorWillSet;
|
||||
case AccessorKind::IsDidSet: return SymbolSubKind::AccessorDidSet;
|
||||
case AccessorKind::IsAddressor: return SymbolSubKind::AccessorAddressor;
|
||||
case AccessorKind::IsMutableAddressor:
|
||||
return SymbolSubKind::AccessorMutableAddressor;
|
||||
case AccessorKind::IsMaterializeForSet:
|
||||
llvm_unreachable("unexpected MaterializeForSet");
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled AccessorKind in switch.");
|
||||
}
|
||||
|
||||
static bool
|
||||
printArtificialName(const swift::ValueDecl *VD, llvm::raw_ostream &OS) {
|
||||
auto *FD = dyn_cast<FuncDecl>(VD);
|
||||
if (!FD)
|
||||
return true;
|
||||
switch (FD->getAccessorKind()) {
|
||||
printArtificialName(const swift::AbstractStorageDecl *ASD, AccessorKind AK, llvm::raw_ostream &OS) {
|
||||
switch (AK) {
|
||||
case AccessorKind::IsGetter:
|
||||
OS << "getter:" << FD->getAccessorStorageDecl()->getFullName();
|
||||
OS << "getter:" << ASD->getFullName();
|
||||
return false;
|
||||
case AccessorKind::IsSetter:
|
||||
OS << "setter:" << FD->getAccessorStorageDecl()->getFullName();
|
||||
OS << "setter:" << ASD->getFullName();
|
||||
return false;
|
||||
case AccessorKind::IsDidSet:
|
||||
OS << "didSet:" << FD->getAccessorStorageDecl()->getFullName();
|
||||
OS << "didSet:" << ASD->getFullName();
|
||||
return false;
|
||||
case AccessorKind::IsWillSet:
|
||||
OS << "willSet:" << FD->getAccessorStorageDecl()->getFullName() ;
|
||||
OS << "willSet:" << ASD->getFullName() ;
|
||||
return false;
|
||||
|
||||
case AccessorKind::NotAccessor:
|
||||
@@ -54,8 +68,12 @@ printArtificialName(const swift::ValueDecl *VD, llvm::raw_ostream &OS) {
|
||||
}
|
||||
|
||||
static bool printDisplayName(const swift::ValueDecl *D, llvm::raw_ostream &OS) {
|
||||
if (!D->hasName())
|
||||
return printArtificialName(D, OS);
|
||||
if (!D->hasName()) {
|
||||
auto *FD = dyn_cast<FuncDecl>(D);
|
||||
if (!FD || FD->getAccessorKind() == AccessorKind::NotAccessor)
|
||||
return true;
|
||||
return printArtificialName(FD->getAccessorStorageDecl(), FD->getAccessorKind(), OS);
|
||||
}
|
||||
|
||||
OS << D->getFullName();
|
||||
return false;
|
||||
@@ -117,6 +135,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
|
||||
SymbolKind Kind;
|
||||
SymbolSubKindSet SubKinds;
|
||||
SymbolRoleSet Roles;
|
||||
SmallVector<SourceLoc, 6> RefsToSuppress;
|
||||
};
|
||||
SmallVector<Entity, 6> EntitiesStack;
|
||||
SmallVector<Expr *, 8> ExprStack;
|
||||
@@ -128,7 +147,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
|
||||
};
|
||||
typedef llvm::PointerIntPair<Decl *, 3> DeclAccessorPair;
|
||||
llvm::DenseMap<Decl *, NameAndUSR> nameAndUSRCache;
|
||||
llvm::DenseMap<DeclAccessorPair, StringRef> accessorUSRCache;
|
||||
llvm::DenseMap<DeclAccessorPair, NameAndUSR> accessorNameAndUSRCache;
|
||||
StringScratchSpace stringStorage;
|
||||
|
||||
bool getNameAndUSR(ValueDecl *D, StringRef &name, StringRef &USR) {
|
||||
@@ -155,20 +174,53 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
|
||||
return false;
|
||||
}
|
||||
|
||||
StringRef getAccessorUSR(AbstractStorageDecl *D, AccessorKind AK) {
|
||||
bool getPseudoAccessorNameAndUSR(AbstractStorageDecl *D, AccessorKind AK, StringRef &Name, StringRef &USR) {
|
||||
assert(AK != AccessorKind::NotAccessor);
|
||||
assert(static_cast<int>(AK) < 0x111 && "AccessorKind too big for pair");
|
||||
DeclAccessorPair key(D, static_cast<int>(AK));
|
||||
auto &result = accessorUSRCache[key];
|
||||
if (result.empty()) {
|
||||
auto &result = accessorNameAndUSRCache[key];
|
||||
if (result.USR.empty()) {
|
||||
SmallString<128> storage;
|
||||
llvm::raw_svector_ostream OS(storage);
|
||||
ide::printAccessorUSR(D, AK, OS);
|
||||
result = stringStorage.copyString(OS.str());
|
||||
{
|
||||
llvm::raw_svector_ostream OS(storage);
|
||||
if(ide::printAccessorUSR(D, AK, OS))
|
||||
return true;
|
||||
result.USR = stringStorage.copyString(OS.str());
|
||||
}
|
||||
|
||||
storage.clear();
|
||||
{
|
||||
llvm::raw_svector_ostream OS(storage);
|
||||
printArtificialName(D, AK, OS);
|
||||
result.name = stringStorage.copyString(OS.str());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Name = result.name;
|
||||
USR = result.USR;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool addRelation(IndexSymbol &Info, SymbolRoleSet RelationRoles, ValueDecl *D) {
|
||||
assert(D);
|
||||
StringRef Name, USR;
|
||||
SymbolKind Kind = getSymbolKindForDecl(D);
|
||||
SymbolSubKindSet SubKinds = 0;
|
||||
|
||||
if (Kind == SymbolKind::Unknown)
|
||||
return true;
|
||||
if (Kind == SymbolKind::Accessor)
|
||||
SubKinds |= getSubKindForAccessor(cast<FuncDecl>(D)->getAccessorKind());
|
||||
if (getNameAndUSR(D, Name, USR))
|
||||
return true;
|
||||
|
||||
Info.Relations.push_back(IndexRelation(RelationRoles, D, Kind, SubKinds, Name, USR));
|
||||
Info.roles |= RelationRoles;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
IndexSwiftASTWalker(IndexDataConsumer &IdxConsumer, ASTContext &Ctx,
|
||||
unsigned BufferID)
|
||||
@@ -250,10 +302,15 @@ private:
|
||||
TypeDecl *CtorTyRef, Type T,
|
||||
SemaReferenceKind Kind) override {
|
||||
SourceLoc Loc = Range.getStart();
|
||||
|
||||
if (isRepressed(Loc) || Loc.isInvalid())
|
||||
return true;
|
||||
|
||||
IndexSymbol Info;
|
||||
if (CtorTyRef)
|
||||
if (!reportRef(CtorTyRef, Loc))
|
||||
if (!reportRef(CtorTyRef, Loc, Info))
|
||||
return false;
|
||||
if (!reportRef(D, Loc))
|
||||
if (!reportRef(D, Loc, Info))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -265,6 +322,19 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void repressRefAtLoc(SourceLoc Loc) {
|
||||
assert(!EntitiesStack.empty());
|
||||
EntitiesStack.back().RefsToSuppress.push_back(Loc);
|
||||
}
|
||||
|
||||
bool isRepressed(SourceLoc Loc) {
|
||||
if (EntitiesStack.empty())
|
||||
return false;
|
||||
auto &Suppressed = EntitiesStack.back().RefsToSuppress;
|
||||
return std::find(Suppressed.begin(), Suppressed.end(), Loc) != Suppressed.end();
|
||||
|
||||
}
|
||||
|
||||
Expr *getCurrentExpr() {
|
||||
return ExprStack.empty() ? nullptr : ExprStack.back();
|
||||
}
|
||||
@@ -275,18 +345,17 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool reportExtension(ExtensionDecl *D);
|
||||
|
||||
bool report(ValueDecl *D);
|
||||
bool reportRef(ValueDecl *D, SourceLoc Loc);
|
||||
bool reportExtension(ExtensionDecl *D);
|
||||
bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
|
||||
|
||||
bool startEntity(Decl *D, IndexSymbol &Info);
|
||||
bool startEntityDecl(ValueDecl *D);
|
||||
bool startEntityRef(ValueDecl *D, SourceLoc Loc);
|
||||
bool startEntity(ValueDecl *D, const IndexSymbol &Info);
|
||||
|
||||
bool passRelated(ValueDecl *D, SourceLoc Loc);
|
||||
bool passInheritedTypes(ArrayRef<TypeLoc> Inherited);
|
||||
bool passRelatedType(const TypeLoc &Ty);
|
||||
bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, SymbolRoleSet Relations, ValueDecl *Related);
|
||||
bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, ValueDecl *Related);
|
||||
bool reportInheritedTypeRefs(ArrayRef<TypeLoc> Inherited, ValueDecl *Inheritee);
|
||||
NominalTypeDecl *getTypeLocAsNominalTypeDecl(const TypeLoc &Ty);
|
||||
|
||||
bool reportPseudoGetterDecl(VarDecl *D) {
|
||||
@@ -316,6 +385,8 @@ private:
|
||||
bool initFuncDeclIndexSymbol(ValueDecl *D, IndexSymbol &Info);
|
||||
bool initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE, ValueDecl *D,
|
||||
SourceLoc Loc, IndexSymbol &Info);
|
||||
bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
|
||||
IndexSymbol &Info);
|
||||
|
||||
std::pair<unsigned, unsigned> getLineCol(SourceLoc Loc) {
|
||||
if (Loc.isInvalid())
|
||||
@@ -484,6 +555,19 @@ bool IndexSwiftASTWalker::visitImports(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::startEntity(Decl *D, IndexSymbol &Info) {
|
||||
switch (IdxConsumer.startSourceEntity(Info)) {
|
||||
case swift::index::IndexDataConsumer::Abort:
|
||||
Cancelled = true;
|
||||
LLVM_FALLTHROUGH;
|
||||
case swift::index::IndexDataConsumer::Skip:
|
||||
return false;
|
||||
case swift::index::IndexDataConsumer::Continue:
|
||||
EntitiesStack.push_back({D, Info.kind, Info.subKinds, Info.roles, {}});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
|
||||
if (!shouldIndex(D))
|
||||
return false;
|
||||
@@ -492,153 +576,129 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
|
||||
if (Loc.isInvalid() && !IsModuleFile)
|
||||
return false;
|
||||
|
||||
IndexSymbol Info;
|
||||
if (isa<FuncDecl>(D)) {
|
||||
IndexSymbol Info;
|
||||
if (initFuncDeclIndexSymbol(D, Info))
|
||||
return false;
|
||||
|
||||
return startEntity(D, Info);
|
||||
|
||||
} else {
|
||||
IndexSymbol Info;
|
||||
if (initIndexSymbol(D, Loc, /*IsRef=*/false, Info))
|
||||
return false;
|
||||
|
||||
return startEntity(D, Info);
|
||||
}
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::startEntityRef(ValueDecl *D, SourceLoc Loc) {
|
||||
if (!shouldIndex(D))
|
||||
return false;
|
||||
|
||||
if (Loc.isInvalid())
|
||||
return false;
|
||||
|
||||
if (isa<AbstractFunctionDecl>(D)) {
|
||||
IndexSymbol Info;
|
||||
if (initCallRefIndexSymbol(getCurrentExpr(), getParentExpr(), D, Loc, Info))
|
||||
if (auto Overridden = D->getOverriddenDecl()) {
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overridden))
|
||||
return false;
|
||||
|
||||
return startEntity(D, Info);
|
||||
|
||||
} else {
|
||||
IndexSymbol Info;
|
||||
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
|
||||
}
|
||||
for (auto Conf : D->getSatisfiedProtocolRequirements()) {
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Conf))
|
||||
return false;
|
||||
|
||||
return startEntity(D, Info);
|
||||
}
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::startEntity(ValueDecl *D, const IndexSymbol &Info) {
|
||||
if (!IdxConsumer.startSourceEntity(Info)) {
|
||||
Cancelled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
EntitiesStack.push_back({D, Info.kind, Info.subKinds, Info.roles});
|
||||
return true;
|
||||
if (auto Parent = getParentDecl()) {
|
||||
// FIXME handle extensions properly
|
||||
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
|
||||
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
|
||||
if (Info.kind == SymbolKind::Accessor)
|
||||
RelationsToParent |= (SymbolRoleSet)SymbolRole::RelationAccessorOf;
|
||||
if (addRelation(Info, RelationsToParent, ParentVD))
|
||||
return false;
|
||||
|
||||
} else if (auto ParentED = dyn_cast<ExtensionDecl>(Parent)) {
|
||||
if (NominalTypeDecl *NTD = ParentED->getExtendedType()->getAnyNominal()) {
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationChildOf, NTD))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return startEntity(D, Info);
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::passRelated(ValueDecl *D, SourceLoc Loc) {
|
||||
bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, SymbolRoleSet Relations, ValueDecl *Related) {
|
||||
if (!shouldIndex(D))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
IndexSymbol Info;
|
||||
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
|
||||
return false;
|
||||
if (addRelation(Info, Relations, Related))
|
||||
return true;
|
||||
|
||||
if (!IdxConsumer.recordRelatedEntity(Info)) {
|
||||
// don't report this ref again when visitDeclReference reports it
|
||||
repressRefAtLoc(Loc);
|
||||
|
||||
if(!reportRef(D, Loc, Info)) {
|
||||
Cancelled = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return !Cancelled;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::passInheritedTypes(ArrayRef<TypeLoc> Inherited) {
|
||||
bool IndexSwiftASTWalker::reportInheritedTypeRefs(ArrayRef<TypeLoc> Inherited, ValueDecl *Inheritee) {
|
||||
for (auto Base : Inherited) {
|
||||
passRelatedType(Base);
|
||||
if(!reportRelatedTypeRef(Base, (SymbolRoleSet) SymbolRole::RelationBaseOf, Inheritee))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::passRelatedType(const TypeLoc &Ty) {
|
||||
bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, ValueDecl *Related) {
|
||||
|
||||
if (IdentTypeRepr *T = dyn_cast_or_null<IdentTypeRepr>(Ty.getTypeRepr())) {
|
||||
auto Comps = T->getComponentRange();
|
||||
if (auto NTD =
|
||||
dyn_cast_or_null<NominalTypeDecl>(Comps.back()->getBoundDecl())) {
|
||||
if (!passRelated(NTD, Comps.back()->getIdLoc()))
|
||||
if (!reportRelatedRef(NTD, Comps.back()->getIdLoc(), Relations, Related))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Ty.getType()) {
|
||||
if (auto nominal = Ty.getType()->getAnyNominal())
|
||||
if (!passRelated(nominal, Ty.getLoc()))
|
||||
if (!reportRelatedRef(nominal, Ty.getLoc(), Relations, Related))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SymbolSubKind getSubKindForAccessor(AccessorKind AK) {
|
||||
switch (AK) {
|
||||
case AccessorKind::NotAccessor: return SymbolSubKind::None;
|
||||
case AccessorKind::IsGetter: return SymbolSubKind::AccessorGetter;
|
||||
case AccessorKind::IsSetter: return SymbolSubKind::AccessorSetter;
|
||||
case AccessorKind::IsWillSet: return SymbolSubKind::AccessorWillSet;
|
||||
case AccessorKind::IsDidSet: return SymbolSubKind::AccessorDidSet;
|
||||
case AccessorKind::IsAddressor: return SymbolSubKind::AccessorAddressor;
|
||||
case AccessorKind::IsMutableAddressor:
|
||||
return SymbolSubKind::AccessorMutableAddressor;
|
||||
case AccessorKind::IsMaterializeForSet:
|
||||
llvm_unreachable("unexpected MaterializeForSet");
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled AccessorKind in switch.");
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,
|
||||
AccessorKind AccKind, bool IsRef,
|
||||
SourceLoc Loc) {
|
||||
if (!shouldIndex(D))
|
||||
return true; // continue walking.
|
||||
|
||||
auto handleInfo = [this, D, AccKind](IndexSymbol &Info) {
|
||||
auto updateInfo = [this, D, AccKind](IndexSymbol &Info) {
|
||||
if (getPseudoAccessorNameAndUSR(D, AccKind, Info.name, Info.USR))
|
||||
return true;
|
||||
Info.kind = SymbolKind::Accessor;
|
||||
Info.subKinds |= getSubKindForAccessor(AccKind);
|
||||
Info.name = "";
|
||||
Info.USR = getAccessorUSR(D, AccKind);
|
||||
Info.roles |= (SymbolRoleSet)SymbolRole::Implicit;
|
||||
Info.group = "";
|
||||
|
||||
if (!IdxConsumer.startSourceEntity(Info)) {
|
||||
Cancelled = true;
|
||||
return false;
|
||||
}
|
||||
if (!IdxConsumer.finishSourceEntity(Info.kind, Info.subKinds, Info.roles)) {
|
||||
Cancelled = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
if (IsRef) {
|
||||
IndexSymbol Info;
|
||||
if (initCallRefIndexSymbol(ExprStack.back(), getParentExpr(), D, Loc, Info))
|
||||
return true; // continue walking.
|
||||
if (updateInfo(Info))
|
||||
return true;
|
||||
|
||||
return handleInfo(Info);
|
||||
|
||||
if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.kind, Info.subKinds, Info.roles))
|
||||
Cancelled = true;
|
||||
} else {
|
||||
IndexSymbol Info;
|
||||
if (initIndexSymbol(D, Loc, IsRef, Info))
|
||||
return true; // continue walking.
|
||||
if (updateInfo(Info))
|
||||
return true;
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationAccessorOf, D))
|
||||
return true;
|
||||
|
||||
return handleInfo(Info);
|
||||
if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.kind, Info.subKinds, Info.roles))
|
||||
Cancelled = true;
|
||||
}
|
||||
return !Cancelled;
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
@@ -679,36 +739,21 @@ bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
|
||||
|
||||
assert(Info.subKinds != 0);
|
||||
|
||||
if (!IdxConsumer.startSourceEntity(Info)) {
|
||||
Cancelled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
passInheritedTypes(D->getInherited());
|
||||
if (Cancelled)
|
||||
if (!startEntity(D, Info))
|
||||
return false;
|
||||
|
||||
EntitiesStack.push_back({D, Info.kind, Info.subKinds, Info.roles});
|
||||
// FIXME: make extensions their own entity
|
||||
if (!reportRelatedRef(NTD, Loc, (SymbolRoleSet)SymbolRole::RelationExtendedBy,
|
||||
NTD))
|
||||
return false;
|
||||
if (!reportInheritedTypeRefs(D->getInherited(), NTD))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::report(ValueDecl *D) {
|
||||
if (startEntityDecl(D)) {
|
||||
if (TypeDecl *TD = dyn_cast<NominalTypeDecl>(D))
|
||||
passInheritedTypes(TD->getInherited());
|
||||
if (Cancelled)
|
||||
return false;
|
||||
if (auto Overridden = D->getOverriddenDecl()) {
|
||||
passRelated(Overridden, SourceLoc());
|
||||
if (Cancelled)
|
||||
return false;
|
||||
}
|
||||
for (auto Conf : D->getSatisfiedProtocolRequirements()) {
|
||||
passRelated(Conf, SourceLoc());
|
||||
if (Cancelled)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass accessors.
|
||||
if (auto VarD = dyn_cast<VarDecl>(D)) {
|
||||
if (!VarD->getGetter() && !VarD->getSetter()) {
|
||||
@@ -751,46 +796,54 @@ bool IndexSwiftASTWalker::report(ValueDecl *D) {
|
||||
SourceEntityWalker::walk(cast<Decl>(FD));
|
||||
}
|
||||
}
|
||||
} else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
|
||||
if (!reportInheritedTypeRefs(NTD->getInherited(), NTD))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !Cancelled;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc) {
|
||||
if (startEntityRef(D, Loc)) {
|
||||
// Report the accessors that were utilized.
|
||||
if (isa<AbstractStorageDecl>(D) && getParentExpr()) {
|
||||
bool UsesGetter = false;
|
||||
bool UsesSetter = false;
|
||||
Expr *CurrE = ExprStack.back();
|
||||
Expr *Parent = getParentExpr();
|
||||
bool isLValue =
|
||||
!CurrE->getType().isNull() && CurrE->getType()->is<LValueType>();
|
||||
if (isa<LoadExpr>(Parent) || !isLValue) {
|
||||
UsesGetter = true;
|
||||
} else if (isa<AssignExpr>(Parent)) {
|
||||
UsesSetter = true;
|
||||
} else {
|
||||
UsesGetter = UsesSetter = true;
|
||||
}
|
||||
//
|
||||
bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
|
||||
IndexSymbol &Info) {
|
||||
if (!shouldIndex(D))
|
||||
return true; // keep walking
|
||||
|
||||
AbstractStorageDecl *ASD = cast<AbstractStorageDecl>(D);
|
||||
if (UsesGetter)
|
||||
if (!reportPseudoAccessor(ASD, AccessorKind::IsGetter, /*IsRef=*/true,
|
||||
Loc))
|
||||
return false;
|
||||
if (UsesSetter)
|
||||
if (!reportPseudoAccessor(ASD, AccessorKind::IsSetter, /*IsRef=*/true,
|
||||
Loc))
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(EntitiesStack.back().D == D);
|
||||
return finishCurrentEntity();
|
||||
if (isa<AbstractFunctionDecl>(D)) {
|
||||
if (initCallRefIndexSymbol(getCurrentExpr(), getParentExpr(), D, Loc, Info))
|
||||
return true;
|
||||
} else if (isa<AbstractStorageDecl>(D)) {
|
||||
if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info))
|
||||
return true;
|
||||
} else {
|
||||
if (initIndexSymbol(D, Loc, /*isRef=*/true, Info))
|
||||
return true;
|
||||
}
|
||||
|
||||
return !Cancelled;
|
||||
|
||||
if (!startEntity(D, Info)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Report the accessors that were utilized.
|
||||
if (isa<AbstractStorageDecl>(D)) {
|
||||
bool UsesGetter = Info.roles & (SymbolRoleSet)SymbolRole::Read;
|
||||
bool UsesSetter = Info.roles & (SymbolRoleSet)SymbolRole::Write;
|
||||
|
||||
AbstractStorageDecl *ASD = cast<AbstractStorageDecl>(D);
|
||||
if (UsesGetter)
|
||||
if (!reportPseudoAccessor(ASD, AccessorKind::IsGetter, /*IsRef=*/true,
|
||||
Loc))
|
||||
return false;
|
||||
if (UsesSetter)
|
||||
if (!reportPseudoAccessor(ASD, AccessorKind::IsSetter, /*IsRef=*/true,
|
||||
Loc))
|
||||
return false;
|
||||
}
|
||||
|
||||
return finishCurrentEntity();
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
|
||||
@@ -926,6 +979,12 @@ bool IndexSwiftASTWalker::initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE,
|
||||
|
||||
Info.roles |= (unsigned)SymbolRole::Call;
|
||||
|
||||
Decl *ParentD = getParentDecl();
|
||||
if (ParentD && isa<ValueDecl>(ParentD)) {
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationCalledBy, cast<ValueDecl>(ParentD)))
|
||||
return true;
|
||||
}
|
||||
|
||||
Expr *BaseE = nullptr;
|
||||
if (auto DotE = dyn_cast<DotSyntaxCallExpr>(ParentE))
|
||||
BaseE = DotE->getBase();
|
||||
@@ -945,7 +1004,7 @@ bool IndexSwiftASTWalker::initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE,
|
||||
|
||||
if (auto TyD = ReceiverTy->getAnyNominal()) {
|
||||
StringRef unused;
|
||||
if (getNameAndUSR(TyD, unused, Info.receiverUSR))
|
||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationReceivedBy, TyD))
|
||||
return true;
|
||||
if (isDynamicCall(BaseE, D))
|
||||
Info.roles |= (unsigned)SymbolRole::Dynamic;
|
||||
@@ -955,6 +1014,29 @@ bool IndexSwiftASTWalker::initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc, IndexSymbol &Info) {
|
||||
|
||||
if (!(CurrentE->getReferencedDecl() == D))
|
||||
return true;
|
||||
|
||||
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
|
||||
return true;
|
||||
|
||||
AccessKind Kind = CurrentE->hasLValueAccessKind() ? CurrentE->getLValueAccessKind() : AccessKind::Read;
|
||||
switch (Kind) {
|
||||
case swift::AccessKind::Read:
|
||||
Info.roles |= (unsigned)SymbolRole::Read;
|
||||
break;
|
||||
case swift::AccessKind::ReadWrite:
|
||||
Info.roles |= (unsigned)SymbolRole::Read;
|
||||
LLVM_FALLTHROUGH;
|
||||
case swift::AccessKind::Write:
|
||||
Info.roles |= (unsigned)SymbolRole::Write;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::hash_code
|
||||
IndexSwiftASTWalker::hashFileReference(llvm::hash_code code,
|
||||
SourceFileOrModule SFOrMod) {
|
||||
|
||||
@@ -83,3 +83,81 @@ SymbolKind index::getSymbolKindForDecl(const Decl *D) {
|
||||
return SymbolKind::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
StringRef index::getSymbolKindString(SymbolKind K) {
|
||||
switch (K) {
|
||||
case SymbolKind::Unknown: return "<unknown>";
|
||||
case SymbolKind::Module: return "module";
|
||||
case SymbolKind::ClangModule: return "clang-module";
|
||||
case SymbolKind::Enum: return "enum";
|
||||
case SymbolKind::EnumElement: return "enum-element";
|
||||
case SymbolKind::Struct: return "struct";
|
||||
case SymbolKind::Class: return "class";
|
||||
case SymbolKind::Protocol: return "protocol";
|
||||
case SymbolKind::Extension: return "extension";
|
||||
case SymbolKind::TypeAlias: return "type-alias";
|
||||
case SymbolKind::Function: return "function";
|
||||
case SymbolKind::Variable: return "variable";
|
||||
case SymbolKind::InstanceMethod: return "instance-method";
|
||||
case SymbolKind::ClassMethod: return "class-method";
|
||||
case SymbolKind::StaticMethod: return "static-method";
|
||||
case SymbolKind::InstanceProperty: return "instance-property";
|
||||
case SymbolKind::ClassProperty: return "class-property";
|
||||
case SymbolKind::StaticProperty: return "static-property";
|
||||
case SymbolKind::Constructor: return "constructor";
|
||||
case SymbolKind::Destructor: return "destructor";
|
||||
case SymbolKind::PrefixOperator: return "prefix-operator";
|
||||
case SymbolKind::PostfixOperator: return "postfix-operator";
|
||||
case SymbolKind::InfixOperator: return "infix-operator";
|
||||
case SymbolKind::Accessor: return "accessor";
|
||||
case SymbolKind::Subscript: return "subscript";
|
||||
case SymbolKind::AssociatedType: return "associated-type";
|
||||
case SymbolKind::GenericTypeParam: return "generic-type-param";
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
||||
void index::applyForEachSymbolSubKind(SymbolSubKindSet SubKinds,
|
||||
llvm::function_ref<void(SymbolSubKind)> Fn) {
|
||||
#define APPLY_FOR_SUBKIND(K) \
|
||||
if (SubKinds & (unsigned)SymbolSubKind::K) \
|
||||
Fn(SymbolSubKind::K)
|
||||
|
||||
APPLY_FOR_SUBKIND(AccessorGetter);
|
||||
APPLY_FOR_SUBKIND(AccessorSetter);
|
||||
APPLY_FOR_SUBKIND(AccessorWillSet);
|
||||
APPLY_FOR_SUBKIND(AccessorDidSet);
|
||||
APPLY_FOR_SUBKIND(AccessorAddressor);
|
||||
APPLY_FOR_SUBKIND(AccessorMutableAddressor);
|
||||
APPLY_FOR_SUBKIND(ExtensionOfStruct);
|
||||
APPLY_FOR_SUBKIND(ExtensionOfClass);
|
||||
APPLY_FOR_SUBKIND(ExtensionOfEnum);
|
||||
APPLY_FOR_SUBKIND(ExtensionOfProtocol);
|
||||
APPLY_FOR_SUBKIND(UnitTest);
|
||||
|
||||
#undef APPLY_FOR_SUBKIND
|
||||
}
|
||||
|
||||
void index::printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS) {
|
||||
bool VisitedOnce = false;
|
||||
applyForEachSymbolSubKind(SubKinds, [&](SymbolSubKind SubKind) {
|
||||
if (VisitedOnce)
|
||||
OS << ',';
|
||||
else
|
||||
VisitedOnce = true;
|
||||
switch (SubKind) {
|
||||
case SymbolSubKind::None: OS << "none"; break;
|
||||
case SymbolSubKind::UnitTest: OS << "test"; break;
|
||||
case SymbolSubKind::AccessorGetter: OS << "get"; break;
|
||||
case SymbolSubKind::AccessorSetter: OS << "set"; break;
|
||||
case SymbolSubKind::AccessorWillSet: OS << "willSet"; break;
|
||||
case SymbolSubKind::AccessorDidSet: OS << "didSet"; break;
|
||||
case SymbolSubKind::AccessorAddressor: OS << "addr"; break;
|
||||
case SymbolSubKind::AccessorMutableAddressor: OS << "mutAddr"; break;
|
||||
case SymbolSubKind::ExtensionOfStruct: OS << "extStruct"; break;
|
||||
case SymbolSubKind::ExtensionOfClass: OS << "extClass"; break;
|
||||
case SymbolSubKind::ExtensionOfEnum: OS << "extEnum"; break;
|
||||
case SymbolSubKind::ExtensionOfProtocol: OS << "extProt"; break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
179
test/Index/kinds.swift
Normal file
179
test/Index/kinds.swift
Normal file
@@ -0,0 +1,179 @@
|
||||
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
|
||||
|
||||
// Enum
|
||||
enum AnEnumeration {
|
||||
// CHECK: [[@LINE-1]]:6 | enum/Swift | AnEnumeration | s:O14swift_ide_test13AnEnumeration | Def | rel: 0
|
||||
|
||||
// EnumElement
|
||||
case Element
|
||||
// CHECK: [[@LINE-1]]:8 | enum-element/Swift | Element | s:FO14swift_ide_test13AnEnumeration7ElementFMS0_S0_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AnEnumeration | s:O14swift_ide_test13AnEnumeration
|
||||
}
|
||||
|
||||
// Struct
|
||||
struct AStruct {
|
||||
// CHECK: [[@LINE-1]]:8 | struct/Swift | AStruct | s:V14swift_ide_test7AStruct | Def | rel: 0
|
||||
|
||||
var base: UnsafeMutablePointer<Int>
|
||||
|
||||
// Subscript
|
||||
subscript(index: Int) -> Int {
|
||||
// CHECK: [[@LINE-1]]:3 | subscript/Swift | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AStruct | s:V14swift_ide_test7AStruct
|
||||
|
||||
// Accessor + AccessorAddressor
|
||||
unsafeAddress {
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(addr)/Swift | | s:FV14swift_ide_test7AStructlu9subscriptFSiSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi
|
||||
|
||||
return UnsafePointer(base)
|
||||
}
|
||||
|
||||
// Accessor + AccessorMutableAddressor
|
||||
unsafeMutableAddress {
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(mutAddr)/Swift | | s:FV14swift_ide_test7AStructau9subscriptFSiSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi
|
||||
|
||||
return base
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Class
|
||||
class AClass {
|
||||
// CHECK: [[@LINE-1]]:7 | class/Swift | AClass | s:C14swift_ide_test6AClass | Def | rel: 0
|
||||
|
||||
// InstanceMethod
|
||||
func instanceMethod() {}
|
||||
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | instanceMethod() | s:FC14swift_ide_test6AClass14instanceMethodFT_T_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// ClassMethod
|
||||
class func classMethod() {}
|
||||
// CHECK: [[@LINE-1]]:14 | class-method/Swift | classMethod() | s:ZFC14swift_ide_test6AClass11classMethodFT_T_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// StaticMethod
|
||||
static func staticMethod() {}
|
||||
// CHECK: [[@LINE-1]]:15 | static-method/Swift | staticMethod() | s:ZFC14swift_ide_test6AClass12staticMethodFT_T_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// InstanceProperty
|
||||
var instanceProperty: Int {
|
||||
// CHECK: [[@LINE-1]]:7 | instance-property/Swift | instanceProperty | s:vC14swift_ide_test6AClass16instancePropertySi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// Accessor + AccessorGetter
|
||||
get {
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(get)/Swift | getter:instanceProperty | s:FC14swift_ide_test6AClassg16instancePropertySi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | instanceProperty | s:vC14swift_ide_test6AClass16instancePropertySi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// Accessor + AccessorSetter
|
||||
set {}
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(set)/Swift | setter:instanceProperty | s:FC14swift_ide_test6AClasss16instancePropertySi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | instanceProperty | s:vC14swift_ide_test6AClass16instancePropertySi
|
||||
}
|
||||
|
||||
var observed = 0 {
|
||||
|
||||
// Accessor + AccessorWillSet
|
||||
willSet {}
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(willSet)/Swift | willSet:observed | s:FC14swift_ide_test6AClassw8observedSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | observed | s:vC14swift_ide_test6AClass8observedSi
|
||||
|
||||
// Accessor + AccessorDidSet
|
||||
didSet {}
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(didSet)/Swift | didSet:observed | s:FC14swift_ide_test6AClassW8observedSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | observed | s:vC14swift_ide_test6AClass8observedSi
|
||||
}
|
||||
|
||||
// ClassProperty
|
||||
class let classProperty = 1
|
||||
// CHECK: [[@LINE-1]]:13 | class-property/Swift | classProperty | s:ZvC14swift_ide_test6AClass13classPropertySi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// StaticProperty
|
||||
static let staticProperty = 1
|
||||
// CHECK: [[@LINE-1]]:14 | static-property/Swift | staticProperty | s:ZvC14swift_ide_test6AClass14staticPropertySi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// Constructor
|
||||
init() {}
|
||||
// CHECK: [[@LINE-1]]:3 | constructor/Swift | init() | s:FC14swift_ide_test6AClasscFT_S0_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
// Destructor
|
||||
deinit {}
|
||||
// CHECK: [[@LINE-1]]:3 | destructor/Swift | deinit | s:FC14swift_ide_test6AClassd | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
}
|
||||
|
||||
// Protocol
|
||||
protocol AProtocol {
|
||||
// CHECK: [[@LINE-1]]:10 | protocol/Swift | AProtocol | s:P14swift_ide_test9AProtocol | Def | rel: 0
|
||||
|
||||
// AssociatedType
|
||||
associatedtype T
|
||||
// CHECK: [[@LINE-1]]:18 | associated-type/Swift | T | s:P14swift_ide_test9AProtocol1T | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AProtocol | s:P14swift_ide_test9AProtocol
|
||||
}
|
||||
|
||||
// Extension
|
||||
extension AnEnumeration {}
|
||||
// CHECK: [[@LINE-1]]:11 | extension(extEnum)/Swift | AnEnumeration | s:O14swift_ide_test13AnEnumeration | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:11 | enum/Swift | AnEnumeration | s:O14swift_ide_test13AnEnumeration | Ref,RelExt | rel: 1
|
||||
// CHECK-NEXT: RelExt | AnEnumeration | s:O14swift_ide_test13AnEnumeration
|
||||
|
||||
extension AStruct {}
|
||||
// CHECK: [[@LINE-1]]:11 | extension(extStruct)/Swift | AStruct | s:V14swift_ide_test7AStruct | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:11 | struct/Swift | AStruct | s:V14swift_ide_test7AStruct | Ref,RelExt | rel: 1
|
||||
// CHECK-NEXT: RelExt | AStruct | s:V14swift_ide_test7AStruct
|
||||
|
||||
extension AClass {}
|
||||
// CHECK: [[@LINE-1]]:11 | extension(extClass)/Swift | AClass | s:C14swift_ide_test6AClass | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:11 | class/Swift | AClass | s:C14swift_ide_test6AClass | Ref,RelExt | rel: 1
|
||||
// CHECK-NEXT: RelExt | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
extension AProtocol {}
|
||||
// CHECK: [[@LINE-1]]:11 | extension(extProt)/Swift | AProtocol | s:P14swift_ide_test9AProtocol | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:11 | protocol/Swift | AProtocol | s:P14swift_ide_test9AProtocol | Ref,RelExt | rel: 1
|
||||
// CHECK-NEXT: RelExt | AProtocol | s:P14swift_ide_test9AProtocol
|
||||
|
||||
// TypeAlias
|
||||
typealias SomeAlias = AStruct
|
||||
// CHECK: [[@LINE-1]]:11 | type-alias/Swift | SomeAlias | s:14swift_ide_test9SomeAlias | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:23 | struct/Swift | AStruct | s:V14swift_ide_test7AStruct | Ref | rel: 0
|
||||
|
||||
// GenericTypeParam
|
||||
struct GenericStruct<ATypeParam> {}
|
||||
// CHECK: [[@LINE-1]]:22 | generic-type-param/Swift | ATypeParam | s:tV14swift_ide_test13GenericStruct10ATypeParamMx | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | GenericStruct | s:V14swift_ide_test13GenericStruct
|
||||
|
||||
func GenericFunc<ATypeParam>(_: ATypeParam) {}
|
||||
// CHECK-NOT: [[@LINE-1]]:18 | generic-type-param/Swift | ATypeParam | {{.*}} | Def,RelChild | rel: 1
|
||||
|
||||
// Function
|
||||
func EmptyFunction() {}
|
||||
// CHECK: [[@LINE-1]]:6 | function/Swift | EmptyFunction() | s:F14swift_ide_test13EmptyFunctionFT_T_ | Def | rel: 0
|
||||
|
||||
// Variable
|
||||
var foo = 1
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | foo | s:v14swift_ide_test3fooSi | Def | rel: 0
|
||||
|
||||
// PrefixOperator
|
||||
prefix func -(a: AStruct) -> AStruct { return a }
|
||||
// CHECK: [[@LINE-1]]:13 | prefix-operator/Swift | -(_:) | s:F14swift_ide_testop1sFVS_7AStructS0_ | Def | rel: 0
|
||||
|
||||
// PostfixOperator
|
||||
postfix func ++(a: AStruct) -> AStruct { return a }
|
||||
// CHECK: [[@LINE-1]]:14 | postfix-operator/Swift | ++(_:) | s:F14swift_ide_testoP2ppFVS_7AStructS0_ | Def | rel: 0
|
||||
|
||||
// InfixOperator
|
||||
func +(a: AStruct, b: AStruct) -> AStruct { return a }
|
||||
// CHECK: [[@LINE-1]]:6 | infix-operator/Swift | +(_:_:) | s:F14swift_ide_testoi1pFTVS_7AStructS0__S0_ | Def | rel: 0
|
||||
|
||||
|
||||
// TODO: UnitTest
|
||||
207
test/Index/roles.swift
Normal file
207
test/Index/roles.swift
Normal file
@@ -0,0 +1,207 @@
|
||||
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
|
||||
|
||||
// Definition
|
||||
let x = 2
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | x | s:v14swift_ide_test1xSi | Def | rel: 0
|
||||
|
||||
// Definition + Read of x
|
||||
var y = x + 1
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | y | s:v14swift_ide_test1ySi | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:9 | variable/Swift | x | s:v14swift_ide_test1xSi | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-3]]:11 | infix-operator/Swift | +(_:_:) | s:Fsoi1pFTSiSi_Si | Ref,Call | rel: 0
|
||||
|
||||
// Read of x + Write of y
|
||||
y = x + 1
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | y | s:v14swift_ide_test1ySi | Ref,Writ | rel: 0
|
||||
// CHECK: [[@LINE-2]]:5 | variable/Swift | x | s:v14swift_ide_test1xSi | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-3]]:7 | infix-operator/Swift | +(_:_:) | s:Fsoi1pFTSiSi_Si | Ref,Call | rel: 0
|
||||
|
||||
// Read of y + Write of y
|
||||
y += x
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | y | s:v14swift_ide_test1ySi | Ref,Read,Writ | rel: 0
|
||||
// CHECK: [[@LINE-2]]:3 | infix-operator/Swift | +=(_:_:) | s:Fsoi2peFTRSiSi_T_ | Ref,Call | rel: 0
|
||||
// CHECK: [[@LINE-3]]:6 | variable/Swift | x | s:v14swift_ide_test1xSi | Ref,Read | rel: 0
|
||||
|
||||
var z: Int {
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | z | s:v14swift_ide_test1zSi | Def | rel: 0
|
||||
get {
|
||||
// CHECK: [[@LINE-1]]:3 | accessor(get)/Swift | getter:z | s:F14swift_ide_testg1zSi | Def,RelChild,RelAcc | rel: 1
|
||||
|
||||
return y
|
||||
// CHECK: [[@LINE-1]]:12 | variable/Swift | y | s:v14swift_ide_test1ySi | Ref,Read | rel: 0
|
||||
}
|
||||
set {
|
||||
// CHECK: [[@LINE-1]]:3 | accessor(set)/Swift | setter:z | s:F14swift_ide_tests1zSi | Def,RelChild,RelAcc | rel: 1
|
||||
|
||||
y = newValue
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | y | s:v14swift_ide_test1ySi | Ref,Writ | rel: 0
|
||||
}
|
||||
}
|
||||
// Write + Read of z
|
||||
z = z + 1
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | z | s:v14swift_ide_test1zSi | Ref,Writ | rel: 0
|
||||
// CHECK: [[@LINE-2]]:1 | accessor(set)/Swift | setter:z | s:F14swift_ide_tests1zSi | Ref,Call,Impl,RelCall | rel: 1
|
||||
// CHECK-NEXT: RelCall | z | s:v14swift_ide_test1zSi
|
||||
// CHECK: [[@LINE-4]]:5 | variable/Swift | z | s:v14swift_ide_test1zSi | Ref,Read | rel: 0
|
||||
// CHECK-NEXT: [[@LINE-5]]:5 | accessor(get)/Swift | getter:z | s:F14swift_ide_testg1zSi | Ref,Call,Impl,RelCall | rel: 1
|
||||
|
||||
// Call
|
||||
func aCalledFunction() {}
|
||||
// CHECK: [[@LINE-1]]:6 | function/Swift | aCalledFunction() | s:F14swift_ide_test15aCalledFunctionFT_T_ | Def | rel: 0
|
||||
|
||||
aCalledFunction()
|
||||
// CHECK: [[@LINE-1]]:1 | function/Swift | aCalledFunction() | s:F14swift_ide_test15aCalledFunctionFT_T_ | Ref,Call | rel: 0
|
||||
|
||||
func aCaller() {
|
||||
// CHECK: [[@LINE-1]]:6 | function/Swift | aCaller() | s:F14swift_ide_test7aCallerFT_T_ | Def | rel: 0
|
||||
|
||||
aCalledFunction()
|
||||
// CHECK: [[@LINE-1]]:3 | function/Swift | aCalledFunction() | s:F14swift_ide_test15aCalledFunctionFT_T_ | Ref,Call,RelCall | rel: 1
|
||||
// CHECK-NEXT: RelCall | aCaller() | s:F14swift_ide_test7aCallerFT_T_
|
||||
}
|
||||
|
||||
// RelationChildOf, Implicit
|
||||
struct AStruct {
|
||||
var x: Int
|
||||
// CHECK: [[@LINE-1]]:7 | instance-property/Swift | x | s:vV14swift_ide_test7AStruct1xSi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AStruct | s:V14swift_ide_test7AStruct
|
||||
|
||||
mutating func aMethod() {
|
||||
// CHECK: [[@LINE-1]]:17 | instance-method/Swift | aMethod() | s:FV14swift_ide_test7AStruct7aMethodFT_T_ | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AStruct | s:V14swift_ide_test7AStruct
|
||||
|
||||
x += 1
|
||||
// CHECK: [[@LINE-1]]:5 | instance-property/Swift | x | s:vV14swift_ide_test7AStruct1xSi | Ref,Read,Writ | rel: 0
|
||||
// CHECK: [[@LINE-2]]:5 | accessor(get)/Swift | getter:x | s:FV14swift_ide_test7AStructg1xSi | Ref,Call,Impl,RelRec,RelCall | rel: 2
|
||||
// CHECK-NEXT: RelCall | x | s:vV14swift_ide_test7AStruct1xSi
|
||||
// CHECK-NEXT: RelRec | AStruct | s:V14swift_ide_test7AStruct
|
||||
// CHECK: [[@LINE-5]]:5 | accessor(set)/Swift | setter:x | s:FV14swift_ide_test7AStructs1xSi | Ref,Call,Impl,RelRec,RelCall | rel: 2
|
||||
// CHECK-NEXT: RelCall | x | s:vV14swift_ide_test7AStruct1xSi
|
||||
// CHECK-NEXT: RelRec | AStruct | s:V14swift_ide_test7AStruct
|
||||
// CHECK: [[@LINE-8]]:7 | infix-operator/Swift | +=(_:_:) | s:Fsoi2peFTRSiSi_T_ | Ref,Call,RelCall | rel: 1
|
||||
// CHECK-NEXT: RelCall | aMethod() | s:FV14swift_ide_test7AStruct7aMethodFT_T_
|
||||
}
|
||||
|
||||
// RelationChildOf, RelationAccessorOf
|
||||
subscript(index: Int) -> Int {
|
||||
// CHECK: [[@LINE-1]]:3 | subscript/Swift | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AStruct | s:V14swift_ide_test7AStruct
|
||||
|
||||
get {
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(get)/Swift | getter:subscript(_:) | s:FV14swift_ide_test7AStructg9subscriptFSiSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi
|
||||
|
||||
return x
|
||||
}
|
||||
set {
|
||||
// CHECK: [[@LINE-1]]:5 | accessor(set)/Swift | setter:subscript(_:) | s:FV14swift_ide_test7AStructs9subscriptFSiSi | Def,RelChild,RelAcc | rel: 1
|
||||
// CHECK-NEXT: RelChild,RelAcc | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi
|
||||
|
||||
x = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AClass {
|
||||
var y: AStruct;
|
||||
var z: [Int]
|
||||
|
||||
init(x: Int) {
|
||||
y = AStruct(x: x)
|
||||
self.z = [1, 2, 3]
|
||||
}
|
||||
|
||||
subscript(index: Int) -> Int {
|
||||
get {
|
||||
return z[0]
|
||||
}
|
||||
set {
|
||||
z[0] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
func foo() -> Int {
|
||||
return z[0]
|
||||
}
|
||||
}
|
||||
|
||||
protocol AProtocol {
|
||||
func foo() -> Int
|
||||
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | foo() | s:FP14swift_ide_test9AProtocol3fooFT_Si | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AProtocol | s:P14swift_ide_test9AProtocol
|
||||
}
|
||||
|
||||
// RelationBaseOf, RelationOverrideOf
|
||||
class ASubClass : AClass, AProtocol {
|
||||
// CHECK: [[@LINE-1]]:7 | class/Swift | ASubClass | s:C14swift_ide_test9ASubClass | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:19 | class/Swift | AClass | s:C14swift_ide_test6AClass | Ref,RelBase | rel: 1
|
||||
// CHECK-NEXT: RelBase | ASubClass | s:C14swift_ide_test9ASubClass
|
||||
// CHECK: [[@LINE-4]]:27 | protocol/Swift | AProtocol | s:P14swift_ide_test9AProtocol | Ref,RelBase | rel: 1
|
||||
// CHECK-NEXT: RelBase | ASubClass | s:C14swift_ide_test9ASubClass
|
||||
|
||||
override func foo() -> Int {
|
||||
// CHECK: [[@LINE-1]]:17 | instance-method/Swift | foo() | s:FC14swift_ide_test9ASubClass3fooFT_Si | Def,RelChild,RelOver | rel: 3
|
||||
// CHECK-NEXT: RelOver | foo() | s:FC14swift_ide_test6AClass3fooFT_Si
|
||||
// CHECK-NEXT: RelOver | foo() | s:FP14swift_ide_test9AProtocol3fooFT_Si
|
||||
// CHECK-NEXT: RelChild | ASubClass | s:C14swift_ide_test9ASubClass
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// RelationExtendedBy
|
||||
// FIXME give extensions their own USR like ObjC?
|
||||
extension AClass {
|
||||
// CHECK: [[@LINE-1]]:11 | extension(extClass)/Swift | AClass | s:C14swift_ide_test6AClass | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:11 | class/Swift | AClass | s:C14swift_ide_test6AClass | Ref,RelExt | rel: 1
|
||||
// CHECK-NEXT: RelExt | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
func bar() -> Int { return 2 }
|
||||
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | bar() | s:FC14swift_ide_test6AClass3barFT_Si | Def,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | AClass | s:C14swift_ide_test6AClass
|
||||
}
|
||||
|
||||
var anInstance = AClass(x: 1)
|
||||
// CHECK: [[@LINE-1]]:18 | class/Swift | AClass | s:C14swift_ide_test6AClass | Ref | rel: 0
|
||||
// CHECK: [[@LINE-2]]:18 | constructor/Swift | init(x:) | s:FC14swift_ide_test6AClasscFT1xSi_S0_ | Ref,Call | rel: 0
|
||||
|
||||
anInstance.y.x = anInstance.y.x
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:12 | instance-property/Swift | y | s:vC14swift_ide_test6AClass1yVS_7AStruct | Ref,Read,Writ | rel: 0
|
||||
// CHECK: [[@LINE-3]]:14 | instance-property/Swift | x | s:vV14swift_ide_test7AStruct1xSi | Ref,Writ | rel: 0
|
||||
// CHECK: [[@LINE-4]]:18 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-5]]:29 | instance-property/Swift | y | s:vC14swift_ide_test6AClass1yVS_7AStruct | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-6]]:31 | instance-property/Swift | x | s:vV14swift_ide_test7AStruct1xSi | Ref,Read | rel: 0
|
||||
|
||||
anInstance.y.aMethod()
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:12 | instance-property/Swift | y | s:vC14swift_ide_test6AClass1yVS_7AStruct | Ref,Read,Writ | rel: 0
|
||||
// CHECK: [[@LINE-3]]:14 | instance-method/Swift | aMethod() | s:FV14swift_ide_test7AStruct7aMethodFT_T_ | Ref,Call | rel: 0
|
||||
|
||||
// FIXME Write role of z occurrence on the RHS?
|
||||
anInstance.z[1] = anInstance.z[0]
|
||||
// CHECK: [[@LINE-1]]:1 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:12 | instance-property/Swift | z | s:vC14swift_ide_test6AClass1zGSaSi_ | Ref,Read,Writ | rel: 0
|
||||
// CHECK: [[@LINE-3]]:19 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-4]]:30 | instance-property/Swift | z | s:vC14swift_ide_test6AClass1zGSaSi_ | Ref,Read,Writ | rel: 0
|
||||
|
||||
let otherInstance = AStruct(x: 1)
|
||||
// CHECK: [[@LINE-1]]:21 | struct/Swift | AStruct | s:V14swift_ide_test7AStruct | Ref | rel: 0
|
||||
|
||||
let _ = otherInstance[0]
|
||||
// CHECK: [[@LINE-1]]:9 | variable/Swift | otherInstance | s:v14swift_ide_test13otherInstanceVS_7AStruct | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:22 | subscript/Swift | subscript(_:) | s:iV14swift_ide_test7AStruct9subscriptFSiSi | Ref,Read | rel: 0
|
||||
|
||||
let _ = anInstance[0]
|
||||
// CHECK: [[@LINE-1]]:9 | variable/Swift | anInstance | s:v14swift_ide_test10anInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:19 | subscript/Swift | subscript(_:) | s:iC14swift_ide_test6AClass9subscriptFSiSi | Ref,Read | rel: 0
|
||||
|
||||
let aSubInstance: AClass = ASubClass(x: 1)
|
||||
// CHECK: [[@LINE-1]]:5 | variable/Swift | aSubInstance | s:v14swift_ide_test12aSubInstanceCS_6AClass | Def | rel: 0
|
||||
// CHECK: [[@LINE-2]]:28 | class/Swift | ASubClass | s:C14swift_ide_test9ASubClass | Ref | rel: 0
|
||||
|
||||
// Dynamic, RelationReceivedBy
|
||||
let _ = aSubInstance.foo()
|
||||
// CHECK: [[@LINE-1]]:9 | variable/Swift | aSubInstance | s:v14swift_ide_test12aSubInstanceCS_6AClass | Ref,Read | rel: 0
|
||||
// CHECK: [[@LINE-2]]:22 | instance-method/Swift | foo() | s:FC14swift_ide_test6AClass3fooFT_Si | Ref,Call,Dyn,RelRec | rel: 1
|
||||
// CHECK-NEXT: RelRec | AClass | s:C14swift_ide_test6AClass
|
||||
|
||||
@@ -71,16 +71,36 @@ private:
|
||||
return impl.finishDependency(getUIDForDependencyKind(kind));
|
||||
}
|
||||
|
||||
bool startSourceEntity(const IndexSymbol &symbol) override {
|
||||
return withEntityInfo(symbol, [this](const EntityInfo &info) {
|
||||
return impl.startSourceEntity(info);
|
||||
});
|
||||
}
|
||||
Action startSourceEntity(const IndexSymbol &symbol) override {
|
||||
|
||||
bool recordRelatedEntity(const IndexSymbol &symbol) override {
|
||||
return withEntityInfo(symbol, [this](const EntityInfo &info) {
|
||||
return impl.recordRelatedEntity(info);
|
||||
});
|
||||
// report any parent relations to this reference
|
||||
if (symbol.roles & (SymbolRoleSet)SymbolRole::RelationBaseOf) {
|
||||
withEntityInfo(symbol, [this](const EntityInfo &info) {
|
||||
return impl.recordRelatedEntity(info);
|
||||
});
|
||||
}
|
||||
|
||||
// filter out references with invalid locations
|
||||
if (symbol.roles & (SymbolRoleSet)SymbolRole::Reference &&
|
||||
(symbol.line == 0 || symbol.column == 0))
|
||||
return Skip;
|
||||
|
||||
|
||||
// start the entity (ref or def)
|
||||
if(!withEntityInfo(symbol, [this](const EntityInfo &info) {
|
||||
return impl.startSourceEntity(info);
|
||||
})) return Abort;
|
||||
|
||||
|
||||
// report relations this occurrence has
|
||||
for (auto Relation: symbol.Relations) {
|
||||
if (Relation.roles & (SymbolRoleSet)SymbolRole::RelationOverrideOf) {
|
||||
if (!withEntityInfo(Relation, [this](const EntityInfo &info) {
|
||||
return impl.recordRelatedEntity(info);
|
||||
})) return Abort;
|
||||
}
|
||||
}
|
||||
return Continue;
|
||||
}
|
||||
|
||||
bool finishSourceEntity(SymbolKind kind, SymbolSubKindSet subKinds,
|
||||
@@ -94,14 +114,16 @@ private:
|
||||
bool withEntityInfo(const IndexSymbol &symbol, F func) {
|
||||
EntityInfo info;
|
||||
bool isRef = symbol.roles & (unsigned)SymbolRole::Reference;
|
||||
bool isImplicit = symbol.roles & (unsigned)SymbolRole::Implicit;
|
||||
|
||||
info.Kind = SwiftLangSupport::getUIDForSymbol(symbol.kind, symbol.subKinds,
|
||||
isRef);
|
||||
info.Name = symbol.name;
|
||||
info.Name = isImplicit? "" : symbol.name;
|
||||
info.USR = symbol.USR;
|
||||
info.Group = symbol.group;
|
||||
info.Line = symbol.line;
|
||||
info.Column = symbol.column;
|
||||
info.ReceiverUSR = symbol.receiverUSR;
|
||||
info.ReceiverUSR = symbol.getReceiverUSR();
|
||||
info.IsDynamic = symbol.roles & (unsigned)SymbolRole::Dynamic;
|
||||
info.IsTestCandidate = symbol.subKinds & SymbolSubKind::UnitTest;
|
||||
std::vector<UIdent> uidAttrs;
|
||||
@@ -113,6 +135,27 @@ private:
|
||||
return func(info);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
bool withEntityInfo(const IndexRelation &relation, F func) {
|
||||
EntityInfo info;
|
||||
bool isRef = (relation.roles & (unsigned)SymbolRole::Reference) ||
|
||||
(relation.roles & (unsigned)SymbolRole::RelationOverrideOf);
|
||||
info.Kind = SwiftLangSupport::getUIDForSymbol(relation.kind, relation.subKinds,
|
||||
isRef);
|
||||
info.Name = relation.name;
|
||||
info.USR = relation.USR;
|
||||
info.Group = relation.group;
|
||||
info.IsDynamic = relation.roles & (unsigned)SymbolRole::Dynamic;
|
||||
info.IsTestCandidate = relation.subKinds & SymbolSubKind::UnitTest;
|
||||
std::vector<UIdent> uidAttrs;
|
||||
if (!isRef) {
|
||||
uidAttrs =
|
||||
SwiftLangSupport::UIDsFromDeclAttributes(relation.decl->getAttrs());
|
||||
info.Attrs = uidAttrs;
|
||||
}
|
||||
return func(info);
|
||||
}
|
||||
|
||||
private:
|
||||
IndexingConsumer &impl;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ add_swift_host_tool(swift-ide-test
|
||||
LINK_LIBRARIES
|
||||
swiftDriver
|
||||
swiftFrontend
|
||||
swiftIndex
|
||||
swiftIDE
|
||||
LLVM_COMPONENT_DEPENDS
|
||||
DebugInfoCodeView
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "swift/IDE/REPLCodeCompletion.h"
|
||||
#include "swift/IDE/SyntaxModel.h"
|
||||
#include "swift/IDE/Utils.h"
|
||||
#include "swift/Index/Index.h"
|
||||
#include "swift/Sema/IDETypeChecking.h"
|
||||
#include "swift/Markup/Markup.h"
|
||||
#include "swift/Config.h"
|
||||
@@ -63,6 +64,7 @@
|
||||
|
||||
using namespace swift;
|
||||
using namespace ide;
|
||||
using namespace index;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -91,6 +93,7 @@ enum class ActionType {
|
||||
PrintUSRs,
|
||||
PrintLocalTypes,
|
||||
PrintTypeInterface,
|
||||
PrintIndexedSymbols,
|
||||
TestCreateCompilerInvocation,
|
||||
CompilerInvocationFromModule,
|
||||
GenerateModuleAPIDescription,
|
||||
@@ -213,6 +216,9 @@ Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
|
||||
clEnumValN(ActionType::Range,
|
||||
"range",
|
||||
"Print information about a given range"),
|
||||
clEnumValN(ActionType::PrintIndexedSymbols,
|
||||
"print-indexed-symbols",
|
||||
"Print indexed symbol information"),
|
||||
clEnumValEnd));
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
@@ -2519,7 +2525,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldWalkIntoFunctionGenericParams() override {
|
||||
bool shouldWalkIntoGenericParams() override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -2669,6 +2675,104 @@ static int doPrintRangeInfo(const CompilerInvocation &InitInvok,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class PrintIndexDataConsumer : public IndexDataConsumer {
|
||||
raw_ostream &OS;
|
||||
bool firstSourceEntity = true;
|
||||
|
||||
void anchor() {}
|
||||
|
||||
void printSymbolKind(SymbolKind kind, SymbolSubKindSet subKinds) {
|
||||
OS << getSymbolKindString(kind);
|
||||
if (subKinds) {
|
||||
OS << '(';
|
||||
printSymbolSubKinds(subKinds, OS);
|
||||
OS << ')';
|
||||
}
|
||||
// FIXME: add and use language enum
|
||||
OS << '/' << "Swift";
|
||||
}
|
||||
|
||||
public:
|
||||
PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {}
|
||||
|
||||
void failed(StringRef error) {}
|
||||
|
||||
bool recordHash(StringRef hash, bool isKnown) { return true; }
|
||||
bool startDependency(SymbolKind kind, StringRef name, StringRef path,
|
||||
bool isSystem, StringRef hash) {
|
||||
OS << getSymbolKindString(kind) << " | ";
|
||||
OS << (isSystem ? "system" : "user") << " | ";
|
||||
OS << name << " | " << path << "-" << hash << "\n";
|
||||
return true;
|
||||
}
|
||||
bool finishDependency(SymbolKind kind) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Action startSourceEntity(const IndexSymbol &symbol) {
|
||||
if (firstSourceEntity) {
|
||||
firstSourceEntity = false;
|
||||
OS << "------------\n";
|
||||
}
|
||||
OS << symbol.line << ':' << symbol.column << " | ";
|
||||
printSymbolKind(symbol.kind, symbol.subKinds);
|
||||
OS << " | " << symbol.name << " | " << symbol.USR << " | ";
|
||||
clang::index::printSymbolRoles(symbol.roles, OS);
|
||||
OS << " | rel: " << symbol.Relations.size() << "\n";
|
||||
|
||||
for (auto Relation : symbol.Relations) {
|
||||
OS << " ";
|
||||
clang::index::printSymbolRoles(Relation.roles, OS);
|
||||
OS << " | " << Relation.name << " | " << Relation.USR << "\n";
|
||||
}
|
||||
return Continue;
|
||||
}
|
||||
bool finishSourceEntity(SymbolKind kind, SymbolSubKindSet subKinds,
|
||||
SymbolRoleSet roles) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void finish() {}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static int doPrintIndexedSymbols(const CompilerInvocation &InitInvok,
|
||||
StringRef SourceFileName) {
|
||||
|
||||
CompilerInvocation Invocation(InitInvok);
|
||||
Invocation.addInputFilename(SourceFileName);
|
||||
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
||||
Invocation.getLangOptions().DisableTypoCorrection = true;
|
||||
|
||||
CompilerInstance CI;
|
||||
|
||||
// Display diagnostics to stderr.
|
||||
PrintingDiagnosticConsumer PrintDiags;
|
||||
CI.addDiagnosticConsumer(&PrintDiags);
|
||||
|
||||
if (CI.setup(Invocation))
|
||||
return 1;
|
||||
CI.performSema();
|
||||
SourceFile *SF = nullptr;
|
||||
for (auto Unit : CI.getMainModule()->getFiles()) {
|
||||
SF = dyn_cast<SourceFile>(Unit);
|
||||
if (SF)
|
||||
break;
|
||||
}
|
||||
assert(SF && "no source file?");
|
||||
assert(SF->getBufferID().hasValue() && "no buffer id?");
|
||||
|
||||
llvm::outs() << llvm::sys::path::filename(SF->getFilename()) << '\n';
|
||||
llvm::outs() << "------------\n";
|
||||
PrintIndexDataConsumer consumer(llvm::outs());
|
||||
indexSourceFile(SF, StringRef(), consumer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int doPrintUSRs(const CompilerInvocation &InitInvok,
|
||||
StringRef SourceFilename) {
|
||||
CompilerInvocation Invocation(InitInvok);
|
||||
@@ -3085,6 +3189,8 @@ int main(int argc, char *argv[]) {
|
||||
options::LineColumnPair,
|
||||
options::EndLineColumnPair);
|
||||
break;
|
||||
case ActionType::PrintIndexedSymbols:
|
||||
ExitCode = doPrintIndexedSymbols(InitInvok, options::SourceFilename);
|
||||
}
|
||||
|
||||
if (options::PrintStats)
|
||||
|
||||
Reference in New Issue
Block a user