[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / unittests / CollectMacrosTests.cpp
blob196ed5cea4693548b00588c45bed96452047ccdc
1 //===-- CollectMacrosTests.cpp ----------------------------------*- C++ -*-===//
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 #include "AST.h"
9 #include "Annotations.h"
10 #include "CollectMacros.h"
11 #include "SourceCode.h"
12 #include "TestTU.h"
13 #include "clang/Basic/SourceLocation.h"
14 #include "llvm/Support/ScopedPrinter.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
18 namespace clang {
19 namespace clangd {
20 namespace {
22 using testing::UnorderedElementsAreArray;
24 TEST(CollectMainFileMacros, SelectedMacros) {
25 // References of the same symbol must have the ranges with the same
26 // name(integer). If there are N different symbols then they must be named
27 // from 1 to N. Macros for which SymbolID cannot be computed must be named
28 // "Unknown".
29 const char *Tests[] = {
30 R"cpp(// Macros: Cursor on definition.
31 #define $1[[FOO]](x,y) (x + y)
32 int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); }
33 )cpp",
34 R"cpp(
35 #define $1[[M]](X) X;
36 #define $2[[abc]] 123
37 int s = $1[[M]]($2[[abc]]);
38 )cpp",
39 // FIXME: Locating macro in duplicate definitions doesn't work. Enable
40 // this once LocateMacro is fixed.
41 // R"cpp(// Multiple definitions.
42 // #define $1[[abc]] 1
43 // int func1() { int a = $1[[abc]];}
44 // #undef $1[[abc]]
46 // #define $2[[abc]] 2
47 // int func2() { int a = $2[[abc]];}
48 // #undef $2[[abc]]
49 // )cpp",
50 R"cpp(
51 #ifdef $Unknown[[UNDEFINED]]
52 #endif
53 )cpp",
54 R"cpp(
55 #ifndef $Unknown[[abc]]
56 #define $1[[abc]]
57 #ifdef $1[[abc]]
58 #endif
59 #endif
60 )cpp",
61 R"cpp(
62 // Macros from token concatenations not included.
63 #define $1[[CONCAT]](X) X##A()
64 #define $2[[PREPEND]](X) MACRO##X()
65 #define $3[[MACROA]]() 123
66 int B = $1[[CONCAT]](MACRO);
67 int D = $2[[PREPEND]](A);
68 )cpp",
69 R"cpp(
70 // FIXME: Macro names in a definition are not detected.
71 #define $1[[MACRO_ARGS2]](X, Y) X Y
72 #define $2[[FOO]] BAR
73 #define $3[[BAR]] 1
74 int A = $2[[FOO]];
75 )cpp"};
76 for (const char *Test : Tests) {
77 Annotations T(Test);
78 auto AST = TestTU::withCode(T.code()).build();
79 auto ActualMacroRefs = AST.getMacros();
80 auto &SM = AST.getSourceManager();
81 auto &PP = AST.getPreprocessor();
83 // Known macros.
84 for (int I = 1;; I++) {
85 const auto ExpectedRefs = T.ranges(llvm::to_string(I));
86 if (ExpectedRefs.empty())
87 break;
89 auto Loc = sourceLocationInMainFile(SM, ExpectedRefs.begin()->start);
90 ASSERT_TRUE(bool(Loc));
91 const auto *Id = syntax::spelledIdentifierTouching(*Loc, AST.getTokens());
92 ASSERT_TRUE(Id);
93 auto Macro = locateMacroAt(*Id, PP);
94 assert(Macro);
95 auto SID = getSymbolID(Macro->Name, Macro->Info, SM);
97 std::vector<Range> Ranges;
98 for (const auto &Ref : ActualMacroRefs.MacroRefs[SID])
99 Ranges.push_back(Ref.Rng);
100 EXPECT_THAT(ExpectedRefs, UnorderedElementsAreArray(Ranges))
101 << "Annotation=" << I << ", MacroName=" << Macro->Name
102 << ", Test = " << Test;
104 // Unknown macros.
105 std::vector<Range> Ranges;
106 for (const auto &Ref : AST.getMacros().UnknownMacros)
107 Ranges.push_back(Ref.Rng);
108 EXPECT_THAT(Ranges, UnorderedElementsAreArray(T.ranges("Unknown")))
109 << "Unknown macros doesn't match in " << Test;
112 } // namespace
113 } // namespace clangd
114 } // namespace clang