2525import org .openrewrite .java .search .UsesJavaVersion ;
2626import org .openrewrite .java .tree .Expression ;
2727import org .openrewrite .java .tree .J ;
28+ import org .openrewrite .java .tree .TypeUtils ;
2829
2930import static java .lang .String .format ;
3031import static org .openrewrite .java .tree .JavaType .Primitive .*;
3334@ Value
3435public class UseVarForPrimitive extends Recipe {
3536
36- String displayName = "Use `var` for primitive-typed variables" ;
37+ String displayName = "Use `var` for primitive and String variables" ;
3738
3839
39- String description = "Try to apply local variable type inference `var` to primitive variables where possible. " +
40- "This recipe will not touch variable declarations with initializers containing ternary operators." ;
40+ String description = "Try to apply local variable type inference `var` to primitive and String literal variables where possible. " +
41+ "This recipe will not touch variable declarations with initializers containing ternary operators." ;
4142
4243
4344 @ Override
@@ -49,46 +50,45 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
4950
5051 static final class VarForPrimitivesVisitor extends JavaIsoVisitor <ExecutionContext > {
5152 @ Override
52- public J .VariableDeclarations visitVariableDeclarations (J .VariableDeclarations vd , ExecutionContext ctx ) {
53- vd = super .visitVariableDeclarations (vd , ctx );
53+ public J .VariableDeclarations visitVariableDeclarations (J .VariableDeclarations vardecl , ExecutionContext ctx ) {
54+ J . VariableDeclarations vd = super .visitVariableDeclarations (vardecl , ctx );
5455
55- boolean isGeneralApplicable = DeclarationCheck .isVarApplicable (this .getCursor (), vd );
56- if (!isGeneralApplicable ) {
56+ if (!DeclarationCheck .isVarApplicable (this .getCursor (), vd )) {
5757 return vd ;
5858 }
5959
60- // Recipe specific
61- boolean isNoPrimitive = !DeclarationCheck .isPrimitive (vd );
62- boolean isByteVariable = DeclarationCheck .declarationHasType (vd , Byte );
63- boolean isShortVariable = DeclarationCheck .declarationHasType (vd , Short );
64- if (isNoPrimitive || isByteVariable || isShortVariable ) {
65- return vd ;
60+ if (isStringLiteralInitializer (vd )) {
61+ return DeclarationCheck .transformToVar (vd );
62+ }
63+ if (DeclarationCheck .isPrimitive (vd ) &&
64+ !DeclarationCheck .declarationHasType (vd , Byte ) &&
65+ !DeclarationCheck .declarationHasType (vd , Short )) {
66+ return DeclarationCheck .transformToVar (vd , it -> it instanceof J .Literal ? expandWithPrimitiveTypeHint (vd , it ) : it );
6667 }
68+ return vd ;
69+ }
6770
68- J .VariableDeclarations finalVd = vd ;
69- return DeclarationCheck .transformToVar (vd , it -> it instanceof J .Literal ? expandWithPrimitivTypeHint (finalVd , it ) : it );
71+ private boolean isStringLiteralInitializer (J .VariableDeclarations vd ) {
72+ if (!TypeUtils .isOfClassType (vd .getType (), "java.lang.String" )) {
73+ return false ;
74+ }
75+ Expression initializer = vd .getVariables ().get (0 ).getInitializer ();
76+ return initializer != null && initializer .unwrap () instanceof J .Literal ;
7077 }
7178
72- private Expression expandWithPrimitivTypeHint (J .VariableDeclarations vd , Expression initializer ) {
79+ private Expression expandWithPrimitiveTypeHint (J .VariableDeclarations vd , Expression initializer ) {
7380 String valueSource = ((J .Literal ) initializer ).getValueSource ();
7481
7582 if (valueSource == null ) {
7683 return initializer ;
7784 }
7885
79- boolean isLongLiteral = Long == vd .getType ();
80- boolean inferredAsLong = valueSource .endsWith ("l" ) || valueSource .endsWith ("L" );
81- boolean isFloatLiteral = Float == vd .getType ();
82- boolean inferredAsFloat = valueSource .endsWith ("f" ) || valueSource .endsWith ("F" );
83- boolean isDoubleLiteral = Double == vd .getType ();
84- boolean inferredAsDouble = valueSource .endsWith ("d" ) || valueSource .endsWith ("D" ) || valueSource .contains ("." );
85-
8686 String typNotation = null ;
87- if (isLongLiteral && !inferredAsLong ) {
87+ if (Long == vd . getType () && !( valueSource . endsWith ( "l" ) || valueSource . endsWith ( "L" )) ) {
8888 typNotation = "L" ;
89- } else if (isFloatLiteral && !inferredAsFloat ) {
89+ } else if (Float == vd . getType () && !( valueSource . endsWith ( "f" ) || valueSource . endsWith ( "F" )) ) {
9090 typNotation = "F" ;
91- } else if (isDoubleLiteral && !inferredAsDouble ) {
91+ } else if (Double == vd . getType () && !( valueSource . endsWith ( "d" ) || valueSource . endsWith ( "D" ) || valueSource . contains ( "." )) ) {
9292 typNotation = "D" ;
9393 }
9494
0 commit comments