1010
1111import java .io .IOException ;
1212import java .io .UncheckedIOException ;
13+ import java .util .HashSet ;
1314import java .util .List ;
1415import java .util .Set ;
16+ import java .util .stream .Stream ;
1517
1618import javax .annotation .processing .AbstractProcessor ;
1719import javax .annotation .processing .ProcessingEnvironment ;
1820import javax .annotation .processing .RoundEnvironment ;
1921import javax .annotation .processing .SupportedAnnotationTypes ;
2022import javax .lang .model .SourceVersion ;
23+ import javax .lang .model .element .Element ;
2124import javax .lang .model .element .ElementKind ;
2225import javax .lang .model .element .Name ;
2326import javax .lang .model .element .RecordComponentElement ;
@@ -53,7 +56,6 @@ public synchronized void init(ProcessingEnvironment env) {
5356
5457 @ Override
5558 public boolean process (Set <? extends TypeElement > tes , RoundEnvironment roundEnv ) {
56-
5759 APContext .setProjectModuleElement (tes , roundEnv );
5860 final var globalTypeInitializers =
5961 roundEnv .getElementsAnnotatedWith (typeElement (GlobalPrism .PRISM_TYPE )).stream ()
@@ -62,9 +64,13 @@ public boolean process(Set<? extends TypeElement> tes, RoundEnvironment roundEnv
6264
6365 InitMap .putAll (globalTypeInitializers );
6466
65- for (final TypeElement type :
66- ElementFilter .typesIn (
67- roundEnv .getElementsAnnotatedWith (typeElement (RecordBuilderPrism .PRISM_TYPE )))) {
67+ var elements = roundEnv .getElementsAnnotatedWith (typeElement (RecordBuilderPrism .PRISM_TYPE ));
68+
69+ var records = new HashSet <>(ElementFilter .typesIn (elements ));
70+ allPackages (elements )
71+ .forEach (e -> findRecordsInPackage (e , records ));
72+
73+ for (final TypeElement type : records ) {
6874 if (type .getKind () != ElementKind .RECORD ) {
6975 logError (type , "Builders can only be generated for record classes" );
7076 continue ;
@@ -93,12 +99,46 @@ public boolean process(Set<? extends TypeElement> tes, RoundEnvironment roundEnv
9399 return false ;
94100 }
95101
102+ private static Stream <? extends Element > allPackages (Set <? extends Element > elements ) {
103+ return Stream .concat (
104+ modulePackages (elements ),
105+ ElementFilter .packagesIn (elements ).stream ());
106+ }
107+
108+ private static Stream <? extends Element > modulePackages (Set <? extends Element > elements ) {
109+ return ElementFilter .modulesIn (elements ).stream ()
110+ .map (Element ::getEnclosedElements )
111+ .flatMap (List ::stream );
112+ }
113+
114+ private void findRecordsInPackage (Element pkg , Set <TypeElement > records ) {
115+ for (var enclosedElement : ElementFilter .typesIn (pkg .getEnclosedElements ())) {
116+ if (enclosedElement .getKind () == ElementKind .RECORD ) {
117+ records .add (enclosedElement );
118+ }
119+ findNestedRecords (enclosedElement , records );
120+ }
121+ }
122+
123+ private void findNestedRecords (TypeElement type , Set <TypeElement > types ) {
124+ for (var enclosedElement : ElementFilter .typesIn (type .getEnclosedElements ())) {
125+ if (enclosedElement .getKind () == ElementKind .RECORD ) {
126+ types .add (enclosedElement );
127+ }
128+ findNestedRecords (enclosedElement , types );
129+ }
130+ }
131+
96132 private void readElement (TypeElement type ) {
97- readElement (type , RecordBuilderPrism . getInstanceOn (type ));
133+ readElement (type , findRecordBuilderPrism (type ));
98134 }
99135
100- private void readElement (TypeElement type , BuilderPrism prism ) {
136+ private static RecordBuilderPrism findRecordBuilderPrism (Element element ) {
137+ var prism = RecordBuilderPrism .getInstanceOn (element );
138+ return prism != null ? prism : findRecordBuilderPrism (element .getEnclosingElement ());
139+ }
101140
141+ private void readElement (TypeElement type , BuilderPrism prism ) {
102142 final var components = type .getRecordComponents ();
103143 final var packageElement = elements ().getPackageOf (type );
104144 boolean isImported = prism .imported ();
@@ -136,9 +176,7 @@ private void methods(
136176 boolean getters = prism .getters ();
137177
138178 for (final var element : components ) {
139-
140179 final var type = UType .parse (element .asType ());
141-
142180 writer .append (
143181 MethodSetter .methodSetter (
144182 element .getSimpleName (), type .shortType (), builderName , typeParams ));
@@ -147,16 +185,13 @@ private void methods(
147185 }
148186
149187 if (APContext .isAssignable (type .mainType (), "java.util.Collection" )) {
150-
151188 String param0ShortType = type .param0 ().shortType ();
152189 Name simpleName = element .getSimpleName ();
153190 writer .append (
154- MethodAdd .methodAdd (
155- simpleName .toString (), builderName , param0ShortType , typeParams ));
191+ MethodAdd .methodAdd (simpleName .toString (), builderName , param0ShortType , typeParams ));
156192 }
157193
158194 if (APContext .isAssignable (type .mainType (), "java.util.Map" )) {
159-
160195 String param0ShortType = type .param0 ().shortType ();
161196 String param1ShortType = type .param1 ().shortType ();
162197 Name simpleName = element .getSimpleName ();
0 commit comments