Skip to content

Commit 2bbb496

Browse files
Tal500Tal Hadad
andauthored
Preserve relativeness of included paths (w.r.t. current directory) (#428)
Co-authored-by: Tal Hadad <thadad@istraresearch.com>
1 parent 0775731 commit 2bbb496

File tree

2 files changed

+52
-28
lines changed

2 files changed

+52
-28
lines changed

integration_test.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## test with python -m pytest integration_test.py
22

33
import os
4+
import pathlib
45
import pytest
56
from testutils import simplecpp, format_include_path_arg, format_include
67

@@ -14,6 +15,7 @@ def __test_relative_header_create_header(dir, with_pragma_once=True):
1415
#else
1516
#error header_was_already_included
1617
#endif
18+
const int dummy = 1;
1719
""")
1820
return header_file, "error: #error header_was_already_included"
1921

@@ -48,33 +50,43 @@ def test_relative_header_1(tmpdir, with_pragma_once, is_sys):
4850
assert double_include_error in stderr
4951

5052
@pytest.mark.parametrize("inv", (False, True))
51-
def test_relative_header_2(tmpdir, inv):
53+
@pytest.mark.parametrize("source_relative", (False, True))
54+
def test_relative_header_2(tmpdir, inv, source_relative):
5255
header_file, _ = __test_relative_header_create_header(tmpdir)
5356

5457
test_file = __test_relative_header_create_source(tmpdir, "test.h", header_file, inv=inv)
5558

56-
args = [test_file]
59+
args = ["test.c" if source_relative else test_file]
5760

58-
_, _, stderr = simplecpp(args, cwd=tmpdir)
61+
_, stdout, stderr = simplecpp(args, cwd=tmpdir)
5962
assert stderr == ''
63+
if source_relative and not inv:
64+
assert '#line 8 "test.h"' in stdout
65+
else:
66+
assert f'#line 8 "{pathlib.PurePath(tmpdir).as_posix()}/test.h"' in stdout
6067

6168
@pytest.mark.parametrize("is_sys", (False, True))
6269
@pytest.mark.parametrize("inv", (False, True))
63-
def test_relative_header_3(tmpdir, is_sys, inv):
70+
@pytest.mark.parametrize("source_relative", (False, True))
71+
def test_relative_header_3(tmpdir, is_sys, inv, source_relative):
6472
test_subdir = os.path.join(tmpdir, "test_subdir")
6573
os.mkdir(test_subdir)
6674
header_file, _ = __test_relative_header_create_header(test_subdir)
6775

6876
test_file = __test_relative_header_create_source(tmpdir, "test_subdir/test.h", header_file, is_include1_sys=is_sys, inv=inv)
6977

70-
args = [test_file]
78+
args = ["test.c" if source_relative else test_file]
7179

72-
_, _, stderr = simplecpp(args, cwd=tmpdir)
80+
_, stdout, stderr = simplecpp(args, cwd=tmpdir)
7381

7482
if is_sys:
7583
assert "missing header: Header not found" in stderr
7684
else:
7785
assert stderr == ''
86+
if source_relative and not inv:
87+
assert '#line 8 "test_subdir/test.h"' in stdout
88+
else:
89+
assert f'#line 8 "{pathlib.PurePath(test_subdir).as_posix()}/test.h"' in stdout
7890

7991
@pytest.mark.parametrize("use_short_path", (False, True))
8092
@pytest.mark.parametrize("is_sys", (False, True))

simplecpp.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3145,11 +3145,11 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
31453145
return "";
31463146
}
31473147

3148-
static std::string getRelativeFileName(const std::string &sourcefile, const std::string &header)
3148+
static std::string getRelativeFileName(const std::string &baseFile, const std::string &header)
31493149
{
31503150
std::string path;
3151-
if (sourcefile.find_first_of("\\/") != std::string::npos)
3152-
path = sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header;
3151+
if (baseFile.find_first_of("\\/") != std::string::npos)
3152+
path = baseFile.substr(0, baseFile.find_last_of("\\/") + 1U) + header;
31533153
else
31543154
path = header;
31553155
return simplecpp::simplifyPath(path);
@@ -3160,12 +3160,22 @@ static std::string openHeaderRelative(std::ifstream &f, const std::string &sourc
31603160
return openHeader(f, getRelativeFileName(sourcefile, header));
31613161
}
31623162

3163+
// returns the simplified header path:
3164+
// * If the header path is absolute, returns it in absolute path
3165+
// * Otherwise, returns it in relative path with respect to the current directory
31633166
static std::string getIncludePathFileName(const std::string &includePath, const std::string &header)
31643167
{
3165-
std::string path = toAbsolutePath(includePath);
3166-
if (!path.empty() && path[path.size()-1U]!='/' && path[path.size()-1U]!='\\')
3167-
path += '/';
3168-
return path + header;
3168+
std::string simplifiedHeader = simplecpp::simplifyPath(header);
3169+
3170+
if (isAbsolutePath(simplifiedHeader)) {
3171+
return simplifiedHeader;
3172+
}
3173+
3174+
std::string basePath = toAbsolutePath(includePath);
3175+
if (!basePath.empty() && basePath[basePath.size()-1U]!='/' && basePath[basePath.size()-1U]!='\\')
3176+
basePath += '/';
3177+
const std::string absolutesimplifiedHeaderPath = basePath + simplifiedHeader;
3178+
return extractRelativePathFromAbsolute(absolutesimplifiedHeaderPath).first;
31693179
}
31703180

31713181
static std::string openHeaderIncludePath(std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
@@ -3183,17 +3193,16 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
31833193
if (isAbsolutePath(header))
31843194
return openHeader(f, header);
31853195

3186-
if (systemheader) {
3187-
// always return absolute path for systemheaders
3188-
return toAbsolutePath(openHeaderIncludePath(f, dui, header));
3196+
// prefer first to search the header relatively to source file if found, when not a system header
3197+
if (!systemheader) {
3198+
std::string relativeHeader = openHeaderRelative(f, sourcefile, header);
3199+
if (!relativeHeader.empty()) {
3200+
return relativeHeader;
3201+
}
31893202
}
31903203

3191-
std::string ret;
3192-
3193-
ret = openHeaderRelative(f, sourcefile, header);
3194-
if (ret.empty())
3195-
return toAbsolutePath(openHeaderIncludePath(f, dui, header));// in a similar way to system headers
3196-
return ret;
3204+
// search the header on the include paths (provided by the flags "-I...")
3205+
return openHeaderIncludePath(f, dui, header);
31973206
}
31983207

31993208
static std::string findPathInMapBothRelativeAndAbsolute(const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string& path) {
@@ -3212,8 +3221,9 @@ static std::string findPathInMapBothRelativeAndAbsolute(const std::map<std::stri
32123221
}
32133222
} else {
32143223
const std::string absolutePath = toAbsolutePath(path);
3215-
if (filedata.find(absolutePath) != filedata.end())
3224+
if (filedata.find(absolutePath) != filedata.end()) {
32163225
return absolutePath;
3226+
}
32173227
}
32183228
// otherwise
32193229
return "";
@@ -3226,7 +3236,10 @@ static std::string getFileIdPath(const std::map<std::string, simplecpp::TokenLis
32263236
}
32273237
if (isAbsolutePath(header)) {
32283238
const std::string simplifiedHeaderPath = simplecpp::simplifyPath(header);
3229-
return (filedata.find(simplifiedHeaderPath) != filedata.end()) ? simplifiedHeaderPath : "";
3239+
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, simplifiedHeaderPath);
3240+
if (!match.empty()) {
3241+
return match;
3242+
}
32303243
}
32313244

32323245
if (!systemheader) {
@@ -3235,18 +3248,17 @@ static std::string getFileIdPath(const std::map<std::string, simplecpp::TokenLis
32353248
if (!match.empty()) {
32363249
return match;
32373250
}
3251+
} else if (filedata.find(header) != filedata.end()) {
3252+
return header;// system header that its file is already in the filedata - return that as is
32383253
}
32393254

32403255
for (std::list<std::string>::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) {
3241-
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, simplecpp::simplifyPath(getIncludePathFileName(*it, header)));
3256+
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, getIncludePathFileName(*it, header));
32423257
if (!match.empty()) {
32433258
return match;
32443259
}
32453260
}
32463261

3247-
if (systemheader && filedata.find(header) != filedata.end())
3248-
return header;// system header that its file wasn't found in the included paths but alreasy in the filedata - return this as is
3249-
32503262
return "";
32513263
}
32523264

0 commit comments

Comments
 (0)