brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · 4eac061 Raw
116 lines · cpp
1//===-- IncludeFixerContext.cpp - Include fixer context ---------*- 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 "IncludeFixerContext.h"10#include "llvm/ADT/STLExtras.h"11 12namespace clang {13namespace include_fixer {14 15namespace {16 17// Splits a multiply qualified names (e.g. a::b::c).18llvm::SmallVector<llvm::StringRef, 8>19SplitQualifiers(llvm::StringRef StringQualifiers) {20  llvm::SmallVector<llvm::StringRef, 8> Qualifiers;21  StringQualifiers.split(Qualifiers, "::");22  return Qualifiers;23}24 25std::string createQualifiedNameForReplacement(26    llvm::StringRef RawSymbolName,27    llvm::StringRef SymbolScopedQualifiersName,28    const find_all_symbols::SymbolInfo &MatchedSymbol) {29  // No need to add missing qualifiers if SymbolIdentifier has a global scope30  // operator "::".31  if (RawSymbolName.starts_with("::"))32    return std::string(RawSymbolName);33 34  std::string QualifiedName = MatchedSymbol.getQualifiedName();35 36  // For nested classes, the qualified name constructed from database misses37  // some stripped qualifiers, because when we search a symbol in database,38  // we strip qualifiers from the end until we find a result. So append the39  // missing stripped qualifiers here.40  //41  // Get stripped qualifiers.42  auto SymbolQualifiers = SplitQualifiers(RawSymbolName);43  std::string StrippedQualifiers;44  while (!SymbolQualifiers.empty() &&45         !llvm::StringRef(QualifiedName).ends_with(SymbolQualifiers.back())) {46    StrippedQualifiers =47        "::" + SymbolQualifiers.back().str() + StrippedQualifiers;48    SymbolQualifiers.pop_back();49  }50  // Append the missing stripped qualifiers.51  std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;52 53  // Try to find and skip the common prefix qualifiers.54  auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);55  auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);56  auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();57  auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();58  while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&59         SymbolScopedQualifiersIter != ScopedQualifiers.end()) {60    if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)61      break;62    ++FullySymbolQualifiersIter;63    ++SymbolScopedQualifiersIter;64  }65  std::string Result;66  for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();67       ++FullySymbolQualifiersIter) {68    if (!Result.empty())69      Result += "::";70    Result += *FullySymbolQualifiersIter;71  }72  return Result;73}74 75} // anonymous namespace76 77IncludeFixerContext::IncludeFixerContext(78    StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols,79    std::vector<find_all_symbols::SymbolInfo> Symbols)80    : FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)),81      MatchedSymbols(std::move(Symbols)) {82  // Remove replicated QuerySymbolInfos with the same range.83  //84  // QuerySymbolInfos may contain replicated elements. Because CorrectTypo85  // callback doesn't always work as we expected. In somecases, it will be86  // triggered at the same position or unidentified symbol multiple times.87  llvm::sort(QuerySymbolInfos,88             [&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {89               return std::make_pair(A.Range.getOffset(), A.Range.getLength()) <90                      std::make_pair(B.Range.getOffset(), B.Range.getLength());91             });92  QuerySymbolInfos.erase(93      llvm::unique(QuerySymbolInfos,94                   [](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {95                     return A.Range == B.Range;96                   }),97      QuerySymbolInfos.end());98  for (const auto &Symbol : MatchedSymbols) {99    HeaderInfos.push_back(100        {Symbol.getFilePath().str(),101         createQualifiedNameForReplacement(102             QuerySymbolInfos.front().RawIdentifier,103             QuerySymbolInfos.front().ScopedQualifiers, Symbol)});104  }105  // Deduplicate header infos.106  HeaderInfos.erase(llvm::unique(HeaderInfos,107                                 [](const HeaderInfo &A, const HeaderInfo &B) {108                                   return A.Header == B.Header &&109                                          A.QualifiedName == B.QualifiedName;110                                 }),111                    HeaderInfos.end());112}113 114} // include_fixer115} // clang116