[include-fixer] make HeaderMapCollector maps from regex instead of postfix.

Summary:
this enables us to map a group of headers to one header name,
e.g. headers from one directory can be mapped to the same header.

Reviewers: bkramer

Subscribers: cfe-commits, hokein

Differential Revision: http://reviews.llvm.org/D21787

llvm-svn: 274494
This commit is contained in:
Eric Liu 2016-07-04 11:22:35 +00:00
parent c8cf2ddb6d
commit f33bc95f8f
7 changed files with 660 additions and 656 deletions

View File

@ -13,8 +13,9 @@ namespace clang {
namespace find_all_symbols {
FindAllSymbolsAction::FindAllSymbolsAction(
SymbolReporter *Reporter, const HeaderMapCollector::HeaderMap *PostfixMap)
: Reporter(Reporter), Collector(PostfixMap), Handler(&Collector),
SymbolReporter *Reporter,
const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap)
: Reporter(Reporter), Collector(RegexHeaderMap), Handler(&Collector),
Matcher(Reporter, &Collector) {
Matcher.registerMatchers(&MatchFinder);
}

View File

@ -25,7 +25,7 @@ class FindAllSymbolsAction : public clang::ASTFrontendAction {
public:
explicit FindAllSymbolsAction(
SymbolReporter *Reporter,
const HeaderMapCollector::HeaderMap *PostfixMap = nullptr);
const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr);
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &Compiler,
@ -43,16 +43,16 @@ class FindAllSymbolsActionFactory : public tooling::FrontendActionFactory {
public:
FindAllSymbolsActionFactory(
SymbolReporter *Reporter,
const HeaderMapCollector::HeaderMap *PostfixMap = nullptr)
: Reporter(Reporter), PostfixMap(PostfixMap) {}
const HeaderMapCollector::RegexHeaderMap *RegexHeaderMap = nullptr)
: Reporter(Reporter), RegexHeaderMap(RegexHeaderMap) {}
virtual clang::FrontendAction *create() override {
return new FindAllSymbolsAction(Reporter, PostfixMap);
return new FindAllSymbolsAction(Reporter, RegexHeaderMap);
}
private:
SymbolReporter *const Reporter;
const HeaderMapCollector::HeaderMap *const PostfixMap;
const HeaderMapCollector::RegexHeaderMap *const RegexHeaderMap;
};
} // namespace find_all_symbols

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "HeaderMapCollector.h"
#include "llvm/Support/Regex.h"
namespace clang {
namespace find_all_symbols {
@ -18,12 +19,10 @@ HeaderMapCollector::getMappedHeader(llvm::StringRef Header) const {
if (Iter != HeaderMappingTable.end())
return Iter->second;
// If there is no complete header name mapping for this header, check the
// postfix mapping.
// FIXME: this is not very efficient. Change PostfixMappingTable to use
// postfix tree if necessary.
if (PostfixMappingTable) {
for (const auto &Entry : *PostfixMappingTable) {
if (Header.endswith(Entry.first()))
// regex header mapping.
if (RegexHeaderMappingTable) {
for (const auto &Entry : *RegexHeaderMappingTable) {
if (llvm::Regex(Entry.first).match(Header))
return Entry.second;
}
}

View File

@ -11,29 +11,32 @@
#define LLVM_CLANG_TOOLS_EXTRA_FIND_ALL_SYMBOLS_HEADER_MAP_COLLECTOR_H
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Regex.h"
#include <string>
namespace clang {
namespace find_all_symbols {
/// \brief HeaderMappCollector collects all remapping header files. This maps
/// complete header names or postfixes of header names to header names.
/// complete header names or header name regex patterns to header names.
class HeaderMapCollector {
public:
typedef llvm::StringMap<std::string> HeaderMap;
typedef std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
RegexHeaderMap;
HeaderMapCollector() : PostfixMappingTable(nullptr) {}
HeaderMapCollector() : RegexHeaderMappingTable(nullptr) {}
explicit HeaderMapCollector(const HeaderMap *PostfixMap)
: PostfixMappingTable(PostfixMap) {}
explicit HeaderMapCollector(const RegexHeaderMap *RegexHeaderMappingTable)
: RegexHeaderMappingTable(RegexHeaderMappingTable) {}
void addHeaderMapping(llvm::StringRef OrignalHeaderPath,
llvm::StringRef MappingHeaderPath) {
HeaderMappingTable[OrignalHeaderPath] = MappingHeaderPath;
};
/// Check if there is a mapping from \p Header or its postfix to another
/// header name.
/// Check if there is a mapping from \p Header or a regex pattern that matches
/// it to another header name.
/// \param Header A header name.
/// \return \p Header itself if there is no mapping for it; otherwise, return
/// a mapped header name.
@ -43,9 +46,9 @@ private:
/// A string-to-string map saving the mapping relationship.
HeaderMap HeaderMappingTable;
// A postfix-to-header name map.
// A map from header patterns to header names.
// This is a reference to a hard-coded map.
const HeaderMap *const PostfixMappingTable;
const RegexHeaderMap *const RegexHeaderMappingTable;
};
} // namespace find_all_symbols

View File

@ -15,7 +15,7 @@
namespace clang {
namespace find_all_symbols {
const HeaderMapCollector::HeaderMap* getSTLPostfixHeaderMap();
const HeaderMapCollector::RegexHeaderMap *getSTLPostfixHeaderMap();
} // namespace find_all_symbols
} // namespace clang

View File

@ -66,15 +66,15 @@ public:
std::string FileName = "symbol.cc";
const std::string InternalHeader = "internal/internal.h";
const std::string InternalHeader = "internal/internal_header.h";
const std::string TopHeader = "<top>";
// Test .inc header path. The header for `IncHeaderClass` should be
// internal.h, which will eventually be mapped to <top>.
std::string IncHeader = "internal/private.inc";
std::string IncHeaderCode = "class IncHeaderClass {};";
HeaderMapCollector::HeaderMap PostfixMap = {
{"internal.h", TopHeader},
HeaderMapCollector::RegexHeaderMap RegexMap = {
{R"(internal_.*\.h$)", TopHeader},
};
std::string InternalCode =
@ -89,7 +89,7 @@ public:
llvm::MemoryBuffer::getMemBuffer(InternalCode));
std::unique_ptr<clang::tooling::FrontendActionFactory> Factory(
new FindAllSymbolsActionFactory(&Reporter, &PostfixMap));
new FindAllSymbolsActionFactory(&Reporter, &RegexMap));
tooling::ToolInvocation Invocation(
{std::string("find_all_symbols"), std::string("-fsyntax-only"),
@ -102,7 +102,8 @@ public:
std::string Content = "#include\"" + std::string(HeaderName) +
"\"\n"
"#include \"internal/internal.h\"";
"#include \"" +
InternalHeader + "\"";
#if !defined(_MSC_VER) && !defined(__MINGW32__)
// Test path cleaning for both decls and macros.
const std::string DirtyHeader = "./internal/./a/b.h";