Enhanced search paths of mapping files. Patch by Kim Gräsman.
Search for mapping files: - in the current working directory; - in the directory where IWYU executable is located; - in the directory where another discovered mapping file is located.
This commit is contained in:
parent
5e6ee85bf7
commit
40999861b2
14
iwyu.cc
14
iwyu.cc
|
@ -3644,12 +3644,19 @@ class IwyuAstConsumer
|
|||
|
||||
// We use an ASTFrontendAction to hook up IWYU with Clang.
|
||||
class IwyuAction : public ASTFrontendAction {
|
||||
public:
|
||||
IwyuAction(const char* executable_path)
|
||||
: executable_path_(executable_path)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ASTConsumer* CreateASTConsumer(CompilerInstance& compiler, // NOLINT
|
||||
llvm::StringRef /* dummy */) {
|
||||
// Do this first thing after getting our hands on a CompilerInstance.
|
||||
InitGlobals(&compiler.getSourceManager(),
|
||||
&compiler.getPreprocessor().getHeaderSearchInfo());
|
||||
&compiler.getPreprocessor().getHeaderSearchInfo(),
|
||||
executable_path_);
|
||||
|
||||
IwyuPreprocessorInfo* const preprocessor_consumer
|
||||
= new IwyuPreprocessorInfo();
|
||||
|
@ -3662,6 +3669,9 @@ class IwyuAction : public ASTFrontendAction {
|
|||
compiler.getPreprocessor().addCommentHandler(preprocessor_consumer);
|
||||
return ast_consumer;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string executable_path_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3704,7 +3714,7 @@ int main(int argc, char **argv) {
|
|||
CHECK_(compiler && "Failed to process argv");
|
||||
|
||||
// Create and execute the frontend to generate an LLVM bitcode module.
|
||||
llvm::OwningPtr<clang::ASTFrontendAction> action(new IwyuAction);
|
||||
llvm::OwningPtr<clang::ASTFrontendAction> action(new IwyuAction(clang_argv[0]));
|
||||
if (!compiler->ExecuteAction(*action))
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ static SourceManagerCharacterDataGetter* data_getter = NULL;
|
|||
static FullUseCache* function_calls_full_use_cache = NULL;
|
||||
static FullUseCache* class_members_full_use_cache = NULL;
|
||||
|
||||
|
||||
static void PrintHelp(const char* extra_msg) {
|
||||
printf("USAGE: iwyu [-Xiwyu --iwyu_opt]... <clang opts> <source file>\n"
|
||||
"Here are the <opts> you can specify:\n"
|
||||
|
@ -182,7 +181,9 @@ static vector<HeaderSearchPath> ComputeHeaderSearchPaths(
|
|||
return NormalizeHeaderSearchPaths(search_path_map);
|
||||
}
|
||||
|
||||
void InitGlobals(clang::SourceManager* sm, clang::HeaderSearch* header_search) {
|
||||
void InitGlobals(clang::SourceManager* sm,
|
||||
clang::HeaderSearch* header_search,
|
||||
const std::string& executable_path) {
|
||||
CHECK_(sm && "InitGlobals() needs a non-NULL SourceManager");
|
||||
source_manager = sm;
|
||||
data_getter = new SourceManagerCharacterDataGetter(*source_manager);
|
||||
|
@ -199,6 +200,11 @@ void InitGlobals(clang::SourceManager* sm, clang::HeaderSearch* header_search) {
|
|||
VERRS(6) << "Search path: " << it->path << " (" << path_type_name << ")\n";
|
||||
}
|
||||
|
||||
// Set up mapping file search paths.
|
||||
include_picker->AddMappingFileSearchPath(".");
|
||||
include_picker->AddMappingFileSearchPath(GetParentPath(executable_path));
|
||||
|
||||
// Add mappings.
|
||||
for (Each<string> it(&GlobalFlags().mapping_files); !it.AtEnd(); ++it) {
|
||||
include_picker->AddMappingsFromFile(*it);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ class SourceManagerCharacterDataGetter;
|
|||
int ParseIwyuCommandlineFlags(int argc, char** argv);
|
||||
|
||||
void InitGlobals(clang::SourceManager* source_manager,
|
||||
clang::HeaderSearch* header_search);
|
||||
clang::HeaderSearch* header_search,
|
||||
const std::string& executable_path);
|
||||
|
||||
// Can be called by tests -- doesn't need a SourceManager or
|
||||
// argc/argv. Note that GlobalSourceManager() and DefaultDataGetter()
|
||||
|
|
|
@ -26,10 +26,9 @@
|
|||
#include "iwyu_verrs.h"
|
||||
#include "port.h" // for CHECK_
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
|
@ -279,6 +278,16 @@ void IncludePicker::AddDirectInclude(const string& includer_filepath,
|
|||
}
|
||||
}
|
||||
|
||||
void IncludePicker::AddMappingFileSearchPath(const string& path) {
|
||||
string absolute_path = MakeAbsolutePath(path);
|
||||
if (std::find(mapping_file_search_path_.begin(),
|
||||
mapping_file_search_path_.end(),
|
||||
absolute_path) == mapping_file_search_path_.end()) {
|
||||
VERRS(6) << "Adding mapping file search path: " << absolute_path << "\n";
|
||||
mapping_file_search_path_.push_back(absolute_path);
|
||||
}
|
||||
}
|
||||
|
||||
void IncludePicker::AddMapping(const string& map_from, const string& map_to) {
|
||||
VERRS(4) << "Adding mapping from " << map_from << " to " << map_to << "\n";
|
||||
CHECK_(!has_called_finalize_added_include_lines_ && "Can't mutate anymore");
|
||||
|
@ -493,6 +502,33 @@ string IncludePicker::MaybeGetIncludeNameAsWritten(
|
|||
return value ? *value : "";
|
||||
}
|
||||
|
||||
error_code IncludePicker::TryReadMappingFile(
|
||||
const string& filename,
|
||||
OwningPtr<MemoryBuffer>& buffer) const {
|
||||
string absolute_path;
|
||||
if (IsAbsolutePath(filename)) {
|
||||
VERRS(5) << "Absolute mapping filename: " << filename << ".\n";
|
||||
absolute_path = filename;
|
||||
} else {
|
||||
VERRS(5) << "Relative mapping filename: " << filename << ". "
|
||||
<< "Scanning search path.\n";
|
||||
// Scan search path
|
||||
for (Each<string> it(&mapping_file_search_path_); !it.AtEnd(); ++it) {
|
||||
string candidate = MakeAbsolutePath(*it, filename);
|
||||
if (llvm::sys::fs::exists(candidate)) {
|
||||
absolute_path = candidate;
|
||||
VERRS(5) << "Found mapping file: " << candidate << ".\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error_code error = MemoryBuffer::getFile(absolute_path, buffer);
|
||||
VERRS(5) << "Opened mapping file: " << filename << "? "
|
||||
<< error.message() << "\n";
|
||||
return error;
|
||||
}
|
||||
|
||||
vector<string> IncludePicker::GetCandidateHeadersForSymbol(
|
||||
const string& symbol) const {
|
||||
CHECK_(has_called_finalize_added_include_lines_ && "Must finalize includes");
|
||||
|
@ -579,13 +615,11 @@ bool IncludePicker::HasMapping(const string& map_from_filepath,
|
|||
// We use this to maintain mappings externally, to make it easier
|
||||
// to update/adjust to local circumstances.
|
||||
void IncludePicker::AddMappingsFromFile(const string& filename) {
|
||||
// TODO(kimgr): Resolve absolute mapping path along some search path
|
||||
// e.g. look also next to IWYU binary.
|
||||
OwningPtr<MemoryBuffer> buffer;
|
||||
llvm::error_code result = MemoryBuffer::getFile(filename, buffer);
|
||||
if (result != 0) {
|
||||
error_code error = TryReadMappingFile(filename, buffer);
|
||||
if (error) {
|
||||
errs() << "Cannot open mapping file '" << filename << "': "
|
||||
<< result.message() << ".\n";
|
||||
<< error.message() << ".\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -680,7 +714,7 @@ void IncludePicker::AddMappingsFromFile(const string& filename) {
|
|||
mapping[2],
|
||||
to_visibility);
|
||||
} else if (directive == "ref") {
|
||||
// Mapping ref, recurse.
|
||||
// Mapping ref.
|
||||
string ref_file = GetScalarValue(it->getValue());
|
||||
if (ref_file.empty()) {
|
||||
errs() << MappingDiag(source_manager, filename, current_node,
|
||||
|
@ -688,6 +722,11 @@ void IncludePicker::AddMappingsFromFile(const string& filename) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Add the path of the file we're currently processing
|
||||
// to the search path. Allows refs to be relative to referrer.
|
||||
AddMappingFileSearchPath(GetParentPath(filename));
|
||||
|
||||
// Recurse.
|
||||
AddMappingsFromFile(ref_file);
|
||||
} else {
|
||||
errs() << MappingDiag(source_manager, filename, current_node,
|
||||
|
|
|
@ -50,6 +50,13 @@
|
|||
#include <utility> // for pair
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
class error_code;
|
||||
}
|
||||
|
||||
namespace include_what_you_use {
|
||||
|
||||
using std::map;
|
||||
|
@ -59,6 +66,10 @@ using std::string;
|
|||
|
||||
using std::vector;
|
||||
|
||||
using llvm::OwningPtr;
|
||||
using llvm::MemoryBuffer;
|
||||
using llvm::error_code;
|
||||
|
||||
class IncludePicker {
|
||||
public:
|
||||
enum Visibility { kUnusedVisibility, kPublic, kPrivate };
|
||||
|
@ -76,6 +87,9 @@ class IncludePicker {
|
|||
const string& includee_filepath,
|
||||
const string& quoted_include_as_written);
|
||||
|
||||
// Add a mapping file search path.
|
||||
void AddMappingFileSearchPath(const string& path);
|
||||
|
||||
// Add this to say "map_to re-exports everything in file map_from".
|
||||
// Both map_to and map_from should be quoted includes.
|
||||
void AddMapping(const string& map_from, const string& map_to);
|
||||
|
@ -182,6 +196,11 @@ class IncludePicker {
|
|||
string MaybeGetIncludeNameAsWritten(const string& includer_filepath,
|
||||
const string& includee_filepath) const;
|
||||
|
||||
// Scan the search paths for filename. If it exists, put file contents
|
||||
// in buffer. If not, return the error code.
|
||||
error_code TryReadMappingFile(const string& filename,
|
||||
OwningPtr<MemoryBuffer>& buffer) const;
|
||||
|
||||
// From symbols to includes.
|
||||
IncludeMap symbol_include_map_;
|
||||
|
||||
|
@ -217,6 +236,8 @@ class IncludePicker {
|
|||
// contents of friend_to_headers_map_["@\"foo/bar/.*\""].
|
||||
map<string, set<string> > friend_to_headers_map_;
|
||||
|
||||
vector<string> mapping_file_search_path_;
|
||||
|
||||
// Make sure we don't do any non-const operations after finalizing.
|
||||
bool has_called_finalize_added_include_lines_;
|
||||
}; // class IncludePicker
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
|
||||
#include "iwyu_stl_util.h"
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/PathV2.h"
|
||||
#include "llvm/Support/system_error.h"
|
||||
|
||||
namespace include_what_you_use {
|
||||
|
||||
namespace {
|
||||
|
@ -123,6 +129,30 @@ string NormalizeFilePath(const string& path) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool IsAbsolutePath(const string& path) {
|
||||
return llvm::sys::path::is_absolute(path);
|
||||
}
|
||||
|
||||
string MakeAbsolutePath(const string& path) {
|
||||
llvm::SmallString<128> absolute_path(path.c_str());
|
||||
llvm::error_code error = llvm::sys::fs::make_absolute(absolute_path);
|
||||
CHECK_(!error);
|
||||
|
||||
return absolute_path.str();
|
||||
}
|
||||
|
||||
string MakeAbsolutePath(const string& base_path, const string& relative_path) {
|
||||
llvm::SmallString<128> absolute_path(base_path.c_str());
|
||||
llvm::sys::path::append(absolute_path, relative_path);
|
||||
|
||||
return absolute_path.str();
|
||||
}
|
||||
|
||||
string GetParentPath(const string& path) {
|
||||
llvm::StringRef parent = llvm::sys::path::parent_path(path);
|
||||
return parent.str();
|
||||
}
|
||||
|
||||
// Converts a file-path, such as /usr/include/stdio.h, to a
|
||||
// quoted include, such as <stdio.h>.
|
||||
string ConvertToQuotedInclude(const string& filepath) {
|
||||
|
|
|
@ -62,11 +62,20 @@ string CanonicalizeFilePath(const string& path);
|
|||
// platforms.
|
||||
string GetCanonicalName(string file_path);
|
||||
|
||||
|
||||
// "Canonicals" the name on Microsoft platforms, then recursively
|
||||
// removes all "./" prefixes.
|
||||
string NormalizeFilePath(const string& path);
|
||||
|
||||
// Is path absolute?
|
||||
bool IsAbsolutePath(const string& path);
|
||||
|
||||
// Get absolute version of path.
|
||||
string MakeAbsolutePath(const string& path);
|
||||
string MakeAbsolutePath(const string& base_path, const string& relative_path);
|
||||
|
||||
// Get the parent of path.
|
||||
string GetParentPath(const string& path);
|
||||
|
||||
// Below, we talk 'quoted' includes. A quoted include is something
|
||||
// that would be written on an #include line, complete with the <> or
|
||||
// "". In the line '#include <time.h>', "<time.h>" is the quoted
|
||||
|
|
Loading…
Reference in New Issue