Skip to content

Commit

Permalink
Add bracenewline.py
Browse files Browse the repository at this point in the history
  • Loading branch information
calcmogul committed May 6, 2024
1 parent 6694a03 commit 3ef1343
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 0 deletions.
2 changes: 2 additions & 0 deletions wpiformat/wpiformat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import sys

from wpiformat.bracecomment import BraceComment
from wpiformat.bracenewline import BraceNewline
from wpiformat.cidentlist import CIdentList
from wpiformat.clangformat import ClangFormat
from wpiformat.clangtidy import ClangTidy
Expand Down Expand Up @@ -516,6 +517,7 @@ def main():
# tasks so it can clean up their formatting.
task_pipeline = [
BraceComment(),
BraceNewline(),
CIdentList(),
EofNewline(),
GTestName(),
Expand Down
66 changes: 66 additions & 0 deletions wpiformat/wpiformat/bracenewline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""This task ensures braces are followed by two line separators."""

import re

from wpiformat.task import Task


class BraceNewline(Task):
def should_process_file(self, config_file, name):
return (
config_file.is_c_file(name)
or config_file.is_cpp_file(name)
or name.endswith("java")
)

def run_pipeline(self, config_file, name, lines):
linesep = Task.get_linesep(lines)

comment_regex = re.compile("//|/\*|\*/")

lines_list = lines.split(linesep)

in_multiline_comment = False
for i in range(len(lines_list)):
match = comment_regex.search(lines_list[i])
if not match:
line = lines_list[i].rstrip()
else:
# While in a multiline comment, we only care about "*/"
if in_multiline_comment:
if match.group() == "*/":
line = lines_list[i][match.start() + len("*/") :].rstrip()
in_multiline_comment = False
else:
line = lines_list[i][0 : match.start()].rstrip()

# If multiline comment is starting
if match.group() == "/*":
line = lines_list[i][0 : match.start()]
in_multiline_comment = True

# If comment ends on same line, handle it immediately
comment_end = lines_list[i].find("*/")
if comment_end != -1:
line += lines_list[i][comment_end + len("*/") :]
line = line.rstrip()
in_multiline_comment = False

if in_multiline_comment:
continue

# If line with "}" isn't at end of file
if i + 1 < len(lines_list) and line.endswith("}"):
next_line = lines_list[i + 1].lstrip()

# If next line is already empty, there's nothing to do
if len(next_line) > 0:
if (
next_line[0] != "}"
and "else" not in next_line
and "#endif" not in next_line
):
lines_list.insert(i + 1, "")
i += 1

return (linesep.join(lines_list), True)
156 changes: 156 additions & 0 deletions wpiformat/wpiformat/test/test_bracenewline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import os

from .test_tasktest import *
from wpiformat.bracenewline import BraceNewline


def test_bracenewline():
test = TaskTest(BraceNewline())

# Brackets on same line
test.add_input(
"./Test.cpp", "void func1() {}" + os.linesep + "void func2() {}" + os.linesep
)
test.add_output(
"void func1() {}" + os.linesep + os.linesep + "void func2() {}" + os.linesep,
True,
)

# Brackets on next line
test.add_input(
"./Test.cpp",
"void func1() {"
+ os.linesep
+ "}"
+ os.linesep
+ "void func2() {"
+ os.linesep
+ "}"
+ os.linesep,
)
test.add_output(
"void func1() {"
+ os.linesep
+ "}"
+ os.linesep
+ os.linesep
+ "void func2() {"
+ os.linesep
+ "}"
+ os.linesep,
True,
)

# Comments after brackets
test.add_input(
"./Test.cpp",
"void func1() {"
+ os.linesep
+ "} // This is a comment"
+ os.linesep
+ "void func2() {"
+ os.linesep
+ "} /* This is a comment */"
+ os.linesep
+ "void func3() {"
+ os.linesep
+ "}"
+ os.linesep,
)
test.add_output(
"void func1() {"
+ os.linesep
+ "} // This is a comment"
+ os.linesep
+ os.linesep
+ "void func2() {"
+ os.linesep
+ "} /* This is a comment */"
+ os.linesep
+ os.linesep
+ "void func3() {"
+ os.linesep
+ "}"
+ os.linesep,
True,
)

# Don't add line separators to uncondensed if statements (after last brace
# is OK)
test.add_input(
"./Test.cpp",
"void func1() {"
+ os.linesep
+ " if (1) {"
+ os.linesep
+ " }"
+ os.linesep
+ " else {"
+ os.linesep
+ " }"
+ os.linesep
+ "}"
+ os.linesep,
)
test.add_latest_input_as_output(True)

# Don't add line separators to condensed if statements (after last brace
# is OK)
test.add_input(
"./Test.cpp",
"void func1() {"
+ os.linesep
+ " if (1) {"
+ os.linesep
+ " } else if () {"
+ os.linesep
+ " } else {"
+ os.linesep
+ " // comment"
+ os.linesep
+ " }"
+ os.linesep
+ "}"
+ os.linesep,
)
test.add_latest_input_as_output(True)

# Don't add line separators before #endif statements
test.add_input(
"./Main.cpp",
"using decay_t = typename decay<T>::type;"
+ os.linesep
+ "} // namespace std"
+ os.linesep
+ "#endif"
+ os.linesep,
)
test.add_latest_input_as_output(True)

# Don't insert line separators within multiline comments
test.add_input(
"./Main.java",
"/* to fine tune the pid loop."
+ os.linesep
+ " *"
+ os.linesep
+ " * @return the {@link PIDController} used by this {@link PIDSubsystem}"
+ os.linesep
+ " */"
+ os.linesep
+ "public PIDController getPIDController() {"
+ os.linesep,
)
test.add_latest_input_as_output(True)

# Don't insert line separators within single line comments
test.add_input(
"./Main.java",
"// @return the {@link PIDController} used by this {@link PIDSubsystem}"
+ os.linesep
+ "public PIDController getPIDController() {"
+ os.linesep,
)
test.add_latest_input_as_output(True)

test.run(OutputType.FILE)

0 comments on commit 3ef1343

Please sign in to comment.