Skip to content

Commit 8fb896f

Browse files
committed
[clang-doc] add start and end line number
1 parent b93376f commit 8fb896f

File tree

6 files changed

+82
-56
lines changed

6 files changed

+82
-56
lines changed

clang-tools-extra/clang-doc/BitcodeReader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
8585
if (R[0] > INT_MAX)
8686
return llvm::createStringError(llvm::inconvertibleErrorCode(),
8787
"integer too large to parse");
88-
Field.emplace((int)R[0], Blob, (bool)R[1]);
88+
Field.emplace((int)R[0], (int) R[1], Blob, (bool)R[2]);
8989
return llvm::Error::success();
9090
}
9191

clang-tools-extra/clang-doc/BitcodeWriter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,16 @@ static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
7777
{// 0. Fixed-size integer (line number)
7878
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
7979
BitCodeConstants::LineNumberSize),
80-
// 1. Boolean (IsFileInRootDir)
80+
// 1. Fixed-size integer (start line number)
81+
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
82+
BitCodeConstants::LineNumberSize),
83+
// 2. Boolean (IsFileInRootDir)
8184
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
8285
BitCodeConstants::BoolSize),
83-
// 2. Fixed-size integer (length of the following string (filename))
86+
// 3. Fixed-size integer (length of the following string (filename))
8487
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
8588
BitCodeConstants::StringLengthSize),
86-
// 3. The string blob
89+
// 4. The string blob
8790
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
8891
}
8992

clang-tools-extra/clang-doc/Mapper.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ template <typename T> bool isTypedefAnonRecord(const T *D) {
2828
return false;
2929
}
3030

31+
Location MapASTVisitor::getDeclLocation(const NamedDecl *D) const {
32+
bool IsFileInRootDir;
33+
llvm::SmallString<128> File =
34+
getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir);
35+
ASTContext &Context = D->getASTContext();
36+
int Start = Context.getSourceManager()
37+
.getPresumedLoc(D->getBeginLoc())
38+
.getLine();
39+
int End = Context.getSourceManager()
40+
.getPresumedLoc(D->getEndLoc())
41+
.getLine();
42+
43+
return Location(Start, End, File, IsFileInRootDir);
44+
}
45+
3146
void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
3247
TraverseDecl(Context.getTranslationUnitDecl());
3348
}
@@ -60,7 +75,7 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) {
6075
llvm::SmallString<128> File =
6176
getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir);
6277
auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()),
63-
getLine(D, D->getASTContext()), File,
78+
getDeclLocation(D), File,
6479
IsFileInRootDir, CDCtx.PublicOnly);
6580

6681
// A null in place of I indicates that the serializer is skipping this decl

clang-tools-extra/clang-doc/Mapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>,
4646
template <typename T> bool mapDecl(const T *D, bool IsDefinition);
4747

4848
int getLine(const NamedDecl *D, const ASTContext &Context) const;
49+
50+
Location getDeclLocation(const NamedDecl *D) const;
51+
4952
llvm::SmallString<128> getFile(const NamedDecl *D, const ASTContext &Context,
5053
StringRef RootDir,
5154
bool &IsFileInRootDir) const;

clang-tools-extra/clang-doc/Representation.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -238,31 +238,33 @@ struct MemberTypeInfo : public FieldTypeInfo {
238238
};
239239

240240
struct Location {
241-
Location(int LineNumber = 0, StringRef Filename = StringRef(),
241+
Location(int StartLineNumber = 0,
242+
int EndLineNumber = 0, StringRef Filename = StringRef(),
242243
bool IsFileInRootDir = false)
243-
: LineNumber(LineNumber), Filename(Filename),
244-
IsFileInRootDir(IsFileInRootDir) {}
244+
: StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber),
245+
Filename(Filename), IsFileInRootDir(IsFileInRootDir) {}
245246

246247
bool operator==(const Location &Other) const {
247-
return std::tie(LineNumber, Filename) ==
248-
std::tie(Other.LineNumber, Other.Filename);
248+
return std::tie(StartLineNumber, EndLineNumber, Filename) ==
249+
std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename);
249250
}
250251

