From 54ca24f6e5e3c675c6985967ad0f337623fa55a1 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Sun, 15 Oct 2017 13:40:18 -0700 Subject: [PATCH] Add bracenewline.py Also renamed newline.py to eofnewline.py. --- wpiformat/test/test_bracenewline.py | 95 +++++++++++++++++++ .../{test_newline.py => test_eofnewline.py} | 6 +- wpiformat/wpiformat/__init__.py | 6 +- wpiformat/wpiformat/bracenewline.py | 66 +++++++++++++ .../wpiformat/{newline.py => eofnewline.py} | 2 +- 5 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 wpiformat/test/test_bracenewline.py rename wpiformat/test/{test_newline.py => test_eofnewline.py} (90%) create mode 100644 wpiformat/wpiformat/bracenewline.py rename wpiformat/wpiformat/{newline.py => eofnewline.py} (93%) diff --git a/wpiformat/test/test_bracenewline.py b/wpiformat/test/test_bracenewline.py new file mode 100644 index 00000000..ee336e30 --- /dev/null +++ b/wpiformat/test/test_bracenewline.py @@ -0,0 +1,95 @@ +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, 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, 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, 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::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) diff --git a/wpiformat/test/test_newline.py b/wpiformat/test/test_eofnewline.py similarity index 90% rename from wpiformat/test/test_newline.py rename to wpiformat/test/test_eofnewline.py index b53e9a06..065d0532 100644 --- a/wpiformat/test/test_newline.py +++ b/wpiformat/test/test_eofnewline.py @@ -1,11 +1,11 @@ import os from test.tasktest import * -from wpiformat.newline import Newline +from wpiformat.eofnewline import EofNewline -def test_newline(): - test = TaskTest(Newline()) +def test_eofnewline(): + test = TaskTest(EofNewline()) file_appendix = \ "#pragma once" + os.linesep + \ diff --git a/wpiformat/wpiformat/__init__.py b/wpiformat/wpiformat/__init__.py index 834903f1..8b5143b2 100644 --- a/wpiformat/wpiformat/__init__.py +++ b/wpiformat/wpiformat/__init__.py @@ -9,16 +9,17 @@ import sys from wpiformat.bracecomment import BraceComment +from wpiformat.bracenewline import BraceNewline from wpiformat.cidentlist import CIdentList from wpiformat.clangformat import ClangFormat from wpiformat.config import Config +from wpiformat.eofnewline import EofNewline from wpiformat.includeguard import IncludeGuard from wpiformat.includeorder import IncludeOrder from wpiformat.javaclass import JavaClass from wpiformat.jni import Jni from wpiformat.licenseupdate import LicenseUpdate from wpiformat.lint import Lint -from wpiformat.newline import Newline from wpiformat.pyformat import PyFormat from wpiformat.stdlib import Stdlib from wpiformat.task import Task @@ -331,11 +332,12 @@ def main(): # so it can clean up their formatting. task_pipeline = [ BraceComment(), + BraceNewline(), CIdentList(), + EofNewline(), IncludeGuard(), LicenseUpdate(str(args.year)), JavaClass(), - Newline(), Stdlib(), IncludeOrder(), UsingDeclaration(), diff --git a/wpiformat/wpiformat/bracenewline.py b/wpiformat/wpiformat/bracenewline.py new file mode 100644 index 00000000..d8828997 --- /dev/null +++ b/wpiformat/wpiformat/bracenewline.py @@ -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 + + output = linesep.join(lines_list) + + if output != lines: + return (output, True, True) + else: + return (lines, False, True) diff --git a/wpiformat/wpiformat/newline.py b/wpiformat/wpiformat/eofnewline.py similarity index 93% rename from wpiformat/wpiformat/newline.py rename to wpiformat/wpiformat/eofnewline.py index 12510c64..b6cfa7bf 100644 --- a/wpiformat/wpiformat/newline.py +++ b/wpiformat/wpiformat/eofnewline.py @@ -3,7 +3,7 @@ from wpiformat.task import Task -class Newline(Task): +class EofNewline(Task): def run_pipeline(self, config_file, name, lines): output = lines.rstrip() + Task.get_linesep(lines)