diff --git a/synthtool/languages/java.py b/synthtool/languages/java.py index 82f2c56b1..fefc9e0db 100644 --- a/synthtool/languages/java.py +++ b/synthtool/languages/java.py @@ -15,6 +15,7 @@ import glob import os import xml.etree.ElementTree as ET +import re import requests import synthtool as s import synthtool.gcp as gcp @@ -398,3 +399,64 @@ def custom_templates(files: List[str], **kwargs) -> None: for file in files: template = gcp.CommonTemplates().render(file, **kwargs) s.copy([template]) + + +def remove_method(filename: str, signature: str): + """Helper to remove an entire method. + + Goes line-by-line to detect the start of the block. Determines + the end of the block by a closing brace at the same indentation + level. This requires the file to be correctly formatted. + + Example: consider the following class: + + class Example { + public void main(String[] args) { + System.out.println("Hello World"); + } + + public String foo() { + return "bar"; + } + } + + To remove the `main` method above, use: + + remove_method('path/to/file', 'public void main(String[] args)') + + Args: + filename (str): Path to source file + signature (str): Full signature of the method to remove. Example: + `public void main(String[] args)`. + """ + lines = [] + leading_regex = None + with open(filename, "r") as fp: + line = fp.readline() + while line: + # for each line, try to find the matching + regex = re.compile("(\\s*)" + re.escape(signature) + ".*") + match = regex.match(line) + if match: + leading_regex = re.compile(match.group(1) + "}") + line = fp.readline() + continue + + # not in a ignore block - preserve the line + if not leading_regex: + lines.append(line) + line = fp.readline() + continue + + # detect the closing tag based on the leading spaces + match = leading_regex.match(line) + if match: + # block is closed, resume capturing content + leading_regex = None + + line = fp.readline() + + with open(filename, "w") as fp: + for line in lines: + # print(line) + fp.write(line) diff --git a/tests/test_language_java.py b/tests/test_language_java.py index 7d97c58fd..f7e10cac6 100644 --- a/tests/test_language_java.py +++ b/tests/test_language_java.py @@ -113,3 +113,30 @@ def assert_valid_yaml(file): assert_valid_yaml(os.path.join(dirpath, file)) finally: os.chdir(cwd) + + +def test_remove_method(): + with tempfile.TemporaryDirectory() as tempdir: + shutil.copyfile( + "tests/testdata/SampleClass.java", tempdir + "/SampleClass.java" + ) + + java.remove_method(tempdir + "/SampleClass.java", "public static void foo()") + java.remove_method(tempdir + "/SampleClass.java", "public void asdf()") + assert_matches_golden( + "tests/testdata/SampleClassGolden.java", tempdir + "/SampleClass.java" + ) + + +def assert_matches_golden(expected, actual): + matching_lines = 0 + with open(actual, "rt") as fp: + with open(expected, "rt") as golden: + while True: + matching_lines += 1 + log_line = fp.readline() + expected = golden.readline() + assert log_line == expected + if not log_line: + break + assert matching_lines > 0 diff --git a/tests/testdata/SampleClass.java b/tests/testdata/SampleClass.java new file mode 100644 index 000000000..849548b9d --- /dev/null +++ b/tests/testdata/SampleClass.java @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dlp; + +class ExampleClass { + public static void foo() { + System.out.println("bar"); + } + + public static class InnerClass { + public void asdf() { + System.out.println("qwer"); + } + } +} diff --git a/tests/testdata/SampleClassGolden.java b/tests/testdata/SampleClassGolden.java new file mode 100644 index 000000000..dbe1fe9d1 --- /dev/null +++ b/tests/testdata/SampleClassGolden.java @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dlp; + +class ExampleClass { + + public static class InnerClass { + } +}