Hiralo created this revision. Hiralo added reviewers: alexfh, njames93, hokein, DmitryPolukhin. Hiralo added a project: clang-tools-extra. Herald added a project: clang. Herald added a subscriber: cfe-commits. Hiralo requested review of this revision.
commit 5c98467825b128aabd04a770ac26905d856a3757 Author: Hiral Oza <hiral....@netapp.com> Date: Wed Oct 21 23:30:22 2020 -0700 clang-tidy: adding "--clang-tidy-config=<file-path>" to specify custom config file. Let clang-tidy to read config from specified file. Example: $ clang-tidy --clang-tidy-config=/some/path/myTidyConfig --list-checks -- ...this will read config from '/some/path/myTidyConfig'. May speed-up tidy runtime since now it will just look-up <file-path> instead of searching ".clang-tidy" in parent-dir(s). Directly specifying config path helps setting build dependencies. Thank you in advance for your kind review. -Hiral Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D89936 Files: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp clang-tools-extra/clang-tidy/ClangTidyOptions.h clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -73,6 +73,13 @@ )"), cl::init(""), cl::cat(ClangTidyCategory)); +static cl::opt<std::string> ClangTidyConfig("clang-tidy-config", cl::desc(R"( +Specify full path of .clang-tidy config file. +For example, --clang-tidy-config=/some/path/myTidyConfig +)"), + cl::init(""), + cl::cat(ClangTidyCategory)); + static cl::opt<std::string> WarningsAsErrors("warnings-as-errors", cl::desc(R"( Upgrades warnings to errors. Same format as '-checks'. @@ -279,6 +286,7 @@ ClangTidyOptions DefaultOptions; DefaultOptions.Checks = DefaultChecks; + DefaultOptions.ClangTidyConfig = ""; DefaultOptions.WarningsAsErrors = ""; DefaultOptions.HeaderFilterRegex = HeaderFilter; DefaultOptions.SystemHeaders = SystemHeaders; @@ -291,6 +299,8 @@ ClangTidyOptions OverrideOptions; if (Checks.getNumOccurrences() > 0) OverrideOptions.Checks = Checks; + if (ClangTidyConfig.getNumOccurrences() > 0) + OverrideOptions.ClangTidyConfig = ClangTidyConfig; if (WarningsAsErrors.getNumOccurrences() > 0) OverrideOptions.WarningsAsErrors = WarningsAsErrors; if (HeaderFilter.getNumOccurrences() > 0) Index: clang-tools-extra/clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -64,6 +64,9 @@ /// Checks filter. llvm::Optional<std::string> Checks; + /// Clang-tidy-config + llvm::Optional<std::string> ClangTidyConfig; + /// WarningsAsErrors filter. llvm::Optional<std::string> WarningsAsErrors; @@ -227,6 +230,8 @@ /// Try to read configuration files from \p Directory using registered /// \c ConfigHandlers. llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Directory); + llvm::Optional<OptionsSource> tryReadConfigFile(llvm::StringRef Path, + bool IsFile); llvm::StringMap<OptionsSource> CachedOptions; ClangTidyOptions OverrideOptions; Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -109,6 +109,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() { ClangTidyOptions Options; Options.Checks = ""; + Options.ClangTidyConfig = ""; Options.WarningsAsErrors = ""; Options.HeaderFilterRegex = ""; Options.SystemHeaders = false; @@ -306,7 +307,41 @@ << "...\n"); assert(FS && "FS must be set."); - llvm::SmallString<128> AbsoluteFilePath(FileName); + llvm::SmallString<1024> AbsoluteFilePath(FileName); + if (!OverrideOptions.ClangTidyConfig.getValue().empty()) { + AbsoluteFilePath.assign(OverrideOptions.ClangTidyConfig.getValue()); + if (FS->makeAbsolute(AbsoluteFilePath)) { + std::string Msg; + llvm::raw_string_ostream ErrStream(Msg); + ErrStream << " reading configuration from <" << AbsoluteFilePath + << "> can't make absolute path.\n"; + llvm::report_fatal_error(ErrStream.str()); + } + bool IsFile = false; + bool IsLink = false; + llvm::sys::fs::is_regular_file(Twine(AbsoluteFilePath), IsFile); + llvm::sys::fs::is_symlink_file(Twine(AbsoluteFilePath), IsLink); + if (!(IsFile || IsLink)) { + std::string Msg; + llvm::raw_string_ostream ErrStream(Msg); + ErrStream << " reading configuration from <" << AbsoluteFilePath + << "> file doesn't exist or not regular/symlink file.\n"; + llvm::report_fatal_error(ErrStream.str()); + } + + std::vector<OptionsSource> RawOptions = + DefaultOptionsProvider::getRawOptions(AbsoluteFilePath.str()); + OptionsSource CommandLineOptions(OverrideOptions, + OptionsSourceTypeCheckCommandLineOption); + + llvm::Optional<OptionsSource> Result; + Result = tryReadConfigFile(AbsoluteFilePath, true); + if (Result) { + RawOptions.push_back(*Result); + } + RawOptions.push_back(CommandLineOptions); + return RawOptions; + } if (FS->makeAbsolute(AbsoluteFilePath)) return {}; @@ -368,6 +403,47 @@ return llvm::None; } +llvm::Optional<OptionsSource> +FileOptionsProvider::tryReadConfigFile(StringRef Path, bool IsFile) { + // llvm::outs() << "tryReadConfigFile IsFile<" << + // OverrideOptions.ClangTidyConfig << ">\n"; + assert(!Path.empty()); + + if (!IsFile) { + tryReadConfigFile(Path); + } + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + llvm::MemoryBuffer::getFile(Path); + if (std::error_code EC = Text.getError()) { + std::string Msg; + llvm::raw_string_ostream ErrStream(Msg); + ErrStream << " Can't read <" << Path << ">: " << EC.message() << "\n"; + llvm::report_fatal_error(ErrStream.str()); + } + + // Skip empty files, e.g. files opened for writing via shell output + // redirection. + if ((*Text)->getBuffer().empty()) { + std::string Msg; + llvm::raw_string_ostream ErrStream(Msg); + ErrStream << " empty configuration file <" << Path << ">.\n"; + llvm::report_fatal_error(ErrStream.str()); + } + llvm::ErrorOr<ClangTidyOptions> ParsedOptions = + parseConfiguration((*Text)->getBuffer()); + if (!ParsedOptions) { + if (ParsedOptions.getError()) { + std::string Msg; + llvm::raw_string_ostream ErrStream(Msg); + ErrStream << " parsing <" << Path + << ">: " << ParsedOptions.getError().message() << "\n"; + llvm::report_fatal_error(ErrStream.str()); + } + } + return OptionsSource(*ParsedOptions, Path); +} + /// Parses -line-filter option and stores it to the \c Options. std::error_code parseLineFilter(StringRef LineFilter, clang::tidy::ClangTidyGlobalOptions &Options) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits