mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Adds a tool `swift-symbolgraph-extract` that reads an existing Swift module and prints a platform- and language-agnostic JSON description of the module, primarly for documentation. Adds a small sub-library `SymbolGraphGen` which houses the core implementation for collecting relevant information about declarations. The main entry point is integrated directly into the driver as a mode: the tool is meant to be run outside of the normal edit-compile-run/test workflow to avoid impacting build times. Along with common options for other tools, unique options include `pretty-print` for debugging, and a `minimum-access-level` options for including internal documentation. A symbol graph is a directed graph where the nodes are symbols in a module and the edges are relationships between them. For example, a `struct S` may have a member `var x`. The graph would have two nodes for `S` and `x`, and one "member-of" relationship edge. Other relationship kinds include "inherits-from" or "conforms to". The data format for a symbol graph is still under development and may change without notice until a specificiation and versioning scheme is published. Various aspects about a symbol are recorded in the nodes, such as availability, documentation comments, or data needed for printing the shapes of declarations without having to understand specifics about the langauge. Implicit and public-underscored stdlib declarations are not included by default. rdar://problem/55346798
141 lines
3.8 KiB
C++
141 lines
3.8 KiB
C++
//===--- DeclarationFragmentPrinter.cpp - Declaration Fragment Printer ----===//
|
|
//
|
|
// 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 "DeclarationFragmentPrinter.h"
|
|
#include "SymbolGraphASTWalker.h"
|
|
|
|
using namespace swift;
|
|
using namespace symbolgraphgen;
|
|
|
|
void DeclarationFragmentPrinter::openFragment(FragmentKind Kind) {
|
|
assert(Kind != FragmentKind::None);
|
|
if (this->Kind != Kind) {
|
|
closeFragment();
|
|
this->Kind = Kind,
|
|
Spelling.clear();
|
|
USR.clear();
|
|
}
|
|
}
|
|
|
|
StringRef
|
|
DeclarationFragmentPrinter::getKindSpelling(FragmentKind Kind) const {
|
|
switch (Kind) {
|
|
case FragmentKind::Keyword:
|
|
return "keyword";
|
|
case FragmentKind::Attribute:
|
|
return "attribute";
|
|
case FragmentKind::NumberLiteral:
|
|
return "number";
|
|
case FragmentKind::StringLiteral:
|
|
return "string";
|
|
case FragmentKind::Identifier:
|
|
return "identifier";
|
|
case FragmentKind::TypeIdentifier:
|
|
return "typeIdentifier";
|
|
case FragmentKind::GenericParameter:
|
|
return "genericParameter";
|
|
case FragmentKind::Text:
|
|
return "text";
|
|
case FragmentKind::None:
|
|
llvm_unreachable("Fragment kind of 'None' has no spelling");
|
|
}
|
|
}
|
|
|
|
void DeclarationFragmentPrinter::closeFragment() {
|
|
if (Kind == FragmentKind::None) {
|
|
return;
|
|
}
|
|
|
|
if (!Spelling.empty()) {
|
|
OS.object([&](){
|
|
OS.attribute("kind", getKindSpelling(Kind));
|
|
OS.attribute("spelling", Spelling.str());
|
|
if (!USR.empty()) {
|
|
OS.attribute("preciseIdentifier", USR.str());
|
|
}
|
|
});
|
|
}
|
|
|
|
Spelling.clear();
|
|
USR.clear();
|
|
Kind = FragmentKind::None;
|
|
}
|
|
|
|
void DeclarationFragmentPrinter::printDeclLoc(const Decl *D) {
|
|
switch (D->getKind()) {
|
|
case DeclKind::Constructor:
|
|
case DeclKind::Destructor:
|
|
case DeclKind::Subscript:
|
|
openFragment(FragmentKind::Keyword);
|
|
break;
|
|
default:
|
|
openFragment(FragmentKind::Identifier);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
DeclarationFragmentPrinter::printNamePre(PrintNameContext Context) {
|
|
switch (Context) {
|
|
case PrintNameContext::Keyword:
|
|
openFragment(FragmentKind::Keyword);
|
|
break;
|
|
case PrintNameContext::GenericParameter:
|
|
openFragment(FragmentKind::GenericParameter);
|
|
break;
|
|
case PrintNameContext::Attribute:
|
|
openFragment(FragmentKind::Attribute);
|
|
break;
|
|
case PrintNameContext::ClassDynamicSelf:
|
|
case PrintNameContext::FunctionParameterExternal:
|
|
openFragment(FragmentKind::Identifier);
|
|
break;
|
|
case PrintNameContext::FunctionParameterLocal:
|
|
openFragment(FragmentKind::Identifier);
|
|
break;
|
|
case PrintNameContext::TupleElement:
|
|
case PrintNameContext::TypeMember:
|
|
case PrintNameContext::Normal:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DeclarationFragmentPrinter::printStructurePre(PrintStructureKind Kind,
|
|
const Decl *D) {
|
|
switch (Kind) {
|
|
case PrintStructureKind::NumberLiteral:
|
|
openFragment(FragmentKind::NumberLiteral);
|
|
break;
|
|
case PrintStructureKind::StringLiteral:
|
|
openFragment(FragmentKind::StringLiteral);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DeclarationFragmentPrinter::printTypeRef(Type T, const TypeDecl *RefTo,
|
|
Identifier Name,
|
|
PrintNameContext NameContext) {
|
|
openFragment(FragmentKind::TypeIdentifier);
|
|
printText(Name.str());
|
|
USR = Walker.getUSR(RefTo);
|
|
closeFragment();
|
|
}
|
|
|
|
void DeclarationFragmentPrinter::printText(StringRef Text) {
|
|
if (Kind == FragmentKind::None) {
|
|
openFragment(FragmentKind::Text);
|
|
}
|
|
Spelling.append(Text);
|
|
}
|