Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ The configuration file is written in json, as **run-cppcheck-config.json**. It i
and `%LOCALAPPDATA%\run-cppcheck` on Windows. The log file may provide more information than the editor plugin if analysis fails.
- **enable_logging**: Default is `true`.
- **extra_args**: Extra arguments to pass to cppcheck. Example: `["--enable=style"]`.

**NOTE:** Some plugins use the `--version` flag to determine the version of cppcheck. For these plugin, you need
to place a run-cppcheck-config.json in the directory where the plugin runs the command, providing the **cppcheck** field.
If this configuration is not found, run-cppcheck tries to find cppcheck in PATH.
106 changes: 70 additions & 36 deletions config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,27 @@ std::string Config::command() const

cmd += "\"" + m_cppcheck + "\"";

for (const auto &arg : m_args) {
// If arg contains double quotes, escape them
std::string escapedArg = arg;
size_t pos = 0;
while ((pos = escapedArg.find("\"", pos)) != std::string::npos) {
escapedArg.replace(pos, 1, "\\\"");
pos += 2;
}
cmd += " \"" + escapedArg + "\"";
if (m_printVersion) {
cmd += " \"--version\"";
} else {
for (const auto &arg : m_args) {
// If arg contains double quotes, escape them
std::string escapedArg = arg;
size_t pos = 0;
while ((pos = escapedArg.find("\"", pos)) != std::string::npos) {
escapedArg.replace(pos, 1, "\\\"");
pos += 2;
}
cmd += " \"" + escapedArg + "\"";

}
}


if (!m_projectFilePath.empty()) {
cmd += " \"--project=" + m_projectFilePath.string() + "\" \"--file-filter=" + m_filename.string() + "\"";
} else {
cmd += " \"" + m_filename.string() + "\"";
if (!m_projectFilePath.empty()) {
cmd += " \"--project=" + m_projectFilePath.string() + "\" \"--file-filter=" + m_filename.string() + "\"";
} else {
cmd += " \"" + m_filename.string() + "\"";
}
}

cmd += " 2>&1";
Expand Down Expand Up @@ -185,6 +189,15 @@ std::string Config::matchFilenameFromCompileCommand()
return "";
}

static bool fileExists(const std::filesystem::path &path)
{
#ifdef _WIN32
return !_access(path.string().c_str(), 0);
#else
return !access(path.string().c_str(), F_OK);
#endif
}

std::string Config::parseArgs(int argc, char **argv)
{
(void) argc;
Expand All @@ -204,6 +217,11 @@ std::string Config::parseArgs(int argc, char **argv)
continue;
}

if (std::string(arg) == "--version") {
m_printVersion = true;
continue;
}

if (arg[0] == '-') {
m_args.push_back(arg);
continue;
Expand All @@ -215,35 +233,51 @@ std::string Config::parseArgs(int argc, char **argv)
m_filename = arg;
}

if (m_filename.empty())
return "Missing filename";
if (!m_printVersion) {
if (m_filename.empty())
return "Missing filename";

if (m_logFilePath.empty()) {
const std::string error = getDefaultLogFilePath(m_logFilePath);
if (!error.empty())
return error;
}
if (m_configPath.empty())
m_configPath = findFile(m_filename, "run-cppcheck-config.json");
if (m_logFilePath.empty()) {
const std::string error = getDefaultLogFilePath(m_logFilePath);
if (!error.empty())
return error;
}

if (m_configPath.empty())
return "Failed to find 'run-cppcheck-config.json' in any parent directory of analyzed file";
if (m_configPath.empty())
m_configPath = findFile(m_filename, "run-cppcheck-config.json");

std::string err = load(m_configPath);
if (!err.empty())
return "Failed to load '" + m_configPath.string() + "': " + err;
if (m_configPath.empty())
return "Failed to find 'run-cppcheck-config.json' in any parent directory of analyzed file";

if (!m_projectFilePath.empty() && m_projectFilePath.is_relative())
m_projectFilePath = m_configPath.parent_path() / m_projectFilePath;
std::string err = load(m_configPath);
if (!err.empty())
return "Failed to load '" + m_configPath.string() + "': " + err;

if (m_filename.is_relative())
m_filename = normalizePath(std::filesystem::current_path() / m_filename);
if (!m_projectFilePath.empty() && m_projectFilePath.is_relative())
m_projectFilePath = m_configPath.parent_path() / m_projectFilePath;

err = matchFilenameFromCompileCommand();
if (m_filename.is_relative())
m_filename = normalizePath(std::filesystem::current_path() / m_filename);

// Only warn if compile_commands.json is corrupted
if (!err.empty())
return "Failed to process compile_commands.json: " + err;
err = matchFilenameFromCompileCommand();

// Only warn if compile_commands.json is corrupted
if (!err.empty())
return "Failed to process compile_commands.json: " + err;
} else {

// If --version is used there is no input file, so check for config
// in current working directory
if (m_configPath.empty())
m_configPath = std::filesystem::current_path() / "run-cppcheck-config.json";

if (!fileExists(m_configPath))
return "";

std::string err = load(m_configPath);
if (!err.empty())
return "Failed to load '" + m_configPath.string() + "': " + err;
}

return "";
}
Expand Down
7 changes: 7 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Config {
, m_cppcheck("cppcheck")
, m_filename("")
, m_args({})
, m_printVersion(false)
{
}

Expand All @@ -41,6 +42,11 @@ class Config {
return m_configPath;
}

bool printVersion() const
{
return m_printVersion;
}

private:
static std::filesystem::path findFile(const std::filesystem::path &input_path, const std::string &filename);
static std::string getDefaultLogFilePath(std::filesystem::path &path);
Expand All @@ -53,6 +59,7 @@ class Config {
std::string m_cppcheck;
std::filesystem::path m_filename;
std::vector<std::string> m_args;
bool m_printVersion;
};

#endif
5 changes: 4 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ int main(int argc, char** argv) {
std::string output;
int res = executeCommand(cmd, output);

std::cerr << output;
if (config.printVersion())
std::cout << output;
else
std::cerr << output;
logfile << output;

return res;
Expand Down