1 //===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the TokenRewriter class, which is used for code
13 //===----------------------------------------------------------------------===//
15 #include "clang/Rewrite/Core/TokenRewriter.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Lex/Lexer.h"
18 #include "clang/Lex/ScratchBuffer.h"
19 using namespace clang
;
21 TokenRewriter::TokenRewriter(FileID FID
, SourceManager
&SM
,
22 const LangOptions
&LangOpts
) {
23 ScratchBuf
.reset(new ScratchBuffer(SM
));
25 // Create a lexer to lex all the tokens of the main file in raw mode.
26 const llvm::MemoryBuffer
*FromFile
= SM
.getBuffer(FID
);
27 Lexer
RawLex(FID
, FromFile
, SM
, LangOpts
);
29 // Return all comments and whitespace as tokens.
30 RawLex
.SetKeepWhitespaceMode(true);
32 // Lex the file, populating our datastructures.
34 RawLex
.LexFromRawLexer(RawTok
);
35 while (RawTok
.isNot(tok::eof
)) {
37 if (Tok
.is(tok::raw_identifier
)) {
38 // Look up the identifier info for the token. This should use
39 // IdentifierTable directly instead of PP.
40 PP
.LookUpIdentifierInfo(Tok
);
44 AddToken(RawTok
, TokenList
.end());
45 RawLex
.LexFromRawLexer(RawTok
);
49 TokenRewriter::~TokenRewriter() {
53 /// RemapIterator - Convert from token_iterator (a const iterator) to
54 /// TokenRefTy (a non-const iterator).
55 TokenRewriter::TokenRefTy
TokenRewriter::RemapIterator(token_iterator I
) {
56 if (I
== token_end()) return TokenList
.end();
58 // FIXME: This is horrible, we should use our own list or something to avoid
60 std::map
<SourceLocation
, TokenRefTy
>::iterator MapIt
=
61 TokenAtLoc
.find(I
->getLocation());
62 assert(MapIt
!= TokenAtLoc
.end() && "iterator not in rewriter?");
67 /// AddToken - Add the specified token into the Rewriter before the other
69 TokenRewriter::TokenRefTy
70 TokenRewriter::AddToken(const Token
&T
, TokenRefTy Where
) {
71 Where
= TokenList
.insert(Where
, T
);
73 bool InsertSuccess
= TokenAtLoc
.insert(std::make_pair(T
.getLocation(),
75 assert(InsertSuccess
&& "Token location already in rewriter!");
81 TokenRewriter::token_iterator
82 TokenRewriter::AddTokenBefore(token_iterator I
, const char *Val
) {
83 unsigned Len
= strlen(Val
);
85 // Plop the string into the scratch buffer, then create a token for this
90 Tok
.setLocation(ScratchBuf
->getToken(Val
, Len
, Spelling
));
93 // TODO: Form a whole lexer around this and relex the token! For now, just
94 // set kind to tok::unknown.
95 Tok
.setKind(tok::unknown
);
97 return AddToken(Tok
, RemapIterator(I
));