Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 99bd46c

Browse files
committed
make the -rewrite-test a bit more interesting: it now
wraps comments in <i> tags. Extend rewrite tokens to support this minimal functionality. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57409 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent cff9cc9 commit 99bd46c

File tree

3 files changed

+82
-25
lines changed

3 files changed

+82
-25
lines changed

Driver/RewriteTest.cpp

+11-20
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
#include "clang/Rewrite/TokenRewriter.h"
1514
#include "clang.h"
1615
#include "clang/Lex/Preprocessor.h"
16+
#include "clang/Rewrite/TokenRewriter.h"
1717
#include <iostream>
1818

1919
void clang::DoRewriteTest(Preprocessor &PP, const std::string &InFileName,
@@ -22,27 +22,18 @@ void clang::DoRewriteTest(Preprocessor &PP, const std::string &InFileName,
2222
const LangOptions &LangOpts = PP.getLangOptions();
2323

2424
TokenRewriter Rewriter(SM.getMainFileID(), SM, LangOpts);
25-
26-
27-
28-
29-
30-
std::pair<const char*,const char*> File =SM.getBufferData(SM.getMainFileID());
31-
32-
// Create a lexer to lex all the tokens of the main file in raw mode. Even
33-
// though it is in raw mode, it will not return comments.
34-
Lexer RawLex(SourceLocation::getFileLoc(SM.getMainFileID(), 0),
35-
LangOpts, File.first, File.second);
36-
37-
RawLex.SetKeepWhitespaceMode(true);
38-
39-
Token RawTok;
40-
RawLex.LexFromRawLexer(RawTok);
41-
while (RawTok.isNot(tok::eof)) {
42-
std::cout << PP.getSpelling(RawTok);
43-
RawLex.LexFromRawLexer(RawTok);
25+
26+
// Throw <i> </i> tags around comments.
27+
for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
28+
E = Rewriter.token_end(); I != E; ++I) {
29+
if (I->isNot(tok::comment)) continue;
30+
31+
Rewriter.AddTokenBefore(I, "<i>");
32+
Rewriter.AddTokenAfter(I, "</i>");
4433
}
4534

35+
36+
// Print out the output.
4637
for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
4738
E = Rewriter.token_end(); I != E; ++I)
4839
std::cout << PP.getSpelling(*I);

include/clang/Rewrite/TokenRewriter.h

+21-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
#define LLVM_CLANG_TOKENREWRITER_H
1717

1818
#include "clang/Basic/SourceLocation.h"
19+
#include "llvm/ADT/OwningPtr.h"
1920
#include <list>
2021
#include <map>
2122

2223
namespace clang {
2324
class Token;
2425
class LangOptions;
26+
class ScratchBuffer;
2527

2628
class TokenRewriter {
2729
/// TokenList - This is the list of raw tokens that make up this file. Each
@@ -37,20 +39,37 @@ namespace clang {
3739
/// backwards.
3840
std::map<SourceLocation, TokenRefTy> TokenAtLoc;
3941

42+
/// ScratchBuf - This is the buffer that we create scratch tokens from.
43+
///
44+
llvm::OwningPtr<ScratchBuffer> ScratchBuf;
45+
46+
TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT
47+
void operator=(const TokenRewriter&); // DO NOT IMPLEMENT.
4048
public:
4149
/// TokenRewriter - This creates a TokenRewriter for the file with the
4250
/// specified FileID.
4351
TokenRewriter(unsigned FileID, SourceManager &SM, const LangOptions &LO);
44-
52+
~TokenRewriter();
4553

4654
typedef std::list<Token>::const_iterator token_iterator;
4755
token_iterator token_begin() const { return TokenList.begin(); }
4856
token_iterator token_end() const { return TokenList.end(); }
4957

58+
59+
token_iterator AddTokenBefore(token_iterator I, const char *Val);
60+
token_iterator AddTokenAfter(token_iterator I, const char *Val) {
61+
assert(I != token_end() && "Cannot insert after token_end()!");
62+
return AddTokenBefore(++I, Val);
63+
}
64+
5065
private:
66+
/// RemapIterator - Convert from token_iterator (a const iterator) to
67+
/// TokenRefTy (a non-const iterator).
68+
TokenRefTy RemapIterator(token_iterator I);
69+
5170
/// AddToken - Add the specified token into the Rewriter before the other
5271
/// position.
53-
void AddToken(const Token &T, TokenRefTy Where);
72+
TokenRefTy AddToken(const Token &T, TokenRefTy Where);
5473
};
5574

5675

lib/Rewrite/TokenRewriter.cpp

+50-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414

1515
#include "clang/Rewrite/TokenRewriter.h"
1616
#include "clang/Lex/Lexer.h"
17+
#include "clang/Lex/ScratchBuffer.h"
1718
#include "clang/Basic/SourceManager.h"
1819
using namespace clang;
1920

2021
TokenRewriter::TokenRewriter(unsigned FileID, SourceManager &SM,
2122
const LangOptions &LangOpts) {
23+
ScratchBuf.reset(new ScratchBuffer(SM));
2224

2325
std::pair<const char*,const char*> File = SM.getBufferData(FileID);
2426

@@ -33,21 +35,66 @@ TokenRewriter::TokenRewriter(unsigned FileID, SourceManager &SM,
3335
Token RawTok;
3436
RawLex.LexFromRawLexer(RawTok);
3537
while (RawTok.isNot(tok::eof)) {
38+
#if 0
39+
if (Tok.is(tok::identifier)) {
40+
// Look up the identifier info for the token. This should use
41+
// IdentifierTable directly instead of PP.
42+
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
43+
}
44+
#endif
45+
3646
AddToken(RawTok, TokenList.end());
3747
RawLex.LexFromRawLexer(RawTok);
3848
}
49+
}
50+
51+
TokenRewriter::~TokenRewriter() {
52+
}
53+
54+
55+
/// RemapIterator - Convert from token_iterator (a const iterator) to
56+
/// TokenRefTy (a non-const iterator).
57+
TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) {
58+
if (I == token_end()) return TokenList.end();
3959

40-
60+
// FIXME: This is horrible, we should use our own list or something to avoid
61+
// this.
62+
std::map<SourceLocation, TokenRefTy>::iterator MapIt =
63+
TokenAtLoc.find(I->getLocation());
64+
assert(MapIt != TokenAtLoc.end() && "iterator not in rewriter?");
65+
return MapIt->second;
4166
}
4267

68+
4369
/// AddToken - Add the specified token into the Rewriter before the other
4470
/// position.
45-
void TokenRewriter::AddToken(const Token &T, TokenRefTy Where) {
71+
TokenRewriter::TokenRefTy
72+
TokenRewriter::AddToken(const Token &T, TokenRefTy Where) {
4673
Where = TokenList.insert(Where, T);
4774

4875
bool InsertSuccess = TokenAtLoc.insert(std::make_pair(T.getLocation(),
4976
Where)).second;
5077
assert(InsertSuccess && "Token location already in rewriter!");
5178
InsertSuccess = InsertSuccess;
79+
return Where;
5280
}
53-
81+
82+
83+
TokenRewriter::token_iterator
84+
TokenRewriter::AddTokenBefore(token_iterator I, const char *Val){
85+
unsigned Len = strlen(Val);
86+
87+
// Plop the string into the scratch buffer, then create a token for this
88+
// string.
89+
Token Tok;
90+
Tok.startToken();
91+
Tok.setLocation(ScratchBuf->getToken(Val, Len));
92+
Tok.setLength(Len);
93+
94+
// TODO: Form a whole lexer around this and relex the token! For now, just
95+
// set kind to tok::unknown.
96+
Tok.setKind(tok::unknown);
97+
98+
return AddToken(Tok, RemapIterator(I));
99+
}
100+

0 commit comments

Comments
 (0)