251252
bool operator!=(const Location &Other) const {
252-
return std::tie(LineNumber, Filename) !=
253-
std::tie(Other.LineNumber, Other.Filename);
253+
return std::tie(StartLineNumber, Filename) !=
254+
std::tie(Other.StartLineNumber, Other.Filename);
254255
}
255256

256257
// This operator is used to sort a vector of Locations.
257258
// No specific order (attributes more important than others) is required. Any
258259
// sort is enough, the order is only needed to call std::unique after sorting
259260
// the vector.
260261
bool operator<(const Location &Other) const {
261-
return std::tie(LineNumber, Filename) <
262-
std::tie(Other.LineNumber, Other.Filename);
262+
return std::tie(StartLineNumber, Filename) <
263+
std::tie(Other.StartLineNumber, Other.Filename);
263264
}
264265

265-
int LineNumber = 0; // Line number of this Location.
266+
int StartLineNumber = 0; // Line number of this Location.
267+
int EndLineNumber = 0;
266268
SmallString<32> Filename; // File for this Location.
267269
bool IsFileInRootDir = false; // Indicates if file is inside root directory
268270
};

clang-tools-extra/clang-doc/Serialize.cpp

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -527,22 +527,20 @@ static void populateInfo(Info &I, const T *D, const FullComment *C,
527527

528528
template <typename T>
529529
static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
530-
int LineNumber, StringRef Filename,
531-
bool IsFileInRootDir,
530+
Location Loc,
532531
bool &IsInAnonymousNamespace) {
533532
populateInfo(I, D, C, IsInAnonymousNamespace);
534533
if (D->isThisDeclarationADefinition())
535-
I.DefLoc.emplace(LineNumber, Filename, IsFileInRootDir);
534+
I.DefLoc = Loc;
536535
else
537-
I.Loc.emplace_back(LineNumber, Filename, IsFileInRootDir);
536+
I.Loc.emplace_back(Loc);
538537
}
539538

540539
static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
541-
const FullComment *FC, int LineNumber,
542-
StringRef Filename, bool IsFileInRootDir,
540+
const FullComment *FC,
541+
Location Loc,
543542
bool &IsInAnonymousNamespace) {
544-
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir,
545-
IsInAnonymousNamespace);
543+
populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
546544
auto &LO = D->getLangOpts();
547545
I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
548546
parseParameters(I, D);
@@ -623,8 +621,7 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
623621
// reference, its value is not relevant in here so it's not used
624622
// anywhere besides the function call.
625623
bool IsInAnonymousNamespace;
626-
populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*LineNumber=*/{},
627-
/*FileName=*/{}, IsFileInRootDir,
624+
populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*Location=*/{},
628625
IsInAnonymousNamespace);
629626
FI.Access =
630627
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
@@ -642,8 +639,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
642639
}
643640

644641
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
645-
emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
646-
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
642+
emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc,
643+
bool PublicOnly) {
647644
auto I = std::make_unique<NamespaceInfo>();
648645
bool IsInAnonymousNamespace = false;
649646
populateInfo(*I, D, FC, IsInAnonymousNamespace);
@@ -663,12 +660,11 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
663660
}
664661

665662
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
666-
emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
667-
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
663+
emitInfo(const RecordDecl *D, const FullComment *FC,
664+
Location Loc, bool PublicOnly) {
668665
auto I = std::make_unique<RecordInfo>();
669666
bool IsInAnonymousNamespace = false;
670-
populateSymbolInfo(*I, D, FC, LineNumber, File, IsFileInRootDir,
671-
IsInAnonymousNamespace);
667+
populateSymbolInfo(*I, D, FC, Loc, IsInAnonymousNamespace);
672668
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
673669
return {};
674670

@@ -681,7 +677,7 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
681677
}
682678
// TODO: remove first call to parseBases, that function should be deleted
683679
parseBases(*I, C);
684-
parseBases(*I, C, IsFileInRootDir, PublicOnly, true);
680+
parseBases(*I, C, true, PublicOnly, true);
685681
}
686682
I->Path = getInfoRelativePath(I->Namespace);
687683

