Java
This page curates a list of example ast-grep rules to check and to rewrite Java code.
No Unused Vars in Java Has Fix
Description
Identifying unused variables is a common task in code refactoring. You should rely on a Java linter or IDE for this task rather than writing a custom rule in ast-grep, but for educational purposes, this rule demonstrates how to find unused variables in Java.
This approach makes some simplifying assumptions. We only consider local variable declarations and ignore the other many ways variables can be declared: Method Parameters, Fields, Class Variables, Constructor Parameters, Loop Variables, Exception Handler Parameters, Lambda Parameters, Annotation Parameters, Enum Constants, and Record Components. Now you may see why it is recommended to use a rule from an established linter or IDE rather than writing your own.
YAML
id: no-unused-vars rule: kind: local_variable_declaration all: - has: has: kind: identifier pattern: $IDENT - not: precedes: stopBy: end has: stopBy: end any: - { kind: identifier, pattern: $IDENT } - { has: {kind: identifier, pattern: $IDENT, stopBy: end}} fix: ''First, we identify the local variable declaration and capture the pattern of the identifier inside of it. Then we use not and precedes to only match the local variable declaration if the identifier we captured does not appear later in the code.
It is important to note that we use all here to force the ordering of the has rule to be before the not rule. This guarantees that the meta-variable $IDENT is captured by looking inside of the local variable declaration.
Additionally, when looking ahead in the code, we can't just look for the identifier directly, but for any node that may contain the identifier.
Example
String unused = "unused"; String used = "used"; System.out.println(used);Find Java field declarations of type String
Description
To extract all Java field names of type String is not as straightforward as one might think. A simple pattern like String $F; would only match fields declared without any modifiers or annotations. However, a pattern like $MOD String $F; cannot be correctly parsed by tree-sitter.
Use playground pattern debugger to explore the AST
You can use the playground's pattern tab to visualize the AST of class A { $MOD String $F; }.
field_declaration $MOD variable_declarator identifier: String ERROR identifier: $FTree-sitter does not think $MOD is a valid modifier, so it produces an ERROR.
While the valid AST for code like private String field; produces different AST structures:
field_declaration modifiers type_identifier variable_declarator identifier: fieldA more robust approach is to use a structural rule that targets field_declaration nodes and applies a has constraint on the type child node to match the type String. This method effectively captures fields regardless of their modifiers or annotations.
YAML
id: find-field-with-type language: java rule: kind: field_declaration has: field: type regex: ^String$Example
@Component class ABC extends Object{ @Resource private final String with_anno; private final String with_multi_mod; public String simple; }Contributed by
Inspired by the post discussion