diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 79b7e0ae4f7..7bda11b3e9b 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -276,7 +276,7 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) // TODO: verbose log which files were ignored? const PathMatch matcher(ignored, caseSensitive); for (const std::string &pathname : pathnamesRef) { - const std::string err = FileLister::recursiveAddFiles(filesResolved, Path::toNativeSeparators(pathname), mSettings.library.markupExtensions(), matcher); + const std::string err = FileLister::recursiveAddFiles(filesResolved, Path::toNativeSeparators(pathname), mSettings.library.markupExtensions(), matcher, mSettings.debugignore); if (!err.empty()) { // TODO: bail out? mLogger.printMessage(err); @@ -619,6 +619,10 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "--debug-clang-output") == 0) mSettings.debugClangOutput = true; + // Show debug messages for ignored files + else if (std::strcmp(argv[i], "--debug-ignore") == 0) + mSettings.debugignore = true; + // Show --debug output after the first simplifications else if (std::strcmp(argv[i], "--debug") == 0 || std::strcmp(argv[i], "--debug-normal") == 0) @@ -823,13 +827,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (!path.empty()) { path = Path::removeQuotationMarks(std::move(path)); path = Path::simplifyPath(std::move(path)); - - // TODO: this only works when it exists - if (Path::isDirectory(path)) { - // If directory name doesn't end with / or \, add it - if (!endsWith(path, '/')) - path += '/'; - } mIgnoredPaths.emplace_back(std::move(path)); } } @@ -1590,11 +1587,24 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; } + for (auto& path : mIgnoredPaths) + { + bool isdir = false; + if (!Path::exists(path, &isdir) && mSettings.debugignore) + std::cout << "path to ignore does not exist: " << path << std::endl; + // TODO: this only works when it exists + if (isdir) { + // If directory name doesn't end with / or \, add it + if (!endsWith(path, '/')) + path += '/'; + } + } + if (!project.guiProject.pathNames.empty()) mPathNames = project.guiProject.pathNames; if (!project.fileSettings.empty()) { - project.ignorePaths(mIgnoredPaths); + project.ignorePaths(mIgnoredPaths, mSettings.debugignore); if (project.fileSettings.empty()) { mLogger.printError("no C or C++ source files found."); mLogger.printMessage("all paths were ignored"); // TODO: log this differently? diff --git a/cli/filelister.cpp b/cli/filelister.cpp index f1b6d97feda..30392ef4b22 100644 --- a/cli/filelister.cpp +++ b/cli/filelister.cpp @@ -29,6 +29,7 @@ #include "utils.h" #include +#include #include #include @@ -45,7 +46,7 @@ // When compiling Unicode targets WinAPI automatically uses *W Unicode versions // of called functions. Thus, we explicitly call *A versions of the functions. -static std::string addFiles2(std::list&files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored) +static std::string addFiles2(std::list&files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored, bool debug = false) { const std::string cleanedPath = Path::toNativeSeparators(path); @@ -85,8 +86,9 @@ static std::string addFiles2(std::list&files, const std::string HANDLE hFind = FindFirstFileA(searchPattern.c_str(), &ffd); if (INVALID_HANDLE_VALUE == hFind) { const DWORD err = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND) { - // no files matched + if (err == ERROR_FILE_NOT_FOUND || // the pattern did not match anything + err == ERROR_PATH_NOT_FOUND) // the given search path does not exist + { return ""; } return "finding files failed. Search pattern: '" + searchPattern + "'. (error: " + std::to_string(err) + ")"; @@ -106,22 +108,30 @@ static std::string addFiles2(std::list&files, const std::string if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { // File Standards::Language lang = Standards::Language::None; - if ((!checkAllFilesInDir || Path::acceptFile(fname, extra, &lang)) && !ignored.match(fname)) { - std::string nativename = Path::fromNativeSeparators(fname); + if ((!checkAllFilesInDir || Path::acceptFile(fname, extra, &lang))) { + if (!ignored.match(fname)) { + std::string nativename = Path::fromNativeSeparators(fname); - // Limitation: file sizes are assumed to fit in a 'size_t' + // Limitation: file sizes are assumed to fit in a 'size_t' #ifdef _WIN64 - const std::size_t filesize = (static_cast(ffd.nFileSizeHigh) << 32) | ffd.nFileSizeLow; + const std::size_t filesize = (static_cast(ffd.nFileSizeHigh) << 32) | ffd.nFileSizeLow; #else - const std::size_t filesize = ffd.nFileSizeLow; + const std::size_t filesize = ffd.nFileSizeLow; #endif - files.emplace_back(std::move(nativename), lang, filesize); + files.emplace_back(std::move(nativename), lang, filesize); + } + else if (debug) + { + std::cout << "ignored path: " << fname << std::endl; + } } } else { // Directory if (recursive) { - if (!ignored.match(fname)) { + // append a slash if it is a directory since that is what we are doing for mIgnoredPaths directory entries. + // otherwise we would ignore all its contents individually instead as a whole. + if (!ignored.match(fname + '/')) { std::list filesSorted; std::string err = addFiles2(filesSorted, fname, extra, recursive, ignored); @@ -135,6 +145,10 @@ static std::string addFiles2(std::list&files, const std::string files.insert(files.end(), std::make_move_iterator(filesSorted.begin()), std::make_move_iterator(filesSorted.end())); } + else if (debug) + { + std::cout << "ignored path: " << fname << std::endl; + } } } } @@ -151,14 +165,14 @@ static std::string addFiles2(std::list&files, const std::string return ""; } -std::string FileLister::addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored) +std::string FileLister::addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored, bool debug) { if (path.empty()) return "no path specified"; std::list filesSorted; - std::string err = addFiles2(filesSorted, path, extra, recursive, ignored); + std::string err = addFiles2(filesSorted, path, extra, recursive, ignored, debug); // files need to be sorted as the filesystems dosn't provide a stable order filesSorted.sort([](const FileWithDetails& a, const FileWithDetails& b) { @@ -183,11 +197,15 @@ static std::string addFiles2(std::list &files, const std::string &path, const std::set &extra, bool recursive, - const PathMatch& ignored - ) + const PathMatch& ignored, + bool debug) { if (ignored.match(path)) + { + if (debug) + std::cout << "ignored path: " << path << std::endl; return ""; + } struct stat file_stat; if (stat(path.c_str(), &file_stat) == -1) @@ -224,20 +242,35 @@ static std::string addFiles2(std::list &files, const bool path_is_directory = Path::isDirectory(new_path); #endif if (path_is_directory) { - if (recursive && !ignored.match(new_path)) { - std::string err = addFiles2(files, new_path, extra, recursive, ignored); - if (!err.empty()) { - return err; + if (recursive) { + // append a slash if it is a directory since that is what we are doing for mIgnoredPaths directory entries. + // otherwise we would ignore all its contents individually instead as a whole. + if (!ignored.match(new_path + '/')) { + std::string err = addFiles2(files, new_path, extra, recursive, ignored, debug); + if (!err.empty()) { + return err; + } + } + else if (debug) + { + std::cout << "ignored path: " << new_path << std::endl; } } } else { Standards::Language lang = Standards::Language::None; - if (Path::acceptFile(new_path, extra, &lang) && !ignored.match(new_path)) { - if (stat(new_path.c_str(), &file_stat) == -1) { - const int err = errno; - return "could not stat file '" + new_path + "' (errno: " + std::to_string(err) + ")"; + if (Path::acceptFile(new_path, extra, &lang)) { + if (!ignored.match(new_path)) + { + if (stat(new_path.c_str(), &file_stat) == -1) { + const int err = errno; + return "could not stat file '" + new_path + "' (errno: " + std::to_string(err) + ")"; + } + files.emplace_back(new_path, lang, file_stat.st_size); + } + else if (debug) + { + std::cout << "ignored path: " << new_path << std::endl; } - files.emplace_back(new_path, lang, file_stat.st_size); } } } @@ -245,7 +278,7 @@ static std::string addFiles2(std::list &files, return ""; } -std::string FileLister::addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored) +std::string FileLister::addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored, bool debug) { if (path.empty()) return "no path specified"; @@ -256,7 +289,7 @@ std::string FileLister::addFiles(std::list &files, const std::s std::list filesSorted; - std::string err = addFiles2(filesSorted, corrected_path, extra, recursive, ignored); + std::string err = addFiles2(filesSorted, corrected_path, extra, recursive, ignored, debug); // files need to be sorted as the filesystems dosn't provide a stable order filesSorted.sort([](const FileWithDetails& a, const FileWithDetails& b) { @@ -269,7 +302,7 @@ std::string FileLister::addFiles(std::list &files, const std::s #endif -std::string FileLister::recursiveAddFiles(std::list &files, const std::string &path, const std::set &extra, const PathMatch& ignored) +std::string FileLister::recursiveAddFiles(std::list &files, const std::string &path, const std::set &extra, const PathMatch& ignored, bool debug) { - return addFiles(files, path, extra, true, ignored); + return addFiles(files, path, extra, true, ignored, debug); } diff --git a/cli/filelister.h b/cli/filelister.h index 6cdd99c7e43..95d47fae021 100644 --- a/cli/filelister.h +++ b/cli/filelister.h @@ -41,9 +41,10 @@ class FileLister { * @param path root path * @param extra Extra file extensions * @param ignored ignored paths + * @param debug log if path was ignored * @return On success, an empty string is returned. On error, a error message is returned. */ - static std::string recursiveAddFiles(std::list &files, const std::string &path, const std::set &extra, const PathMatch& ignored); + static std::string recursiveAddFiles(std::list &files, const std::string &path, const std::set &extra, const PathMatch& ignored, bool debug = false); /** * @brief (Recursively) add source files to a map. @@ -55,9 +56,10 @@ class FileLister { * @param extra Extra file extensions * @param recursive Enable recursion * @param ignored ignored paths + * @param debug log when a path was ignored * @return On success, an empty string is returned. On error, a error message is returned. */ - static std::string addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored); + static std::string addFiles(std::list &files, const std::string &path, const std::set &extra, bool recursive, const PathMatch& ignored, bool debug = false); }; /// @} diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 2d30b80f633..f9b4a2d15cd 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -42,7 +42,7 @@ #include "json.h" // TODO: align the exclusion logic with PathMatch -void ImportProject::ignorePaths(const std::vector &ipaths) +void ImportProject::ignorePaths(const std::vector &ipaths, bool debug) { for (auto it = fileSettings.cbegin(); it != fileSettings.cend();) { bool ignore = false; @@ -63,8 +63,11 @@ void ImportProject::ignorePaths(const std::vector &ipaths) } } } - if (ignore) + if (ignore) { + if (debug) + std::cout << "ignored path: " << it->filename() << std::endl; it = fileSettings.erase(it); + } else ++it; } diff --git a/lib/importproject.h b/lib/importproject.h index 243c2aff3a2..8a3705b3e2a 100644 --- a/lib/importproject.h +++ b/lib/importproject.h @@ -93,7 +93,7 @@ class CPPCHECKLIB WARN_UNUSED ImportProject { std::string platform; } guiProject; - void ignorePaths(const std::vector &ipaths); + void ignorePaths(const std::vector &ipaths, bool debug = false); void ignoreOtherConfigs(const std::string &cfg); Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr); diff --git a/lib/pathmatch.h b/lib/pathmatch.h index 4ee7eea6c15..f0ace4fbc94 100644 --- a/lib/pathmatch.h +++ b/lib/pathmatch.h @@ -35,6 +35,9 @@ class CPPCHECKLIB PathMatch { /** * The constructor. + * + * If a path is a directory it needs to end with a file separator. + * * @param paths List of masks. * @param caseSensitive Match the case of the characters when * matching paths? @@ -43,6 +46,9 @@ class CPPCHECKLIB PathMatch { /** * @brief Match path against list of masks. + * + * If you want to match a directory the given path needs to end with a path separator. + * * @param path Path to match. * @return true if any of the masks match the path, false otherwise. */ diff --git a/lib/settings.h b/lib/settings.h index 6286029bd62..49e4f1e6a3e 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -184,6 +184,9 @@ class CPPCHECKLIB WARN_UNUSED Settings { /** @brief Is --debug-clang-output given? */ bool debugClangOutput{}; + /** @brief Is --debug-ignore given? */ + bool debugignore{}; + /** @brief Internal: Is --debug-lookup or --debug-lookup=all given? */ bool debuglookup{}; diff --git a/test/cli/more-projects_test.py b/test/cli/more-projects_test.py index f61b0c42e9f..51290a7d6a3 100644 --- a/test/cli/more-projects_test.py +++ b/test/cli/more-projects_test.py @@ -705,7 +705,7 @@ def test_project_file_ignore_3(tmpdir): assert_cppcheck(args, ec_exp=1, err_exp=[], out_exp=out_lines) -@pytest.mark.xfail +@pytest.mark.xfail(strict=True) def test_json_file_ignore(tmpdir): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 01c2adaaf4e..e0a431a4430 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -2033,6 +2033,7 @@ def test_ignore(tmpdir): with open(test_file, 'wt'): pass + # TODO: this should say that all paths are ignored lines_exp = [ 'cppcheck: error: could not find or open any of the paths given.', 'cppcheck: Maybe all paths were ignored?' @@ -2222,89 +2223,66 @@ def __write_compdb(tmpdir, test_file): return compile_commands -# TODO: -i appears to be ignored -@pytest.mark.xfail(strict=True) -def test_ignore_project_2(tmpdir): +def __test_ignore_project_2(tmpdir, extra_args, append=False, inject_path=False): os.mkdir(os.path.join(tmpdir, 'src')) test_file = os.path.join(tmpdir, 'src', 'test.cpp') with open(test_file, 'wt'): pass lines_exp = [ - 'cppcheck: error: could not find or open any of the paths given.', - 'cppcheck: Maybe all paths were ignored?' + 'cppcheck: error: no C or C++ source files found.', + 'cppcheck: all paths were ignored' ] - project_file = __write_compdb(tmpdir, test_file) args = [ - '-itest.cpp', + '-q', '--project={}'.format(project_file) ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout + if inject_path: + extra_args = [ extra_args[0].replace('$path', str(test_file)) ] + if append: + args += extra_args + else: + args = extra_args + args + print(args) + + exitcode, stdout, stderr = cppcheck(args, cwd=tmpdir) + assert exitcode == 1, stdout if stdout else stderr assert stdout.splitlines() == lines_exp - # make sure it also matches when specified after project - project_file = __write_compdb(tmpdir, test_file) - args = [ - '--project={}'.format(project_file), - '-itest.cpp' - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +@pytest.mark.xfail(strict=True) # TODO: -i appears to be ignored +def test_ignore_project_2_file(tmpdir): + __test_ignore_project_2(tmpdir, ['-itest.cpp']) - project_file = __write_compdb(tmpdir, test_file) - args = [ - '-isrc/test.cpp', - '--project={}'.format(project_file) - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +@pytest.mark.xfail(strict=True) # TODO: -i appears to be ignored +def test_ignore_project_2_file_append(tmpdir): + # make sure it also matches when specified after project + __test_ignore_project_2(tmpdir, ['-itest.cpp'], append=True) - project_file = __write_compdb(tmpdir, test_file) - args = [ - '-isrc\\test.cpp', - '--project={}'.format(project_file) - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +@pytest.mark.xfail(strict=True) # TODO: -i appears to be ignored +def test_ignore_project_2_file_relative(tmpdir): + __test_ignore_project_2(tmpdir, ['-isrc/test.cpp']) - project_file = __write_compdb(tmpdir, test_file) - args = [ - '-isrc/', - '--project={}'.format(project_file) - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +@pytest.mark.xfail(strict=True) # TODO: -i appears to be ignored +def test_ignore_project_2_file_relative_backslash(tmpdir): + __test_ignore_project_2(tmpdir, ['-isrc\\test.cpp']) - project_file = __write_compdb(tmpdir, test_file) - args = [ - '-isrc\\', - '--project={}'.format(project_file) - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +def test_ignore_project_2_path_relative(tmpdir): + __test_ignore_project_2(tmpdir, ['-isrc/']) - project_file = __write_compdb(tmpdir, test_file) - args = [ - '-i{}'.format(test_file), - '--project={}'.format(project_file) - ] - exitcode, stdout, _ = cppcheck(args, cwd=tmpdir) - assert exitcode == 1, stdout - assert stdout.splitlines() == lines_exp +def test_ignore_project_2_path_relative_backslash(tmpdir): + __test_ignore_project_2(tmpdir, ['-isrc\\']) + + +def test_ignore_project_2_abspath(tmpdir): + __test_ignore_project_2(tmpdir, ['-i$path'], inject_path=True) def test_dumpfile_platform(tmpdir): @@ -3162,4 +3140,29 @@ def test_debug_valueflow_xml(tmp_path): # #13606 assert 'floatvalue' in value_elem[1].attrib assert value_elem[1].attrib['floatvalue'] == '1e-07' assert 'floatvalue' in value_elem[2].attrib - assert value_elem[2].attrib['floatvalue'] == '1e-07' \ No newline at end of file + assert value_elem[2].attrib['floatvalue'] == '1e-07' + + +def test_dir_ignore(tmp_path): + test_file = tmp_path / 'test.cpp' + with open(test_file, 'wt'): + pass + + lib_dir = tmp_path / 'lib' + os.mkdir(lib_dir) + lib_test_file = lib_dir / 'test.cpp' + with open(lib_test_file, 'wt'): + pass + + args = [ + '-ilib', + '--debug-ignore', + str(tmp_path) + ] + # make sure the whole directory is being ignored instead of each of its contents individually + out_lines = [ + 'ignored path: {}'.format(lib_dir), + 'Checking {} ...'.format(test_file) + ] + + assert_cppcheck(args, ec_exp=0, err_exp=[], out_exp=out_lines, cwd=str(tmp_path)) \ No newline at end of file diff --git a/test/cli/testutils.py b/test/cli/testutils.py index 00b9483d08e..f352af49f15 100644 --- a/test/cli/testutils.py +++ b/test/cli/testutils.py @@ -236,8 +236,8 @@ def cppcheck(*args, **kwargs): return return_code, stdout, stderr -def assert_cppcheck(args, ec_exp=None, out_exp=None, err_exp=None, env=None): - exitcode, stdout, stderr = cppcheck(args, env) +def assert_cppcheck(args, ec_exp=None, out_exp=None, err_exp=None, env=None, cwd=None): + exitcode, stdout, stderr = cppcheck(args, env=env, cwd=cwd) if ec_exp is not None: assert exitcode == ec_exp, stdout if out_exp is not None: diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index ec2b5cbcd9b..c6ff476e589 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -440,6 +440,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(debugClangOutput); TEST_CASE(debugXmlMultiple); TEST_CASE(debugNormalXmlMultiple); + TEST_CASE(debugIgnore); TEST_CASE(ignorepaths1); TEST_CASE(ignorepaths2); @@ -448,6 +449,11 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(ignorefilepaths1); TEST_CASE(ignorefilepaths2); TEST_CASE(ignorefilepaths3); + TEST_CASE(ignorefilepaths4); + TEST_CASE(ignorefilepaths5); + TEST_CASE(ignorefilepaths6); + TEST_CASE(ignorefilepaths7); + TEST_CASE(ignorefilepaths8); TEST_CASE(nonexistentpath); @@ -2974,12 +2980,21 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: printing debug output in XML format does not support multiple input files.\n", logger->str()); } + void debugIgnore() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-ignore", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugignore); + } + void ignorepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorepaths2() { @@ -2988,6 +3003,8 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorepaths3() { @@ -2997,6 +3014,8 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorepaths4() { @@ -3006,6 +3025,8 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorefilepaths1() { @@ -3014,6 +3035,8 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorefilepaths2() { @@ -3022,6 +3045,8 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src/foo.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); } void ignorefilepaths3() { @@ -3030,6 +3055,63 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); + } + + void ignorefilepaths4() { + REDIRECT; + const char * const argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"}; + ASSERT(!fillSettingsFromArgs(argv)); + ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); + ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); + TODO_ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\n", "cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str()); + } + + void ignorefilepaths5() { + REDIRECT; + const char * const argv[] = {"cppcheck", "-ifile.cpp", "file.cpp"}; + ASSERT(!fillSettingsFromArgs(argv)); + ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); + ASSERT_EQUALS("file.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("file.cpp", parser->getPathNames()[0]); + ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str()); + } + + void ignorefilepaths6() { + REDIRECT; + const char * const argv[] = {"cppcheck", "-isrc/file.cpp", "src/file.cpp"}; + ASSERT(!fillSettingsFromArgs(argv)); + ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); + ASSERT_EQUALS("src/file.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("src/file.cpp", parser->getPathNames()[0]); + ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str()); + } + + void ignorefilepaths7() { + REDIRECT; + const char * const argv[] = {"cppcheck", "-isrc\\file.cpp", "src/file.cpp"}; + ASSERT(!fillSettingsFromArgs(argv)); + ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); + ASSERT_EQUALS("src/file.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("src/file.cpp", parser->getPathNames()[0]); + ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str()); + } + + void ignorefilepaths8() { + REDIRECT; + const char * const argv[] = {"cppcheck", "-isrc/file.cpp", "src\\file.cpp"}; + ASSERT(!fillSettingsFromArgs(argv)); + ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); + ASSERT_EQUALS("src/file.cpp", parser->getIgnoredPaths()[0]); + ASSERT_EQUALS(1, parser->getPathNames().size()); + ASSERT_EQUALS("src/file.cpp", parser->getPathNames()[0]); + ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str()); } void nonexistentpath() { diff --git a/test/testfilelister.cpp b/test/testfilelister.cpp index f49b049df0c..fefafededd9 100644 --- a/test/testfilelister.cpp +++ b/test/testfilelister.cpp @@ -40,6 +40,7 @@ class TestFileLister : public TestFixture { TEST_CASE(recursiveAddFilesEmptyPath); TEST_CASE(excludeFile1); TEST_CASE(excludeFile2); + TEST_CASE(excludeDir); TEST_CASE(addFiles); } @@ -136,6 +137,21 @@ class TestFileLister : public TestFixture { ASSERT_EQUALS(basedir + "lib/token.cpp", files.begin()->path()); } + void excludeDir() const { + const std::string basedir = findBaseDir() + "."; + + std::list files; + std::vector ignored{"lib/"}; // needs to end with slash so it matches directories - added by CmdLineParser + PathMatch matcher(ignored); + std::string err = FileLister::recursiveAddFiles(files, basedir, {}, matcher); + ASSERT_EQUALS("", err); + ASSERT(!files.empty()); + const auto it = std::find_if(files.cbegin(), files.cend(), [](const FileWithDetails& f){ + return f.spath().find("/lib/") != std::string::npos; + }); + ASSERT(it == files.cend()); + } + void addFiles() const { const std::string adddir = findBaseDir() + "."; @@ -165,12 +181,7 @@ class TestFileLister : public TestFixture { { const std::string addfile = Path::join(Path::join(adddir, "lib2"), "token.cpp"); // does not exist const std::string err = FileLister::addFiles(files, addfile, {}, true,PathMatch({})); -#ifdef _WIN32 - // TODO: get rid of this error - caused by missing intermediate folder - ASSERT_EQUALS("finding files failed. Search pattern: '" + dirprefix_nat + "lib2\\token.cpp'. (error: 3)", err); -#else ASSERT_EQUALS("", err); -#endif } { const std::string addfile = Path::join(Path::join(adddir, "lib"), "matchcompiler.h"); diff --git a/test/testpath.cpp b/test/testpath.cpp index 1c022117a0d..4a43cf3e53c 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -55,6 +55,7 @@ class TestPath : public TestFixture { TEST_CASE(simplifyPath); TEST_CASE(getAbsolutePath); TEST_CASE(exists); + TEST_CASE(fromNativeSeparators); } void removeQuotationMarks() const { @@ -577,6 +578,20 @@ class TestPath : public TestFixture { ASSERT_EQUALS(false, Path::exists("testpath.txt", &b)); ASSERT_EQUALS(false, b); } + + void fromNativeSeparators() const { + ASSERT_EQUALS("lib/file.c", Path::fromNativeSeparators("lib/file.c")); + ASSERT_EQUALS("lib//file.c", Path::fromNativeSeparators("lib//file.c")); + ASSERT_EQUALS("/lib/file.c", Path::fromNativeSeparators("/lib/file.c")); + ASSERT_EQUALS("//lib/file.c", Path::fromNativeSeparators("//lib/file.c")); + ASSERT_EQUALS("./lib/file.c", Path::fromNativeSeparators("./lib/file.c")); + + ASSERT_EQUALS("lib/file.c", Path::fromNativeSeparators("lib\\file.c")); + ASSERT_EQUALS("lib//file.c", Path::fromNativeSeparators("lib\\\\file.c")); + ASSERT_EQUALS("/lib/file.c", Path::fromNativeSeparators("\\lib\\file.c")); + ASSERT_EQUALS("//lib/file.c", Path::fromNativeSeparators("\\\\lib\\file.c")); + ASSERT_EQUALS("./lib/file.c", Path::fromNativeSeparators(".\\lib\\file.c")); + } }; REGISTER_TEST(TestPath)