forked from OSchip/llvm-project
[clangd] IncludeCleaner: Decrease API dependency on clangd
Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D118882
This commit is contained in:
parent
005fd8aa70
commit
089d9c50b2
|
@ -14,6 +14,7 @@
|
|||
#include "SourceCode.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
|
@ -21,6 +22,7 @@
|
|||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Tooling/Syntax/Tokens.h"
|
||||
#include "llvm/ADT/STLFunctionalExtras.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
|
@ -207,10 +209,10 @@ clangd::Range getDiagnosticRange(llvm::StringRef Code, unsigned HashOffset) {
|
|||
|
||||
// Finds locations of macros referenced from within the main file. That includes
|
||||
// references that were not yet expanded, e.g `BAR` in `#define FOO BAR`.
|
||||
void findReferencedMacros(ParsedAST &AST, ReferencedLocations &Result) {
|
||||
void findReferencedMacros(const SourceManager &SM, Preprocessor &PP,
|
||||
const syntax::TokenBuffer *Tokens,
|
||||
ReferencedLocations &Result) {
|
||||
trace::Span Tracer("IncludeCleaner::findReferencedMacros");
|
||||
auto &SM = AST.getSourceManager();
|
||||
auto &PP = AST.getPreprocessor();
|
||||
// FIXME(kirillbobyrev): The macros from the main file are collected in
|
||||
// ParsedAST's MainFileMacros. However, we can't use it here because it
|
||||
// doesn't handle macro references that were not expanded, e.g. in macro
|
||||
|
@ -220,8 +222,7 @@ void findReferencedMacros(ParsedAST &AST, ReferencedLocations &Result) {
|
|||
// this mechanism (as opposed to iterating through all tokens) will improve
|
||||
// the performance of findReferencedMacros and also improve other features
|
||||
// relying on MainFileMacros.
|
||||
for (const syntax::Token &Tok :
|
||||
AST.getTokens().spelledTokens(SM.getMainFileID())) {
|
||||
for (const syntax::Token &Tok : Tokens->spelledTokens(SM.getMainFileID())) {
|
||||
auto Macro = locateMacroAt(Tok, PP);
|
||||
if (!Macro)
|
||||
continue;
|
||||
|
@ -287,18 +288,26 @@ FileID headerResponsible(FileID ID, const SourceManager &SM,
|
|||
|
||||
} // namespace
|
||||
|
||||
ReferencedLocations findReferencedLocations(ParsedAST &AST) {
|
||||
ReferencedLocations findReferencedLocations(const SourceManager &SM,
|
||||
ASTContext &Ctx, Preprocessor &PP,
|
||||
const syntax::TokenBuffer *Tokens) {
|
||||
trace::Span Tracer("IncludeCleaner::findReferencedLocations");
|
||||
ReferencedLocations Result;
|
||||
ReferencedLocationCrawler Crawler(Result, AST.getSourceManager());
|
||||
Crawler.TraverseAST(AST.getASTContext());
|
||||
findReferencedMacros(AST, Result);
|
||||
ReferencedLocationCrawler Crawler(Result, SM);
|
||||
Crawler.TraverseAST(Ctx);
|
||||
if (Tokens)
|
||||
findReferencedMacros(SM, PP, Tokens, Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
ReferencedFiles findReferencedFiles(const ReferencedLocations &Locs,
|
||||
const IncludeStructure &Includes,
|
||||
const SourceManager &SM) {
|
||||
ReferencedLocations findReferencedLocations(ParsedAST &AST) {
|
||||
return findReferencedLocations(AST.getSourceManager(), AST.getASTContext(),
|
||||
AST.getPreprocessor(), &AST.getTokens());
|
||||
}
|
||||
|
||||
ReferencedFiles
|
||||
findReferencedFiles(const ReferencedLocations &Locs, const SourceManager &SM,
|
||||
llvm::function_ref<FileID(FileID)> HeaderResponsible) {
|
||||
std::vector<SourceLocation> Sorted{Locs.User.begin(), Locs.User.end()};
|
||||
llvm::sort(Sorted); // Group by FileID.
|
||||
ReferencedFilesBuilder Builder(SM);
|
||||
|
@ -318,7 +327,7 @@ ReferencedFiles findReferencedFiles(const ReferencedLocations &Locs,
|
|||
// HeaderIDs, as each inclusion of a non-self-contained file is distinct.
|
||||
llvm::DenseSet<FileID> UserFiles;
|
||||
for (FileID ID : Builder.Files)
|
||||
UserFiles.insert(headerResponsible(ID, SM, Includes));
|
||||
UserFiles.insert(HeaderResponsible(ID));
|
||||
|
||||
llvm::DenseSet<stdlib::Header> StdlibFiles;
|
||||
for (const auto &Symbol : Locs.Stdlib)
|
||||
|
@ -328,6 +337,14 @@ ReferencedFiles findReferencedFiles(const ReferencedLocations &Locs,
|
|||
return {std::move(UserFiles), std::move(StdlibFiles)};
|
||||
}
|
||||
|
||||
ReferencedFiles findReferencedFiles(const ReferencedLocations &Locs,
|
||||
const IncludeStructure &Includes,
|
||||
const SourceManager &SM) {
|
||||
return findReferencedFiles(Locs, SM, [&SM, &Includes](FileID ID) {
|
||||
return headerResponsible(ID, SM, Includes);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<const Inclusion *>
|
||||
getUnused(ParsedAST &AST,
|
||||
const llvm::DenseSet<IncludeStructure::HeaderID> &ReferencedFiles) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "ParsedAST.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLFunctionalExtras.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
@ -41,15 +42,17 @@ struct ReferencedLocations {
|
|||
/// associated locations. These may be macro expansions, and are not resolved
|
||||
/// to their spelling or expansion location. These locations are later used to
|
||||
/// determine which headers should be marked as "used" and "directly used".
|
||||
/// - We also examine all identifier tokens in the file in case they reference
|
||||
/// macros.
|
||||
///
|
||||
/// - If \p Tokens is not nullptr, we also examine all identifier tokens in the
|
||||
/// file in case they reference macros macros.
|
||||
/// We use this to compute unused headers, so we:
|
||||
///
|
||||
/// - cover the whole file in a single traversal for efficiency
|
||||
/// - don't attempt to describe where symbols were referenced from in
|
||||
/// ambiguous cases (e.g. implicitly used symbols, multiple declarations)
|
||||
/// - err on the side of reporting all possible locations
|
||||
ReferencedLocations findReferencedLocations(const SourceManager &SM,
|
||||
ASTContext &Ctx, Preprocessor &PP,
|
||||
const syntax::TokenBuffer *Tokens);
|
||||
ReferencedLocations findReferencedLocations(ParsedAST &AST);
|
||||
|
||||
struct ReferencedFiles {
|
||||
|
@ -60,6 +63,12 @@ struct ReferencedFiles {
|
|||
/// Retrieves IDs of all files containing SourceLocations from \p Locs.
|
||||
/// The output only includes things SourceManager sees as files (not macro IDs).
|
||||
/// This can include <built-in>, <scratch space> etc that are not true files.
|
||||
/// \p HeaderResponsible returns the public header that should be included given
|
||||
/// symbols from a file with the given FileID (example: public headers should be
|
||||
/// preferred to non self-contained and private headers).
|
||||
ReferencedFiles
|
||||
findReferencedFiles(const ReferencedLocations &Locs, const SourceManager &SM,
|
||||
llvm::function_ref<FileID(FileID)> HeaderResponsible);
|
||||
ReferencedFiles findReferencedFiles(const ReferencedLocations &Locs,
|
||||
const IncludeStructure &Includes,
|
||||
const SourceManager &SM);
|
||||
|
@ -81,8 +90,8 @@ std::vector<const Inclusion *> computeUnusedIncludes(ParsedAST &AST);
|
|||
std::vector<Diag> issueUnusedIncludesDiagnostics(ParsedAST &AST,
|
||||
llvm::StringRef Code);
|
||||
|
||||
/// Affects whether standard library includes should be considered for removal.
|
||||
/// This is off by default for now due to implementation limitations:
|
||||
/// Affects whether standard library includes should be considered for
|
||||
/// removal. This is off by default for now due to implementation limitations:
|
||||
/// - macros are not tracked
|
||||
/// - symbol names without a unique associated header are not tracked
|
||||
/// - references to std-namespaced C types are not properly tracked:
|
||||
|
|
Loading…
Reference in New Issue