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