1515import java .util .List ;
1616import java .util .Objects ;
1717import java .util .Optional ;
18+ import java .util .concurrent .atomic .AtomicBoolean ;
1819import java .util .stream .Collectors ;
1920
2021import org .jspecify .annotations .NonNull ;
3435import org .openrewrite .java .tree .J .Assignment ;
3536import org .openrewrite .java .tree .J .Block ;
3637import org .openrewrite .java .tree .J .ClassDeclaration ;
38+ import org .openrewrite .java .tree .J .Identifier ;
3739import org .openrewrite .java .tree .J .MethodDeclaration ;
3840import org .openrewrite .java .tree .J .VariableDeclarations ;
3941import org .openrewrite .java .tree .JLeftPadded ;
@@ -113,7 +115,7 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ct
113115 } else if (constructors .size () == 1 ) {
114116 MethodDeclaration c = constructors .get (0 );
115117 getCursor ().putMessage ("applicableConstructor" , c );
116- applicable = isNotConstructorInitializingField (c , fieldName );
118+ applicable = ! isConstructorInitializingField (c , fieldName );
117119 } else {
118120 List <MethodDeclaration > autowiredConstructors = constructors .stream ()
119121 .filter (constr -> constr .getLeadingAnnotations ().stream ()
@@ -123,7 +125,7 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ct
123125 if (autowiredConstructors .size () == 1 ) {
124126 MethodDeclaration c = autowiredConstructors .get (0 );
125127 getCursor ().putMessage ("applicableConstructor" , autowiredConstructors .get (0 ));
126- applicable = isNotConstructorInitializingField (c , fieldName );
128+ applicable = ! isConstructorInitializingField (c , fieldName );
127129 }
128130 }
129131 if (applicable ) {
@@ -133,31 +135,6 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ct
133135 return super .visitClassDeclaration (classDecl , ctx );
134136 }
135137
136- public static boolean isNotConstructorInitializingField (MethodDeclaration c , String fieldName ) {
137- return c .getBody () == null || c .getBody ().getStatements ().stream ().filter (J .Assignment .class ::isInstance )
138- .map (J .Assignment .class ::cast ).noneMatch (a -> {
139- Expression expr = a .getVariable ();
140- if (expr instanceof J .FieldAccess ) {
141- J .FieldAccess fa = (J .FieldAccess ) expr ;
142- if (fieldName .equals (fa .getSimpleName ()) && fa .getTarget () instanceof J .Identifier ) {
143- J .Identifier target = (J .Identifier ) fa .getTarget ();
144- if ("this" .equals (target .getSimpleName ())) {
145- return true ;
146- }
147- }
148- }
149- if (expr instanceof J .Identifier ) {
150- JavaType .Variable fieldType = c .getMethodType ().getDeclaringType ().getMembers ().stream ()
151- .filter (v -> fieldName .equals (v .getName ())).findFirst ().orElse (null );
152- if (fieldType != null ) {
153- J .Identifier identifier = (J .Identifier ) expr ;
154- return fieldType .equals (identifier .getFieldType ());
155- }
156- }
157- return false ;
158- });
159- }
160-
161138 @ Override
162139 public J .VariableDeclarations visitVariableDeclarations (J .VariableDeclarations multiVariable ,
163140 ExecutionContext ctx ) {
@@ -285,20 +262,22 @@ public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, Execut
285262 md = md .withParameters (newParams );
286263 updateCursor (md );
287264
288- // noinspection ConstantConditions
289- ShallowClass type = JavaType .ShallowClass .build (methodType );
290- J .FieldAccess fa = new J .FieldAccess (Tree .randomId (), Space .EMPTY , Markers .EMPTY , new J .Identifier (Tree .randomId (), Space .EMPTY , Markers .EMPTY , Collections .emptyList (), "this" , md .getMethodType ().getDeclaringType (), null ), JLeftPadded .build (createFieldNameIdentifier ()), type );
291- Assignment assign = new J .Assignment (Tree .randomId (), Space .build ("\n " , Collections .emptyList ()), Markers .EMPTY , fa , JLeftPadded .build (createFieldNameIdentifier ()), type );
292- assign = autoFormat (assign , p , getCursor ());
293- List <Statement > newStatements = new ArrayList <>(md .getBody ().getStatements ());
294- boolean empty = newStatements .isEmpty ();
295- if (empty ) {
296- newStatements .add (assign );
297- md = md .withBody (autoFormat (md .getBody ().withStatements (newStatements ), p , getCursor ()));
298- } else {
299- // Prefix is off otherwise even after autoFormat
300- newStatements .add (assign .withPrefix (newStatements .get (newStatements .size () - 1 ).getPrefix ()));
301- md = md .withBody (md .getBody ().withStatements (newStatements ));
265+ if (!isConstructorInitializingField (md , fieldName )) {
266+ // noinspection ConstantConditions
267+ ShallowClass type = JavaType .ShallowClass .build (methodType );
268+ J .FieldAccess fa = new J .FieldAccess (Tree .randomId (), Space .EMPTY , Markers .EMPTY , new J .Identifier (Tree .randomId (), Space .EMPTY , Markers .EMPTY , Collections .emptyList (), "this" , md .getMethodType ().getDeclaringType (), null ), JLeftPadded .build (createFieldNameIdentifier ()), type );
269+ Assignment assign = new J .Assignment (Tree .randomId (), Space .build ("\n " , Collections .emptyList ()), Markers .EMPTY , fa , JLeftPadded .build (createFieldNameIdentifier ()), type );
270+ assign = autoFormat (assign , p , getCursor ());
271+ List <Statement > newStatements = new ArrayList <>(md .getBody ().getStatements ());
272+ boolean empty = newStatements .isEmpty ();
273+ if (empty ) {
274+ newStatements .add (assign );
275+ md = md .withBody (autoFormat (md .getBody ().withStatements (newStatements ), p , getCursor ()));
276+ } else {
277+ // Prefix is off otherwise even after autoFormat
278+ newStatements .add (assign .withPrefix (newStatements .get (newStatements .size () - 1 ).getPrefix ()));
279+ md = md .withBody (md .getBody ().withStatements (newStatements ));
280+ }
302281 }
303282 }
304283 return md ;
@@ -321,4 +300,48 @@ private static String getFieldType(JavaType.FullyQualified fullyQualifiedType) {
321300
322301 return fullyQualifiedType .getClassName ();
323302 }
303+
304+ private static boolean isConstructorInitializingField (MethodDeclaration c , String fieldName ) {
305+ AtomicBoolean res = new AtomicBoolean ();
306+ new JavaIsoVisitor <AtomicBoolean >() {
307+
308+ @ Override
309+ public Assignment visitAssignment (Assignment assignment , AtomicBoolean ab ) {
310+ if (ab .get () || getCursor ().firstEnclosing (MethodDeclaration .class ) != c ) {
311+ return assignment ;
312+ }
313+ Assignment a = super .visitAssignment (assignment , ab );
314+ Expression expr = a .getVariable ();
315+ if (expr instanceof J .FieldAccess ) {
316+ J .FieldAccess fa = (J .FieldAccess ) expr ;
317+ if (fieldName .equals (fa .getSimpleName ()) && fa .getTarget () instanceof J .Identifier ) {
318+ J .Identifier target = (J .Identifier ) fa .getTarget ();
319+ if ("this" .equals (target .getSimpleName ())) {
320+ ab .set (true );
321+ return a ;
322+ }
323+ }
324+ }
325+ return a ;
326+ }
327+
328+ @ Override
329+ public Identifier visitIdentifier (Identifier identifier , AtomicBoolean ab ) {
330+ if (ab .get () || getCursor ().firstEnclosing (MethodDeclaration .class ) != c ) {
331+ return identifier ;
332+ }
333+ Identifier id = super .visitIdentifier (identifier , ab );
334+ JavaType .Variable fieldType = c .getMethodType ().getDeclaringType ().getMembers ().stream ()
335+ .filter (v -> fieldName .equals (v .getName ())).findFirst ().orElse (null );
336+ if (fieldType != null && fieldType .equals (id .getFieldType ())) {
337+ ab .set (true );
338+ }
339+ return id ;
340+ }
341+ }.visit (c , res );
342+ return res .get ();
343+ }
344+
345+
346+
324347}
0 commit comments