Skip to content

Commit 25167b5

Browse files
committed
Implemented cppcheck-opensource#2990: Print relative paths if -rp or --relative-paths is given
1 parent b0f571b commit 25167b5

8 files changed

Lines changed: 108 additions & 3 deletions

File tree

cli/cmdlineparser.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
249249
else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0)
250250
_settings->_force = true;
251251

252+
// Output relative paths
253+
else if (strcmp(argv[i], "-rp") == 0 || strcmp(argv[i], "--relative-paths") == 0)
254+
_settings->_relativePaths = true;
255+
else if (strncmp(argv[i], "-rp=", 4) == 0 || strncmp(argv[i], "--relative-paths=", 17) == 0) {
256+
_settings->_relativePaths = true;
257+
std::string paths = argv[i]+(argv[i][3]=='='?4:17);
258+
std::string::size_type pos;
259+
do {
260+
pos = paths.find(';');
261+
_settings->_basePaths.push_back(Path::fromNativeSeparators(paths.substr(0, pos)));
262+
paths.erase(0, pos+1);
263+
} while (pos != std::string::npos);
264+
}
265+
252266
// Write results in results.xml
253267
else if (strcmp(argv[i], "--xml") == 0)
254268
_settings->_xml = true;
@@ -684,6 +698,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
684698
return false;
685699
}
686700

701+
// Use paths _pathnames if no base paths for relative path output are given
702+
if (_settings->_basePaths.empty() && _settings->_relativePaths)
703+
_settings->_basePaths = _pathnames;
704+
687705
return true;
688706
}
689707

@@ -780,6 +798,11 @@ void CmdLineParser::PrintHelp() const
780798
" * win64\n"
781799
" 64 bit Windows\n"
782800
" -q, --quiet Only print error messages.\n"
801+
" -rp, --relative-paths\n"
802+
" -rp=<paths>, --relative-paths=<paths>\n"
803+
" Use relative paths in output. When given, <paths> are\n"
804+
" used as base. You can separate multiple paths by ';'.\n"
805+
" Otherwise path where source files are searched is used.\n"
783806
" --report-progress Report progress messages while checking a file.\n"
784807
#ifdef HAVE_RULES
785808
" --rule=<rule> Match regular expression.\n"

lib/path.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,21 @@ std::string Path::getFilenameExtensionInLowerCase(const std::string &path)
154154
return extension;
155155
}
156156

