src/cleanup_rules/java/rules.toml (685 lines of code) (raw):
# Copyright (c) 2023 Uber Technologies, Inc.
#
# <p>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
# <p>http://www.apache.org/licenses/LICENSE-2.0
#
# <p>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.
# The language specific rules in this file are applied after the API specific change has been performed.
# Before:
# (true)
# After
# true
[[rules]]
name = "simplify_parenthesized_expression"
query = "(parenthesized_expression ([(true) (false) (identifier)] @expression)) @p_expr"
replace = "@expression"
replace_node = "p_expr"
is_seed_rule = false
groups = ["boolean_expression_simplify"]
# Before :
# if (true) { doSomething(); }
# After :
# { doSomething(); }
#
# Before :
# if (true) { doSomething(); } else { doSomethingElse();}
# After :
# { doSomething(); }
#
[[rules]]
groups = ["if_cleanup"]
name = "simplify_if_statement_true"
query = """
(
(if_statement
condition : (condition (true))
consequence : ((statement) @consequence))
@if_statement)
"""
replace = "@consequence"
replace_node = "if_statement"
is_seed_rule = false
# Before :
# if (true) { doSomething(); } else { doSomethingElse();}
# After :
# { doSomethingElse(); }
#
# Before :
# if (true) { doSomething(); }
# After :
#
[[rules]]
groups = ["if_cleanup"]
name = "simplify_if_statement_false"
query = """
(
(if_statement
condition : (condition (false))
consequence : ((statement) @consequence)
alternative : ((_) @alternative) ?)
@if_statement)"""
replace = "@alternative"
replace_node = "if_statement"
is_seed_rule = false
# Before :
# !false
# After :
# true
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_not_false"
query = """
(
(unary_expression
operator: "!"
operand: (false))
@unary_expression)
"""
replace = "true"
replace_node = "unary_expression"
is_seed_rule = false
# Before :
# !true
# After :
# false
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_not_true"
query = """
(
(unary_expression
operator: \"!\"
operand: (true))
@unary_expression)
"""
replace = "false"
replace_node = "unary_expression"
is_seed_rule = false
# Before :
# {
# someStepsBefore();
# {
# someSteps();
# }
# someStepsAfter();
# }
# After :
# {
# someStepsBefore();
# someSteps();
# someStepsAfter();
# }
#
[[rules]]
name = "remove_unnecessary_nested_block"
query = """
([
(block
(
(_)* @pre
(block (_)* @nested.statements) @nested.block
(_)* @post
)
)
(constructor_body
(
(_)* @pre
(block (_)* @nested.statements) @nested.block
(_)* @post
)
)
]@block)"""
replace = "@nested.statements"
replace_node = "nested.block"
is_seed_rule = false
# Before :
# true && abc()
# After :
# abc()
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_true_and_something"
query = """
(
(binary_expression
left: (true)
operator:"&&"
right : (_) @rhs)
) @binary_expression
"""
replace = "@rhs"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# abc() && true
# After :
# abc()
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_something_and_true"
query = """
(
(binary_expression
left : (_) @lhs
operator:"&&"
right: (true)
)
@binary_expression)"""
replace = "@lhs"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# false && abc()
# After :
# false
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_false_and_something"
query = """
(
(binary_expression
left: (false)
operator : "&&"
right : (_) @rhs
)
@binary_expression)"""
replace = "false"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# abc && false
# After :
# false
#
[[rules]]
name = "simplify_something_and_false"
groups = ["boolean_expression_simplify"]
query = """
(
(binary_expression
left : (_) @lhs
operator : "&&"
right: (false)) @binary_expression
)
"""
replace = "false"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# abc || true
# After :
# true
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_something_or_true"
query = """
(
(binary_expression
left : (_) @lhs
operator:"||"
right: (true)
)
@binary_expression)"""
replace = "true"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# true || abc()
# After :
# true
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_true_or_something"
query = """
(
(binary_expression
left : (true)
operator:"||"
right: (_) @rhs
)
@binary_expression)
"""
replace = "true"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# abc() || false
# After :
# abc()
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_something_or_false"
query = """(
(
binary_expression
left : (_) @lhs
operator:"||"
right: (false)
)
@binary_expression)"""
replace = "@lhs"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# false || abc()
# After :
# abc()
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_false_or_something"
query = """
(
(binary_expression
left : (false)
operator:"||"
right: (_) @rhs
)
@binary_expression)"""
replace = "@rhs"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# (x) == x
# x == (x)
# x == x
# After :
# true
# true
# true
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_equals_equals_true"
query = """
(
(binary_expression
left : [(parenthesized_expression (_) @lhs) (_) @lhs]
operator:"=="
right: [(parenthesized_expression (_) @rhs) (_) @rhs]
)
@binary_expression
(#eq? @lhs @rhs)
)"""
replace = "true"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# false == true
# true == false
# After :
# false
# false
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_equals_equals_false"
query = """
(
(binary_expression
left : [(false) @lhs (true) @lhs (string_literal) (decimal_integer_literal) @lhs (decimal_floating_point_literal) @lhs]
operator:"=="
right: [(false) @rhs (true) @rhs (string_literal) @rhs (decimal_integer_literal) @rhs (decimal_floating_point_literal) @rhs]
)
@binary_expression
(#not-eq? @lhs @rhs)
)"""
replace = "false"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# false != false
# true != true
# After :
# false
# false
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_not_equals_false"
query = """
(
(binary_expression
left : [(false) @lhs (true) @lhs (string_literal) (decimal_integer_literal) @lhs (decimal_floating_point_literal) @lhs]
operator:"!="
right: [(false) @rhs (true) @rhs (string_literal) @rhs (decimal_integer_literal) @rhs (decimal_floating_point_literal) @rhs]
)
@binary_expression
(#eq? @lhs @rhs)
)"""
replace = "false"
replace_node = "binary_expression"
is_seed_rule = false
# Before:
# false != true
# true != false
# After :
# true
# true
#
[[rules]]
groups = ["boolean_expression_simplify"]
name = "simplify_not_equals_true"
query = """
(
(binary_expression
left : [(false) @lhs (true) @lhs (string_literal) (decimal_integer_literal) @lhs (decimal_floating_point_literal) @lhs]
operator:"!="
right: [(false) @rhs (true) @rhs (string_literal) @rhs (decimal_integer_literal) @rhs (decimal_floating_point_literal) @rhs]
)
@binary_expression
(#not-eq? @lhs @rhs)
)"""
replace = "true"
replace_node = "binary_expression"
is_seed_rule = false
# Before :
# {
# something();
# return 10;
# somethingMore();
# return 100;
# }
# After :
# {
# something();
# return 10;
# }
#
[[rules]]
name = "delete_all_statements_after_return"
query = """(
(block ((statement)* @pre)
((return_statement) @r)
((statement)+ @post)) @b)"""
replace = ""
replace_node = "post"
is_seed_rule = false
# Before :
# condition ? abc() : abc();
# After :
# abc()
#
[[rules]]
groups = ["if_cleanup"]
name = "simplify_ternary_similar_consequent_alternative"
query = """
(
(ternary_expression condition: (_)
consequence: (_)* @consequence
alternative: (_)* @alternative)
@ternary_expression
(#eq? @consequence @alternative)
)"""
replace = "@consequence"
replace_node = "ternary_expression"
is_seed_rule = false
# Before :
# true ? abc() : def();
# After :
# abc()
#
[[rules]]
groups = ["if_cleanup"]
name = "simplify_ternary_operator_true"
query = """
(
(ternary_expression condition: (true)
consequence: (_)* @consequence
alternative: (_)* @alternative)
@ternary_expression)"""
replace = "@consequence"
replace_node = "ternary_expression"
is_seed_rule = false
# Before :
# false ? abc() : def();
# After :
# def()
#
[[rules]]
groups = ["if_cleanup"]
name = "simplify_ternary_operator_false"
query = """
(
(ternary_expression condition: (false)
consequence: (_)* @consequence
alternative: (_)* @alternative)
@ternary_expression)"""
replace = "@alternative"
replace_node = "ternary_expression"
is_seed_rule = false
[[rules]]
name = "delete_empty_enum_declaration"
query = """
(enum_declaration) @enum_declaration"""
replace = ""
replace_node = "enum_declaration"
is_seed_rule = false
[[rules.filters]]
enclosing_node = "(enum_declaration) @ed"
not_contains = ["(enum_constant) @ec"]
# This rule deltes all the content of the file if it contains
# no type declaration, enum declaration and annotation type declaration.
#
# It optionally captures the @package_name for the deleted file.
[[rules]]
name = "delete_file_with_no_type_declarations"
query = """(
(program
(package_declaration (_) @package_name)?) @program)"""
replace = ""
replace_node = "program"
is_seed_rule = false
[[rules.filters]]
enclosing_node = "(program) @c_program"
not_contains = [
"(enum_declaration) @c_enum_declaration",
"(class_declaration) @c_class_declaration",
"(interface_declaration) @c_interface_declaration",
"(annotation_type_declaration) @c_annotation_type_declaration",
"(module_declaration) @c_module_declaration",
"(record_declaration) @c_arecord_declaration",
]
# This rule is part (and entry point) for the inline local variable cleanup. Example:
#
# Before :
# public foo someMethod() {
# boolean isFlag = true;
# somethingElse();
# }
#
# After :
# public foo someMethod() {
# somethingElse();
# }
#
# Before inlining a variable we need to ensure that the variable is not re assigned anywhere within the method body
# to a value which is not the same as the initializer of variable we are inlining..
# Note the below negative example of this rule where the variable `isFlag` is re-assigned to the value `getFlagStatus()` while it's
# initializer is `true`. In such a scenario the variable `isFlag` should not be inlined.
#
# public foo someMethod() {
# boolean isFlag = true;
# isFlag = getFlagStatus();
# somethingElse();
# }
#
[[rules]]
name = "delete_variable_declaration"
query = """
(
((local_variable_declaration
declarator: (variable_declarator
name: (_) @variable_name
value: [(true) (false)] @init)) @variable_declaration)
)
"""
replace = ""
replace_node = "variable_declaration"
is_seed_rule = false
# Check if there is no assignment where the variable @variable_name is
# assigned to a value other than @init, within the method body
# Please note that the tree-sitter queries in the filter uses holes (i.e. `@variable_name` and `@init`).
# These holes will be filled contextually based on the code snippet matched to `rule.query
[[rules.filters]]
enclosing_node = "[(method_declaration) (constructor_declaration)] @md"
not_contains = ["""
(
((assignment_expression
left: (_) @a.lhs
right: (_) @a.rhs) @assignment)
(#eq? @a.lhs "@variable_name")
(#not-eq? @a.rhs "@init")
)"""]
# This rule is part (and entry point) of the inline field declaration cleanup.
# Same as the rule `delete_variable_declaration`, but applicable to fields.
[[rules]]
name = "delete_field_declaration"
query = """
(
((field_declaration
declarator: (variable_declarator
name: (_) @variable_name
value: [(true) (false)] @init)) @field_declaration)
)
"""
replace = ""
replace_node = "field_declaration"
is_seed_rule = false
# Check if there is no assignment where the variable @variable_name is
# assigned to a value other than @init, within the method body
[[rules.filters]]
enclosing_node = "(class_declaration) @cd"
not_contains = ["""(
((assignment_expression
left: (_) @a.lhs
right: (_) @a.rhs) @assignment)
(#eq? @a.lhs "@variable_name")
(#not-eq? @a.rhs "@init")
)"""]
# This rule is part of inline variable declaration and field declaration cleanup.
# Delete assignment for a particular (@variable_name, @init) if:
# (i) If the enclosing method does not contain a variable declaration for @variable_name
# (ii) If the Rhs of the assignment is same as the initializer of the variable it previously inlined.
[[rules]]
name = "delete_boolean_assignments_for_variable"
query = """
(
(expression_statement (assignment_expression
left: (_) @l
right: (_) @r)) @expression_statement
(#eq? @l "@variable_name")
(#eq? @r "@init")
)
"""
replace = ""
replace_node = "expression_statement"
is_seed_rule = false
holes = ["variable_name", "init"]
# The enclosing methode declaration should not contain a local variable decalration named "@variable_name"
# which is initialized to "@init".
[[rules.filters]]
enclosing_node = "[(method_declaration) (constructor_declaration)] @md"
not_contains = ["""(
((local_variable_declaration
declarator: (variable_declarator
name: (_) @vdcl.lhs
value: (_) @vdcl.init)) @field_declaration)
(#eq? @vdcl.lhs "@l")
)"""]
# This rule is part (and entry point) of the inline variable / field declaration.
# delete assignment if
# (i) if it is the only assignment in the entire class in the enclosing class
# (ii) There is a field declaration with the same rhs as this assignment in the enclosing class
# (iii) There is no local variable declaration of the same name in the enclosing method
[[rules]]
name = "delete_parent_assignment"
query = """
(
(expression_statement (assignment_expression
left: (_) @variable_name
right: (_) @init)) @expression_statement
)
"""
replace = ""
replace_node = "expression_statement"
is_seed_rule = false
# The enclosing methode declaration should not contain a local variable decalration named "@variable_name"
[[rules.filters]]
enclosing_node = "(method_declaration) @md"
not_contains = [
"""(
((local_variable_declaration
declarator: (variable_declarator
name: (_) @vdcl.lhs
value: (_)? @vdcl.init)) @variable_declaration)
(#eq? @vdcl.lhs "@variable_name")
)""",
]
[[rules.filters]]
# There should exist no field declaration named `@variable_name` and
# there should be no assignments to @variable_name that are not same as `@init`.
enclosing_node = "(class_declaration) @cd"
not_contains = ["""(
((assignment_expression
left: (_) @a.lhs
right: (_) @a.rhs) @a)
(#eq? @a.lhs "@variable_name")
(#not-eq? @a.rhs "@init")
)""", """(
((field_declaration
declarator: (variable_declarator
name: (_) @fdcl.lhs
value: (_) @fdcl.init)) @field_declaration)
(#eq? @fdcl.lhs "@variable_name")
(#not-eq? @fdcl.init "@init")
)"""]
# Replace identifier with value if :
# (i) There is no local variable declaration in the enclosing method with the name as the identifier
# TODO: Add field filter
[[rules]]
name = "replace_identifier_with_value"
query = """
(
(identifier) @identifier
(#eq? @identifier "@variable_name")
)
"""
replace = "@init"
replace_node = "identifier"
holes = ["variable_name", "init"]
is_seed_rule = false
[[rules.filters]]
# There should exist no local variable declaration named `@identifer`
enclosing_node = "[(method_declaration) (constructor_declaration)] @md"
not_contains = ["""(
((local_variable_declaration
declarator: (variable_declarator
name: (_) @vdcl.lhs
value: (_) @vdcl.init)) @field_declaration)
(#eq? @vdcl.lhs "@identifier")
)"""]
# Dummy rule that acts as a junction for all boolean based cleanups
# Let's say you want to define rules from A -> B, A -> C, D -> B, D -> C, ...
# A pattern here is - if there is an outgoing edge to B there is another to C.
# In these cases, you can use a dummy rule X as shown below:
# X -> B, X - C, A -> X, D -> X, ...
[[rules]]
name = "boolean_literal_cleanup"
is_seed_rule = false
# Dummy rule that acts as a junction for all statement based cleanups
[[rules]]
name = "statement_cleanup"
is_seed_rule = false