Add support for group/backreferences regex replacement in mapping files.
This is useful to generically remap files from one directory to another. The following mapping would for instance map all files under the "foo/" directory to "third_party/foo/", for instance, mapping "foo/bar.h" to "third_party/foo/bar.h". [ { include: ['@"(foo/.*)"', private, '"third_party/\1"', public ] } ] This is useful for large project where different third_party libraries are compiled together. In Chromium for instance, include paths would look like: -Ithird_party -Ithird_party/v8/include This allows code in V8 to include its own headers directly. Other third_parties would include them via "third_party/v8/include/...". Because files are accessible from two different paths, IWYU can't know which should be used. Using a mapping file, adding or removing the "third_party/v8/include" prefix where needed, resolves this problem.
This commit is contained in:
parent
b74819dc5f
commit
6fb66575fb
|
@ -1436,10 +1436,14 @@ void IncludePicker::ExpandRegexes() {
|
|||
for (const auto& incmap : quoted_includes_to_quoted_includers_) {
|
||||
const string& hdr = incmap.first;
|
||||
for (const string& regex_key : filepath_include_map_regex_keys) {
|
||||
const string regex = regex_key.substr(1);
|
||||
const vector<MappedInclude>& map_to = filepath_include_map_[regex_key];
|
||||
if (RegexMatch(regex_dialect, hdr, regex_key.substr(1)) &&
|
||||
if (RegexMatch(regex_dialect, hdr, regex) &&
|
||||
!ContainsQuotedInclude(map_to, hdr)) {
|
||||
Extend(&filepath_include_map_[hdr], filepath_include_map_[regex_key]);
|
||||
for (const MappedInclude& target : map_to) {
|
||||
filepath_include_map_[hdr].push_back(MappedInclude(
|
||||
RegexReplace(regex_dialect, hdr, regex, target.quoted_include)));
|
||||
}
|
||||
MarkVisibility(&include_visibility_map_, hdr,
|
||||
include_visibility_map_[regex_key]);
|
||||
}
|
||||
|
|
|
@ -46,4 +46,26 @@ bool RegexMatch(RegexDialect dialect, const std::string& str,
|
|||
CHECK_UNREACHABLE_("Unexpected regex dialect");
|
||||
}
|
||||
|
||||
std::string RegexReplace(RegexDialect dialect, const std::string& str,
|
||||
const std::string& pattern,
|
||||
const std::string& replacement) {
|
||||
switch (dialect) {
|
||||
case RegexDialect::LLVM: {
|
||||
// llvm::Regex::sub has search semantics. Enclose the pattern in ^...$
|
||||
// for start/end anchoring.
|
||||
llvm::Regex r("^" + pattern + "$");
|
||||
return r.sub(replacement, str);
|
||||
}
|
||||
|
||||
case RegexDialect::ECMAScript: {
|
||||
// std::regex_replace has search semantics. Enclose the pattern in ^...$
|
||||
// for start/end anchoring.
|
||||
std::regex r("^" + pattern + "$", std::regex_constants::ECMAScript);
|
||||
return std::regex_replace(str, r, replacement,
|
||||
std::regex_constants::format_first_only);
|
||||
}
|
||||
}
|
||||
CHECK_UNREACHABLE_("Unexpected regex dialect");
|
||||
}
|
||||
|
||||
} // namespace include_what_you_use
|
||||
|
|
|
@ -23,6 +23,12 @@ bool ParseRegexDialect(const char* str, RegexDialect* dialect);
|
|||
bool RegexMatch(RegexDialect dialect, const std::string& str,
|
||||
const std::string& pattern);
|
||||
|
||||
// Returns input string with the first match of pattern replaced, for the given
|
||||
// regex dialect.
|
||||
std::string RegexReplace(RegexDialect dialect, const std::string& str,
|
||||
const std::string& pattern,
|
||||
const std::string& replacement);
|
||||
|
||||
} // namespace include_what_you_use
|
||||
|
||||
#endif // INCLUDE_WHAT_YOU_USE_IWYU_REGEX_H_
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//===--- mapping_replace_regex_ecmascript.cc - test input file for iwyu ---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// IWYU_ARGS: -I . \
|
||||
// -Xiwyu --regex=ecmascript \
|
||||
// -Xiwyu --mapping_file=tests/cxx/mapping_replace_regex_ecmascript.imp
|
||||
|
||||
// Generically map include paths to a different include directory:
|
||||
// * The include of tests/cxx/direct.h should nominally be replaced by
|
||||
// tests/cxx/indirect.h, where IndirectClass is defined
|
||||
// * But we provide a mapping adding a "foobar" prefix to any include under
|
||||
// "tests/cxx", resulting in suggesting foobar/tests/cxx/indirect.h.
|
||||
|
||||
#include "tests/cxx/direct.h"
|
||||
|
||||
void f() {
|
||||
// IWYU: IndirectClass is defined in "foobar/tests/cxx/indirect.h"
|
||||
IndirectClass i;
|
||||
}
|
||||
|
||||
/**** IWYU_SUMMARY
|
||||
|
||||
tests/cxx/mapping_replace_regex_ecmascript.cc should add these lines:
|
||||
#include "foobar/tests/cxx/indirect.h"
|
||||
|
||||
tests/cxx/mapping_replace_regex_ecmascript.cc should remove these lines:
|
||||
- #include "tests/cxx/direct.h" // lines XX-XX
|
||||
|
||||
The full include-list for tests/cxx/mapping_replace_regex_ecmascript.cc:
|
||||
#include "foobar/tests/cxx/indirect.h" // for IndirectClass
|
||||
|
||||
***** IWYU_SUMMARY */
|
|
@ -0,0 +1,5 @@
|
|||
# Maps headers to a different include path.
|
||||
# The foobar directory does not exist; we just want IWYU to suggest using it.
|
||||
[
|
||||
{ include: ['@"(tests/cxx/.*)"', private, '"foobar/$1"', public ] },
|
||||
]
|
|
@ -0,0 +1,38 @@
|
|||
//===--- mapping_replace_regex_llvm.cc - test input file for iwyu ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// IWYU_ARGS: -I . \
|
||||
// -Xiwyu --regex=llvm \
|
||||
// -Xiwyu --mapping_file=tests/cxx/mapping_replace_regex_llvm.imp
|
||||
|
||||
// Generically map include paths to a different include directory:
|
||||
// * The include of tests/cxx/direct.h should nominally be replaced by
|
||||
// tests/cxx/indirect.h, where IndirectClass is defined
|
||||
// * But we provide a mapping adding a "foobar" prefix to any include under
|
||||
// "tests/cxx", resulting in suggesting foobar/tests/cxx/indirect.h.
|
||||
|
||||
#include "tests/cxx/direct.h"
|
||||
|
||||
void f() {
|
||||
// IWYU: IndirectClass is defined in "foobar/tests/cxx/indirect.h"
|
||||
IndirectClass i;
|
||||
}
|
||||
|
||||
/**** IWYU_SUMMARY
|
||||
|
||||
tests/cxx/mapping_replace_regex_llvm.cc should add these lines:
|
||||
#include "foobar/tests/cxx/indirect.h"
|
||||
|
||||
tests/cxx/mapping_replace_regex_llvm.cc should remove these lines:
|
||||
- #include "tests/cxx/direct.h" // lines XX-XX
|
||||
|
||||
The full include-list for tests/cxx/mapping_replace_regex_llvm.cc:
|
||||
#include "foobar/tests/cxx/indirect.h" // for IndirectClass
|
||||
|
||||
***** IWYU_SUMMARY */
|
|
@ -0,0 +1,5 @@
|
|||
# Maps headers to a different include path.
|
||||
# The foobar directory does not exist; we just want IWYU to suggest using it.
|
||||
[
|
||||
{ include: ['@"(tests/cxx/.*)"', private, '"foobar/\1"', public ] },
|
||||
]
|
Loading…
Reference in New Issue