1 //===--- BracketTest.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
19 // Return a version of Code with each paired bracket marked with ^.
20 std::string
decorate(llvm::StringRef Code
, const TokenStream
&Stream
) {
22 const char *Pos
= Code
.data();
23 for (const Token
&Tok
: Stream
.tokens()) {
26 const char *NewPos
= Tok
.text().begin();
27 assert(NewPos
>= Code
.begin() && NewPos
< Code
.end());
28 Result
.append(Pos
, NewPos
- Pos
);
29 Result
.push_back('^');
32 Result
.append(Pos
, Code
.end() - Pos
);
36 // Checks that the brackets matched in Stream are those annotated in MarkedCode.
37 void verifyMatchedSet(llvm::StringRef Code
, llvm::StringRef MarkedCode
,
38 const TokenStream
&Stream
) {
39 EXPECT_EQ(MarkedCode
, decorate(Code
, Stream
));
42 // Checks that paired brackets within the stream nest properly.
43 void verifyNesting(const TokenStream
&Stream
) {
44 std::vector
<const Token
*> Stack
;
45 for (const auto &Tok
: Stream
.tokens()) {
47 Stack
.push_back(&Tok
);
48 else if (Tok
.Pair
< 0) {
49 ASSERT_FALSE(Stack
.empty()) << Tok
;
50 ASSERT_EQ(Stack
.back(), Tok
.pair())
51 << *Stack
.back() << " != " << *Tok
.pair() << " = pair of " << Tok
;
55 ASSERT_THAT(Stack
, testing::IsEmpty());
58 // Checks that ( pairs with a ) on its right, etc.
59 void verifyMatchKind(const TokenStream
&Stream
) {
60 for (const auto &Tok
: Stream
.tokens()) {
63 auto Want
= [&]() -> std::pair
<bool, tok::TokenKind
> {
66 return {true, tok::r_paren
};
68 return {false, tok::l_paren
};
70 return {true, tok::r_brace
};
72 return {false, tok::l_brace
};
74 return {true, tok::r_square
};
76 return {false, tok::l_square
};
78 ADD_FAILURE() << "Paired non-bracket " << Tok
;
79 return {false, tok::eof
};
82 EXPECT_EQ(Tok
.Pair
> 0, Want
.first
) << Tok
;
83 EXPECT_EQ(Tok
.pair()->Kind
, Want
.second
) << Tok
;
87 // Verifies an expected bracket pairing like:
89 // The input is annotated code, with the brackets expected to be matched marked.
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.
97 void verifyBrackets(llvm::StringRef MarkedCode
) {
98 SCOPED_TRACE(MarkedCode
);
99 llvm::Annotations
A(MarkedCode
);
100 std::string Code
= A
.code().str();
101 LangOptions LangOpts
;
102 auto Stream
= lex(Code
, LangOpts
);
103 pairBrackets(Stream
);
105 verifyMatchedSet(Code
, MarkedCode
, Stream
);
106 verifyNesting(Stream
);
107 verifyMatchKind(Stream
);
110 TEST(Bracket
, SimplePair
) {
111 verifyBrackets("^{ ^[ ^( ^) ^( ^) ^] ^}");
112 verifyBrackets(") ^{ ^[ ^] ^} (");
113 verifyBrackets("{ [ ( ] }"); // FIXME
116 } // namespace pseudo