Skip to content

Commit 044f28d

Browse files
authored
Merge pull request #488 from stfc/483_inline_directives
(Closes #483) inline directives should be comments (usually)
2 parents 669e2b1 + 59ee5e2 commit 044f28d

File tree

5 files changed

+50
-17
lines changed

5 files changed

+50
-17
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Modifications by (in alphabetical order):
2020
* P. Vitt, University of Siegen, Germany
2121
* A. Voysey, UK Met Office
2222

23+
25/11/2025 PR #488 for #483. Do not recognize inline comments as Directives.
24+
2325
31/10/2025 PR #486 for #483. Recognize any comment that begins ``!$``, ``c$`` or ``*$`` followed by
2426
a character as a Directive node.
2527

src/fparser/common/readfortran.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,10 @@ class Comment:
437437
:param reader: The reader object being used to read the input \
438438
source.
439439
:type reader: :py:class:`fparser.common.readfortran.FortranReaderBase`
440-
440+
:param inline: whether this was an inline comment.
441441
"""
442442

443-
def __init__(self, comment, linenospan, reader):
443+
def __init__(self, comment, linenospan, reader, inline: bool = False):
444444
self.comment = comment
445445
self.span = linenospan
446446
self.reader = reader
@@ -449,6 +449,7 @@ def __init__(self, comment, linenospan, reader):
449449
# tests as a reader can return an instance of either class and
450450
# we might want to check the contents in a consistent way.
451451
self.line = comment
452+
self.inline = inline
452453

453454
def __repr__(self):
454455
return self.__class__.__name__ + "(%r,%s)" % (self.comment, self.span)
@@ -1010,9 +1011,15 @@ def multiline_item(
10101011
prefix, lines, suffix, (startlineno, endlineno), self, errmessage
10111012
)
10121013

1013-
def comment_item(self, comment, startlineno, endlineno):
1014-
"""Construct Comment item."""
1015-
return Comment(comment, (startlineno, endlineno), self)
1014+
def comment_item(
1015+
self, comment, startlineno, endlineno, inline_comment: bool = False
1016+
):
1017+
"""Construct Comment item.
1018+
1019+
:param inline_comment: whether the comment is an inline comment.
1020+
Defaults to False.
1021+
"""
1022+
return Comment(comment, (startlineno, endlineno), self, inline_comment)
10161023

10171024
def cpp_directive_item(self, line, startlineno, endlineno):
10181025
"""
@@ -1245,7 +1252,14 @@ def handle_inline_comment(
12451252
newline = line[:idx]
12461253
if '"' not in newline and "'" not in newline:
12471254
if self.format.is_f77 or not line[idx:].startswith("!f2py"):
1248-
put_item(self.comment_item(line[idx:], lineno, lineno))
1255+
# Its an inline comment if there is a non whitespace
1256+
# character before the comment.
1257+
is_inline = not (line.lstrip() == line[idx:])
1258+
put_item(
1259+
self.comment_item(
1260+
line[idx:], lineno, lineno, inline_comment=is_inline
1261+
)
1262+
)
12491263
return newline, quotechar, True
12501264

12511265
# We must allow for quotes...

src/fparser/two/Fortran2003.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ def __new__(cls, string: Union[str, FortranReaderBase], parent_cls=None):
159159
from fparser.common import readfortran
160160

161161
if isinstance(string, readfortran.Comment):
162+
# Inline comments cannot be directives.
163+
if string.inline:
164+
return
162165
# Directives must start with one of the specified directive
163166
# prefixes.
164167
lower = string.comment.lower()

src/fparser/two/tests/fortran2003/test_usestmt_r1109.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@
4545

4646

4747
@pytest.fixture(autouse=True)
48-
@pytest.mark.usefixtures("f2003_create")
49-
def use_f2003():
48+
def use_f2003(f2003_create):
5049
"""
5150
A pytest fixture that just sets things up so that the f2003_create
5251
fixture is used automatically for every test in this file.

src/fparser/two/tests/test_comments_and_directives.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -431,13 +431,12 @@ def test_directive_stmts():
431431
)
432432
program = Program(reader)
433433
out = walk(program, Directive)
434-
assert len(out) == 4
435-
assert out[0].items[0] == "!$dir inline"
436-
assert out[1].items[0] == "!dir$ compiler directive"
437-
assert out[2].items[0] == "!$omp target"
438-
assert out[3].items[0] == "!$omp loop"
434+
assert len(out) == 3
435+
assert out[0].items[0] == "!dir$ compiler directive"
436+
assert out[1].items[0] == "!$omp target"
437+
assert out[2].items[0] == "!$omp loop"
439438

440-
assert out[3].tostr() == "!$omp loop"
439+
assert out[2].tostr() == "!$omp loop"
441440

442441
# Check the restore_reader works correctly for directive.
443442
old = reader.get_item()
@@ -451,9 +450,10 @@ def test_directive_stmts():
451450
for comment in out:
452451
if comment.items[0] != "":
453452
comments = comments + 1
454-
assert comments == 2
455-
assert str(out[2]) == "! A comment!"
456-
assert str(out[3]) == "!!$ Another comment"
453+
assert comments == 3
454+
assert str(out[1]) == "!$dir inline"
455+
assert str(out[3]) == "! A comment!"
456+
assert str(out[4]) == "!!$ Another comment"
457457

458458
# Check that passing something that isn't a comment into a Directive
459459
# __new__ call doesn't create a Directive.
@@ -601,3 +601,18 @@ def test_directives_as_comments(directive, expected, free):
601601
# Check that the comments contain the correct strings.
602602
for i, direc in enumerate(out):
603603
assert direc.items[0] == expected[i]
604+
605+
606+
def test_inline_directive_is_comment():
607+
"""Inline comments on statements should be comments even if containing
608+
directive markers."""
609+
source = """Program my_prog
610+
integer :: x !$dir directive
611+
612+
x = 1 !$dir comment
613+
end program
614+
"""
615+
reader = get_reader(source, ignore_comments=False, process_directives=True)
616+
program = Program(reader)
617+
out = walk(program, Directive)
618+
assert len(out) == 0

0 commit comments

Comments
 (0)