@@ -135,6 +135,47 @@ static std::filesystem::path normalizePath(const std::filesystem::path path)
135135 return result;
136136}
137137
138+ std::string Config::matchFilenameFromCompileCommand ()
139+ {
140+ if (m_projectFilePath.empty () || m_projectFilePath.extension () != " .json" )
141+ return " " ;
142+
143+ // Read compile_commands file
144+ std::ifstream ifs (m_projectFilePath);
145+ if (ifs.fail ())
146+ return std::strerror (errno);
147+
148+ const std::string text (std::istreambuf_iterator<char >(ifs), {});
149+
150+ // Parse JSON
151+ picojson::value compileCommands;
152+ const std::string err = picojson::parse (compileCommands, text);
153+ if (!err.empty ()) {
154+ return err;
155+ }
156+
157+ if (!compileCommands.is <picojson::array>())
158+ return " Compilation database is not a JSON array" ;
159+
160+ for (const picojson::value &fileInfo : compileCommands.get <picojson::array>()) {
161+ picojson::object obj = fileInfo.get <picojson::object>();
162+
163+ if (obj.count (" file" ) && obj[" file" ].is <std::string>()) {
164+ const std::string file = obj[" file" ].get <std::string>();
165+
166+ // TODO should we warn if the file is not found?
167+ std::error_code err;
168+ if (std::filesystem::equivalent (file, m_filename, err)) {
169+ m_filename = file;
170+ return " " ;
171+ }
172+ }
173+
174+ }
175+
176+ return " " ;
177+ }
178+
138179std::string Config::parseArgs (int argc, char **argv)
139180{
140181 (void ) argc;
@@ -170,12 +211,12 @@ std::string Config::parseArgs(int argc, char **argv)
170211 return error;
171212 }
172213 if (m_configPath.empty ())
173- m_configPath = findConfig (m_filename);
214+ m_configPath = findFile (m_filename, " run-cppcheck-config.json " );
174215
175216 if (m_configPath.empty ())
176217 return " Failed to find 'run-cppcheck-config.json' in any parent directory of analyzed file" ;
177218
178- const std::string err = load (m_configPath);
219+ std::string err = load (m_configPath);
179220 if (!err.empty ())
180221 return " Failed to load '" + m_configPath.string () + " ': " + err;
181222
@@ -185,11 +226,17 @@ std::string Config::parseArgs(int argc, char **argv)
185226 if (m_filename.is_relative ())
186227 m_filename = normalizePath (std::filesystem::current_path () / m_filename);
187228
229+ err = matchFilenameFromCompileCommand ();
230+
231+ // Only warn if compile_commands.json is corrupted
232+ if (!err.empty ())
233+ return " Failed to process compile_commands.json: " + err;
234+
188235 return " " ;
189236}
190237
191238// Find config file by recursively searching parent directories of input file
192- std::filesystem::path Config::findConfig (const std::filesystem::path &input_path)
239+ std::filesystem::path Config::findFile (const std::filesystem::path &input_path, const std::string &filename )
193240{
194241 auto path = input_path;
195242
@@ -198,7 +245,7 @@ std::filesystem::path Config::findConfig(const std::filesystem::path &input_path
198245
199246 do {
200247 path = path.parent_path ();
201- const auto config_path = path / " run-cppcheck-config.json " ;
248+ const auto config_path = path / filename ;
202249
203250 if (std::filesystem::exists (config_path))
204251 return config_path;
0 commit comments