4
4
import javax .lang .model .type .TypeMirror ;
5
5
import javax .lang .model .util .ElementFilter ;
6
6
7
+ import static java .util .stream .Collectors .toSet ;
8
+
7
9
import java .util .*;
8
10
import java .util .function .Supplier ;
9
11
import java .util .stream .Collectors ;
@@ -41,11 +43,8 @@ final class TypeReader {
41
43
private boolean nonAccessibleField ;
42
44
43
45
private final Map <String , Element > mixInFields ;
44
-
45
46
private final String typePropertyKey ;
46
-
47
47
private final Map <String , Integer > frequencyMap = new HashMap <>();
48
-
49
48
private final List <MethodProperty > methodProperties = new ArrayList <>();
50
49
51
50
private boolean optional ;
@@ -139,10 +138,9 @@ void read(TypeElement type) {
139
138
for (var param : constructor .getParams ()) {
140
139
var name = param .name ();
141
140
var element = param .element ();
142
- var matchingField =
143
- localFields .stream ()
144
- .filter (f -> f .propertyName ().equals (name ) || f .fieldName ().equals (name ))
145
- .findFirst ();
141
+ var matchingField = localFields .stream ()
142
+ .filter (f -> f .propertyName ().equals (name ) || f .fieldName ().equals (name ))
143
+ .findFirst ();
146
144
matchingField .ifPresentOrElse (f -> f .readParam (element ), () -> readField (element , localFields ));
147
145
}
148
146
}
@@ -161,7 +159,6 @@ void read(TypeElement type) {
161
159
} else {
162
160
commonField .addSubType (currentSubType );
163
161
}
164
-
165
162
if (commonField == null && currentSubType != null ) {
166
163
localField .setSubTypeField ();
167
164
}
@@ -172,22 +169,19 @@ void read(TypeElement type) {
172
169
private void readField (Element element , List <FieldReader > localFields ) {
173
170
final Element mixInField = mixInFields .get (element .getSimpleName ().toString ());
174
171
if (mixInField != null && APContext .types ().isSameType (mixInField .asType (), element .asType ())) {
175
-
176
172
var mixinModifiers = new HashSet <>(mixInField .getModifiers ());
177
173
var modifiers = new HashSet <>(mixInField .getModifiers ());
178
174
179
175
Arrays .stream (Modifier .values ())
180
- .filter (m -> m != Modifier .PRIVATE || m != Modifier .PROTECTED || m != Modifier .PUBLIC )
181
- .forEach (
182
- m -> {
183
- modifiers .remove (m );
184
- mixinModifiers .remove (m );
185
- });
176
+ .filter (m -> m != Modifier .PRIVATE || m != Modifier .PROTECTED || m != Modifier .PUBLIC )
177
+ .forEach (m -> {
178
+ modifiers .remove (m );
179
+ mixinModifiers .remove (m );
180
+ });
186
181
187
182
if (!modifiers .equals (mixinModifiers )) {
188
183
APContext .logError (mixInField , "mixIn fields must have the same modifiers as the target class" );
189
184
}
190
-
191
185
element = mixInField ;
192
186
}
193
187
if (element .asType ().toString ().contains ("java.util.Optional" )) {
@@ -304,13 +298,17 @@ private void matchFieldsToSetterOrConstructor() {
304
298
}
305
299
306
300
private void matchFieldToSetter (FieldReader field ) {
307
- if (!matchFieldToSetter2 (field , false )
301
+ if (hasNoSetter (field )) {
302
+ logError ("Non public field " + baseType + " " + field .fieldName () + " with no matching setter or constructor?" );
303
+ }
304
+ }
305
+
306
+ private boolean hasNoSetter (FieldReader field ) {
307
+ return !matchFieldToSetter2 (field , false )
308
308
&& !matchFieldToSetter2 (field , true )
309
309
&& !matchFieldToSetterByParam (field )
310
310
&& !field .isPublicField ()
311
- && !field .isSubTypeField ()) {
312
- logError ("Non public field " + baseType + " " + field .fieldName () + " with no matching setter or constructor?" );
313
- }
311
+ && !field .isSubTypeField ();
314
312
}
315
313
316
314
private boolean matchFieldToSetterByParam (FieldReader field ) {
@@ -458,7 +456,26 @@ private MethodReader determineConstructor() {
458
456
// fallback to the single public constructor
459
457
return allPublic .get (0 );
460
458
}
461
- // find the largest constructor
459
+
460
+ // find the right constructor
461
+ var constructorFields = allFields .stream ()
462
+ .filter (FieldReader ::includeFromJson )
463
+ .filter (this ::hasNoSetter )
464
+ .map (f -> f .element ().asType ().toString ())
465
+ .map (Util ::trimAnnotations )
466
+ .collect (toSet ());
467
+
468
+ return allPublic .stream ()
469
+ .filter (c -> c .getParams ().size () == constructorFields .size ())
470
+ .filter (c -> c .getParams ().stream ()
471
+ .map (p -> p .element ().asType ().toString ())
472
+ .map (Util ::trimAnnotations )
473
+ .allMatch (constructorFields ::contains ))
474
+ .findFirst ()
475
+ .orElseGet (this ::largest );
476
+ }
477
+
478
+ private MethodReader largest () {
462
479
int argCount = 0 ;
463
480
MethodReader largestConstructor = null ;
464
481
for (MethodReader ctor : publicConstructors ) {
0 commit comments