blob: b30f1e80ef2f53f63e7c529bb89439505744355e [file] [log] [blame]
Ted Kremenek5e0020e2008-03-18 22:21:07 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
15#include "clang/AST/ASTConsumer.h"
16#include "clang/Rewrite/Rewriter.h"
17#include "clang/Rewrite/HTMLRewrite.h"
18#include "clang/Basic/SourceManager.h"
19#include "llvm/Support/MemoryBuffer.h"
20#include "clang/AST/ASTContext.h"
Ted Kremenek13e479b2008-03-19 07:53:42 +000021#include "clang/Basic/Diagnostic.h"
22#include "clang/Analysis/LocalCheckers.h"
23#include "clang/AST/CFG.h"
Ted Kremenek1b3188c2008-03-18 23:55:46 +000024#include <sstream>
Ted Kremenek5e0020e2008-03-18 22:21:07 +000025
26using namespace clang;
27
Ted Kremenek13e479b2008-03-19 07:53:42 +000028//===----------------------------------------------------------------------===//
29// Functional HTML pretty-printing.
30//===----------------------------------------------------------------------===//
31
Ted Kremenek5e0020e2008-03-18 22:21:07 +000032namespace {
33 class HTMLPrinter : public ASTConsumer {
34 Rewriter R;
35 public:
36 HTMLPrinter() {}
37 virtual ~HTMLPrinter();
38
39 void Initialize(ASTContext &context);
40 };
41}
42
43ASTConsumer* clang::CreateHTMLPrinter() { return new HTMLPrinter(); }
44
45void HTMLPrinter::Initialize(ASTContext &context) {
46 R.setSourceMgr(context.getSourceManager());
47}
48
49HTMLPrinter::~HTMLPrinter() {
Ted Kremenek5e0020e2008-03-18 22:21:07 +000050
Ted Kremenek13e479b2008-03-19 07:53:42 +000051 unsigned FileID = R.getSourceMgr().getMainFileID();
Ted Kremenek5e0020e2008-03-18 22:21:07 +000052 html::EscapeText(R, FileID);
53 html::AddLineNumbers(R, FileID);
Ted Kremenekad0a2032008-03-19 06:14:37 +000054 html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
Ted Kremenek5e0020e2008-03-18 22:21:07 +000055
56 // Emit the HTML.
57
58 if (const RewriteBuffer *RewriteBuf = R.getRewriteBufferFor(FileID)) {
59 std::string S(RewriteBuf->begin(), RewriteBuf->end());
60 printf("%s\n", S.c_str());
61 }
62}
Ted Kremenek13e479b2008-03-19 07:53:42 +000063
64//===----------------------------------------------------------------------===//
65// Other HTML pretty-printing code used to test new features.
66//===----------------------------------------------------------------------===//
67
68namespace {
69 class HTMLTest : public ASTConsumer {
70 Rewriter R;
71 ASTContext* Ctx;
72 public:
73 HTMLTest() : Ctx(NULL) {}
74 virtual ~HTMLTest();
75 virtual void HandleTopLevelDecl(Decl* D);
76
77 void Initialize(ASTContext &context);
78 void ProcessBody(Stmt* S);
79 };
80}
81
82ASTConsumer* clang::CreateHTMLTest() { return new HTMLTest(); }
83
84void HTMLTest::Initialize(ASTContext &context) {
85 Ctx = &context;
86 R.setSourceMgr(context.getSourceManager());
87}
88
89void HTMLTest::HandleTopLevelDecl(Decl* D) {
90 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
91 if (Stmt* B = FD->getBody()) {
92 SourceLocation L = B->getLocStart();
93
94 if (L.isFileID() && L.getFileID() == R.getSourceMgr().getMainFileID())
95 ProcessBody(B);
96 }
97}
98
99HTMLTest::~HTMLTest() {
100
101 unsigned FileID = R.getSourceMgr().getMainFileID();
102 html::EscapeText(R, FileID);
103 html::AddLineNumbers(R, FileID);
104 html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
105
106 // Emit the HTML.
107
108 if (const RewriteBuffer *RewriteBuf = R.getRewriteBufferFor(FileID)) {
109 std::string S(RewriteBuf->begin(), RewriteBuf->end());
110 printf("%s\n", S.c_str());
111 }
112}
113
114namespace {
115 class HTMLDiagnostic : public DiagnosticClient {
116 Rewriter& R;
117 public:
118 HTMLDiagnostic(Rewriter& r) : R(r) {}
119 virtual void HandleDiagnostic(Diagnostic &Diags,
120 Diagnostic::Level DiagLevel,
121 FullSourceLoc Pos,
122 diag::kind ID,
123 const std::string *Strs,
124 unsigned NumStrs,
125 const SourceRange *Ranges,
126 unsigned NumRanges);
127 };
128}
129
130void HTMLTest::ProcessBody(Stmt* S) {
131 CFG* cfg = CFG::buildCFG(S);
132
133 if (!cfg)
134 return;
135
136 HTMLDiagnostic HD(R);
137 Diagnostic D(HD);
138
139 CheckDeadStores(*cfg, *Ctx, D);
140}
141
142void HTMLDiagnostic::HandleDiagnostic(Diagnostic &Diags,
143 Diagnostic::Level DiagLevel,
144 FullSourceLoc Pos,
145 diag::kind ID,
146 const std::string *Strs,
147 unsigned NumStrs,
148 const SourceRange *Ranges,
149 unsigned NumRanges) {
150
151 // For now, just draw a box above the line in question, and emit the
152 // warning.
153
154 if (!Pos.isValid())
155 return;
156
Ted Kremenek0f1b67b2008-03-19 23:55:53 +0000157 SourceManager& SM = R.getSourceMgr();
158
Ted Kremenek13e479b2008-03-19 07:53:42 +0000159 FullSourceLoc LPos = Pos.getLogicalLoc();
160 unsigned FileID = LPos.getLocation().getFileID();
161
Ted Kremenek0f1b67b2008-03-19 23:55:53 +0000162 assert (&LPos.getManager() == &SM && "SourceManagers are different!");
163
164 unsigned MainFileID = SM.getMainFileID();
165
166 if (FileID != MainFileID)
Ted Kremenek13e479b2008-03-19 07:53:42 +0000167 return;
168
169
170 // Compute the column number. Rewind from the current position to the start
171 // of the line.
172
173 unsigned ColNo = LPos.getColumnNumber();
174 const char *TokLogicalPtr = LPos.getCharacterData();
175 const char *LineStart = TokLogicalPtr-ColNo;
176
177 // Ripped from TextDiagnostics::FormatDiagnostic:
178
179 std::string Msg = Diags.getDescription(ID);
180
181 for (unsigned i = 0; i < Msg.size() - 1; ++i) {
182 if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
183 unsigned StrNo = Msg[i + 1] - '0';
184 Msg = std::string(Msg.begin(), Msg.begin() + i) +
185 (StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
186 std::string(Msg.begin() + i + 2, Msg.end());
187 }
Ted Kremeneke8e019e2008-03-19 21:59:05 +0000188 }
189
190 // Create the html for the message.
Ted Kremenek13e479b2008-03-19 07:53:42 +0000191
192 std::ostringstream os;
193
Ted Kremeneke8e019e2008-03-19 21:59:05 +0000194 os << "\n<tr><td class=\"num\"></td><td class=\"line\">"
195 << "<div class=\"msg\" style=\"margin-left:"
196 << ColNo << "ex\">";
Ted Kremenek13e479b2008-03-19 07:53:42 +0000197
198 switch (DiagLevel) {
199 default: assert(0 && "Unknown diagnostic type!");
200 case Diagnostic::Note: os << "note: "; break;
201 case Diagnostic::Warning: os << "warning: "; break;
202 case Diagnostic::Error: os << "error: "; break;
203 case Diagnostic::Fatal: os << "fatal error: "; break;
204 break;
205 }
206
Ted Kremeneke8e019e2008-03-19 21:59:05 +0000207 os << Msg << "</div></td></tr>";
Ted Kremenek13e479b2008-03-19 07:53:42 +0000208
Ted Kremeneke8e019e2008-03-19 21:59:05 +0000209 // Insert the new html.
Ted Kremenek13e479b2008-03-19 07:53:42 +0000210
Ted Kremenek0f1b67b2008-03-19 23:55:53 +0000211 const llvm::MemoryBuffer *Buf = SM.getBuffer(FileID);
Ted Kremenek13e479b2008-03-19 07:53:42 +0000212 const char* FileStart = Buf->getBufferStart();
213
Ted Kremenek13e479b2008-03-19 07:53:42 +0000214 R.InsertStrBefore(SourceLocation::getFileLoc(FileID, LineStart - FileStart),
215 os.str());
Ted Kremenek0f1b67b2008-03-19 23:55:53 +0000216
217 // Now highlight the ranges.
218
219 for (unsigned i = 0; i < NumRanges; ++i) {
220
221 SourceLocation B = SM.getLogicalLoc(Ranges->getBegin());
222 SourceLocation E = SM.getLogicalLoc(Ranges->getEnd());
223
224 // We do this because the position seems to point to the beginning of
225 // the last character. FIXME: Is this what is suppose to happen?
226 std::pair<unsigned,unsigned> X = SM.getDecomposedFileLoc(E);
227 E = SourceLocation::getFileLoc(X.first, X.second+1);
228
229 ++Ranges;
230
231 if (B.getFileID() != MainFileID || E.getFileID() != MainFileID)
232 continue;
233
234 // Highlight the range. Make the span tag the outermost tag for the
235 // selected range.
236 R.InsertCStrBefore(B, "<span class=\"mrange\">");
237 R.InsertCStrAfter(E, "</span>");
238 }
239
Ted Kremenek13e479b2008-03-19 07:53:42 +0000240}