Skip to content

Commit

Permalink
[clang-doc] Fix link generation
Browse files Browse the repository at this point in the history
Before making a link to a reference it is required to check that the
reference has a path (eg. primitives won't have paths).
This was done by checking if the path was empty; that worked because
when generating paths the outdirectory was included, so if the path was
assigned it had that outdirectory at least.
The path generation was changed, it's now only the composite of the
namespaces without the outdirectory. So if the info is in the global
namespace the path would be empty and the old check wouldn't work as expected.
A new attribute has been added to the Reference struct that indicates if
the info's parent is the global namespace.
Paths generation now fails if the path is empty and if the info
is not in the global namespace.

Differential Revision: https://reviews.llvm.org/D64958

llvm-svn: 367958
  • Loading branch information
DiegoAstiazaran committed Aug 6, 2019
1 parent b31f60b commit 15e468e
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 8 deletions.
2 changes: 2 additions & 0 deletions clang-tools-extra/clang-doc/BitcodeReader.cpp
Expand Up @@ -292,6 +292,8 @@ llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
return decodeRecord(R, I->RefType, Blob);
case REFERENCE_PATH:
return decodeRecord(R, I->Path, Blob);
case REFERENCE_IS_IN_GLOBAL_NAMESPACE:
return decodeRecord(R, I->IsInGlobalNamespace, Blob);
case REFERENCE_FIELD:
return decodeRecord(R, F, Blob);
default:
Expand Down
5 changes: 4 additions & 1 deletion clang-tools-extra/clang-doc/BitcodeWriter.cpp
Expand Up @@ -172,6 +172,8 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
{REFERENCE_NAME, {"Name", &StringAbbrev}},
{REFERENCE_TYPE, {"RefType", &IntAbbrev}},
{REFERENCE_PATH, {"Path", &StringAbbrev}},
{REFERENCE_IS_IN_GLOBAL_NAMESPACE,
{"IsInGlobalNamespace", &BoolAbbrev}},
{REFERENCE_FIELD, {"Field", &IntAbbrev}}};
assert(Inits.size() == RecordIdCount);
for (const auto &Init : Inits) {
Expand Down Expand Up @@ -215,7 +217,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
// Reference Block
{BI_REFERENCE_BLOCK_ID,
{REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_PATH,
REFERENCE_FIELD}}};
REFERENCE_IS_IN_GLOBAL_NAMESPACE, REFERENCE_FIELD}}};

// AbbreviationMap

Expand Down Expand Up @@ -387,6 +389,7 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
emitRecord(R.Name, REFERENCE_NAME);
emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
emitRecord(R.Path, REFERENCE_PATH);
emitRecord(R.IsInGlobalNamespace, REFERENCE_IS_IN_GLOBAL_NAMESPACE);
emitRecord((unsigned)Field, REFERENCE_FIELD);
}

Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-doc/BitcodeWriter.h
Expand Up @@ -109,6 +109,7 @@ enum RecordId {
REFERENCE_NAME,
REFERENCE_TYPE,
REFERENCE_PATH,
REFERENCE_IS_IN_GLOBAL_NAMESPACE,
REFERENCE_FIELD,
RI_LAST,
RI_FIRST = VERSION
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clang-doc/HTMLGenerator.cpp
Expand Up @@ -247,7 +247,7 @@ static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {

static std::unique_ptr<HTMLNode> genTypeReference(const Reference &Type,
StringRef CurrentDirectory) {
if (Type.Path.empty())
if (Type.Path.empty() && !Type.IsInGlobalNamespace)
return llvm::make_unique<TextNode>(Type.Name);
llvm::SmallString<128> Path =
computeRelativePath(Type.Path, CurrentDirectory);
Expand Down
18 changes: 14 additions & 4 deletions clang-tools-extra/clang-doc/Representation.h
Expand Up @@ -114,11 +114,17 @@ struct CommentInfo {
struct Reference {
Reference() = default;
Reference(llvm::StringRef Name) : Name(Name) {}
Reference(llvm::StringRef Name, StringRef Path) : Name(Name), Path(Path) {}
// An empty path means the info is in the global namespace because the path is
// a composite of the parent namespaces.
Reference(llvm::StringRef Name, StringRef Path)
: Name(Name), Path(Path), IsInGlobalNamespace(Path.empty()) {}
Reference(SymbolID USR, StringRef Name, InfoType IT)
: USR(USR), Name(Name), RefType(IT) {}
// An empty path means the info is in the global namespace because the path is
// a composite of the parent namespaces.
Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
: USR(USR), Name(Name), RefType(IT), Path(Path) {}
: USR(USR), Name(Name), RefType(IT), Path(Path),
IsInGlobalNamespace(Path.empty()) {}

bool operator==(const Reference &Other) const {
return std::tie(USR, Name, RefType) ==
Expand All @@ -130,8 +136,12 @@ struct Reference {
InfoType RefType = InfoType::IT_default; // Indicates the type of this
// Reference (namespace, record,
// function, enum, default).
llvm::SmallString<128> Path; // Path of directory where the clang-doc
// generated file will be saved
// Path of directory where the clang-doc generated file will be saved
// (possibly unresolved)
llvm::SmallString<128> Path;
// Indicates if the info's parent is the global namespace, or if the info is
// the global namespace
bool IsInGlobalNamespace = false;
};

// A base struct for TypeInfos
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-doc/YAMLGenerator.cpp
Expand Up @@ -156,6 +156,7 @@ template <> struct MappingTraits<Reference> {
IO.mapOptional("Name", Ref.Name, SmallString<16>());
IO.mapOptional("USR", Ref.USR, SymbolID());
IO.mapOptional("Path", Ref.Path, SmallString<128>());
IO.mapOptional("IsInGlobalNamespace", Ref.IsInGlobalNamespace, false);
}
};

Expand Down
5 changes: 3 additions & 2 deletions clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
Expand Up @@ -80,7 +80,8 @@ TEST(YAMLGeneratorTest, emitRecordYAML) {
I.Members.emplace_back("int", "path/to/int", "X",
AccessSpecifier::AS_private);
I.TagType = TagTypeKind::TTK_Class;
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "path/to/F");
// F is in the global namespace
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
"path/to/G");

Expand Down Expand Up @@ -120,7 +121,7 @@ TagType: Class
Parents:
- Type: Record
Name: 'F'
Path: 'path/to/F'
IsInGlobalNamespace: true
VirtualParents:
- Type: Record
Name: 'G'
Expand Down

0 comments on commit 15e468e

Please sign in to comment.