mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Move Symbol logic into SymbolGraph
Up to now, the `SymbolGraphASTWalker` was only concerned with one module. This change prepares for emitting multiple symbol graph files, for each module that the module of interest extended. There is only one walker, so extract the symbol logic into `SymbolGraph`, where it can be reused. rdar://58941718
This commit is contained in:
@@ -10,21 +10,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/GenericSignature.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "swift/AST/USRGeneration.h"
|
||||
#include "swift/Basic/PrimitiveParsing.h"
|
||||
#include "swift/Markup/Markup.h"
|
||||
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
|
||||
|
||||
#include "DeclarationFragmentPrinter.h"
|
||||
#include "SymbolGraphASTWalker.h"
|
||||
|
||||
using namespace swift;
|
||||
@@ -34,7 +24,7 @@ SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
|
||||
const SymbolGraphOptions &Options)
|
||||
: Options(Options),
|
||||
M(M),
|
||||
Graph(M, Options.Target) {}
|
||||
Graph(M, Options.Target, Ctx) {}
|
||||
|
||||
/// Returns `true` if the symbol should be included as a node in the graph.
|
||||
bool SymbolGraphASTWalker::shouldIncludeNode(const Decl *D) const {
|
||||
@@ -125,223 +115,13 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
|
||||
|
||||
// Record all of the possible relationships (edges) originating
|
||||
// with this declaration.
|
||||
recordMemberRelationship(VD);
|
||||
recordConformanceRelationships(VD);
|
||||
recordInheritanceRelationships(VD);
|
||||
recordDefaultImplementationRelationships(VD);
|
||||
recordOverrideRelationship(VD);
|
||||
recordRequirementRelationships(VD);
|
||||
recordOptionalRequirementRelationships(VD);
|
||||
Graph.recordMemberRelationship(VD);
|
||||
Graph.recordConformanceRelationships(VD);
|
||||
Graph.recordInheritanceRelationships(VD);
|
||||
Graph.recordDefaultImplementationRelationships(VD);
|
||||
Graph.recordOverrideRelationship(VD);
|
||||
Graph.recordRequirementRelationships(VD);
|
||||
Graph.recordOptionalRequirementRelationships(VD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StringRef SymbolGraphASTWalker::getUSR(const ValueDecl *VD) {
|
||||
auto Found = USRCache.find(VD);
|
||||
if (Found != USRCache.end()) {
|
||||
return Found->second;
|
||||
}
|
||||
llvm::SmallString<32> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
ide::printDeclUSR(VD, OS);
|
||||
auto USR = Ctx.allocateCopy(Scratch.str());
|
||||
USRCache.insert({VD, USR});
|
||||
return USR;
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::getPathComponents(const ValueDecl *VD,
|
||||
SmallVectorImpl<SmallString<32>> &Components) {
|
||||
// Collect the spellings of the fully qualified identifier components.
|
||||
auto Decl = VD;
|
||||
while (Decl && !isa<ModuleDecl>(Decl)) {
|
||||
SmallString<32> Scratch;
|
||||
Decl->getFullName().getString(Scratch);
|
||||
Components.push_back(Scratch);
|
||||
if (const auto *DC = Decl->getDeclContext()) {
|
||||
if (const auto *Proto = DC->getExtendedProtocolDecl()) {
|
||||
Decl = Proto;
|
||||
} else if (const auto *Ext = dyn_cast_or_null<ExtensionDecl>(DC->getAsDecl())) {
|
||||
Decl = Ext->getExtendedNominal();
|
||||
} else {
|
||||
Decl = dyn_cast_or_null<ValueDecl>(DC->getAsDecl());
|
||||
}
|
||||
} else {
|
||||
Decl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// The list is leaf-to-root, but our list is root-to-leaf, so reverse it.
|
||||
std::reverse(Components.begin(), Components.end());
|
||||
}
|
||||
|
||||
PrintOptions SymbolGraphASTWalker::getDeclarationFragmentsPrintOptions() const {
|
||||
PrintOptions Opts;
|
||||
Opts.FunctionDefinitions = false;
|
||||
Opts.ArgAndParamPrinting =
|
||||
PrintOptions::ArgAndParamPrintingMode::ArgumentOnly;
|
||||
Opts.PrintGetSetOnRWProperties = false;
|
||||
Opts.PrintPropertyAccessors = false;
|
||||
Opts.PrintSubscriptAccessors = false;
|
||||
Opts.SkipUnderscoredKeywords = true;
|
||||
Opts.SkipAttributes = true;
|
||||
Opts.PrintOverrideKeyword = true;
|
||||
Opts.PrintImplicitAttrs = false;
|
||||
Opts.PrintFunctionRepresentationAttrs =
|
||||
PrintOptions::FunctionRepresentationMode::None;
|
||||
Opts.PrintUserInaccessibleAttrs = false;
|
||||
Opts.SkipPrivateStdlibDecls = true;
|
||||
Opts.SkipUnderscoredStdlibProtocols = true;
|
||||
|
||||
Opts.ExclusiveAttrList.clear();
|
||||
|
||||
#define DECL_ATTR(SPELLING, CLASS, OPTIONS, CODE) Opts.ExcludeAttrList.push_back(DAK_##CLASS);
|
||||
#define TYPE_ATTR(X) Opts.ExcludeAttrList.push_back(TAK_##X);
|
||||
#include "swift/AST/Attr.def"
|
||||
|
||||
return Opts;
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::serializeDeclarationFragments(StringRef Key,
|
||||
const ValueDecl *VD,
|
||||
llvm::json::OStream &OS) {
|
||||
DeclarationFragmentPrinter Printer(*this, OS, Key);
|
||||
VD->print(Printer, getDeclarationFragmentsPrintOptions());
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::serializeSubheadingDeclarationFragments(StringRef Key,
|
||||
const ValueDecl *VD,
|
||||
llvm::json::OStream &OS) {
|
||||
DeclarationFragmentPrinter Printer(*this, OS, Key);
|
||||
auto Options = getDeclarationFragmentsPrintOptions();
|
||||
Options.VarInitializers = false;
|
||||
Options.PrintDefaultArgumentValue = false;
|
||||
Options.PrintEmptyArgumentNames = false;
|
||||
Options.PrintOverrideKeyword = false;
|
||||
VD->print(Printer, Options);
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::serializeDeclarationFragments(StringRef Key, Type T,
|
||||
llvm::json::OStream &OS) {
|
||||
DeclarationFragmentPrinter Printer(*this, OS, Key);
|
||||
T->print(Printer, getDeclarationFragmentsPrintOptions());
|
||||
}
|
||||
|
||||
void SymbolGraphASTWalker::recordEdge(const ValueDecl *Source,
|
||||
const ValueDecl *Target,
|
||||
RelationshipKind Kind) {
|
||||
if (Target->isPrivateStdlibDecl(
|
||||
/*treatNonBuiltinProtocolsAsPublic = */false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// There might be relationships on implicit declarations,
|
||||
// such as overriding implicit @objc init().
|
||||
if (Target->isImplicit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Graph.Nodes.insert(Source);
|
||||
Graph.Nodes.insert(Target);
|
||||
|
||||
Graph.Edges.insert({this, Kind, Source, Target});
|
||||
}
|
||||
|
||||
void SymbolGraphASTWalker::recordMemberRelationship(const ValueDecl *VD) {
|
||||
auto *DC = VD->getDeclContext();
|
||||
switch (DC->getContextKind()) {
|
||||
case DeclContextKind::GenericTypeDecl:
|
||||
case DeclContextKind::ExtensionDecl:
|
||||
case swift::DeclContextKind::EnumElementDecl:
|
||||
return recordEdge(VD, VD->getDeclContext()->getSelfNominalTypeDecl(),
|
||||
RelationshipKind::MemberOf());
|
||||
case swift::DeclContextKind::AbstractClosureExpr:
|
||||
case swift::DeclContextKind::Initializer:
|
||||
case swift::DeclContextKind::TopLevelCodeDecl:
|
||||
case swift::DeclContextKind::SubscriptDecl:
|
||||
case swift::DeclContextKind::AbstractFunctionDecl:
|
||||
case swift::DeclContextKind::SerializedLocal:
|
||||
case swift::DeclContextKind::Module:
|
||||
case swift::DeclContextKind::FileUnit:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::recordInheritanceRelationships(const ValueDecl *VD) {
|
||||
if (const auto *NTD = dyn_cast<NominalTypeDecl>(VD)) {
|
||||
for (const auto &InheritanceLoc : NTD->getInherited()) {
|
||||
auto Ty = InheritanceLoc.getType();
|
||||
if (!Ty) {
|
||||
continue;
|
||||
}
|
||||
auto *InheritedTypeDecl =
|
||||
dyn_cast_or_null<ClassDecl>(Ty->getAnyNominal());
|
||||
if (!InheritedTypeDecl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
recordEdge(VD, InheritedTypeDecl, RelationshipKind::InheritsFrom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolGraphASTWalker::recordDefaultImplementationRelationships(
|
||||
const ValueDecl *VD) {
|
||||
if (const auto *Extension = dyn_cast<ExtensionDecl>(VD->getDeclContext())) {
|
||||
if (const auto *Protocol = Extension->getExtendedProtocolDecl()) {
|
||||
for (const auto *Member : Protocol->getMembers()) {
|
||||
if (const auto *MemberVD = dyn_cast<ValueDecl>(Member)) {
|
||||
if (MemberVD->getFullName().compare(VD->getFullName()) == 0) {
|
||||
recordEdge(VD, MemberVD,
|
||||
RelationshipKind::DefaultImplementationOf());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::recordRequirementRelationships(const ValueDecl *VD) {
|
||||
if (const auto *Protocol = dyn_cast<ProtocolDecl>(VD->getDeclContext())) {
|
||||
if (VD->isProtocolRequirement()) {
|
||||
recordEdge(VD, Protocol, RelationshipKind::RequirementOf());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolGraphASTWalker::recordOptionalRequirementRelationships(
|
||||
const ValueDecl *VD) {
|
||||
if (const auto *Protocol = dyn_cast<ProtocolDecl>(VD->getDeclContext())) {
|
||||
if (VD->isProtocolRequirement()) {
|
||||
if (const auto *ClangDecl = VD->getClangDecl()) {
|
||||
if (const auto *Method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {
|
||||
if (Method->isOptional()) {
|
||||
recordEdge(VD, Protocol,
|
||||
RelationshipKind::OptionalRequirementOf());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SymbolGraphASTWalker::recordConformanceRelationships(const ValueDecl *VD) {
|
||||
if (const auto *NTD = dyn_cast<NominalTypeDecl>(VD)) {
|
||||
for (const auto *Conformance : NTD->getAllConformances()) {
|
||||
recordEdge(VD, Conformance->getProtocol(),
|
||||
RelationshipKind::ConformsTo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolGraphASTWalker::recordOverrideRelationship(const ValueDecl *VD) {
|
||||
if (const auto *Override = VD->getOverriddenDecl()) {
|
||||
recordEdge(VD, Override, RelationshipKind::Overrides());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user