2626import java .util .LinkedHashSet ;
2727import java .util .Map ;
2828import java .util .Set ;
29+ import java .util .function .UnaryOperator ;
30+ import java .util .stream .Collectors ;
2931
3032import org .gradle .api .tasks .SourceSet ;
3133import org .gradle .testkit .runner .BuildResult ;
4042import org .junit .jupiter .params .provider .EnumSource ;
4143
4244import org .springframework .util .ClassUtils ;
45+ import org .springframework .util .CollectionUtils ;
4346import org .springframework .util .FileSystemUtils ;
4447import org .springframework .util .StringUtils ;
4548
@@ -65,7 +68,7 @@ class ArchitectureCheckTests {
6568
6669 @ BeforeEach
6770 void setup (@ TempDir Path projectDir ) {
68- this .gradleBuild = new GradleBuild (projectDir ).withNullMarked (false );
71+ this .gradleBuild = new GradleBuild (projectDir ).withNullMarkedEnabled (false );
6972 }
7073
7174 @ ParameterizedTest (name = "{0}" )
@@ -275,14 +278,23 @@ void whenBeanMethodExposesNonPrivateTypeShouldSucceedAndWriteEmptyReport(Task ta
275278 @ Test
276279 void whenPackageIsNotAnnotatedWithNullMarkedWithMainSourcesShouldFailAndWriteEmptyReport () throws IOException {
277280 prepareTask (Task .CHECK_ARCHITECTURE_MAIN , "nullmarked/notannotated" );
278- buildAndFail (this .gradleBuild .withNullMarked (true ), Task .CHECK_ARCHITECTURE_MAIN ,
281+ buildAndFail (this .gradleBuild .withNullMarkedEnabled (true ), Task .CHECK_ARCHITECTURE_MAIN ,
279282 "Package org.springframework.boot.build.architecture.nullmarked.notannotated is not annotated with @NullMarked" );
280283 }
281284
285+ @ Test
286+ void whenPackageIsIgnoredAndNotAnnotatedWithNullMarkedWithMainSourcesShouldSucceedAndWriteEmptyReport ()
287+ throws IOException {
288+ prepareTask (Task .CHECK_ARCHITECTURE_MAIN , "nullmarked/notannotated" );
289+ build (this .gradleBuild .withNullMarkedEnabled (true )
290+ .withNullMarkedIgnoredPackages ("org.springframework.boot.build.architecture.nullmarked.notannotated" ),
291+ Task .CHECK_ARCHITECTURE_MAIN );
292+ }
293+
282294 @ Test
283295 void whenPackageIsNotAnnotatedWithNullMarkedWithTestSourcesShouldSucceedAndWriteEmptyReport () throws IOException {
284296 prepareTask (Task .CHECK_ARCHITECTURE_TEST , "nullmarked/notannotated" );
285- build (this .gradleBuild .withNullMarked (true ), Task .CHECK_ARCHITECTURE_TEST );
297+ build (this .gradleBuild .withNullMarkedEnabled (true ), Task .CHECK_ARCHITECTURE_TEST );
286298 }
287299
288300 @ Test
@@ -386,7 +398,7 @@ private static final class GradleBuild {
386398
387399 private final Map <Task , Boolean > prohibitObjectsRequireNonNull = new LinkedHashMap <>();
388400
389- private Boolean nullMarked ;
401+ private NullMarkedExtension nullMarkedExtension ;
390402
391403 private GradleBuild (Path projectDir ) {
392404 this .projectDir = projectDir ;
@@ -396,16 +408,29 @@ Path getProjectDir() {
396408 return this .projectDir ;
397409 }
398410
399- GradleBuild withNullMarked (Boolean nullMarked ) {
400- this .nullMarked = nullMarked ;
411+ GradleBuild withProhibitObjectsRequireNonNull (Task task , boolean prohibitObjectsRequireNonNull ) {
412+ this .prohibitObjectsRequireNonNull .put (task , prohibitObjectsRequireNonNull );
413+ return this ;
414+ }
415+
416+ GradleBuild withNullMarkedEnabled (Boolean enabled ) {
417+ configureNullMarkedExtension ((nullMarked ) -> nullMarked .withEnabled (enabled ));
401418 return this ;
402419 }
403420
404- GradleBuild withProhibitObjectsRequireNonNull ( Task task , boolean prohibitObjectsRequireNonNull ) {
405- this . prohibitObjectsRequireNonNull . put ( task , prohibitObjectsRequireNonNull );
421+ GradleBuild withNullMarkedIgnoredPackages ( String ... ignorePackages ) {
422+ configureNullMarkedExtension (( nullMarked ) -> nullMarked . withIgnoredPackages ( ignorePackages ) );
406423 return this ;
407424 }
408425
426+ private void configureNullMarkedExtension (UnaryOperator <NullMarkedExtension > configurer ) {
427+ NullMarkedExtension nullMarkedExtension = this .nullMarkedExtension ;
428+ if (nullMarkedExtension == null ) {
429+ nullMarkedExtension = new NullMarkedExtension (null , null );
430+ }
431+ this .nullMarkedExtension = configurer .apply (nullMarkedExtension );
432+ }
433+
409434 GradleBuild withDependencies (String ... dependencies ) {
410435 this .dependencies .addAll (Arrays .asList (dependencies ));
411436 return this ;
@@ -444,11 +469,22 @@ private GradleRunner prepareRunner(String... arguments) throws IOException {
444469 .append (" prohibitObjectsRequireNonNull = " )
445470 .append (prohibitObjectsRequireNonNull )
446471 .append ("\n }\n \n " ));
447- if (this .nullMarked != null ) {
448- buildFile .append ("architectureCheck {\n " )
449- .append (" nullMarked = " )
450- .append (this .nullMarked )
451- .append ("\n }\n " );
472+ NullMarkedExtension nullMarkedExtension = this .nullMarkedExtension ;
473+ if (nullMarkedExtension != null ) {
474+ buildFile .append ("architectureCheck {" );
475+ buildFile .append ("\n nullMarked {" );
476+ if (nullMarkedExtension .enabled () != null ) {
477+ buildFile .append ("\n enabled = " ).append (nullMarkedExtension .enabled ());
478+ }
479+ if (!CollectionUtils .isEmpty (nullMarkedExtension .ignoredPackages ())) {
480+ buildFile .append ("\n ignoredPackages = " )
481+ .append (nullMarkedExtension .ignoredPackages ()
482+ .stream ()
483+ .map (StringUtils ::quote )
484+ .collect (Collectors .joining ("," , "[" , "]" )));
485+ }
486+ buildFile .append ("\n }" );
487+ buildFile .append ("\n }\n \n " );
452488 }
453489 Files .writeString (this .projectDir .resolve ("build.gradle" ), buildFile , StandardCharsets .UTF_8 );
454490 return GradleRunner .create ()
@@ -457,6 +493,18 @@ private GradleRunner prepareRunner(String... arguments) throws IOException {
457493 .withPluginClasspath ();
458494 }
459495
496+ private record NullMarkedExtension (Boolean enabled , Set <String > ignoredPackages ) {
497+
498+ private NullMarkedExtension withEnabled (Boolean enabled ) {
499+ return new NullMarkedExtension (enabled , this .ignoredPackages );
500+ }
501+
502+ private NullMarkedExtension withIgnoredPackages (String ... ignoredPackages ) {
503+ return new NullMarkedExtension (this .enabled , new LinkedHashSet <>(Arrays .asList (ignoredPackages )));
504+ }
505+
506+ }
507+
460508 }
461509
462510}
0 commit comments