1 //===--- TestLexer.h - Format C++ code --------------------------*- C++ -*-===//
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 /// \file
11 /// This file contains a TestLexer to create FormatTokens from strings.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef CLANG_UNITTESTS_FORMAT_TESTLEXER_H
16 #define CLANG_UNITTESTS_FORMAT_TESTLEXER_H
17 
18 #include "../../lib/Format/FormatTokenLexer.h"
19 #include "../../lib/Format/TokenAnalyzer.h"
20 #include "../../lib/Format/TokenAnnotator.h"
21 #include "../../lib/Format/UnwrappedLineParser.h"
22 
23 #include "clang/Basic/FileManager.h"
24 #include "clang/Basic/SourceManager.h"
25 
26 #include <numeric>
27 #include <ostream>
28 
29 namespace clang {
30 namespace format {
31 
32 typedef llvm::SmallVector<FormatToken *, 8> TokenList;
33 
34 inline std::ostream &operator<<(std::ostream &Stream, const FormatToken &Tok) {
35   Stream << "(" << Tok.Tok.getName() << ", \"" << Tok.TokenText.str() << "\" , "
36          << getTokenTypeName(Tok.getType()) << ")";
37   return Stream;
38 }
39 inline std::ostream &operator<<(std::ostream &Stream, const TokenList &Tokens) {
40   Stream << "{";
41   for (size_t I = 0, E = Tokens.size(); I != E; ++I) {
42     Stream << (I > 0 ? ", " : "") << *Tokens[I];
43   }
44   Stream << "} (" << Tokens.size() << " tokens)";
45   return Stream;
46 }
47 
uneof(const TokenList & Tokens)48 inline TokenList uneof(const TokenList &Tokens) {
49   assert(!Tokens.empty() && Tokens.back()->is(tok::eof));
50   return TokenList(Tokens.begin(), std::prev(Tokens.end()));
51 }
52 
text(llvm::ArrayRef<FormatToken * > Tokens)53 inline std::string text(llvm::ArrayRef<FormatToken *> Tokens) {
54   return std::accumulate(Tokens.begin(), Tokens.end(), std::string(),
55                          [](const std::string &R, FormatToken *Tok) {
56                            return (R + Tok->TokenText).str();
57                          });
58 }
59 
60 class TestLexer : public UnwrappedLineConsumer {
61 public:
62   TestLexer(llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
63             std::vector<std::unique_ptr<llvm::MemoryBuffer>> &Buffers,
64             FormatStyle Style = getLLVMStyle())
Allocator(Allocator)65       : Allocator(Allocator), Buffers(Buffers), Style(Style),
66         SourceMgr("test.cpp", ""), IdentTable(getFormattingLangOpts(Style)) {}
67 
lex(llvm::StringRef Code)68   TokenList lex(llvm::StringRef Code) {
69     FormatTokenLexer Lex = getNewLexer(Code);
70     ArrayRef<FormatToken *> Result = Lex.lex();
71     return TokenList(Result.begin(), Result.end());
72   }
73 
annotate(llvm::StringRef Code)74   TokenList annotate(llvm::StringRef Code) {
75     FormatTokenLexer Lex = getNewLexer(Code);
76     auto Tokens = Lex.lex();
77     UnwrappedLineParser Parser(Style, Lex.getKeywords(), 0, Tokens, *this);
78     Parser.parse();
79     TokenAnnotator Annotator(Style, Lex.getKeywords());
80     for (auto &Line : UnwrappedLines) {
81       AnnotatedLine Annotated(Line);
82       Annotator.annotate(Annotated);
83       Annotator.calculateFormattingInformation(Annotated);
84     }
85     UnwrappedLines.clear();
86     return TokenList(Tokens.begin(), Tokens.end());
87   }
88 
id(llvm::StringRef Code)89   FormatToken *id(llvm::StringRef Code) {
90     auto Result = uneof(lex(Code));
91     assert(Result.size() == 1U && "Code must expand to 1 token.");
92     return Result[0];
93   }
94 
95 protected:
consumeUnwrappedLine(const UnwrappedLine & TheLine)96   void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
97     UnwrappedLines.push_back(TheLine);
98   }
finishRun()99   void finishRun() override {}
100 
getNewLexer(StringRef Code)101   FormatTokenLexer getNewLexer(StringRef Code) {
102     Buffers.push_back(
103         llvm::MemoryBuffer::getMemBufferCopy(Code, "<scratch space>"));
104     clang::FileID FID =
105         SourceMgr.get().createFileID(Buffers.back()->getMemBufferRef());
106     return FormatTokenLexer(SourceMgr.get(), FID, 0, Style, Encoding, Allocator,
107                             IdentTable);
108   }
109 
110 public:
111   llvm::SpecificBumpPtrAllocator<FormatToken>& Allocator;
112   std::vector<std::unique_ptr<llvm::MemoryBuffer>>& Buffers;
113   FormatStyle Style;
114   encoding::Encoding Encoding = encoding::Encoding_UTF8;
115   clang::SourceManagerForFile SourceMgr;
116   IdentifierTable IdentTable;
117   SmallVector<UnwrappedLine, 16> UnwrappedLines;
118 };
119 
120 } // namespace format
121 } // namespace clang
122 
123 #endif // LLVM_CLANG_UNITTESTS_FORMAT_TEST_LEXER_H
124