Skip to content

Commit a612e34

Browse files
committedJun 24, 2019
Augment location information when dumping the AST to JSON.
Rather than create JSON objects for source locations and ranges, we instead stream them out directly. This allows us to elide duplicate information (without JSON field reordering causing an issue) like file names and line numbers, similar to the text dump. This also adds token length information when dumping the source location. llvm-svn: 364226
1 parent 9c8282a commit a612e34

23 files changed

+6105
-9671
lines changed
 

‎clang/include/clang/AST/JSONNodeDumper.h

+9-6
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class JSONNodeDumper
124124
ASTContext& Ctx;
125125
PrintingPolicy PrintPolicy;
126126
const comments::CommandTraits *Traits;
127+
StringRef LastLocFilename;
128+
unsigned LastLocLine;
127129

128130
using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
129131
using InnerCommentVisitor =
@@ -139,14 +141,15 @@ class JSONNodeDumper
139141
JOS.attribute(Key, Value);
140142
}
141143

142-
// Creates a single SourceLocation JSON representation of the given location.
143-
llvm::json::Object createBareSourceLocation(SourceLocation Loc);
144-
// Creates a JSON representation of a SourceLocation based on its presumed
144+
// Writes the attributes of a SourceLocation object without.
145+
void writeBareSourceLocation(SourceLocation Loc);
146+
147+
// Writes the attributes of a SourceLocation to JSON based on its presumed
145148
// spelling location. If the given location represents a macro invocation,
146149
// this outputs two sub-objects: one for the spelling and one for the
147150
// expansion location.
148-
llvm::json::Object createSourceLocation(SourceLocation Loc);
149-
llvm::json::Object createSourceRange(SourceRange R);
151+
void writeSourceLocation(SourceLocation Loc);
152+
void writeSourceRange(SourceRange R);
150153
std::string createPointerRepresentation(const void *Ptr);
151154
llvm::json::Object createQualType(QualType QT, bool Desugar = true);
152155
llvm::json::Object createBareDeclRef(const Decl *D);
@@ -178,7 +181,7 @@ class JSONNodeDumper
178181
const PrintingPolicy &PrintPolicy,
179182
const comments::CommandTraits *Traits)
180183
: NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), PrintPolicy(PrintPolicy),
181-
Traits(Traits) {}
184+
Traits(Traits), LastLocLine(0) {}
182185

183186
void Visit(const Attr *A);
184187
void Visit(const Stmt *Node);

‎clang/lib/AST/JSONNodeDumper.cpp

+44-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "clang/AST/JSONNodeDumper.h"
2+
#include "clang/Lex/Lexer.h"
23
#include "llvm/ADT/StringSwitch.h"
34

45
using namespace clang;
@@ -28,7 +29,7 @@ void JSONNodeDumper::Visit(const Attr *A) {
2829
}
2930
JOS.attribute("id", createPointerRepresentation(A));
3031
JOS.attribute("kind", AttrName);
31-
JOS.attribute("range", createSourceRange(A->getRange()));
32+
JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });
3233
attributeOnlyIfTrue("inherited", A->isInherited());
3334
attributeOnlyIfTrue("implicit", A->isImplicit());
3435

@@ -47,7 +48,8 @@ void JSONNodeDumper::Visit(const Stmt *S) {
4748

4849
JOS.attribute("id", createPointerRepresentation(S));
4950
JOS.attribute("kind", S->getStmtClassName());
50-
JOS.attribute("range", createSourceRange(S->getSourceRange()));
51+
JOS.attributeObject("range",
52+
[S, this] { writeSourceRange(S->getSourceRange()); });
5153

5254
if (const auto *E = dyn_cast<Expr>(S)) {
5355
JOS.attribute("type", createQualType(E->getType()));
@@ -90,8 +92,10 @@ void JSONNodeDumper::Visit(const Decl *D) {
9092
return;
9193

9294
JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
93-
JOS.attribute("loc", createSourceLocation(D->getLocation()));
94-
JOS.attribute("range", createSourceRange(D->getSourceRange()));
95+
JOS.attributeObject("loc",
96+
[D, this] { writeSourceLocation(D->getLocation()); });
97+
JOS.attributeObject("range",
98+
[D, this] { writeSourceRange(D->getSourceRange()); });
9599
attributeOnlyIfTrue("isImplicit", D->isImplicit());
96100
attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());
97101

@@ -118,8 +122,10 @@ void JSONNodeDumper::Visit(const comments::Comment *C,
118122

119123
JOS.attribute("id", createPointerRepresentation(C));
120124
JOS.attribute("kind", C->getCommentKindName());
121-
JOS.attribute("loc", createSourceLocation(C->getLocation()));
122-
JOS.attribute("range", createSourceRange(C->getSourceRange()));
125+
JOS.attributeObject("loc",
126+
[C, this] { writeSourceLocation(C->getLocation()); });
127+
JOS.attributeObject("range",
128+
[C, this] { writeSourceRange(C->getSourceRange()); });
123129

124130
InnerCommentVisitor::visit(C, FC);
125131
}
@@ -128,7 +134,7 @@ void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
128134
const Decl *From, StringRef Label) {
129135
JOS.attribute("kind", "TemplateArgument");
130136
if (R.isValid())
131-
JOS.attribute("range", createSourceRange(R));
137+
JOS.attributeObject("range", [R, this] { writeSourceRange(R); });
132138

133139
if (From)
134140
JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));
@@ -165,43 +171,47 @@ void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
165171
attributeOnlyIfTrue("selected", A.isSelected());
166172
}
167173

