brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 15e4b08 Raw
212 lines · cpp
1//===-- StdLibTests.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Annotations.h"10#include "ClangdServer.h"11#include "CodeComplete.h"12#include "Compiler.h"13#include "Config.h"14#include "SyncAPI.h"15#include "TestFS.h"16#include "index/Index.h"17#include "index/StdLib.h"18#include "clang/Basic/LangOptions.h"19#include "clang/Basic/SourceManager.h"20#include "llvm/Testing/Support/Error.h"21#include "gmock/gmock.h"22#include "gtest/gtest.h"23#include <memory>24 25using namespace testing;26 27namespace clang {28namespace clangd {29namespace {30 31// Check the generated header sources contains usual standard library headers.32TEST(StdLibTests, getStdlibUmbrellaHeader) {33  LangOptions LO;34  LO.CPlusPlus = true;35 36  auto CXX = getStdlibUmbrellaHeader(LO).str();37  EXPECT_THAT(CXX, HasSubstr("#include <string>"));38  EXPECT_THAT(CXX, HasSubstr("#include <cstdio>"));39  EXPECT_THAT(CXX, Not(HasSubstr("#include <ios646.h>")));40 41  LO.CPlusPlus = false;42  auto C = getStdlibUmbrellaHeader(LO).str();43  EXPECT_THAT(C, Not(HasSubstr("#include <string>")));44  EXPECT_THAT(C, Not(HasSubstr("#include <cstdio>")));45  EXPECT_THAT(C, HasSubstr("#include <stdio.h>"));46}47 48MATCHER_P(Named, Name, "") { return arg.Name == Name; }49 50// Build an index, and check if it contains the right symbols.51TEST(StdLibTests, indexStandardLibrary) {52  MockFS FS;53  FS.Files["std/foo.h"] = R"cpp(54  #include <platform_stuff.h>55  #if __cplusplus >= 201703L56    int foo17();57  #elif __cplusplus >= 201402L58    int foo14();59  #else60    bool foo98();61  #endif62  )cpp";63  FS.Files["nonstd/platform_stuff.h"] = "int magic = 42;";64 65  ParseInputs OriginalInputs;66  OriginalInputs.TFS = &FS;67  OriginalInputs.CompileCommand.Filename = testPath("main.cc");68  OriginalInputs.CompileCommand.CommandLine = {"clang++", testPath("main.cc"),69                                               "-isystemstd/",70                                               "-isystemnonstd/", "-std=c++14"};71  OriginalInputs.CompileCommand.Directory = testRoot();72  IgnoreDiagnostics Diags;73  auto CI = buildCompilerInvocation(OriginalInputs, Diags);74  ASSERT_TRUE(CI);75 76  StdLibLocation Loc;77  Loc.Paths.push_back(testPath("std/"));78 79  auto Symbols =80      indexStandardLibrary("#include <foo.h>", std::move(CI), Loc, FS);81  EXPECT_THAT(Symbols, ElementsAre(Named("foo14")));82}83 84TEST(StdLibTests, StdLibSet) {85  StdLibSet Set;86  MockFS FS;87  FS.Files["std/_"] = "";88  FS.Files["libc/_"] = "";89 90  HeaderSearchOptions HSOpts;91  auto Add = [&](const LangOptions &LO,92                 std::vector<llvm::StringRef> SearchPath) {93    SourceManagerForFile SM("scratch", "");94    SM.get().getFileManager().setVirtualFileSystem(FS.view(std::nullopt));95    HeaderSearch HS(HSOpts, SM.get(), SM.get().getDiagnostics(), LO,96                    /*Target=*/nullptr);97    for (auto P : SearchPath)98      HS.AddSearchPath(99          DirectoryLookup(100              cantFail(SM.get().getFileManager().getDirectoryRef(testPath(P))),101              SrcMgr::C_System, /*isFramework=*/false),102          true);103    return Set.add(LO, HS);104  };105 106  Config Cfg;107  Cfg.Index.StandardLibrary = false;108  WithContextValue Disabled(Config::Key, std::move(Cfg));109 110  LangOptions LO;111  LO.CPlusPlus = true;112  EXPECT_FALSE(Add(LO, {"std"})) << "Disabled in config";113 114  Cfg = Config();115  Cfg.Index.StandardLibrary = true;116  WithContextValue Enabled(Config::Key, std::move(Cfg));117 118  EXPECT_FALSE(Add(LO, {"std"})) << "No <vector> found";119  FS.Files["std/vector"] = "class vector;";120  EXPECT_TRUE(Add(LO, {"std"})) << "Indexing as C++98";121  EXPECT_FALSE(Add(LO, {"std"})) << "Don't reindex";122  LO.CPlusPlus11 = true;123  EXPECT_TRUE(Add(LO, {"std"})) << "Indexing as C++11";124  LO.CPlusPlus = false;125  EXPECT_FALSE(Add(LO, {"libc"})) << "No <stdio.h>";126  FS.Files["libc/stdio.h"] = true;127  EXPECT_TRUE(Add(LO, {"libc"})) << "Indexing as C";128}129 130MATCHER_P(StdlibSymbol, Name, "") {131  return arg.Name == Name && arg.Includes.size() == 1 &&132         llvm::StringRef(arg.Includes.front().Header).starts_with("<");133}134 135TEST(StdLibTests, EndToEnd) {136  Config Cfg;137  Cfg.Index.StandardLibrary = true;138  WithContextValue Enabled(Config::Key, std::move(Cfg));139 140  MockFS FS;141  FS.Files["stdlib/vector"] =142      "namespace std { template <class> class vector; }";143  FS.Files["stdlib/list"] =144      " namespace std { template <typename T> class list; }";145  MockCompilationDatabase CDB;146  CDB.ExtraClangFlags.push_back("-isystem" + testPath("stdlib"));147  ClangdServer::Options Opts = ClangdServer::optsForTest();148  Opts.BuildDynamicSymbolIndex = true; // also used for stdlib index149  ClangdServer Server(CDB, FS, Opts);150 151  Annotations A("std::^");152 153  Server.addDocument(testPath("foo.cc"), A.code());154  ASSERT_TRUE(Server.blockUntilIdleForTest());155  clangd::CodeCompleteOptions CCOpts;156  auto Completions =157      cantFail(runCodeComplete(Server, testPath("foo.cc"), A.point(), CCOpts));158  EXPECT_THAT(159      Completions.Completions,160      UnorderedElementsAre(StdlibSymbol("list"), StdlibSymbol("vector")));161}162 163TEST(StdLibTests, StdLibDocComments) {164  Config Cfg;165  Cfg.Index.StandardLibrary = true;166  WithContextValue Enabled(Config::Key, std::move(Cfg));167 168  MockFS FS;169  FS.Files["stdlib/vector"] = R"cpp(170    namespace std {171      struct vector {172        /**doc comment*/173        struct inner {};174      };175    }176  )cpp";177  MockCompilationDatabase CDB;178  CDB.ExtraClangFlags.push_back("-isystem" + testPath("stdlib"));179  ClangdServer::Options Opts = ClangdServer::optsForTest();180  Opts.BuildDynamicSymbolIndex = true; // also used for stdlib index181  ClangdServer Server(CDB, FS, Opts);182 183  // Open an empty file. <vector> will not be part of the preamble index,184  // but it will be part of the stdlib index.185  Server.addDocument(testPath("foo.cc"), "");186 187  // Wait for the stdlib index to be built.188  ASSERT_TRUE(Server.blockUntilIdleForTest());189 190  // Check that the index contains the doc comment.191  SymbolSlab Result;192  EXPECT_THAT_ERROR(runCustomAction(Server, testPath("foo.cc"),193                                    [&](InputsAndAST Inputs) {194                                      FuzzyFindRequest Req;195                                      Req.Query = "inner";196                                      Req.Scopes = {"std::vector::"};197                                      SymbolSlab::Builder Builder;198                                      Inputs.Inputs.Index->fuzzyFind(199                                          Req, [&](const Symbol &Sym) {200                                            Builder.insert(Sym);201                                          });202                                      Result = std::move(Builder).build();203                                    }),204                    llvm::Succeeded());205  ASSERT_EQ(Result.size(), 1u);206  EXPECT_EQ(Result.begin()->Documentation, "doc comment");207}208 209} // namespace210} // namespace clangd211} // namespace clang212