Skip to content

SymbolGraph: Serialize interface language #29414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/SymbolGraphGen/Edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ void Edge::serialize(llvm::json::OStream &OS) const {

// In case a dependent module isn't available, serialize a fallback name.
auto TargetModuleName = Target->getModuleContext()->getName().str();

if (TargetModuleName != Walker->M.getName().str()) {
auto TargetSymbolIdentifier = Walker->getSymbolIdentifier(Target);
auto TargetComponents = TargetSymbolIdentifier.SimpleComponents;
SmallVector<SmallString<32>, 8> TargetPathComponents;
Walker->getPathComponents(Target, TargetPathComponents);

SmallString<128> Scratch(TargetModuleName);
for (auto it = TargetComponents.begin();
it != TargetComponents.end(); ++it) {
for (auto it = TargetPathComponents.begin();
it != TargetPathComponents.end(); ++it) {
Scratch.push_back('.');
Scratch.append(*it);
}
Expand Down
24 changes: 20 additions & 4 deletions lib/SymbolGraphGen/Symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,30 @@ void Symbol::serializeKind(llvm::json::OStream &OS) const {

void Symbol::serializeIdentifier(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const {
AttributeRAII A("identifier", OS);
Walker.getSymbolIdentifier(VD).serialize(OS);
OS.attributeObject("identifier", [&](){
OS.attribute("precise", Walker.getUSR(VD));
OS.attribute("interfaceLanguage", "swift");
});
}

void Symbol::serializePathComponents(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const {
OS.attributeArray("pathComponents", [&](){
SmallVector<SmallString<32>, 8> PathComponents;
Walker.getPathComponents(VD, PathComponents);
for (auto Component : PathComponents) {
OS.value(Component);
}
});
}

void Symbol::serializeNames(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const {
OS.attributeObject("names", [&](){
auto Identifier = Walker.getSymbolIdentifier(VD);
OS.attribute("title", Identifier.SimpleComponents.back());
SmallVector<SmallString<32>, 8> PathComponents;
Walker.getPathComponents(VD, PathComponents);

OS.attribute("title", PathComponents.back());
// "navigator": null
Walker.serializeSubheadingDeclarationFragments("subheading", VD, OS);
// "prose": null
Expand Down Expand Up @@ -370,6 +385,7 @@ void Symbol::serialize(SymbolGraphASTWalker &Walker,
OS.object([&](){
serializeKind(OS);
serializeIdentifier(Walker, OS);
serializePathComponents(Walker, OS);
serializeNames(Walker, OS);
serializeDocComment(Walker, OS);

Expand Down
43 changes: 3 additions & 40 deletions lib/SymbolGraphGen/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,46 +24,6 @@ namespace symbolgraphgen {
struct AvailabilityDomain;
struct SymbolGraphASTWalker;

/**
An identifier for a symbol that provides a globally unique identifier suitable for
internal lookups and a locally unique path for human use, such as a URL.
*/
struct SymbolIdentifier {
/**
A string that uniquely identifies a symbol within a module in the event of
ambiguities. A precise identifier need not be human readable.
*/
StringRef PreciseIdentifier;

/**
The components for a "fully qualified" identifier.
*/
ArrayRef<StringRef> SimpleComponents;

SymbolIdentifier(llvm::StringRef PreciseIdentifier,
ArrayRef<StringRef> SimpleComponents)
: PreciseIdentifier(PreciseIdentifier),
SimpleComponents(SimpleComponents) {
assert(!PreciseIdentifier.empty());
}

void serialize(llvm::json::OStream &OS) const {
OS.object([&](){
OS.attribute("precise", PreciseIdentifier);
OS.attributeArray("simpleComponents", [&](){
for (auto Component : SimpleComponents) {
OS.value(Component);
}
});
});
}

bool operator==(const SymbolIdentifier &Other) const {
return PreciseIdentifier == Other.PreciseIdentifier &&
SimpleComponents == Other.SimpleComponents;
}
};

/// A symbol from a module: a node in a graph.
struct Symbol {
const ValueDecl *VD;
Expand All @@ -76,6 +36,9 @@ struct Symbol {
void serializeIdentifier(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const;

void serializePathComponents(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const;

void serializeNames(SymbolGraphASTWalker &Walker,
llvm::json::OStream &OS) const;

Expand Down
29 changes: 6 additions & 23 deletions lib/SymbolGraphGen/SymbolGraphASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,15 @@ StringRef SymbolGraphASTWalker::getUSR(const ValueDecl *VD) {
return USR;
}

SymbolIdentifier
SymbolGraphASTWalker::getSymbolIdentifier(const ValueDecl *VD) {
// Look in the symbol identifier cache for this declartion.
auto Found = SymbolIdentifierCache.find(VD);
if (Found != SymbolIdentifierCache.end()) {
return Found->getSecond();
}

// Not found; need to build a symbol identifier and add it to the cache.
auto PreciseIdentifier = getUSR(VD);
llvm::SmallVector<llvm::StringRef, 4> SimpleIdentifierChain;

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);
SimpleIdentifierChain.push_back(Ctx.allocateCopy(Scratch.str()));
Components.push_back(Scratch);
if (const auto *DC = Decl->getDeclContext()) {
if (const auto *Proto = DC->getExtendedProtocolDecl()) {
Decl = Proto;
Expand All @@ -179,17 +170,9 @@ SymbolGraphASTWalker::getSymbolIdentifier(const ValueDecl *VD) {
Decl = nullptr;
}
}

// The list is leaf-to-root, but our list is root-to-leaf, so reverse it.
std::reverse(SimpleIdentifierChain.begin(), SimpleIdentifierChain.end());

SymbolIdentifier Identifier {
PreciseIdentifier,
Ctx.allocateCopy(llvm::makeArrayRef(SimpleIdentifierChain))
};

SymbolIdentifierCache.insert({VD, Identifier});
return Identifier;
// 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 {
Expand Down
8 changes: 2 additions & 6 deletions lib/SymbolGraphGen/SymbolGraphASTWalker.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class ValueDecl;

namespace symbolgraphgen {

struct SymbolIdentifier;
struct SymbolGraph;
struct SymbolGraphOptions;

Expand All @@ -49,9 +48,6 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
/// A context for allocations.
markup::MarkupContext Ctx;

/// A cache of identifiers for declarations that may be seen more than once.
llvm::DenseMap<const Decl *, SymbolIdentifier> SymbolIdentifierCache;

/// A cache of USRs for declarations.
llvm::DenseMap<const ValueDecl *, StringRef> USRCache;

Expand All @@ -72,8 +68,8 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
/// Get the USR of a declaration and add it to the local allocator.
StringRef getUSR(const ValueDecl *VD);

/// Returns a `SymbolIdentifier` for a given declaration.
SymbolIdentifier getSymbolIdentifier(const ValueDecl *VD);
/// Returns an array of path components for a declaration.
void getPathComponents(const ValueDecl *VD, SmallVectorImpl<SmallString<32>> &Components);

// MARK: - Declaration Fragments

Expand Down