157+
std::string Path::getRelativePath(const std::string& absolutePath, const std::vector<std::string>& basePaths)
158+
{
159+
for (std::vector<std::string>::const_iterator i = basePaths.begin(); i != basePaths.end(); ++i) {
160+
if (absolutePath == *i) // Seems to be a file
161+
continue;
162+
163+
bool endsWithSep = (*i)[i->length()-1] == '/';
164+
if (absolutePath.compare(0, i->length(), *i) == 0 && absolutePath[i->length() - (endsWithSep?1:0)] == '/') {
165+
std::string rest = absolutePath.substr(i->length() + (endsWithSep?0:1));
166+
return rest;
167+
}
168+
}
169+
return absolutePath;
170+
}
171+
157172
bool Path::isC(const std::string &path)
158173
{
159174
// In unix, ".C" is concidered C++ file

lib/path.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define PATH_H_INCLUDED
2121

2222
#include <string>
23+
#include <vector>
2324

2425
/// @addtogroup Core
2526
/// @{
@@ -84,6 +85,14 @@ class Path {
8485
*/
8586
static std::string getFilenameExtensionInLowerCase(const std::string &path);
8687

88+
/**
89+
* @brief Create a relative path from an absolute one, if absolute path is inside the basePaths.
90+
* @param absolutePath Path to be made relative.
91+
* @param basePaths Paths to which it may be made relative.
92+
* @return relative path, if possible. Otherwise absolutePath is returned unchanged
93+
*/
94+
static std::string getRelativePath(const std::string& absolutePath, const std::vector<std::string>& basePaths);
95+
8796
/**
8897
* @brief Check if the file extension indicates that it's a C/C++ source file.
8998
* Check if the file has source file extension: *.c;*.cpp;*.cxx;*.c++;*.cc;*.txx

lib/preprocessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
20022002

20032003
if (!processedFile.empty()) {
20042004
// Remove space characters that are after or before new line character
2005-
processedFile = "#file \"" + filename + "\"\n" + processedFile + "\n#endfile";
2005+
processedFile = "#file \"" + Path::fromNativeSeparators(filename) + "\"\n" + processedFile + "\n#endfile";
20062006
code.insert(pos, processedFile);
20072007

20082008
path = filename;

lib/settings.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define settingsH
2121

2222
#include <list>
23+
#include <vector>
2324
#include <string>
2425
#include <set>
2526
#include "suppressions.h"
@@ -90,6 +91,12 @@ class Settings {
9091
/** @brief Force checking the files with "too many" configurations (--force). */
9192
bool _force;
9293

94+
/** @brief Use relative paths in output. */
95+
bool _relativePaths;
96+
97+
/** @brief Paths used as base for conversion to relative paths. */
98+
std::vector<std::string> _basePaths;
99+
93100
/** @brief write XML results (--xml) */
94101
bool _xml;
95102

lib/tokenize.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ void Tokenizer::createTokens(std::istream &code)
345345

346346
if (!foundOurfile) {
347347
// The "_files" vector remembers what files have been tokenized..
348-
_files.push_back(Path::simplifyPath(line.c_str()));
348+
_files.push_back(Path::getRelativePath(Path::simplifyPath(line.c_str()), _settings->_basePaths));
349349
FileIndex = static_cast<unsigned int>(_files.size() - 1);
350350
}
351351

@@ -1943,7 +1943,7 @@ bool Tokenizer::tokenize(std::istream &code,
19431943
_configuration = configuration;
19441944

19451945
// The "_files" vector remembers what files have been tokenized..
1946-
_files.push_back(Path::simplifyPath(FileName));
1946+
_files.push_back(Path::getRelativePath(Path::simplifyPath(FileName), _settings->_basePaths));
19471947

19481948
createTokens(code);
19491949

test/testcmdlineparser.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class TestCmdlineParser : public TestFixture {
4242
TEST_CASE(debugwarnings);
4343
TEST_CASE(forceshort);
4444
TEST_CASE(forcelong);
45+
TEST_CASE(relativePaths);
4546
TEST_CASE(quietshort);
4647
TEST_CASE(quietlong);
4748
TEST_CASE(defines_noarg);
@@ -248,6 +249,42 @@ class TestCmdlineParser : public TestFixture {
248249
ASSERT_EQUALS(true, settings._force);
249250
}
250251

252+
void relativePaths() {
253+
REDIRECT;
254+
Settings settings;
255+
CmdLineParser parser(&settings);
256+
257+
const char *argvs[] = {"cppcheck", "-rp", "file.cpp"};
258+
ASSERT(parser.ParseFromArgs(3, argvs));
259+
ASSERT_EQUALS(true, settings._relativePaths);
260+
261+
settings._relativePaths = false;
262+
263+
const char *argvl[] = {"cppcheck", "--relative-paths", "file.cpp"};
264+
ASSERT(parser.ParseFromArgs(3, argvl));
265+
ASSERT_EQUALS(true, settings._relativePaths);
266+
267+
settings._relativePaths = false;
268+
settings._basePaths.clear();
269+
270+
const char *argvsp[] = {"cppcheck", "-rp=C:/foo;C:\\bar", "file.cpp"};
271+
ASSERT(parser.ParseFromArgs(3, argvsp));
272+
ASSERT_EQUALS(true, settings._relativePaths);
273+
ASSERT_EQUALS(2, settings._basePaths.size());
274+
ASSERT_EQUALS("C:/foo", settings._basePaths[0]);
275+
ASSERT_EQUALS("C:/bar", settings._basePaths[1]);
276+
277+
settings._relativePaths = false;
278+
settings._basePaths.clear();
279+
280+
const char *argvlp[] = {"cppcheck", "--relative-paths=C:/foo;C:\\bar", "file.cpp"};
281+
ASSERT(parser.ParseFromArgs(3, argvlp));
282+
ASSERT_EQUALS(true, settings._relativePaths);
283+
ASSERT_EQUALS(2, settings._basePaths.size());
284+
ASSERT_EQUALS("C:/foo", settings._basePaths[0]);
285+
ASSERT_EQUALS("C:/bar", settings._basePaths[1]);
286+
}
287+
251288
void quietshort() {
252289
REDIRECT;
253290
const char *argv[] = {"cppcheck", "-q", "file.cpp"};

test/testpath.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class TestPath : public TestFixture {
3030
void run() {
3131
TEST_CASE(simplify_path);
3232
TEST_CASE(accept_file);
33+
TEST_CASE(getRelative);
3334
TEST_CASE(is_c);
3435
TEST_CASE(is_cpp);
3536
TEST_CASE(is_java);
@@ -76,6 +77,19 @@ class TestPath : public TestFixture {
7677
ASSERT(Path::acceptFile("C")==false);
7778
}
7879

80+
void getRelative() {
81+
std::vector<std::string> basePaths;
82+
basePaths.push_back("C:/foo");
83+
basePaths.push_back("C:/bar/");
84+
basePaths.push_back("C:/test.cpp");
85+
86+
ASSERT_EQUALS("x.c", Path::getRelativePath("C:/foo/x.c", basePaths));
87+
ASSERT_EQUALS("y.c", Path::getRelativePath("C:/bar/y.c", basePaths));
88+
ASSERT_EQUALS("foo/y.c", Path::getRelativePath("C:/bar/foo/y.c", basePaths));
89+
ASSERT_EQUALS("C:/test.cpp", Path::getRelativePath("C:/test.cpp", basePaths));
90+
ASSERT_EQUALS("C:/foobar/test.cpp", Path::getRelativePath("C:/foobar/test.cpp", basePaths));
91+
}
92+
7993
void is_c() {
8094
ASSERT(Path::isC("index.cpp")==false);
8195
ASSERT(Path::isC("")==false);

0 commit comments

Comments
 (0)