Skip to content

Commit 9ff31c2

Browse files
committed
Add bracenewline.py
Also renamed newline.py to eofnewline.py.
1 parent 9cb9ab6 commit 9ff31c2

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

wpiformat/wpiformat/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99

1010
from wpiformat.bracecomment import BraceComment
11+
from wpiformat.bracenewline import BraceNewline
1112
from wpiformat.cidentlist import CIdentList
1213
from wpiformat.clangformat import ClangFormat
1314
from wpiformat.config import Config
@@ -349,6 +350,7 @@ def main():
349350
# so it can clean up their formatting.
350351
task_pipeline = [
351352
BraceComment(),
353+
BraceNewline(),
352354
CIdentList(),
353355
EofNewline(),
354356
IncludeGuard(),

wpiformat/wpiformat/bracenewline.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""This task ensures braces are followed by two line separators."""
2+
3+
import re
4+
5+
from wpiformat.task import Task
6+
7+
8+
class BraceNewline(Task):
9+
10+
def should_process_file(self, config_file, name):
11+
return config_file.is_c_file(name) or config_file.is_cpp_file(
12+
name) or name.endswith("java")
13+
14+
def run_pipeline(self, config_file, name, lines):
15+
linesep = Task.get_linesep(lines)
16+
17+
comment_regex = re.compile("//|/\*|\*/")
18+
19+
lines_list = lines.split(linesep)
20+
21+
in_multiline_comment = False
22+
for i in range(len(lines_list)):
23+
match = comment_regex.search(lines_list[i])
24+
if not match:
25+
line = lines_list[i].rstrip()
26+
else:
27+
# While in a multiline comment, we only care about "*/"
28+
if in_multiline_comment:
29+
if match.group() == "*/":
30+
line = lines_list[i][match.start() +
31+
len("*/"):].rstrip()
32+
in_multiline_comment = False
33+
else:
34+
line = lines_list[i][0:match.start()].rstrip()
35+
36+
# If multiline comment is starting
37+
if match.group() == "/*":
38+
line = lines_list[i][0:match.start()]
39+
in_multiline_comment = True
40+
41+
# If comment ends on same line, handle it immediately
42+
comment_end = lines_list[i].find("*/")
43+
if comment_end != -1:
44+
line += lines_list[i][comment_end + len("*/"):]
45+
line = line.rstrip()
46+
in_multiline_comment = False
47+
48+
if in_multiline_comment:
49+
continue
50+
51+
# If line with "}" isn't at end of file
52+
if i + 1 < len(lines_list) and line.endswith("}"):
53+
next_line = lines_list[i + 1].lstrip()
54+
55+
# If next line is already empty, there's nothing to do
56+
if len(next_line) > 0:
57+
if next_line[
58+
0] != "}" and "else" not in next_line and "#endif" not in next_line:
59+
lines_list.insert(i + 1, "")
60+
i += 1
61+
62+
return (linesep.join(lines_list), True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import os
2+
3+
from .tasktest import *
4+
from wpiformat.bracenewline import BraceNewline
5+
6+
7+
def test_bracenewline():
8+
test = TaskTest(BraceNewline())
9+
10+
# Brackets on same line
11+
test.add_input("./Test.cpp",
12+
"void func1() {}" + os.linesep + \
13+
"void func2() {}" + os.linesep)
14+
test.add_output(
15+
"void func1() {}" + os.linesep + \
16+
os.linesep + \
17+
"void func2() {}" + os.linesep, True, True)
18+
19+
# Brackets on next line
20+
test.add_input("./Test.cpp",
21+
"void func1() {" + os.linesep + \
22+
"}" + os.linesep + \
23+
"void func2() {" + os.linesep + \
24+
"}" + os.linesep)
25+
test.add_output(
26+
"void func1() {" + os.linesep + \
27+
"}" + os.linesep + \
28+
os.linesep + \
29+
"void func2() {" + os.linesep + \
30+
"}" + os.linesep, True, True)
31+
32+
# Comments after brackets
33+
test.add_input("./Test.cpp",
34+
"void func1() {" + os.linesep + \
35+
"} // This is a comment" + os.linesep + \
36+
"void func2() {" + os.linesep + \
37+
"} /* This is a comment */" + os.linesep + \
38+
"void func3() {" + os.linesep + \
39+
"}" + os.linesep)
40+
test.add_output(
41+
"void func1() {" + os.linesep + \
42+
"} // This is a comment" + os.linesep + \
43+
os.linesep + \
44+
"void func2() {" + os.linesep + \
45+
"} /* This is a comment */" + os.linesep + \
46+
os.linesep + \
47+
"void func3() {" + os.linesep + \
48+
"}" + os.linesep, True, True)
49+
50+
# Don't add line separators to uncondensed if statements (after last brace
51+
# is OK)
52+
test.add_input("./Test.cpp",
53+
"void func1() {" + os.linesep + \
54+
" if (1) {" + os.linesep + \
55+
" }" + os.linesep + \
56+
" else {" + os.linesep + \
57+
" }" + os.linesep + \
58+
"}" + os.linesep)
59+
test.add_latest_input_as_output(True)
60+
61+
# Don't add line separators to condensed if statements (after last brace
62+
# is OK)
63+
test.add_input("./Test.cpp",
64+
"void func1() {" + os.linesep + \
65+
" if (1) {" + os.linesep + \
66+
" } else if () {" + os.linesep + \
67+
" } else {" + os.linesep + \
68+
" // comment" + os.linesep + \
69+
" }" + os.linesep + \
70+
"}" + os.linesep)
71+
test.add_latest_input_as_output(True)
72+
73+
# Don't add line separators before #endif statements
74+
test.add_input("./Main.cpp",
75+
"using decay_t = typename decay<T>::type;" + os.linesep + \
76+
"} // namespace std" + os.linesep + \
77+
"#endif" + os.linesep)
78+
test.add_latest_input_as_output(True)
79+
80+
# Don't insert line separators within multiline comments
81+
test.add_input("./Main.java",
82+
"/* to fine tune the pid loop." + os.linesep + \
83+
" *" + os.linesep + \
84+
" * @return the {@link PIDController} used by this {@link PIDSubsystem}" + os.linesep + \
85+
" */" + os.linesep + \
86+
"public PIDController getPIDController() {" + os.linesep)
87+
test.add_latest_input_as_output(True)
88+
89+
# Don't insert line separators within single line comments
90+
test.add_input("./Main.java",
91+
"// @return the {@link PIDController} used by this {@link PIDSubsystem}" + os.linesep + \
92+
"public PIDController getPIDController() {" + os.linesep)
93+
test.add_latest_input_as_output(True)
94+
95+
test.run(OutputType.FILE)

0 commit comments

Comments
 (0)