Skip to content

Commit

Permalink
Add a warning to chplcheck for confusing indentation (chapel-lang#23667)
Browse files Browse the repository at this point in the history
This PR adds a warning to the Chapel linter for "misleading
indentation". Misleading indentation occurs when a non-curly-brace block
is used in a for loop or if-else statement, but a line of code
underneath is indented to the same extent. For example:

```Chapel
for i in 1..10 do
  writeln("Hello, ");
  writeln("World!");
```

The issue with the above code is that it _looks_ like both statements
are a part of the loop; the user might have even intended that. However,
the syntax of the `do` keyword is that only the statement following it
is part of the block; thus, the code printing `World` is not run in a
loop. Thus, the way the code _looks_ (and might be written in an
indentation-sensitive language like Python) is not how it actually
behaves.

```
➜  chapel git:(confusing-indentation) cat good.chpl
for i in 1..10 do
    writeln("Hello!");
writeln("World!");
➜  chapel git:(confusing-indentation) python3 tools/chapel-py/chplcheck.py good.chpl
➜  chapel git:(confusing-indentation) cat bad.chpl
for i in 1..10 do
    writeln("Hello!");
    writeln("World!");
➜  chapel git:(confusing-indentation) python3 tools/chapel-py/chplcheck.py bad.chpl
bad.chpl:3: node violates rule MisleadingIndentation
```

Reviewed by @jabraham17 -- thanks!
  • Loading branch information
DanilaFe authored Oct 24, 2023
2 parents f462c76 + e8cbf80 commit 47622e1
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions tools/chapel-py/chplcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import chapel
import chapel.core
import chapel.replace
import re
import sys
import argparse
Expand Down Expand Up @@ -134,6 +135,20 @@ def check_reserved_prefix(node):
def check_redundant_block(node):
return node.block_style() != "unnecessary"

def check_misleading_indentation(node):
prev = None
for child in node:
yield from check_misleading_indentation(child)

if prev is not None:
if child.location().start()[1] == prev.location().start()[1]:
yield child

if isinstance(child, chapel.core.Loop) and child.block_style() == "implicit":
grandchildren = list(child)
if len(grandchildren) > 0:
prev = list(grandchildren[-1])[0]

Rules = [
("CamelCaseVariables", chapel.core.VarLikeDecl, check_camel_case_var),
("CamelCaseRecords", chapel.core.Record, check_camel_case),
Expand Down Expand Up @@ -162,5 +177,8 @@ def main():
for group in consecutive_decls(ast):
report_violation(group[1], "ConsecutiveDecls")

for node in check_misleading_indentation(ast):
report_violation(node, "MisleadingIndentation")

if __name__ == "__main__":
main()

0 comments on commit 47622e1

Please sign in to comment.