Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | c4bab56944e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,115 @@ +//===-- IncludeFixerContext.cpp - Include fixer context ---------*- 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 "IncludeFixerContext.h" +#include <algorithm> + +namespace clang { +namespace include_fixer { + +namespace { + +// Splits a multiply qualified names (e.g. a::b::c). +llvm::SmallVector<llvm::StringRef, 8> +SplitQualifiers(llvm::StringRef StringQualifiers) { + llvm::SmallVector<llvm::StringRef, 8> Qualifiers; + StringQualifiers.split(Qualifiers, "::"); + return Qualifiers; +} + +std::string createQualifiedNameForReplacement( + llvm::StringRef RawSymbolName, + llvm::StringRef SymbolScopedQualifiersName, + const find_all_symbols::SymbolInfo &MatchedSymbol) { + // No need to add missing qualifiers if SymbolIdentifier has a global scope + // operator "::". + if (RawSymbolName.startswith("::")) + return std::string(RawSymbolName); + + std::string QualifiedName = MatchedSymbol.getQualifiedName(); + + // For nested classes, the qualified name constructed from database misses + // some stripped qualifiers, because when we search a symbol in database, + // we strip qualifiers from the end until we find a result. So append the + // missing stripped qualifiers here. + // + // Get stripped qualifiers. + auto SymbolQualifiers = SplitQualifiers(RawSymbolName); + std::string StrippedQualifiers; + while (!SymbolQualifiers.empty() && + !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) { + StrippedQualifiers = + "::" + SymbolQualifiers.back().str() + StrippedQualifiers; + SymbolQualifiers.pop_back(); + } + // Append the missing stripped qualifiers. + std::string FullyQualifiedName = QualifiedName + StrippedQualifiers; + + // Try to find and skip the common prefix qualifiers. + auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName); + auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName); + auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin(); + auto SymbolScopedQualifiersIter = ScopedQualifiers.begin(); + while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() && + SymbolScopedQualifiersIter != ScopedQualifiers.end()) { + if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter) + break; + ++FullySymbolQualifiersIter; + ++SymbolScopedQualifiersIter; + } + std::string Result; + for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end(); + ++FullySymbolQualifiersIter) { + if (!Result.empty()) + Result += "::"; + Result += *FullySymbolQualifiersIter; + } + return Result; +} + +} // anonymous namespace + +IncludeFixerContext::IncludeFixerContext( + StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols, + std::vector<find_all_symbols::SymbolInfo> Symbols) + : FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)), + MatchedSymbols(std::move(Symbols)) { + // Remove replicated QuerySymbolInfos with the same range. + // + // QuerySymbolInfos may contain replicated elements. Because CorrectTypo + // callback doesn't always work as we expected. In somecases, it will be + // triggered at the same position or unidentified symbol multiple times. + std::sort(QuerySymbolInfos.begin(), QuerySymbolInfos.end(), + [&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) { + return std::make_pair(A.Range.getOffset(), A.Range.getLength()) < + std::make_pair(B.Range.getOffset(), B.Range.getLength()); + }); + QuerySymbolInfos.erase( + std::unique(QuerySymbolInfos.begin(), QuerySymbolInfos.end(), + [](const QuerySymbolInfo &A, const QuerySymbolInfo &B) { + return A.Range == B.Range; + }), + QuerySymbolInfos.end()); + for (const auto &Symbol : MatchedSymbols) { + HeaderInfos.push_back( + {Symbol.getFilePath().str(), + createQualifiedNameForReplacement( + QuerySymbolInfos.front().RawIdentifier, + QuerySymbolInfos.front().ScopedQualifiers, Symbol)}); + } + // Deduplicate header infos. + HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(), + [](const HeaderInfo &A, const HeaderInfo &B) { + return A.Header == B.Header && + A.QualifiedName == B.QualifiedName; + }), + HeaderInfos.end()); +} + +} // include_fixer +} // clang