clang-tools 10.0.0

DumpAST.cpp
Go to the documentation of this file.
1 //===--- DumpAST.cpp ---------------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // Defines a few tweaks that expose AST and related information.
9 // Some of these are fairly clang-specific and hidden (e.g. textual AST dumps).
10 // Others are more generally useful (class layout) and are exposed by default.
11 //===----------------------------------------------------------------------===//
12 #include "XRefs.h"
13 #include "refactor/Tweak.h"
14 #include "clang/AST/ASTTypeTraits.h"
15 #include "clang/AST/Type.h"
16 #include "llvm/Support/FormatVariadic.h"
17 #include "llvm/Support/ScopedPrinter.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 namespace clang {
21 namespace clangd {
22 namespace {
23
24 /// Dumps the AST of the selected node.
25 /// Input:
26 /// fcall("foo");
27 /// ^^^^^
28 /// Message:
29 /// CallExpr
30 /// |-DeclRefExpr fcall
31 /// `-StringLiteral "foo"
32 class DumpAST : public Tweak {
33 public:
34 const char *id() const override final;
35
36 bool prepare(const Selection &Inputs) override {
37 for (auto N = Inputs.ASTSelection.commonAncestor(); N && !Node;
38 N = N->Parent)
39 if (dumpable(N->ASTNode))
40 Node = N->ASTNode;
41 return Node.hasValue();
42 }
43 Expected<Effect> apply(const Selection &Inputs) override;
44 std::string title() const override {
45 return llvm::formatv("Dump {0} AST", Node->getNodeKind().asStringRef());
46 }
47 Intent intent() const override { return Info; }
48 bool hidden() const override { return true; }
49
50 private:
51 static bool dumpable(const ast_type_traits::DynTypedNode &N) {
52 // Sadly not all node types can be dumped, and there's no API to check.
53 // See DynTypedNode::dump().
54 return N.get<Decl>() || N.get<Stmt>() || N.get<Type>();
55 }
56
57 llvm::Optional<ast_type_traits::DynTypedNode> Node;
58 };
59 REGISTER_TWEAK(DumpAST)
60
61 llvm::Expected<Tweak::Effect> DumpAST::apply(const Selection &Inputs) {
62 std::string Str;
63 llvm::raw_string_ostream OS(Str);
64 Node->dump(OS, Inputs.AST->getSourceManager());
65 return Effect::showMessage(std::move(OS.str()));
66 }
67
68 /// Dumps the SelectionTree.
69 /// Input:
70 /// int fcall(int);
71 /// void foo() {
72 /// fcall(2 + 2);
73 /// ^^^^^
74 /// }
75 /// Message:
76 /// TranslationUnitDecl
77 /// FunctionDecl void foo()
78 /// CompoundStmt {}
79 /// .CallExpr fcall(2 + 2)
80 /// ImplicitCastExpr fcall
81 /// .DeclRefExpr fcall
82 /// BinaryOperator 2 + 2
83 /// *IntegerLiteral 2
84 class ShowSelectionTree : public Tweak {
85 public:
86 const char *id() const override final;
87
88 bool prepare(const Selection &Inputs) override { return true; }
89 Expected<Effect> apply(const Selection &Inputs) override {
90 return Effect::showMessage(llvm::to_string(Inputs.ASTSelection));
91 }
92 std::string title() const override { return "Show selection tree"; }
93 Intent intent() const override { return Info; }
94 bool hidden() const override { return true; }
95 };
96 REGISTER_TWEAK(ShowSelectionTree)
97
98 /// Dumps the symbol under the cursor.
99 /// Inputs:
100 /// void foo();
101 /// ^^^
102 /// Message:
103 /// foo -
104 /// {"containerName":null,"id":"CA2EBE44A1D76D2A","name":"foo","usr":"c:@F@foo#"}
105 class DumpSymbol : public Tweak {
106 const char *id() const override final;
107 bool prepare(const Selection &Inputs) override { return true; }
108 Expected<Effect> apply(const Selection &Inputs) override {
109 std::string Storage;
110 llvm::raw_string_ostream Out(Storage);
111
112 for (auto &Sym : getSymbolInfo(
113 *Inputs.AST, sourceLocToPosition(Inputs.AST->getSourceManager(),
114 Inputs.Cursor)))
115 Out << Sym;
116 return Effect::showMessage(Out.str());
117 }
118 std::string title() const override { return "Dump symbol under the cursor"; }
119 Intent intent() const override { return Info; }
120 bool hidden() const override { return true; }
121 };
122 REGISTER_TWEAK(DumpSymbol)
123
124 /// Shows the layout of the RecordDecl under the cursor.
125 /// Input:
126 /// struct X { int foo; };
127 /// ^^^^^^^^
128 /// Message:
129 /// 0 | struct S
130 /// 0 | int foo
131 /// | [sizeof=4, dsize=4, align=4,
132 /// | nvsize=4, nvalign=4]
133 class DumpRecordLayout : public Tweak {
134 public:
135 const char *id() const override final;
136
137 bool prepare(const Selection &Inputs) override {
138 if (auto *Node = Inputs.ASTSelection.commonAncestor())
139 if (auto *D = Node->ASTNode.get<Decl>())
140 Record = dyn_cast<RecordDecl>(D);
141 return Record && Record->isThisDeclarationADefinition() &&
142 !Record->isDependentType();
143 }
144 Expected<Effect> apply(const Selection &Inputs) override {
145 std::string Str;
146 llvm::raw_string_ostream OS(Str);
147 Inputs.AST->getASTContext().DumpRecordLayout(Record, OS);
148 return Effect::showMessage(std::move(OS.str()));
149 }
150 std::string title() const override {
151 return llvm::formatv(
152 "Show {0} layout",
153 TypeWithKeyword::getTagTypeKindName(Record->getTagKind()));
154 }
155 Intent intent() const override { return Info; }
156 // FIXME: this is interesting to most users. However:
157 // - triggering is too broad (e.g. triggers on comments within a class)
158 // - showMessage has inconsistent UX (e.g. newlines are stripped in VSCode)
159 // - the output itself is a bit hard to decipher.
160 bool hidden() const override { return true; }
161
162 private:
163 const RecordDecl *Record = nullptr;
164 };
165 REGISTER_TWEAK(DumpRecordLayout)
166
167 } // namespace
168 } // namespace clangd
169 } // namespace clang
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
clang::doc::Record
llvm::SmallVector< uint64_t, 1024 > Record
Definition: BitcodeReader.cpp:18
REGISTER_TWEAK
#define REGISTER_TWEAK(Subclass)
Definition: Tweak.h:129
Tweak.h
clang::clangd::getSymbolInfo
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:519
clang::clangd::sourceLocToPosition
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:200
clang::clangd::MessageType::Info
An information message.
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
XRefs.h