|
| 1 | +//===--- IncludeCleanerTests.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 | + |
| 9 | +#include "Annotations.h" |
| 10 | +#include "IncludeCleaner.h" |
| 11 | +#include "TestTU.h" |
| 12 | +#include "gmock/gmock.h" |
| 13 | +#include "gtest/gtest.h" |
| 14 | + |
| 15 | +namespace clang { |
| 16 | +namespace clangd { |
| 17 | +namespace { |
| 18 | + |
| 19 | +TEST(IncludeCleaner, ReferencedLocations) { |
| 20 | + struct TestCase { |
| 21 | + std::string HeaderCode; |
| 22 | + std::string MainCode; |
| 23 | + }; |
| 24 | + TestCase Cases[] = { |
| 25 | + // DeclRefExpr |
| 26 | + { |
| 27 | + "int ^x();", |
| 28 | + "int y = x();", |
| 29 | + }, |
| 30 | + // RecordDecl |
| 31 | + { |
| 32 | + "class ^X;", |
| 33 | + "X *y;", |
| 34 | + }, |
| 35 | + // TypedefType and UsingDecls |
| 36 | + { |
| 37 | + "using ^Integer = int;", |
| 38 | + "Integer x;", |
| 39 | + }, |
| 40 | + { |
| 41 | + "namespace ns { struct ^X; struct ^X {}; }", |
| 42 | + "using ns::X;", |
| 43 | + }, |
| 44 | + { |
| 45 | + "namespace ns { struct X; struct X {}; }", |
| 46 | + "using namespace ns;", |
| 47 | + }, |
| 48 | + { |
| 49 | + "struct ^A {}; using B = A; using ^C = B;", |
| 50 | + "C a;", |
| 51 | + }, |
| 52 | + { |
| 53 | + "typedef bool ^Y; template <typename T> struct ^X {};", |
| 54 | + "X<Y> x;", |
| 55 | + }, |
| 56 | + { |
| 57 | + "struct Foo; struct ^Foo{}; typedef Foo ^Bar;", |
| 58 | + "Bar b;", |
| 59 | + }, |
| 60 | + // MemberExpr |
| 61 | + { |
| 62 | + "struct ^X{int ^a;}; X ^foo();", |
| 63 | + "int y = foo().a;", |
| 64 | + }, |
| 65 | + // Expr (type is traversed) |
| 66 | + { |
| 67 | + "class ^X{}; X ^foo();", |
| 68 | + "auto bar() { return foo(); }", |
| 69 | + }, |
| 70 | + // Redecls |
| 71 | + { |
| 72 | + "class ^X; class ^X{}; class ^X;", |
| 73 | + "X *y;", |
| 74 | + }, |
| 75 | + // Constructor |
| 76 | + { |
| 77 | + "struct ^X { ^X(int) {} int ^foo(); };", |
| 78 | + "auto x = X(42); auto y = x.foo();", |
| 79 | + }, |
| 80 | + // Static function |
| 81 | + { |
| 82 | + "struct ^X { static bool ^foo(); }; bool X::^foo() {}", |
| 83 | + "auto b = X::foo();", |
| 84 | + }, |
| 85 | + // TemplateRecordDecl |
| 86 | + { |
| 87 | + "template <typename> class ^X;", |
| 88 | + "X<int> *y;", |
| 89 | + }, |
| 90 | + // Type name not spelled out in code |
| 91 | + { |
| 92 | + "class ^X{}; X ^getX();", |
| 93 | + "auto x = getX();", |
| 94 | + }, |
| 95 | + // Enums |
| 96 | + { |
| 97 | + "enum ^Color { ^Red = 42, Green = 9000};", |
| 98 | + "int MyColor = Red;", |
| 99 | + }, |
| 100 | + { |
| 101 | + "struct ^X { enum ^Language { ^CXX = 42, Python = 9000}; };", |
| 102 | + "int Lang = X::CXX;", |
| 103 | + }, |
| 104 | + { |
| 105 | + // When a type is resolved via a using declaration, the |
| 106 | + // UsingShadowDecl is not referenced in the AST. |
| 107 | + // Compare to TypedefType, or DeclRefExpr::getFoundDecl(). |
| 108 | + // ^ |
| 109 | + "namespace ns { class ^X; }; using ns::X;", |
| 110 | + "X *y;", |
| 111 | + }}; |
| 112 | + for (const TestCase &T : Cases) { |
| 113 | + TestTU TU; |
| 114 | + TU.Code = T.MainCode; |
| 115 | + Annotations Header(T.HeaderCode); |
| 116 | + TU.HeaderCode = Header.code().str(); |
| 117 | + auto AST = TU.build(); |
| 118 | + |
| 119 | + std::vector<Position> Points; |
| 120 | + for (const auto &Loc : findReferencedLocations(AST)) { |
| 121 | + if (AST.getSourceManager().getBufferName(Loc).endswith( |
| 122 | + TU.HeaderFilename)) { |
| 123 | + Points.push_back(offsetToPosition( |
| 124 | + TU.HeaderCode, AST.getSourceManager().getFileOffset(Loc))); |
| 125 | + } |
| 126 | + } |
| 127 | + llvm::sort(Points); |
| 128 | + |
| 129 | + EXPECT_EQ(Points, Header.points()) << T.HeaderCode << "\n---\n" |
| 130 | + << T.MainCode; |
| 131 | + } |
| 132 | +} |
| 133 | + |
| 134 | +} // namespace |
| 135 | +} // namespace clangd |
| 136 | +} // namespace clang |
0 commit comments