-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-doc] Add Start and End Line Numbers #135081
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,7 @@ llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field, | |
if (R[0] > INT_MAX) | ||
return llvm::createStringError(llvm::inconvertibleErrorCode(), | ||
"integer too large to parse"); | ||
Field.emplace((int)R[0], Blob, (bool)R[1]); | ||
Field.emplace((int)R[0], (int)R[1], Blob, (bool)R[2]); | ||
return llvm::Error::success(); | ||
} | ||
|
||
|
@@ -135,7 +135,7 @@ llvm::Error decodeRecord(const Record &R, | |
if (R[0] > INT_MAX) | ||
return llvm::createStringError(llvm::inconvertibleErrorCode(), | ||
"integer too large to parse"); | ||
Field.emplace_back((int)R[0], Blob, (bool)R[1]); | ||
Field.emplace_back((int)R[0], (int)R[1], Blob, (bool)R[2]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||
return llvm::Error::success(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,18 @@ template <typename T> bool isTypedefAnonRecord(const T *D) { | |
return false; | ||
} | ||
|
||
Location MapASTVisitor::getDeclLocation(const NamedDecl *D) const { | ||
bool IsFileInRootDir; | ||
llvm::SmallString<128> File = | ||
getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); | ||
ASTContext &Context = D->getASTContext(); | ||
int Start = | ||
Context.getSourceManager().getPresumedLoc(D->getBeginLoc()).getLine(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Extracting out a source manager reference would make the difference between these two lines clearer. |
||
int End = Context.getSourceManager().getPresumedLoc(D->getEndLoc()).getLine(); | ||
|
||
return Location(Start, End, File, IsFileInRootDir); | ||
} | ||
|
||
void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) { | ||
TraverseDecl(Context.getTranslationUnitDecl()); | ||
} | ||
|
@@ -60,8 +72,7 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) { | |
llvm::SmallString<128> File = | ||
getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); | ||
auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()), | ||
getLine(D, D->getASTContext()), File, | ||
IsFileInRootDir, CDCtx.PublicOnly); | ||
getDeclLocation(D), CDCtx.PublicOnly); | ||
|
||
// A null in place of I indicates that the serializer is skipping this decl | ||
// for some reason (e.g. we're only reporting public decls). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -238,31 +238,32 @@ struct MemberTypeInfo : public FieldTypeInfo { | |
}; | ||
|
||
struct Location { | ||
Location(int LineNumber = 0, StringRef Filename = StringRef(), | ||
bool IsFileInRootDir = false) | ||
: LineNumber(LineNumber), Filename(Filename), | ||
IsFileInRootDir(IsFileInRootDir) {} | ||
Location(int StartLineNumber = 0, int EndLineNumber = 0, | ||
StringRef Filename = StringRef(), bool IsFileInRootDir = false) | ||
: StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber), | ||
Filename(Filename), IsFileInRootDir(IsFileInRootDir) {} | ||
|
||
bool operator==(const Location &Other) const { | ||
return std::tie(LineNumber, Filename) == | ||
std::tie(Other.LineNumber, Other.Filename); | ||
return std::tie(StartLineNumber, EndLineNumber, Filename) == | ||
std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); | ||
} | ||
|
||
bool operator!=(const Location &Other) const { | ||
return std::tie(LineNumber, Filename) != | ||
std::tie(Other.LineNumber, Other.Filename); | ||
return std::tie(StartLineNumber, Filename) != | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has gone out of sync with ==. Maybe it would be better to implement this as |
||
std::tie(Other.StartLineNumber, Other.Filename); | ||
} | ||
|
||
// This operator is used to sort a vector of Locations. | ||
// No specific order (attributes more important than others) is required. Any | ||
// sort is enough, the order is only needed to call std::unique after sorting | ||
// the vector. | ||
bool operator<(const Location &Other) const { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, from the comment, it appears that this need to be a strict weak order that respects the equality constraint given above. Accordingly, this should also include EndLineNumber. |
||
return std::tie(LineNumber, Filename) < | ||
std::tie(Other.LineNumber, Other.Filename); | ||
return std::tie(StartLineNumber, Filename) < | ||
std::tie(Other.StartLineNumber, Other.Filename); | ||
} | ||
|
||
int LineNumber = 0; // Line number of this Location. | ||
int StartLineNumber = 0; // Line number of this Location. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stale comments? |
||
int EndLineNumber = 0; | ||
SmallString<32> Filename; // File for this Location. | ||
bool IsFileInRootDir = false; // Indicates if file is inside root directory | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -527,22 +527,18 @@ static void populateInfo(Info &I, const T *D, const FullComment *C, | |
|
||
template <typename T> | ||
static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, | ||
int LineNumber, StringRef Filename, | ||
bool IsFileInRootDir, | ||
bool &IsInAnonymousNamespace) { | ||
Location Loc, bool &IsInAnonymousNamespace) { | ||
populateInfo(I, D, C, IsInAnonymousNamespace); | ||
if (D->isThisDeclarationADefinition()) | ||
I.DefLoc.emplace(LineNumber, Filename, IsFileInRootDir); | ||
I.DefLoc = Loc; | ||
else | ||
I.Loc.emplace_back(LineNumber, Filename, IsFileInRootDir); | ||
I.Loc.emplace_back(Loc); | ||
} | ||
|
||
static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, | ||
const FullComment *FC, int LineNumber, | ||
StringRef Filename, bool IsFileInRootDir, | ||
const FullComment *FC, Location Loc, | ||
bool &IsInAnonymousNamespace) { | ||
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir, | ||
IsInAnonymousNamespace); | ||
populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace); | ||
auto &LO = D->getLangOpts(); | ||
I.ReturnType = getTypeInfoForType(D->getReturnType(), LO); | ||
parseParameters(I, D); | ||
|
@@ -571,7 +567,7 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, | |
static void populateMemberTypeInfo(MemberTypeInfo &I, const FieldDecl *D) { | ||
assert(D && "Expect non-null FieldDecl in populateMemberTypeInfo"); | ||
|
||
ASTContext& Context = D->getASTContext(); | ||
ASTContext &Context = D->getASTContext(); | ||
// TODO investigate whether we can use ASTContext::getCommentForDecl instead | ||
// of this logic. See also similar code in Mapper.cpp. | ||
RawComment *Comment = Context.getRawCommentForDeclNoCache(D); | ||
|
@@ -623,8 +619,7 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, | |
// reference, its value is not relevant in here so it's not used | ||
// anywhere besides the function call. | ||
bool IsInAnonymousNamespace; | ||
populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*LineNumber=*/{}, | ||
/*FileName=*/{}, IsFileInRootDir, | ||
populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*Location=*/{}, | ||
IsInAnonymousNamespace); | ||
FI.Access = | ||
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe()); | ||
|
@@ -642,8 +637,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, | ||
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
auto I = std::make_unique<NamespaceInfo>(); | ||
bool IsInAnonymousNamespace = false; | ||
populateInfo(*I, D, FC, IsInAnonymousNamespace); | ||
|
@@ -663,12 +658,11 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, | ||
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
auto I = std::make_unique<RecordInfo>(); | ||
bool IsInAnonymousNamespace = false; | ||
populateSymbolInfo(*I, D, FC, LineNumber, File, IsFileInRootDir, | ||
IsInAnonymousNamespace); | ||
populateSymbolInfo(*I, D, FC, Loc, IsInAnonymousNamespace); | ||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
||
|
@@ -681,7 +675,7 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
// TODO: remove first call to parseBases, that function should be deleted | ||
parseBases(*I, C); | ||
parseBases(*I, C, IsFileInRootDir, PublicOnly, true); | ||
parseBases(*I, C, true, PublicOnly, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this always true? also |
||
} | ||
I->Path = getInfoRelativePath(I->Namespace); | ||
|
||
|
@@ -730,12 +724,11 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, | ||
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
FunctionInfo Func; | ||
bool IsInAnonymousNamespace = false; | ||
populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, | ||
IsInAnonymousNamespace); | ||
populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); | ||
Func.Access = clang::AccessSpecifier::AS_none; | ||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
@@ -745,12 +738,11 @@ emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, | ||
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
FunctionInfo Func; | ||
bool IsInAnonymousNamespace = false; | ||
populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, | ||
IsInAnonymousNamespace); | ||
populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); | ||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
||
|
@@ -774,43 +766,52 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber, | ||
StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
TypedefInfo Info; | ||
emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
|
||
TypedefInfo Info; | ||
ASTContext &Context = D->getASTContext(); | ||
bool IsInAnonymousNamespace = false; | ||
populateInfo(Info, D, FC, IsInAnonymousNamespace); | ||
|
||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
||
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); | ||
Info.DefLoc = Loc; | ||
auto &LO = D->getLangOpts(); | ||
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); | ||
|
||
if (Info.Underlying.Type.Name.empty()) { | ||
// Typedef for an unnamed type. This is like "typedef struct { } Foo;" | ||
// The record serializer explicitly checks for this syntax and constructs | ||
// a record with that name, so we don't want to emit a duplicate here. | ||
return {}; | ||
} | ||
Info.IsUsing = false; | ||
|
||
if (RawComment *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) { | ||
Comment->setAttached(); | ||
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) { | ||
Info.Description.emplace_back(); | ||
parseFullComment(Fc, Info.Description.back()); | ||
} | ||
} | ||
// Info is wrapped in its parent scope so is returned in the second position. | ||
return {nullptr, MakeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))}; | ||
} | ||
|
||
// A type alias is a C++ "using" declaration for a type. It gets mapped to a | ||
// TypedefInfo with the IsUsing flag set. | ||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, | ||
StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
TypedefInfo Info; | ||
|
||
bool IsInAnonymousNamespace = false; | ||
populateInfo(Info, D, FC, IsInAnonymousNamespace); | ||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
||
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); | ||
Info.DefLoc = Loc; | ||
auto &LO = D->getLangOpts(); | ||
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); | ||
Info.IsUsing = true; | ||
|
@@ -820,12 +821,12 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, | |
} | ||
|
||
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> | ||
emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, | ||
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { | ||
emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, | ||
bool PublicOnly) { | ||
EnumInfo Enum; | ||
bool IsInAnonymousNamespace = false; | ||
populateSymbolInfo(Enum, D, FC, LineNumber, File, IsFileInRootDir, | ||
IsInAnonymousNamespace); | ||
populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace); | ||
|
||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) | ||
return {}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're touching these, lets use
static_cast<T>
. If C style casts are prevalent in the rest of the file, we should address those separately.