Skip to content

Commit 6bcfbbc

Browse files
authored
Merge pull request #187 from Pennycook/bugfix/backslash-eof
Accept C files ending in a backslash-newline
2 parents adba0e7 + 8d54152 commit 6bcfbbc

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

codebasin/file_source.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -460,17 +460,14 @@ def logical_result(self):
460460
)
461461

462462

463-
def c_file_source(fp, relaxed=False, directives_only=False):
463+
def c_file_source(fp, directives_only=False):
464464
"""
465465
Process file fp in terms of logical (sloc) and physical lines of C code.
466466
Yield blocks of logical lines of code with physical extents.
467467
Return total lines at exit.
468-
Relaxed allows for inconsistent state at the end of parsing, usefule for
469-
special composition cases.
470468
directives_only sets up parser to only process directive lines such that
471469
the output can be fed to another file source (i.e. Fortran).
472470
"""
473-
474471
current_physical_line = one_space_line()
475472
cleaner = c_cleaner(current_physical_line, directives_only)
476473

@@ -479,6 +476,7 @@ def c_file_source(fp, relaxed=False, directives_only=False):
479476
total_sloc = 0
480477

481478
physical_line_num = 0
479+
continued = False
482480
for physical_line_num, line in enumerate(fp, start=1):
483481
current_physical_line.__init__()
484482
end = len(line)
@@ -513,22 +511,28 @@ def c_file_source(fp, relaxed=False, directives_only=False):
513511
yield curr_line
514512

515513
total_sloc += curr_line.physical_reset()
516-
if not relaxed and not cleaner.state == ["TOPLEVEL"]:
514+
515+
# Even if code is technically wrong, we should only fail when necessary.
516+
parsing_failed = not cleaner.state == ["TOPLEVEL"]
517+
if continued:
518+
log.warning("backslash-newline at end of file")
519+
parsing_failed = False
520+
521+
if parsing_failed:
517522
raise RuntimeError(
518-
"Parser must end at top level without 'relaxed' mode.",
523+
"Parsing failed. Please open a bug report at: "
524+
"https://github.com/intel/code-base-investigator/issues/new?template=bug_report.yml", # noqa: E501
519525
)
520526

521527
return (total_sloc, total_physical_lines)
522528

523529

524-
def fortran_file_source(fp, relaxed=False):
530+
def fortran_file_source(fp):
525531
"""
526532
Process file fp in terms of logical (sloc) and physical lines of
527533
fixed-form Fortran code.
528534
Yield blocks of logical lines of code with physical extents.
529535
Return total lines at exit.
530-
Relaxed allows for inconsistent state at the end of parsing, usefule for
531-
special composition cases.
532536
"""
533537

534538
current_physical_line = one_space_line()
@@ -593,9 +597,12 @@ def fortran_file_source(fp, relaxed=False):
593597
yield curr_line
594598

595599
total_sloc += curr_line.physical_reset()
596-
if not relaxed and not cleaner.state == ["TOPLEVEL"]:
600+
601+
parsing_failed = not cleaner.state == ["TOPLEVEL"]
602+
if parsing_failed:
597603
raise RuntimeError(
598-
"Parser must end at top level without 'relaxed' mode.",
604+
"Parsing failed. Please open a bug report at: "
605+
"https://github.com/intel/code-base-investigator/issues/new?template=bug_report.yml", # noqa: E501
599606
)
600607

601608
return (total_sloc, total_physical_lines)
@@ -642,7 +649,7 @@ def process(self, lineiter):
642649
pass
643650

644651

645-
def asm_file_source(fp, relaxed=False):
652+
def asm_file_source(fp):
646653
"""
647654
Process file fp in terms of logical (sloc) and physical lines of ASM code.
648655
Yield blocks of logical lines of code with physical extents.

codebasin/finder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def find(
176176
leave=False,
177177
disable=not show_progress,
178178
):
179+
log.debug(f"Parsing {f}")
179180
state.insert_file(f)
180181

181182
# Process each tree, by associating nodes with platforms

tests/preprocessor/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Copyright (C) 2019 Intel Corporation
2+
# SPDX-License-Identifier: BSD-3-Clause

tests/preprocessor/test_warnings.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright (C) 2019-2024 Intel Corporation
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
4+
import logging
5+
import os
6+
import tempfile
7+
import unittest
8+
from pathlib import Path
9+
10+
from codebasin import file_parser
11+
12+
13+
class TestPreprocessorWarnings(unittest.TestCase):
14+
"""
15+
Test that preprocessor generates warnings for weird corner cases.
16+
"""
17+
18+
def setUp(self):
19+
self.cwd = os.getcwd()
20+
21+
def tearDown(self):
22+
os.chdir(self.cwd)
23+
24+
def test_backslash_eof(self):
25+
"""Check backslash-newline at EOF is only a warning"""
26+
tmp = tempfile.TemporaryDirectory()
27+
path = Path(tmp.name)
28+
os.chdir(tmp.name)
29+
30+
with open(path / "test.hpp", mode="w") as f:
31+
f.write("#define BAD_MACRO \\\n")
32+
33+
parser = file_parser.FileParser(path / "test.hpp")
34+
35+
logging.disable(logging.NOTSET)
36+
logger = logging.getLogger("codebasin")
37+
with self.assertLogs(logger, level="WARNING") as cm:
38+
_ = parser.parse_file()
39+
logging.disable()
40+
self.assertRegex(cm.output[0], "backslash-newline at end of file")
41+
42+
tmp.cleanup()

0 commit comments

Comments
 (0)