@@ -135,6 +135,47 @@ static std::filesystem::path normalizePath(const std::filesystem::path path)
135
135
return result;
136
136
}
137
137
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
+
138
179
std::string Config::parseArgs (int argc, char **argv)
139
180
{
140
181
(void ) argc;
@@ -170,12 +211,12 @@ std::string Config::parseArgs(int argc, char **argv)
170
211
return error;
171
212
}
172
213
if (m_configPath.empty ())
173
- m_configPath = findConfig (m_filename);
214
+ m_configPath = findFile (m_filename, " run-cppcheck-config.json " );
174
215
175
216
if (m_configPath.empty ())
176
217
return " Failed to find 'run-cppcheck-config.json' in any parent directory of analyzed file" ;
177
218
178
- const std::string err = load (m_configPath);
219
+ std::string err = load (m_configPath);
179
220
if (!err.empty ())
180
221
return " Failed to load '" + m_configPath.string () + " ': " + err;
181
222
@@ -185,11 +226,17 @@ std::string Config::parseArgs(int argc, char **argv)
185
226
if (m_filename.is_relative ())
186
227
m_filename = normalizePath (std::filesystem::current_path () / m_filename);
187
228
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
+
188
235
return " " ;
189
236
}
190
237
191
238
// 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 )
193
240
{
194
241
auto path = input_path;
195
242
@@ -198,7 +245,7 @@ std::filesystem::path Config::findConfig(const std::filesystem::path &input_path
198
245
199
246
do {
200
247
path = path.parent_path ();
201
- const auto config_path = path / " run-cppcheck-config.json " ;
248
+ const auto config_path = path / filename ;
202
249
203
250
if (std::filesystem::exists (config_path))
204
251
return config_path;
0 commit comments