@@ -730,30 +726,28 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
730726
}
731727

732728
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
733-
emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
734-
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
729+
emitInfo(const FunctionDecl *D, const FullComment *FC,
730+
Location Loc, bool PublicOnly) {
735731
FunctionInfo Func;
736732
bool IsInAnonymousNamespace = false;
737-
populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir,
738-
IsInAnonymousNamespace);
733+
populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
739734
Func.Access = clang::AccessSpecifier::AS_none;
740735
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
741736
return {};
742-
737+
743738
// Info is wrapped in its parent scope so is returned in the second position.
744739
return {nullptr, MakeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
745740
}
746741

747742
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
748-
emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
749-
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
743+
emitInfo(const CXXMethodDecl *D, const FullComment *FC,
744+
Location Loc, bool PublicOnly) {
750745
FunctionInfo Func;
751746
bool IsInAnonymousNamespace = false;
752-
populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir,
753-
IsInAnonymousNamespace);
747+
populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
754748
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
755749
return {};
756-
750+
757751
Func.IsMethod = true;
758752

759753
const NamedDecl *Parent = nullptr;
@@ -774,43 +768,52 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
774768
}
775769

776770
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
777-
emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber,
778-
StringRef File, bool IsFileInRootDir, bool PublicOnly) {
771+
emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc,
772+
bool PublicOnly) {
773+
779774
TypedefInfo Info;
780-
775+
ASTContext& Context = D->getASTContext();
781776
bool IsInAnonymousNamespace = false;
782777
populateInfo(Info, D, FC, IsInAnonymousNamespace);
778+
783779
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
784780
return {};
785-
786-
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
781+
782+
Info.DefLoc = Loc;
787783
auto &LO = D->getLangOpts();
788784
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
785+
789786
if (Info.Underlying.Type.Name.empty()) {
790787
// Typedef for an unnamed type. This is like "typedef struct { } Foo;"
791788
// The record serializer explicitly checks for this syntax and constructs
792789
// a record with that name, so we don't want to emit a duplicate here.
793790
return {};
794791
}
795792
Info.IsUsing = false;
796-
793+
if (RawComment *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) {
794+
Comment->setAttached();
795+
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
796+
Info.Description.emplace_back();
797+
parseFullComment(Fc, Info.Description.back());
798+
}
799+
}
797800
// Info is wrapped in its parent scope so is returned in the second position.
798801
return {nullptr, MakeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))};
799802
}
800803

801804
// A type alias is a C++ "using" declaration for a type. It gets mapped to a
802805
// TypedefInfo with the IsUsing flag set.
803806
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
804-
emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber,
805-
StringRef File, bool IsFileInRootDir, bool PublicOnly) {
807+
emitInfo(const TypeAliasDecl *D, const FullComment *FC,
808+
Location Loc, bool PublicOnly) {
806809
TypedefInfo Info;
807810

808811
bool IsInAnonymousNamespace = false;
809812
populateInfo(Info, D, FC, IsInAnonymousNamespace);
810813
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
811814
return {};
812815

813-
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
816+
Info.DefLoc = Loc;
814817
auto &LO = D->getLangOpts();
815818
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
816819
Info.IsUsing = true;
@@ -820,15 +823,15 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber,
820823
}
821824

822825
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
823-
emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
824-
llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
826+
emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc,
827+
bool PublicOnly) {
825828
EnumInfo Enum;
826829
bool IsInAnonymousNamespace = false;
827-
populateSymbolInfo(Enum, D, FC, LineNumber, File, IsFileInRootDir,
828-
IsInAnonymousNamespace);
830+
populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace);
831+
829832
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
830833
return {};
831-
834+
832835
Enum.Scoped = D->isScoped();
833836
if (D->isFixed()) {
834837
auto Name = D->getIntegerType().getAsString();

0 commit comments

Comments
 (0)