123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- //=== unittests/Sema/CodeCompleteTest.cpp - Code Complete tests ==============//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Frontend/CompilerInstance.h"
- #include "clang/Frontend/FrontendActions.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Parse/ParseAST.h"
- #include "clang/Sema/Sema.h"
- #include "clang/Sema/SemaDiagnostic.h"
- #include "clang/Tooling/Tooling.h"
- #include "gtest/gtest.h"
- #include "gmock/gmock.h"
- namespace {
- using namespace clang;
- using namespace clang::tooling;
- using ::testing::UnorderedElementsAre;
- const char TestCCName[] = "test.cc";
- using VisitedContextResults = std::vector<std::string>;
- class VisitedContextFinder: public CodeCompleteConsumer {
- public:
- VisitedContextFinder(VisitedContextResults &Results)
- : CodeCompleteConsumer(/*CodeCompleteOpts=*/{},
- /*CodeCompleteConsumer*/ false),
- VCResults(Results),
- CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
- void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
- CodeCompletionResult *Results,
- unsigned NumResults) override {
- VisitedContexts = Context.getVisitedContexts();
- VCResults = getVisitedNamespace();
- }
- CodeCompletionAllocator &getAllocator() override {
- return CCTUInfo.getAllocator();
- }
- CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
- std::vector<std::string> getVisitedNamespace() const {
- std::vector<std::string> NSNames;
- for (const auto *Context : VisitedContexts)
- if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
- NSNames.push_back(NS->getQualifiedNameAsString());
- return NSNames;
- }
- private:
- VisitedContextResults& VCResults;
- CodeCompletionTUInfo CCTUInfo;
- CodeCompletionContext::VisitedContextSet VisitedContexts;
- };
- class CodeCompleteAction : public SyntaxOnlyAction {
- public:
- CodeCompleteAction(ParsedSourceLocation P, VisitedContextResults &Results)
- : CompletePosition(std::move(P)), VCResults(Results) {}
- bool BeginInvocation(CompilerInstance &CI) override {
- CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
- CI.setCodeCompletionConsumer(new VisitedContextFinder(VCResults));
- return true;
- }
- private:
- // 1-based code complete position <Line, Col>;
- ParsedSourceLocation CompletePosition;
- VisitedContextResults& VCResults;
- };
- ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
- Offset = std::min(Code.size(), Offset);
- StringRef Before = Code.substr(0, Offset);
- int Lines = Before.count('\n');
- size_t PrevNL = Before.rfind('\n');
- size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
- return {TestCCName, static_cast<unsigned>(Lines + 1),
- static_cast<unsigned>(Offset - StartOfLine + 1)};
- }
- VisitedContextResults runCodeCompleteOnCode(StringRef Code) {
- VisitedContextResults Results;
- auto TokenOffset = Code.find('^');
- assert(TokenOffset != StringRef::npos &&
- "Completion token ^ wasn't found in Code.");
- std::string WithoutToken = Code.take_front(TokenOffset);
- WithoutToken += Code.drop_front(WithoutToken.size() + 1);
- assert(StringRef(WithoutToken).find('^') == StringRef::npos &&
- "expected exactly one completion token ^ inside the code");
- auto Action = llvm::make_unique<CodeCompleteAction>(
- offsetToPosition(WithoutToken, TokenOffset), Results);
- clang::tooling::runToolOnCodeWithArgs(Action.release(), Code, {"-std=c++11"},
- TestCCName);
- return Results;
- }
- TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
- auto VisitedNS = runCodeCompleteOnCode(R"cpp(
- namespace ns1 {}
- namespace ns2 {}
- namespace ns3 {}
- namespace ns3 { namespace nns3 {} }
- namespace foo {
- using namespace ns1;
- namespace ns4 {} // not visited
- namespace { using namespace ns2; }
- inline namespace bar { using namespace ns3::nns3; }
- } // foo
- namespace ns { foo::^ }
- )cpp");
- EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
- "foo::(anonymous)"));
- }
- TEST(SemaCodeCompleteTest, VisitedNSForInvalideQualifiedId) {
- auto VisitedNS = runCodeCompleteOnCode(R"cpp(
- namespace ns { foo::^ }
- )cpp");
- EXPECT_TRUE(VisitedNS.empty());
- }
- } // namespace
|