13 #include "clang/Basic/LangOptions.h" 14 #include "clang/Format/Format.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/raw_os_ostream.h" 17 #include "llvm/Testing/Support/Error.h" 18 #include "gmock/gmock.h" 19 #include "gtest/gtest.h" 27 using ::testing::UnorderedElementsAreArray;
29 MATCHER_P2(Pos,
Line, Col,
"") {
30 return arg.line == int(
Line) && arg.character == int(Col);
36 Position position(
int line,
int character) {
39 Pos.character = character;
43 Range range(
const std::pair<int, int> p1,
const std::pair<int, int> p2) {
45 range.start = position(p1.first, p1.second);
46 range.end = position(p2.first, p2.second);
79 const char File[] = R
"(0:0 = 0 89 TEST(SourceCodeTests, PositionToOffset) {
91 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(-1, 2)), llvm::Failed());
146 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(3, 0)), llvm::Failed());
147 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(3, 1)), llvm::Failed());
152 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(-1, 2)), llvm::Failed());
203 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(3, 0)), llvm::Failed());
204 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(3, 1)), llvm::Failed());
208 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(-1, 2)), llvm::Failed());
209 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(3, 0)), llvm::Failed());
210 for (
Line L : FileLines) {
213 for (
unsigned I = 0; I <= L.Length; ++I)
216 EXPECT_THAT_EXPECTED(
positionToOffset(File, position(L.Number, L.Length+1)),
218 EXPECT_THAT_EXPECTED(
224 TEST(SourceCodeTests, OffsetToPosition) {
229 EXPECT_THAT(
offsetToPosition(File, 8), Pos(1, 0)) <<
"start of second line";
250 EXPECT_THAT(
offsetToPosition(File, 8), Pos(1, 0)) <<
"start of second line";
266 for (
Line L : FileLines) {
267 for (
unsigned I = 0; I <= L.Length; ++I)
273 TEST(SourceCodeTests, IsRangeConsecutive) {
281 TEST(SourceCodeTests, SourceLocationInMainFile) {
282 Annotations Source(R
"cpp( 285 ^baz ^() {} {} {} {} { }^ 288 SourceManagerForFile Owner("foo.cpp", Source.code());
289 SourceManager &SM = Owner.get();
291 SourceLocation StartOfFile = SM.getLocForStartOfFile(SM.getMainFileID());
295 EXPECT_THAT_EXPECTED(
297 HasValue(StartOfFile.getLocWithOffset(Source.code().size())));
306 for (
auto P : Source.points()) {
309 HasValue(StartOfFile.getLocWithOffset(Offset)));
313 TEST(SourceCodeTests, CollectIdentifiers) {
314 auto Style = format::getLLVMStyle();
317 void foo() { int xyz; int abc = xyz; return foo(); } 320 EXPECT_EQ(IDs.size(), 7u); 321 EXPECT_EQ(IDs["include"], 1u);
322 EXPECT_EQ(IDs[
"void"], 1u);
323 EXPECT_EQ(IDs[
"int"], 2u);
324 EXPECT_EQ(IDs[
"xyz"], 2u);
325 EXPECT_EQ(IDs[
"abc"], 1u);
326 EXPECT_EQ(IDs[
"return"], 1u);
327 EXPECT_EQ(IDs[
"foo"], 2u);
330 TEST(SourceCodeTests, CollectWords) {
334 std::string getSomeText() { return "magic word"; } 336 std::set<std::string> ActualWords(Words.keys().begin(), Words.keys().end()); 337 std::set<std::string> ExpectedWords = {"define",
"fizz",
"buzz",
"this",
338 "comment",
"string",
"some",
"text",
339 "return",
"magic",
"word"};
340 EXPECT_EQ(ActualWords, ExpectedWords);
343 TEST(SourceCodeTests, VisibleNamespaces) {
344 std::vector<std::pair<const char *, std::vector<std::string>>> Cases = {
347 // Using directive resolved against enclosing namespaces. 352 {"ns",
"",
"bar",
"foo",
"ns::bar"},
356 // Don't include namespaces we've closed, ignore namespace aliases. 357 using namespace clang; 361 namespace ll = ::llvm; 369 // Using directives visible even if a namespace is reopened. 370 // Ignore anonymous namespaces. 371 namespace foo{ using namespace bar; } 372 namespace foo{ namespace { 374 {"foo",
"",
"bar",
"foo::bar"},
387 // Namespaces with multiple chunks. 389 using namespace c::d; 404 for (
const auto& Case : Cases) {
405 EXPECT_EQ(Case.second,
411 TEST(SourceCodeTests, GetMacros) {
412 Annotations Code(R
"cpp( 417 auto AST = TU.build();
419 AST.getSourceManager().getMainFileID());
422 EXPECT_THAT(*Result, MacroName(
"MACRO"));
425 TEST(SourceCodeTests, IsInsideMainFile){
427 TU.HeaderCode = R
"cpp( 428 #define DEFINE_CLASS(X) class X {}; 429 #define DEFINE_YY DEFINE_CLASS(YY) 432 DEFINE_CLASS(Header2) 441 TU.ExtraArgs.push_back("-DHeader=Header3");
442 TU.ExtraArgs.push_back(
"-DMain=Main3");
443 auto AST = TU.build();
444 const auto& SM =
AST.getSourceManager();
445 auto DeclLoc = [&
AST](llvm::StringRef
Name) {
448 for (
const auto *HeaderDecl : {
"Header1",
"Header2",
"Header3"})
451 for (
const auto *MainDecl : {
"Main1",
"Main2",
"Main3",
"YY"})
456 TEST(SourceCodeTests, HalfOpenFileRange) {
459 Annotations Test(R
"cpp( 460 #define FOO(X, Y) int Y = ++X 464 #define BUZZ BAZZ(ADD) 466 #define ADD(a) int f = a + 1; 471 $a[[P<P<P<P<P<int>>>>> a]]; 474 $d[[FOO(BAR(BAR(b)), d)]]; 475 // FIXME: We might want to select everything inside the outer ECHO. 476 ECHO(ECHO($e[[int) ECHO(e]])); 483 llvm::errs() << Test.code(); 484 const SourceManager &SM = AST.getSourceManager();
485 const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
487 auto SourceRangeToRange = [&SM](SourceRange SrcRange) {
491 auto CheckRange = [&](llvm::StringRef
Name) {
494 SCOPED_TRACE(
"Checking range: " +
Name);
496 Range HalfOpenRange = SourceRangeToRange(*FileRange);
497 EXPECT_EQ(HalfOpenRange, Test.ranges(
Name)[0]);
SourceLocation Loc
'#' location in the include directive
llvm::StringSet collectWords(llvm::StringRef Content)
Collects words from the source code.
OptionalMatcher< InnerMatcher > HasValue(const InnerMatcher &inner_matcher)
size_t lspLength(llvm::StringRef Code)
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
Documents should not be synced at all.
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
std::vector< std::string > visibleNamespaces(llvm::StringRef Code, const format::FormatStyle &Style)
Heuristically determine namespaces visible at a point, without parsing Code.
bool isRangeConsecutive(const Range &Left, const Range &Right)
SourceLocation getBeginningOfIdentifier(const ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
Position offsetToPosition(llvm::StringRef Code, size_t Offset)
Turn an offset in Code into a [line, column] pair.
TEST(BackgroundQueueTest, Priority)
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
static constexpr llvm::StringLiteral Name
Key< OffsetEncoding > kCurrentOffsetEncoding
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
static TestTU withCode(llvm::StringRef Code)
llvm::Optional< SourceRange > toHalfOpenFileRange(const SourceManager &SM, const LangOptions &LangOpts, SourceRange R)
Turns a token range into a half-open range and checks its correctness.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
CharSourceRange Range
SourceRange for the file name.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
llvm::StringMap< unsigned > collectIdentifiers(llvm::StringRef Content, const format::FormatStyle &Style)
Collects identifiers with counts in the source code.
llvm::Optional< DefinedMacro > locateMacroAt(SourceLocation Loc, Preprocessor &PP)
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)