blob: dd3fc6dd58b79ff14f3f051a10eea4b3eb907559 [file] [log] [blame]
//===-- ClangdUnitTests.cpp - ClangdUnit tests ------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
#include "ClangdUnit.h"
#include "SourceCode.h"
#include "TestTU.h"
#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace clang {
namespace clangd {
namespace {
using testing::ElementsAre;
TEST(ClangdUnitTest, GetBeginningOfIdentifier) {
std::string Preamble = R"cpp(
struct Bar { int func(); };
#define MACRO(X) void f() { X; }
Bar* bar;
)cpp";
// First ^ is the expected beginning, last is the search position.
for (std::string Text : std::vector<std::string>{
"int ^f^oo();", // inside identifier
"int ^foo();", // beginning of identifier
"int ^foo^();", // end of identifier
"int foo(^);", // non-identifier
"^int foo();", // beginning of file (can't back up)
"int ^f0^0();", // after a digit (lexing at N-1 is wrong)
"int ^λλ^λ();", // UTF-8 handled properly when backing up
// identifier in macro arg
"MACRO(bar->^func())", // beginning of identifier
"MACRO(bar->^fun^c())", // inside identifier
"MACRO(bar->^func^())", // end of identifier
"MACRO(^bar->func())", // begin identifier
"MACRO(^bar^->func())", // end identifier
"^MACRO(bar->func())", // beginning of macro name
"^MAC^RO(bar->func())", // inside macro name
"^MACRO^(bar->func())", // end of macro name
}) {
std::string WithPreamble = Preamble + Text;
Annotations TestCase(WithPreamble);
auto AST = TestTU::withCode(TestCase.code()).build();
const auto &SourceMgr = AST.getASTContext().getSourceManager();
SourceLocation Actual = getBeginningOfIdentifier(
AST, TestCase.points().back(), SourceMgr.getMainFileID());
Position ActualPos = offsetToPosition(
TestCase.code(),
SourceMgr.getFileOffset(SourceMgr.getSpellingLoc(Actual)));
EXPECT_EQ(TestCase.points().front(), ActualPos) << Text;
}
}
MATCHER_P(DeclNamed, Name, "") {
if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
if (ND->getName() == Name)
return true;
if (auto *Stream = result_listener->stream()) {
llvm::raw_os_ostream OS(*Stream);
arg->dump(OS);
}
return false;
}
TEST(ClangdUnitTest, TopLevelDecls) {
TestTU TU;
TU.HeaderCode = R"(
int header1();
int header2;
)";
TU.Code = "int main();";
auto AST = TU.build();
EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
}
} // namespace
} // namespace clangd
} // namespace clang