168-
llvm::json::Object
169-
JSONNodeDumper::createBareSourceLocation(SourceLocation Loc) {
174+
void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc) {
170175
PresumedLoc Presumed = SM.getPresumedLoc(Loc);
171176

172-
if (Presumed.isInvalid())
173-
return llvm::json::Object{};
174-
175-
return llvm::json::Object{{"file", Presumed.getFilename()},
176-
{"line", Presumed.getLine()},
177-
{"col", Presumed.getColumn()}};
177+
if (Presumed.isValid()) {
178+
if (LastLocFilename != Presumed.getFilename()) {
179+
JOS.attribute("file", Presumed.getFilename());
180+
JOS.attribute("line", Presumed.getLine());
181+
} else if (LastLocLine != Presumed.getLine())
182+
JOS.attribute("line", Presumed.getLine());
183+
JOS.attribute("col", Presumed.getColumn());
184+
JOS.attribute("tokLen",
185+
Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts()));
186+
LastLocFilename = Presumed.getFilename();
187+
LastLocLine = Presumed.getLine();
188+
}
178189
}
179190

180-
llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) {
191+
void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
181192
SourceLocation Spelling = SM.getSpellingLoc(Loc);
182193
SourceLocation Expansion = SM.getExpansionLoc(Loc);
183194

184-
llvm::json::Object SLoc = createBareSourceLocation(Spelling);
185195
if (Expansion != Spelling) {
186196
// If the expansion and the spelling are different, output subobjects
187197
// describing both locations.
188-
llvm::json::Object ELoc = createBareSourceLocation(Expansion);
189-
190-
// If there is a macro expansion, add extra information if the interesting
191-
// bit is the macro arg expansion.
192-
if (SM.isMacroArgExpansion(Loc))
193-
ELoc["isMacroArgExpansion"] = true;
194-
195-
return llvm::json::Object{{"spellingLoc", std::move(SLoc)},
196-
{"expansionLoc", std::move(ELoc)}};
197-
}
198-
199-
return SLoc;
198+
JOS.attributeObject(
199+
"spellingLoc", [Spelling, this] { writeBareSourceLocation(Spelling); });
200+
JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
201+
writeBareSourceLocation(Expansion);
202+
// If there is a macro expansion, add extra information if the interesting
203+
// bit is the macro arg expansion.
204+
if (SM.isMacroArgExpansion(Loc))
205+
JOS.attribute("isMacroArgExpansion", true);
206+
});
207+
} else
208+
writeBareSourceLocation(Spelling);
200209
}
201210

202-
llvm::json::Object JSONNodeDumper::createSourceRange(SourceRange R) {
203-
return llvm::json::Object{{"begin", createSourceLocation(R.getBegin())},
204-
{"end", createSourceLocation(R.getEnd())}};
211+
void JSONNodeDumper::writeSourceRange(SourceRange R) {
212+
JOS.attributeObject("begin",
213+
[R, this] { writeSourceLocation(R.getBegin()); });
214+
JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });
205215
}
206216

207217
std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
@@ -523,7 +533,8 @@ void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
523533

524534
void JSONNodeDumper::VisitDependentSizedExtVectorType(
525535
const DependentSizedExtVectorType *VT) {
526-
JOS.attribute("attrLoc", createSourceLocation(VT->getAttributeLoc()));
536+
JOS.attributeObject(
537+
"attrLoc", [VT, this] { writeSourceLocation(VT->getAttributeLoc()); });
527538
}
528539

529540
void JSONNodeDumper::VisitVectorType(const VectorType *VT) {

0 commit comments

Comments
 (0)
Please sign in to comment.