llvm-project
117 строк · 3.7 Кб
1//===--- BracketTest.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang-pseudo/Bracket.h"
10#include "clang-pseudo/Token.h"
11#include "clang/Basic/LangOptions.h"
12#include "llvm/Testing/Annotations/Annotations.h"
13#include "gmock/gmock.h"
14#include "gtest/gtest.h"
15
16namespace clang {
17namespace pseudo {
18
19// Return a version of Code with each paired bracket marked with ^.
20std::string decorate(llvm::StringRef Code, const TokenStream &Stream) {
21std::string Result;
22const char *Pos = Code.data();
23for (const Token &Tok : Stream.tokens()) {
24if (Tok.Pair == 0)
25continue;
26const char *NewPos = Tok.text().begin();
27assert(NewPos >= Code.begin() && NewPos < Code.end());
28Result.append(Pos, NewPos - Pos);
29Result.push_back('^');
30Pos = NewPos;
31}
32Result.append(Pos, Code.end() - Pos);
33return Result;
34}
35
36// Checks that the brackets matched in Stream are those annotated in MarkedCode.
37void verifyMatchedSet(llvm::StringRef Code, llvm::StringRef MarkedCode,
38const TokenStream &Stream) {
39EXPECT_EQ(MarkedCode, decorate(Code, Stream));
40}
41
42// Checks that paired brackets within the stream nest properly.
43void verifyNesting(const TokenStream &Stream) {
44std::vector<const Token *> Stack;
45for (const auto &Tok : Stream.tokens()) {
46if (Tok.Pair > 0)
47Stack.push_back(&Tok);
48else if (Tok.Pair < 0) {
49ASSERT_FALSE(Stack.empty()) << Tok;
50ASSERT_EQ(Stack.back(), Tok.pair())
51<< *Stack.back() << " != " << *Tok.pair() << " = pair of " << Tok;
52Stack.pop_back();
53}
54}
55ASSERT_THAT(Stack, testing::IsEmpty());
56}
57
58// Checks that ( pairs with a ) on its right, etc.
59void verifyMatchKind(const TokenStream &Stream) {
60for (const auto &Tok : Stream.tokens()) {
61if (Tok.Pair == 0)
62continue;
63auto Want = [&]() -> std::pair<bool, tok::TokenKind> {
64switch (Tok.Kind) {
65case tok::l_paren:
66return {true, tok::r_paren};
67case tok::r_paren:
68return {false, tok::l_paren};
69case tok::l_brace:
70return {true, tok::r_brace};
71case tok::r_brace:
72return {false, tok::l_brace};
73case tok::l_square:
74return {true, tok::r_square};
75case tok::r_square:
76return {false, tok::l_square};
77default:
78ADD_FAILURE() << "Paired non-bracket " << Tok;
79return {false, tok::eof};
80}
81}();
82EXPECT_EQ(Tok.Pair > 0, Want.first) << Tok;
83EXPECT_EQ(Tok.pair()->Kind, Want.second) << Tok;
84}
85}
86
87// Verifies an expected bracket pairing like:
88// ^( [ ^)
89// The input is annotated code, with the brackets expected to be matched marked.
90//
91// The input doesn't specify which bracket matches with which, but we verify:
92// - exactly the marked subset are paired
93// - ( is paired to a later ), etc
94// - brackets properly nest
95// This uniquely determines the bracket structure, so we indirectly verify it.
96// If particular tests should emphasize which brackets are paired, use comments.
97void verifyBrackets(llvm::StringRef MarkedCode) {
98SCOPED_TRACE(MarkedCode);
99llvm::Annotations A(MarkedCode);
100std::string Code = A.code().str();
101LangOptions LangOpts;
102auto Stream = lex(Code, LangOpts);
103pairBrackets(Stream);
104
105verifyMatchedSet(Code, MarkedCode, Stream);
106verifyNesting(Stream);
107verifyMatchKind(Stream);
108}
109
110TEST(Bracket, SimplePair) {
111verifyBrackets("^{ ^[ ^( ^) ^( ^) ^] ^}");
112verifyBrackets(") ^{ ^[ ^] ^} (");
113verifyBrackets("{ [ ( ] }"); // FIXME
114}
115
116} // namespace pseudo
117} // namespace clang
118