Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion .github/workflows/selfcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:

- name: Self check (unusedFunction / no test / no gui)
run: |
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1531 --suppress=unusedFunction:lib/importproject.cpp:1555"
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1584 --suppress=unusedFunction:lib/importproject.cpp:1608"
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
env:
DISABLE_VALUEFLOW: 1
Expand Down
16 changes: 11 additions & 5 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
}
if (projectType == ImportProject::Type::COMPILE_DB)
mSettings.maxConfigsProject = 1;
if (projectType == ImportProject::Type::VS_SLN || projectType == ImportProject::Type::VS_VCXPROJ) {
if (projectType == ImportProject::Type::VS_SLN ||
projectType == ImportProject::Type::VS_SLNX ||
projectType == ImportProject::Type::VS_VCXPROJ) {
mSettings.libraries.emplace_back("windows");
}
for (const auto &error : project.errors)
Expand All @@ -1214,7 +1216,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
mLogger.printError("--project-configuration parameter is empty.");
return Result::Fail;
}
if (projectType != ImportProject::Type::VS_SLN && projectType != ImportProject::Type::VS_VCXPROJ) {
if (projectType != ImportProject::Type::VS_SLN &&
projectType != ImportProject::Type::VS_SLNX &&
projectType != ImportProject::Type::VS_VCXPROJ) {
mLogger.printError("--project-configuration has no effect - no Visual Studio project provided.");
return Result::Fail;
}
Expand Down Expand Up @@ -1649,7 +1653,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
mSettings.platform.defaultSign = defaultSign;

if (!mSettings.analyzeAllVsConfigs) {
if (projectType != ImportProject::Type::VS_SLN && projectType != ImportProject::Type::VS_VCXPROJ) {
if (projectType != ImportProject::Type::VS_SLN &&
projectType != ImportProject::Type::VS_SLNX &&
projectType != ImportProject::Type::VS_VCXPROJ) {
if (mAnalyzeAllVsConfigsSetOnCmdLine) {
mLogger.printError("--no-analyze-all-vs-configs has no effect - no Visual Studio project provided.");
return Result::Fail;
Expand Down Expand Up @@ -1935,13 +1941,13 @@ void CmdLineParser::printHelp() const

oss <<
" --project=<file> Run Cppcheck on project. The <file> can be a Visual\n"
" Studio Solution (*.sln), Visual Studio Project\n"
" Studio Solution (*.sln) or (*.slnx), Visual Studio Project\n"
" (*.vcxproj), compile database (compile_commands.json),\n"
" or Borland C++ Builder 6 (*.bpr). The files to analyse,\n"
" include paths, defines, platform and undefines in\n"
" the specified file will be used.\n"
" --project-configuration=<config>\n"
" If used together with a Visual Studio Solution (*.sln)\n"
" If used together with a Visual Studio Solution (*.sln) or (*.slnx)\n"
" or Visual Studio Project (*.vcxproj) you can limit\n"
" the configuration cppcheck should check.\n"
" For example: '--project-configuration=Release|Win32'\n"
Expand Down
6 changes: 4 additions & 2 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ QStringList MainWindow::selectFilesToAnalyze(QFileDialog::FileMode mode)
QMap<QString,QString> filters;
filters[tr("C/C++ Source")] = FileList::getDefaultFilters().join(" ");
filters[tr("Compile database")] = compile_commands_json;
filters[tr("Visual Studio")] = "*.sln *.vcxproj";
filters[tr("Visual Studio")] = "*.sln *.slnx *.vcxproj";
filters[tr("Borland C++ Builder 6")] = "*.bpr";
QString lastFilter = mSettings->value(SETTINGS_LAST_ANALYZE_FILES_FILTER).toString();
selected = QFileDialog::getOpenFileNames(this,
Expand Down Expand Up @@ -811,13 +811,14 @@ void MainWindow::analyzeFiles()

const QString file0 = (!selected.empty() ? selected[0].toLower() : QString());
if (file0.endsWith(".sln")
|| file0.endsWith(".slnx")
|| file0.endsWith(".vcxproj")
|| file0.endsWith(compile_commands_json)
|| file0.endsWith(".bpr")) {
ImportProject p;
p.import(selected[0].toStdString());

if (file0.endsWith(".sln")) {
if (file0.endsWith(".sln") || file0.endsWith(".slnx")) {
QStringList configs;
for (auto it = p.fileSettings.cbegin(); it != p.fileSettings.cend(); ++it) {
const QString cfg(QString::fromStdString(it->cfg));
Expand Down Expand Up @@ -1968,6 +1969,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const QStringLis
switch (result) {
case ImportProject::Type::COMPILE_DB:
case ImportProject::Type::VS_SLN:
case ImportProject::Type::VS_SLNX:
case ImportProject::Type::VS_VCXPROJ:
case ImportProject::Type::BORLAND:
case ImportProject::Type::CPPCHECK_GUI:
Expand Down
6 changes: 3 additions & 3 deletions gui/projectfiledialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static std::string suppressionAsText(const SuppressionList::Suppression& s)

QStringList ProjectFileDialog::getProjectConfigs(const QString &fileName)
{
if (!fileName.endsWith(".sln") && !fileName.endsWith(".vcxproj"))
if (!fileName.endsWith(".sln") && !fileName.endsWith(".slnx") && !fileName.endsWith(".vcxproj"))
return QStringList();
QStringList ret;
ImportProject importer;
Expand Down Expand Up @@ -596,7 +596,7 @@ void ProjectFileDialog::updatePathsAndDefines()
{
const QString &fileName = mUI->mEditImportProject->text();
const bool importProject = !fileName.isEmpty();
const bool hasConfigs = fileName.endsWith(".sln") || fileName.endsWith(".vcxproj");
const bool hasConfigs = fileName.endsWith(".sln") || fileName.endsWith(".slnx") || fileName.endsWith(".vcxproj");
mUI->mBtnClearImportProject->setEnabled(importProject);
mUI->mListCheckPaths->setEnabled(!importProject);
mUI->mListIncludeDirs->setEnabled(!importProject);
Expand Down Expand Up @@ -626,7 +626,7 @@ void ProjectFileDialog::browseImportProject()
const QFileInfo inf(mProjectFile->getFilename());
const QDir &dir = inf.absoluteDir();
QMap<QString,QString> filters;
filters[tr("Visual Studio")] = "*.sln *.vcxproj";
filters[tr("Visual Studio")] = "*.sln *.slnx *.vcxproj";
filters[tr("Compile database")] = "compile_commands.json";
filters[tr("Borland C++ Builder 6")] = "*.bpr";
QString fileName = QFileDialog::getOpenFileName(this, tr("Import Project"),
Expand Down
53 changes: 53 additions & 0 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
setRelativePaths(filename);
return ImportProject::Type::VS_SLN;
}
} else if (endsWith(filename, ".slnx")) {
if (importSlnx(filename, fileFilters)) {
setRelativePaths(filename);
return ImportProject::Type::VS_SLNX;
}
} else if (endsWith(filename, ".vcxproj")) {
std::map<std::string, std::string, cppcheck::stricmp> variables;
std::vector<SharedItemsProject> sharedItemsProjects;
Expand Down Expand Up @@ -503,6 +508,54 @@ bool ImportProject::importSln(std::istream &istr, const std::string &path, const
return true;
}

bool ImportProject::importSlnx(const std::string& filename, const std::vector<std::string>& fileFilters)
{
tinyxml2::XMLDocument doc;
const tinyxml2::XMLError error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_SUCCESS) {
errors.emplace_back(std::string("Visual Studio project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(error));
return false;
}

const tinyxml2::XMLElement* const rootnode = doc.FirstChildElement();
if (rootnode == nullptr) {
errors.emplace_back("Visual Studio project file has no XML root node");
return false;
}

std::map<std::string, std::string, cppcheck::stricmp> variables;
variables["SolutionDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));

bool found = false;
std::vector<SharedItemsProject> sharedItemsProjects;

for (const tinyxml2::XMLElement* node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
const char* name = node->Name();
if (std::strcmp(name, "Project") == 0) {
const char* labelAttribute = node->Attribute("Path");
if (labelAttribute) {
std::string vcxproj(labelAttribute);
vcxproj = Path::toNativeSeparators(std::move(vcxproj));
if (!Path::isAbsolute(vcxproj))
vcxproj = variables["SolutionDir"] + vcxproj;
vcxproj = Path::fromNativeSeparators(std::move(vcxproj));
if (!importVcxproj(vcxproj, variables, "", fileFilters, sharedItemsProjects)) {
errors.emplace_back("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
}
found = true;
}
}
}

if (!found) {
errors.emplace_back("no projects found in Visual Studio solution file");
return false;
}

return true;
}

namespace {
struct ProjectConfiguration {
explicit ProjectConfiguration(const tinyxml2::XMLElement *cfg) {
Expand Down
2 changes: 2 additions & 0 deletions lib/importproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
FAILURE,
COMPILE_DB,
VS_SLN,
VS_SLNX,
VS_VCXPROJ,
BORLAND,
CPPCHECK_GUI
Expand Down Expand Up @@ -120,6 +121,7 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
void setRelativePaths(const std::string &filename);

bool importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
bool importSlnx(const std::string& filename, const std::vector<std::string>& fileFilters);
SharedItemsProject importVcxitems(const std::string &filename, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache);
bool importBcb6Prj(const std::string &projectFilename);

Expand Down
6 changes: 5 additions & 1 deletion man/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,16 @@ To ignore certain folders you can use `-i`. This will skip analysis of source fi

## Visual Studio

You can run Cppcheck on individual project files (\*.vcxproj) or on a whole solution (\*.sln)
You can run Cppcheck on individual project files (\*.vcxproj) or on a whole solution (\*.sln) or (\*.slnx)

Running Cppcheck on an entire Visual Studio solution:

cppcheck --project=foobar.sln

Running Cppcheck on an entire Visual Studio 2026 solution:

cppcheck --project=foobar.slnx

Running Cppcheck on a Visual Studio project:

cppcheck --project=foobar.vcxproj
Expand Down
Loading