TEST(MergeIndexTest, Refs) {
  FileIndex Dyn({"unittest"});
  FileIndex StaticIndex({"unittest"});
  auto MergedIndex = mergeIndex(&Dyn, &StaticIndex);

  const char *HeaderCode = "class Foo;";
  auto HeaderSymbols = TestTU::withHeaderCode("class Foo;").headerSymbols();
  auto Foo = findSymbol(HeaderSymbols, "Foo");

  // Build dynamic index for test.cc.
  Annotations Test1Code(R"(class $Foo[[Foo]];)");
  TestTU Test;
  Test.HeaderCode = HeaderCode;
  Test.Code = Test1Code.code();
  Test.Filename = "test.cc";
  auto AST = Test.build();
  Dyn.update(Test.Filename, &AST.getASTContext(), AST.getPreprocessorPtr(),
             AST.getLocalTopLevelDecls());

  // Build static index for test.cc.
  Test.HeaderCode = HeaderCode;
  Test.Code = "// static\nclass Foo {};";
  Test.Filename = "test.cc";
  auto StaticAST = Test.build();
  // Add stale refs for test.cc.
  StaticIndex.update(Test.Filename, &StaticAST.getASTContext(),
                     StaticAST.getPreprocessorPtr(),
                     StaticAST.getLocalTopLevelDecls());

  // Add refs for test2.cc
  Annotations Test2Code(R"(class $Foo[[Foo]] {};)");
  TestTU Test2;
  Test2.HeaderCode = HeaderCode;
  Test2.Code = Test2Code.code();
  Test2.Filename = "test2.cc";
  StaticAST = Test2.build();
  StaticIndex.update(Test2.Filename, &StaticAST.getASTContext(),
                     StaticAST.getPreprocessorPtr(),
                     StaticAST.getLocalTopLevelDecls());

  RefsRequest Request;
  Request.IDs = {Foo.ID};
  RefSlab::Builder Results;
  MergedIndex->refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); });

  EXPECT_THAT(
      std::move(Results).build(),
      ElementsAre(Pair(
          _, UnorderedElementsAre(AllOf(RefRange(Test1Code.range("Foo")),
                                        FileURI("unittest:///test.cc")),
                                  AllOf(RefRange(Test2Code.range("Foo")),
                                        FileURI("unittest:///test2.cc"))))));
}
示例#2
0
llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data) {
  auto RIFF = riff::readFile(Data);
  if (!RIFF)
    return RIFF.takeError();
  if (RIFF->Type != riff::fourCC("CdIx"))
    return makeError("wrong RIFF type");
  llvm::StringMap<llvm::StringRef> Chunks;
  for (const auto &Chunk : RIFF->Chunks)
    Chunks.try_emplace(llvm::StringRef(Chunk.ID.data(), Chunk.ID.size()),
                       Chunk.Data);

  for (llvm::StringRef RequiredChunk : {"meta", "stri"})
    if (!Chunks.count(RequiredChunk))
      return makeError("missing required chunk " + RequiredChunk);

  Reader Meta(Chunks.lookup("meta"));
  if (Meta.consume32() != Version)
    return makeError("wrong version");

  auto Strings = readStringTable(Chunks.lookup("stri"));
  if (!Strings)
    return Strings.takeError();

  IndexFileIn Result;
  if (Chunks.count("srcs")) {
    Reader SrcsReader(Chunks.lookup("srcs"));
    Result.Sources.emplace();
    while (!SrcsReader.eof()) {
      auto IGN = readIncludeGraphNode(SrcsReader, Strings->Strings);
      auto Entry = Result.Sources->try_emplace(IGN.URI).first;
      Entry->getValue() = std::move(IGN);
      // We change all the strings inside the structure to point at the keys in
      // the map, since it is the only copy of the string that's going to live.
      Entry->getValue().URI = Entry->getKey();
      for (auto &Include : Entry->getValue().DirectIncludes)
        Include = Result.Sources->try_emplace(Include).first->getKey();
    }
    if (SrcsReader.err())
      return makeError("malformed or truncated include uri");
  }

  if (Chunks.count("symb")) {
    Reader SymbolReader(Chunks.lookup("symb"));
    SymbolSlab::Builder Symbols;
    while (!SymbolReader.eof())
      Symbols.insert(readSymbol(SymbolReader, Strings->Strings));
    if (SymbolReader.err())
      return makeError("malformed or truncated symbol");
    Result.Symbols = std::move(Symbols).build();
  }
  if (Chunks.count("refs")) {
    Reader RefsReader(Chunks.lookup("refs"));
    RefSlab::Builder Refs;
    while (!RefsReader.eof()) {
      auto RefsBundle = readRefs(RefsReader, Strings->Strings);
      for (const auto &Ref : RefsBundle.second) // FIXME: bulk insert?
        Refs.insert(RefsBundle.first, Ref);
    }
    if (RefsReader.err())
      return makeError("malformed or truncated refs");
    Result.Refs = std::move(Refs).build();
  }
  return std::move(Result);
}