xref: /llvm-project/clang/unittests/Format/TokenAnnotatorTest.cpp (revision a77c67f93917596f9eded9edaced4a9d355a4e1c)
1 //===- unittest/Format/TokenAnnotatorTest.cpp - Formatting unit tests -----===//
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/Format/Format.h"
10 
11 #include "FormatTestUtils.h"
12 #include "TestLexer.h"
13 #include "gtest/gtest.h"
14 
15 namespace clang {
16 namespace format {
17 namespace {
18 
19 class TokenAnnotatorTest : public ::testing::Test {
20 protected:
21   TokenList annotate(llvm::StringRef Code,
22                      const FormatStyle &Style = getLLVMStyle()) {
23     return TestLexer(Allocator, Buffers, Style).annotate(Code);
24   }
25   llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
26   std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
27 };
28 
29 #define EXPECT_TOKEN_KIND(FormatTok, Kind)                                     \
30   EXPECT_EQ((FormatTok)->Tok.getKind(), Kind) << *(FormatTok)
31 #define EXPECT_TOKEN_TYPE(FormatTok, Type)                                     \
32   EXPECT_EQ((FormatTok)->getType(), Type) << *(FormatTok)
33 #define EXPECT_TOKEN(FormatTok, Kind, Type)                                    \
34   do {                                                                         \
35     EXPECT_TOKEN_KIND(FormatTok, Kind);                                        \
36     EXPECT_TOKEN_TYPE(FormatTok, Type);                                        \
37   } while (false);
38 
39 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmpInMacroDefinition) {
40   // This is a regression test for mis-parsing the & after decltype as a binary
41   // operator instead of a reference (when inside a macro definition).
42   auto Tokens = annotate("auto x = [](const decltype(x) &ptr) {};");
43   EXPECT_EQ(Tokens.size(), 18u) << Tokens;
44   EXPECT_TOKEN(Tokens[7], tok::kw_decltype, TT_Unknown);
45   EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_TypeDeclarationParen);
46   EXPECT_TOKEN(Tokens[9], tok::identifier, TT_Unknown);
47   EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen);
48   EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference);
49   // Same again with * instead of &:
50   Tokens = annotate("auto x = [](const decltype(x) *ptr) {};");
51   EXPECT_EQ(Tokens.size(), 18u) << Tokens;
52   EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen);
53   EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference);
54 
55   // Also check that we parse correctly within a macro definition:
56   Tokens = annotate("#define lambda [](const decltype(x) &ptr) {}");
57   EXPECT_EQ(Tokens.size(), 17u) << Tokens;
58   EXPECT_TOKEN(Tokens[7], tok::kw_decltype, TT_Unknown);
59   EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_TypeDeclarationParen);
60   EXPECT_TOKEN(Tokens[9], tok::identifier, TT_Unknown);
61   EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen);
62   EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference);
63   // Same again with * instead of &:
64   Tokens = annotate("#define lambda [](const decltype(x) *ptr) {}");
65   EXPECT_EQ(Tokens.size(), 17u) << Tokens;
66   EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen);
67   EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference);
68 }
69 
70 TEST_F(TokenAnnotatorTest, UnderstandsClasses) {
71   auto Tokens = annotate("class C {};");
72   EXPECT_EQ(Tokens.size(), 6u) << Tokens;
73   EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_RecordLBrace);
74 }
75 
76 TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
77   auto Tokens = annotate("struct S {};");
78   EXPECT_EQ(Tokens.size(), 6u) << Tokens;
79   EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_RecordLBrace);
80 }
81 
82 TEST_F(TokenAnnotatorTest, UnderstandsUnions) {
83   auto Tokens = annotate("union U {};");
84   EXPECT_EQ(Tokens.size(), 6u) << Tokens;
85   EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_RecordLBrace);
86 }
87 
88 TEST_F(TokenAnnotatorTest, UnderstandsEnums) {
89   auto Tokens = annotate("enum E {};");
90   EXPECT_EQ(Tokens.size(), 6u) << Tokens;
91   EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_RecordLBrace);
92 }
93 
94 TEST_F(TokenAnnotatorTest, UnderstandsLBracesInMacroDefinition) {
95   auto Tokens = annotate("#define BEGIN NS {");
96   EXPECT_EQ(Tokens.size(), 6u) << Tokens;
97   EXPECT_TOKEN(Tokens[4], tok::l_brace, TT_Unknown);
98 }
99 
100 TEST_F(TokenAnnotatorTest, UnderstandsDelete) {
101   auto Tokens = annotate("delete (void *)p;");
102   EXPECT_EQ(Tokens.size(), 8u) << Tokens;
103   EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_CastRParen);
104 
105   Tokens = annotate("delete[] (void *)p;");
106   EXPECT_EQ(Tokens.size(), 10u) << Tokens;
107   EXPECT_TOKEN(Tokens[6], tok::r_paren, TT_CastRParen);
108 
109   Tokens = annotate("delete[] /*comment*/ (void *)p;");
110   EXPECT_EQ(Tokens.size(), 11u) << Tokens;
111   EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_CastRParen);
112 
113   Tokens = annotate("delete[/*comment*/] (void *)p;");
114   EXPECT_EQ(Tokens.size(), 11u) << Tokens;
115   EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_CastRParen);
116 
117   Tokens = annotate("delete/*comment*/[] (void *)p;");
118   EXPECT_EQ(Tokens.size(), 11u) << Tokens;
119   EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_CastRParen);
120 }
121 
122 } // namespace
123 } // namespace format
124 } // namespace clang
125