1 /* <lambda>null2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava.model.testsuite.typeitem 18 19 import com.android.tools.metalava.model.ClassTypeItem 20 import com.android.tools.metalava.model.Codebase 21 import com.android.tools.metalava.model.TypeModifiers 22 import com.android.tools.metalava.model.TypeNullability.NONNULL 23 import com.android.tools.metalava.model.TypeNullability.PLATFORM 24 import com.android.tools.metalava.model.isNullnessAnnotation 25 import com.android.tools.metalava.model.provider.InputFormat 26 import com.android.tools.metalava.model.testsuite.BaseModelTest 27 import com.android.tools.metalava.model.testsuite.assertHasNonNullNullability 28 import com.android.tools.metalava.model.testsuite.assertHasNullableNullability 29 import com.android.tools.metalava.model.testsuite.assertHasPlatformNullability 30 import com.android.tools.metalava.model.testsuite.assertHasUndefinedNullability 31 import com.android.tools.metalava.model.testsuite.runNullabilityTest 32 import com.android.tools.metalava.testing.KnownSourceFiles 33 import com.android.tools.metalava.testing.java 34 import com.android.tools.metalava.testing.kotlin 35 import com.google.common.truth.Truth.assertThat 36 import org.junit.Test 37 38 class CommonTypeModifiersTest : BaseModelTest() { 39 40 @Test 41 fun `Test annotation on basic types`() { 42 runCodebaseTest( 43 java( 44 """ 45 package test.pkg; 46 public class Foo { 47 public @A int foo1() {} 48 public @A String foo2() {} 49 public <T> @A T foo3() {} 50 } 51 @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) 52 public @interface A {} 53 """ 54 ), 55 kotlin( 56 """ 57 package test.pkg 58 class Foo { 59 fun foo1(): @A Int {} 60 fun foo2(): @A String {} 61 fun <T> foo3(): @A T {} 62 } 63 @Target(AnnotationTarget.TYPE) 64 annotation class A 65 """ 66 ), 67 signature( 68 """ 69 // Signature format: 2.0 70 package test.pkg { 71 public class Foo { 72 method public @test.pkg.A int foo1(); 73 method public @test.pkg.A String foo2(); 74 method public <T> @test.pkg.A T foo3(); 75 } 76 } 77 """ 78 .trimIndent() 79 ) 80 ) { 81 val methods = codebase.assertClass("test.pkg.Foo").methods() 82 assertThat(methods).hasSize(3) 83 84 // @test.pkg.A int 85 val primitiveMethod = methods[0] 86 val primitive = primitiveMethod.returnType() 87 primitive.assertPrimitiveTypeItem { 88 assertThat(annotationNames()).containsExactly("test.pkg.A") 89 } 90 assertThat(primitiveMethod.annotationNames()).isEmpty() 91 92 // @test.pkg.A String 93 val stringMethod = methods[1] 94 val string = stringMethod.returnType() 95 string.assertClassTypeItem { 96 assertThat(annotationNames()).containsExactly("test.pkg.A") 97 } 98 val stringMethodAnnotations = stringMethod.annotationNames() 99 // The Kotlin version puts a nullability annotation on the method 100 if (stringMethodAnnotations.isNotEmpty()) { 101 assertThat(stringMethodAnnotations) 102 .containsExactly("org.jetbrains.annotations.NotNull") 103 } 104 105 // @test.pkg.A T 106 val variableMethod = methods[2] 107 val variable = variableMethod.returnType() 108 val typeParameter = variableMethod.typeParameterList.single() 109 variable.assertReferencesTypeParameter(typeParameter) { 110 assertThat(annotationNames()).containsExactly("test.pkg.A") 111 } 112 assertThat(variableMethod.annotationNames()).isEmpty() 113 } 114 } 115 116 @Test 117 fun `Test type-use annotations with multiple allowed targets`() { 118 runCodebaseTest( 119 java( 120 """ 121 package test.pkg; 122 public class Foo { 123 public @A int foo1() {} 124 public @A String foo2() {} 125 public @A <T> T foo3() {} 126 } 127 @java.lang.annotation.Target({ java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE_USE }) 128 public @interface A {} 129 """ 130 ), 131 kotlin( 132 """ 133 package test.pkg 134 class Foo { 135 @A fun foo(): @A Int {} 136 @A fun foo(): @A String {} 137 @A fun <T> foo(): @A T {} 138 } 139 @Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) 140 annotation class A 141 """ 142 ), 143 signature( 144 """ 145 // Signature format: 2.0 146 package test.pkg { 147 public class Foo { 148 method @test.pkg.A public @test.pkg.A int foo1(); 149 method @test.pkg.A public @test.pkg.A String foo2(); 150 method @test.pkg.A public <T> @test.pkg.A T foo3(); 151 } 152 } 153 """ 154 .trimIndent() 155 ) 156 ) { 157 val methods = codebase.assertClass("test.pkg.Foo").methods() 158 assertThat(methods).hasSize(3) 159 160 // @test.pkg.A int 161 val primitiveMethod = methods[0] 162 val primitive = primitiveMethod.returnType() 163 primitive.assertPrimitiveTypeItem { 164 assertThat(annotationNames()).containsExactly("test.pkg.A") 165 } 166 assertThat(primitiveMethod.annotationNames()).containsExactly("test.pkg.A") 167 168 // @test.pkg.A String 169 val stringMethod = methods[1] 170 val string = stringMethod.returnType() 171 string.assertClassTypeItem { 172 assertThat(annotationNames()).containsExactly("test.pkg.A") 173 } 174 // The Kotlin version puts a nullability annotation on the method 175 val stringMethodAnnotations = 176 stringMethod.annotationNames().filter { !isNullnessAnnotation(it.orEmpty()) } 177 assertThat(stringMethodAnnotations).containsExactly("test.pkg.A") 178 179 // @test.pkg.A T 180 val variableMethod = methods[2] 181 val variable = variableMethod.returnType() 182 val typeParameter = variableMethod.typeParameterList.single() 183 variable.assertReferencesTypeParameter(typeParameter) { 184 assertThat(annotationNames()).containsExactly("test.pkg.A") 185 } 186 assertThat(variableMethod.annotationNames()).containsExactly("test.pkg.A") 187 } 188 } 189 190 @Test 191 fun `Test kotlin type-use annotations with multiple allowed targets on non-type target`() { 192 runCodebaseTest( 193 kotlin( 194 """ 195 package test.pkg 196 class Foo { 197 // @A can be applied to a function or type. 198 // Because of the positioning, it should apply to the function here. 199 @A fun foo(): Int {} 200 @A fun foo(): String {} 201 @A fun <T> foo(): T {} 202 } 203 @Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) 204 annotation class A 205 """ 206 ) 207 ) { 208 val methods = codebase.assertClass("test.pkg.Foo").methods() 209 assertThat(methods).hasSize(3) 210 211 val primitiveMethod = methods[0] 212 val primitive = primitiveMethod.returnType() 213 primitive.assertPrimitiveTypeItem { assertThat(annotationNames()).isEmpty() } 214 assertThat(primitiveMethod.annotationNames()).containsExactly("test.pkg.A") 215 216 val stringMethod = methods[1] 217 val string = stringMethod.returnType() 218 string.assertClassTypeItem { assertThat(annotationNames()).isEmpty() } 219 assertThat(stringMethod.annotationNames()) 220 .containsExactly("org.jetbrains.annotations.NotNull", "test.pkg.A") 221 222 val variableMethod = methods[2] 223 val variable = variableMethod.returnType() 224 val typeParameter = variableMethod.typeParameterList.single() 225 variable.assertReferencesTypeParameter(typeParameter) { 226 assertThat(annotationNames()).isEmpty() 227 } 228 assertThat(variableMethod.annotationNames()).containsExactly("test.pkg.A") 229 } 230 } 231 232 @Test 233 fun `Test filtering of annotations based on target usages`() { 234 runCodebaseTest( 235 java( 236 """ 237 package test.pkg; 238 public class Foo { 239 public @A String bar(@A int arg) {} 240 public @A String baz; 241 } 242 243 @java.lang.annotation.Target({ java.lang.annotation.ElementType.TYPE_USE, java.lang.annotation.ElementType.PARAMETER }) 244 public @interface A {} 245 """ 246 .trimIndent() 247 ) 248 ) { 249 val fooClass = codebase.assertClass("test.pkg.Foo") 250 251 // @A is TYPE_USE and PARAMETER, so it should not appear on the method 252 val method = fooClass.methods().single() 253 assertThat(method.annotationNames()).isEmpty() 254 val methodReturn = method.returnType() 255 assertThat(methodReturn.annotationNames()).containsExactly("test.pkg.A") 256 257 // @A is TYPE_USE and PARAMETER, so it should appear on the parameter as well as type 258 val methodParam = method.parameters().single() 259 assertThat(methodParam.annotationNames()).containsExactly("test.pkg.A") 260 val methodParamType = methodParam.type() 261 assertThat(methodParamType.annotationNames()).containsExactly("test.pkg.A") 262 263 // @A is TYPE_USE and PARAMETER, so it should not appear on the field 264 val field = fooClass.fields().single() 265 assertThat(field.annotationNames()).isEmpty() 266 val fieldType = field.type() 267 assertThat(fieldType.annotationNames()).containsExactly("test.pkg.A") 268 } 269 } 270 271 @Test 272 fun `Test annotations on qualified class type`() { 273 runCodebaseTest( 274 java( 275 """ 276 package test.pkg; 277 public class Foo { 278 public test.pkg.@test.pkg.A Foo foo() {} 279 } 280 """ 281 ), 282 signature( 283 """ 284 // Signature format: 2.0 285 package test.pkg { 286 public class Foo { 287 method public test.pkg.@test.pkg.A Foo foo(); 288 } 289 } 290 """ 291 .trimIndent() 292 ) 293 ) { 294 val method = codebase.assertClass("test.pkg.Foo").methods().single() 295 assertThat(method.annotationNames()).isEmpty() 296 297 val returnType = method.returnType() 298 returnType.assertClassTypeItem { 299 assertThat(qualifiedName).isEqualTo("test.pkg.Foo") 300 assertThat(annotationNames()).containsExactly("test.pkg.A") 301 } 302 } 303 } 304 305 @Test 306 fun `Test annotations on class type parameters`() { 307 runCodebaseTest( 308 java( 309 """ 310 package test.pkg; 311 312 public class Foo { 313 public java.util.@test.pkg.A Map<java.lang.@test.pkg.B @test.pkg.C String, java.lang.@test.pkg.D String> foo() {} 314 } 315 """ 316 ), 317 signature( 318 """ 319 // Signature format: 2.0 320 package test.pkg { 321 public class Foo { 322 method public java.util.@test.pkg.A Map<java.lang.@test.pkg.B @test.pkg.C String, java.lang.@test.pkg.D String> foo(); 323 } 324 } 325 """ 326 .trimIndent() 327 ) 328 ) { 329 val method = codebase.assertClass("test.pkg.Foo").methods().single() 330 assertThat(method.annotationNames()).isEmpty() 331 332 val mapType = method.returnType() 333 mapType.assertClassTypeItem { 334 assertThat(annotationNames()).containsExactly("test.pkg.A") 335 assertThat(arguments).hasSize(2) 336 337 // java.lang.@test.pkg.B @test.pkg.C String 338 val string1 = arguments[0] 339 assertThat(string1.isString()).isTrue() 340 assertThat(string1.annotationNames()).containsExactly("test.pkg.B", "test.pkg.C") 341 342 // java.lang.@test.pkg.D String 343 val string2 = arguments[1] 344 assertThat(string2.isString()).isTrue() 345 assertThat(string2.annotationNames()).containsExactly("test.pkg.D") 346 } 347 } 348 } 349 350 @Test 351 fun `Test annotations on array type and component type`() { 352 runCodebaseTest( 353 java( 354 """ 355 package test.pkg; 356 public class Foo { 357 public test.pkg.@test.pkg.A @test.pkg.B Foo @test.pkg.B @test.pkg.C [] foo() {} 358 } 359 """ 360 ), 361 signature( 362 """ 363 // Signature format: 2.0 364 package test.pkg { 365 public class Foo { 366 method public test.pkg.@test.pkg.A @test.pkg.B Foo @test.pkg.B @test.pkg.C [] foo(); 367 } 368 } 369 """ 370 .trimIndent() 371 ) 372 ) { 373 val method = codebase.assertClass("test.pkg.Foo").methods().single() 374 assertThat(method.annotationNames()).isEmpty() 375 376 val returnType = method.returnType() 377 returnType.assertArrayTypeItem { 378 assertThat(annotationNames()).containsExactly("test.pkg.B", "test.pkg.C") 379 380 componentType.assertClassTypeItem { 381 assertThat(qualifiedName).isEqualTo("test.pkg.Foo") 382 assertThat(annotationNames()).containsExactly("test.pkg.A", "test.pkg.B") 383 } 384 } 385 } 386 } 387 388 @Test 389 fun `Test leading annotation on array type`() { 390 runCodebaseTest( 391 java( 392 """ 393 package test.pkg; 394 public class Foo { 395 public <T> @test.pkg.A T[] foo() {} 396 } 397 """ 398 ), 399 signature( 400 """ 401 // Signature format: 5.0 402 // - kotlin-name-type-order=yes 403 // - include-type-use-annotations=yes 404 package test.pkg { 405 public class Foo { 406 method public <T> foo(): @test.pkg.A T[]; 407 } 408 } 409 """ 410 .trimIndent() 411 ) 412 ) { 413 val method = codebase.assertClass("test.pkg.Foo").methods().single() 414 val methodTypeParam = method.typeParameterList.single() 415 val returnType = method.returnType() 416 returnType.assertArrayTypeItem { 417 componentType.assertReferencesTypeParameter(methodTypeParam) { 418 assertThat(annotationNames()).containsExactly("test.pkg.A") 419 } 420 } 421 } 422 } 423 424 @Test 425 fun `Test annotations on multidimensional array`() { 426 runCodebaseTest( 427 java( 428 """ 429 package test.pkg; 430 public class Foo { 431 public test.pkg.@test.pkg.A Foo @test.pkg.B [] @test.pkg.C [] @test.pkg.D [] foo() {} 432 } 433 """ 434 .trimIndent() 435 ), 436 signature( 437 """ 438 // Signature format: 2.0 439 package test.pkg { 440 public class Foo { 441 method public test.pkg.@test.pkg.A Foo @test.pkg.B [] @test.pkg.C [] @test.pkg.D [] foo(); 442 } 443 } 444 """ 445 .trimIndent() 446 ) 447 ) { 448 val method = codebase.assertClass("test.pkg.Foo").methods().single() 449 assertThat(method.annotationNames()).isEmpty() 450 451 val returnType = method.returnType() 452 // Outer array 453 returnType.assertArrayTypeItem { 454 assertThat(annotationNames()).containsExactly("test.pkg.B") 455 456 // Middle array 457 componentType.assertArrayTypeItem { 458 assertThat(annotationNames()).containsExactly("test.pkg.C") 459 460 // Inner array 461 componentType.assertArrayTypeItem { 462 assertThat(annotationNames()).containsExactly("test.pkg.D") 463 464 // Component type 465 componentType.assertClassTypeItem { 466 assertThat(qualifiedName).isEqualTo("test.pkg.Foo") 467 assertThat(annotationNames()).containsExactly("test.pkg.A") 468 } 469 } 470 } 471 } 472 } 473 } 474 475 @Test 476 fun `Test annotations on multidimensional vararg array`() { 477 runCodebaseTest( 478 java( 479 """ 480 package test.pkg; 481 public class Foo { 482 public void foo(test.pkg.@test.pkg.A Foo @test.pkg.B [] @test.pkg.C [] @test.pkg.D ... arg) {} 483 } 484 """ 485 .trimIndent() 486 ), 487 signature( 488 """ 489 // Signature format: 4.0 490 package test.pkg { 491 public class Foo { 492 method public void foo(test.pkg.@test.pkg.A Foo @test.pkg.B [] @test.pkg.C [] @test.pkg.D ...); 493 } 494 } 495 """ 496 .trimIndent() 497 ) 498 ) { 499 val type = 500 codebase.assertClass("test.pkg.Foo").methods().single().parameters().single().type() 501 type.assertArrayTypeItem { 502 assertThat(isVarargs).isTrue() 503 assertThat(annotationNames()).containsExactly("test.pkg.B") 504 505 // Middle array 506 componentType.assertArrayTypeItem { 507 assertThat(annotationNames()).containsExactly("test.pkg.C") 508 509 // Inner array 510 componentType.assertArrayTypeItem { 511 assertThat(annotationNames()).containsExactly("test.pkg.D") 512 513 // Component type 514 componentType.assertClassTypeItem { 515 assertThat(qualifiedName).isEqualTo("test.pkg.Foo") 516 assertThat(annotationNames()).containsExactly("test.pkg.A") 517 } 518 } 519 } 520 } 521 } 522 } 523 524 @Test 525 fun `Test inner parameterized types with annotations`() { 526 runCodebaseTest( 527 java( 528 """ 529 package test.pkg; 530 public class Outer<O> { 531 public class Inner<I> { 532 } 533 534 public <P1, P2> test.pkg.@test.pkg.A Outer<@test.pkg.B P1>.@test.pkg.C Inner<@test.pkg.D P2> foo() { 535 return new Outer<P1>.Inner<P2>(); 536 } 537 } 538 """ 539 ), 540 signature( 541 """ 542 // Signature format: 3.0 543 package test.pkg { 544 public class Outer<O> { 545 ctor public Outer(); 546 method public <P1, P2> test.pkg.@test.pkg.A Outer<@test.pkg.B P1!>.@test.pkg.C Inner<@test.pkg.D P2!>! foo(); 547 } 548 public class Outer.Inner<I> { 549 ctor public Outer.Inner(); 550 } 551 } 552 """ 553 .trimIndent() 554 ) 555 ) { 556 val method = codebase.assertClass("test.pkg.Outer").methods().single() 557 val methodTypeParameters = method.typeParameterList 558 assertThat(methodTypeParameters).hasSize(2) 559 val p1 = methodTypeParameters[0] 560 val p2 = methodTypeParameters[1] 561 562 // Outer<P1>.Inner<P2> 563 val returnType = method.returnType() 564 returnType.assertClassTypeItem { 565 assertThat(qualifiedName).isEqualTo("test.pkg.Outer.Inner") 566 assertThat(arguments).hasSize(1) 567 assertThat(annotationNames()).containsExactly("test.pkg.C") 568 569 val innerTypeArgument = arguments.single() 570 innerTypeArgument.assertReferencesTypeParameter(p2) { 571 assertThat(name).isEqualTo("P2") 572 assertThat(annotationNames()).containsExactly("test.pkg.D") 573 } 574 575 outerClassType.assertNotNullTypeItem { 576 assertThat(qualifiedName).isEqualTo("test.pkg.Outer") 577 assertThat(outerClassType).isNull() 578 assertThat(arguments).hasSize(1) 579 assertThat(annotationNames()).containsExactly("test.pkg.A") 580 581 val outerClassArgument = arguments.single() 582 outerClassArgument.assertReferencesTypeParameter(p1) { 583 assertThat(name).isEqualTo("P1") 584 assertThat(annotationNames()).containsExactly("test.pkg.B") 585 } 586 } 587 } 588 } 589 } 590 591 @Test 592 fun `Test interface types`() { 593 runCodebaseTest( 594 java( 595 """ 596 package test.pkg; 597 public class Foo implements test.pkg.@test.pkg.A Bar, test.pkg.Baz {} 598 """ 599 ), 600 signature( 601 """ 602 // Signature format: 4.0 603 package test.pkg { 604 public class Foo implements test.pkg.@test.pkg.A Bar, test.pkg.Baz { 605 } 606 } 607 """ 608 .trimIndent() 609 ) 610 ) { 611 val foo = codebase.assertClass("test.pkg.Foo") 612 val interfaces = foo.interfaceTypes() 613 assertThat(interfaces).hasSize(2) 614 615 val bar = interfaces[0] 616 assertThat(bar.qualifiedName).isEqualTo("test.pkg.Bar") 617 val annotations = bar.modifiers.annotations() 618 assertThat(annotations).hasSize(1) 619 assertThat(annotations.single().qualifiedName).isEqualTo("test.pkg.A") 620 621 val baz = interfaces[1] 622 assertThat(baz.qualifiedName).isEqualTo("test.pkg.Baz") 623 } 624 } 625 626 @Test 627 fun `Test super class type`() { 628 runCodebaseTest( 629 java( 630 """ 631 package test.pkg; 632 public class Foo extends test.pkg.@test.pkg.A Bar {} 633 class Bar {} 634 @interface A {} 635 """ 636 ), 637 signature( 638 """ 639 // Signature format: 4.0 640 package test.pkg { 641 public class Foo extends test.pkg.@test.pkg.A Bar { 642 } 643 public class Bar { 644 } 645 public @interface A { 646 } 647 } 648 """ 649 .trimIndent() 650 ) 651 ) { 652 val foo = codebase.assertClass("test.pkg.Foo") 653 val superClass = foo.superClassType() 654 assertThat(superClass).isNotNull() 655 superClass.assertClassTypeItem { 656 assertThat(qualifiedName).isEqualTo("test.pkg.Bar") 657 assertThat(annotationNames()).containsExactly("test.pkg.A") 658 } 659 } 660 } 661 662 @Test 663 fun `Test super class and interface types of interface`() { 664 runCodebaseTest( 665 java( 666 """ 667 package test.pkg; 668 public interface Foo extends test.pkg.@test.pkg.A Bar, test.pkg.@test.pkg.B Baz<@test.pkg.C String>, test.pkg.Biz {} 669 """ 670 ), 671 signature( 672 """ 673 // Signature format: 4.0 674 package test.pkg { 675 public interface Foo extends test.pkg.@test.pkg.A Bar test.pkg.@test.pkg.B Baz<@test.pkg.C String> test.pkg.Biz { 676 } 677 } 678 """ 679 .trimIndent() 680 ) 681 ) { 682 val foo = codebase.assertClass("test.pkg.Foo") 683 assertThat(foo.superClassType()).isNull() 684 685 val interfaces = foo.interfaceTypes() 686 assertThat(interfaces).hasSize(3) 687 688 val bar = interfaces[0] 689 assertThat(bar.qualifiedName).isEqualTo("test.pkg.Bar") 690 assertThat(bar.annotationNames()).containsExactly("test.pkg.A") 691 692 val baz = interfaces[1] 693 assertThat(baz.qualifiedName).isEqualTo("test.pkg.Baz") 694 assertThat(baz.arguments).hasSize(1) 695 assertThat(baz.annotationNames()).containsExactly("test.pkg.B") 696 697 val bazTypeArgument = baz.arguments.single() 698 assertThat(bazTypeArgument.isString()).isTrue() 699 assertThat(bazTypeArgument.annotationNames()).containsExactly("test.pkg.C") 700 701 val biz = interfaces[2] 702 assertThat(biz.qualifiedName).isEqualTo("test.pkg.Biz") 703 assertThat(biz.annotationNames()).isEmpty() 704 } 705 } 706 707 @Test 708 fun `Test annotated array types in multiple contexts`() { 709 runCodebaseTest( 710 java( 711 """ 712 package test.pkg; 713 public class Foo { 714 public test.pkg.Foo @test.pkg.A [] method(test.pkg.Foo @test.pkg.A [] arg) {} 715 public test.pkg.Foo @test.pkg.A [] field; 716 } 717 """ 718 ), 719 signature( 720 """ 721 // Signature format: 4.0 722 package test.pkg { 723 public class Foo { 724 method public test.pkg.Foo @test.pkg.A [] method(test.pkg.Foo @test.pkg.A []); 725 field public test.pkg.Foo @test.pkg.A [] field; 726 property public test.pkg.Foo @test.pkg.A [] prop; 727 } 728 } 729 """ 730 .trimIndent() 731 ) 732 ) { 733 val foo = codebase.assertClass("test.pkg.Foo") 734 val method = foo.methods().single() 735 val returnType = method.returnType() 736 val paramType = method.parameters().single().type() 737 val fieldType = foo.fields().single().type() 738 // Properties can't be defined in java, this is only present for signature type 739 val propertyType = foo.properties().singleOrNull()?.type() 740 741 // Do full check for one type, then verify the others are equal 742 returnType.assertArrayTypeItem { 743 assertThat(annotationNames()).containsExactly("test.pkg.A") 744 745 componentType.assertClassTypeItem { 746 assertThat(qualifiedName).isEqualTo("test.pkg.Foo") 747 assertThat(annotationNames()).isEmpty() 748 } 749 } 750 751 assertThat(returnType).isEqualTo(paramType) 752 assertThat(returnType).isEqualTo(fieldType) 753 if (propertyType != null) { 754 assertThat(returnType).isEqualTo(propertyType) 755 } 756 } 757 } 758 759 @Test 760 fun `Test annotations with spaces in the annotation string`() { 761 runCodebaseTest( 762 signature( 763 """ 764 // Signature format: 5.0 765 // - include-type-use-annotations=yes 766 // - kotlin-name-type-order=yes 767 package test.pkg { 768 public class Foo extends test.pkg.@test.pkg.A(a=1, b=2, c=3) Bar implements test.pkg.@test.pkg.A(a=1, b=2, c=3) Baz test.pkg.@test.pkg.A(a=1, b=2, c=3) Biz { 769 method public <T> foo(_: @test.pkg.A(a=1, b=2, c=3) T @test.pkg.A(a=1, b=2, c=3) []): java.util.@test.pkg.A(a=1, b=2, c=3) List<java.lang.@test.pkg.A(a=1, b=2, c=3) String>; 770 } 771 } 772 """ 773 .trimIndent() 774 ) 775 ) { 776 // Check the modifiers contain one annotation, `@test.pkg.A(a=1, b=2, c=3)` 777 val testModifiers = { modifiers: TypeModifiers -> 778 assertThat(modifiers.annotations()).hasSize(1) 779 val annotation = modifiers.annotations().single() 780 assertThat(annotation.qualifiedName).isEqualTo("test.pkg.A") 781 val attributes = annotation.attributes 782 assertThat(attributes.toString()).isEqualTo("[a=1, b=2, c=3]") 783 } 784 val fooClass = codebase.assertClass("test.pkg.Foo") 785 786 val superClass = fooClass.superClassType() 787 superClass.assertNotNullTypeItem { 788 assertThat(qualifiedName).isEqualTo("test.pkg.Bar") 789 testModifiers(modifiers) 790 } 791 792 val interfaces = fooClass.interfaceTypes() 793 val bazInterface = interfaces[0] 794 assertThat(bazInterface.qualifiedName).isEqualTo("test.pkg.Baz") 795 testModifiers(bazInterface.modifiers) 796 val bizInterface = interfaces[1] 797 assertThat(bizInterface.qualifiedName).isEqualTo("test.pkg.Biz") 798 testModifiers(bizInterface.modifiers) 799 800 val fooMethod = fooClass.methods().single() 801 val typeParam = fooMethod.typeParameterList.single() 802 803 val parameterType = fooMethod.parameters().single().type() 804 parameterType.assertArrayTypeItem { 805 testModifiers(modifiers) 806 componentType.assertReferencesTypeParameter(typeParam) { testModifiers(modifiers) } 807 } 808 809 val stringList = fooMethod.returnType() 810 stringList.assertClassTypeItem { 811 assertThat(qualifiedName).isEqualTo("java.util.List") 812 testModifiers(modifiers) 813 814 val string = arguments.single() 815 assertThat(string.isString()).isTrue() 816 testModifiers(string.modifiers) 817 } 818 } 819 } 820 821 @Test 822 fun `Test adding and removing annotations`() { 823 // Not supported for text codebases due to caching 824 runCodebaseTest( 825 java( 826 """ 827 package test.pkg; 828 import java.lang.annotation.ElementType; 829 import java.lang.annotation.Target; 830 public class Foo { 831 public @A @B String foo() {} 832 } 833 @Target(ElementType.TYPE_USE) 834 public @interface A {} 835 @Target(ElementType.TYPE_USE) 836 public @interface B {} 837 """ 838 .trimIndent() 839 ), 840 ) { 841 val stringType = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 842 assertThat(stringType.annotationNames()).containsExactly("test.pkg.A", "test.pkg.B") 843 844 // Remove annotation 845 val annotationA = stringType.modifiers.annotations().first() 846 assertThat(annotationA.qualifiedName).isEqualTo("test.pkg.A") 847 stringType.modifiers.removeAnnotation(annotationA) 848 assertThat(stringType.annotationNames()).containsExactly("test.pkg.B") 849 850 // Add annotation 851 stringType.modifiers.addAnnotation(annotationA) 852 assertThat(stringType.annotationNames()).containsExactly("test.pkg.B", "test.pkg.A") 853 } 854 } 855 856 @Test 857 fun `Test nullability of primitives`() { 858 runNullabilityTest( 859 java( 860 """ 861 package test.pkg; 862 public class Foo { 863 public int foo() {} 864 } 865 """ 866 .trimIndent() 867 ), 868 signature( 869 """ 870 // Signature format: 5.0 871 // - include-type-use-annotations=yes 872 // - kotlin-name-type-order=yes 873 // - kotlin-style-nulls=no 874 package test.pkg { 875 public class Foo { 876 method public foo(): int; 877 } 878 } 879 """ 880 .trimIndent() 881 ), 882 kotlin( 883 """ 884 package test.pkg 885 class Foo { 886 fun foo(): Int {} 887 } 888 """ 889 .trimIndent() 890 ), 891 signature( 892 """ 893 // Signature format: 5.0 894 // - include-type-use-annotations=yes 895 // - kotlin-name-type-order=yes 896 package test.pkg { 897 public class Foo { 898 method public foo(): int; 899 } 900 } 901 """ 902 .trimIndent() 903 ) 904 ) { 905 val primitive = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 906 // Primitives are always non-null without an annotation needed 907 primitive.assertHasNonNullNullability(expectAnnotation = false) 908 } 909 } 910 911 @Test 912 fun `Test nullability of simple classes`() { 913 runNullabilityTest( 914 java( 915 """ 916 package test.pkg; 917 import libcore.util.NonNull; 918 import libcore.util.Nullable; 919 public class Foo { 920 public String platformString() {} 921 public @Nullable String nullableString() {} 922 public @NonNull String nonNullString() {} 923 } 924 """ 925 .trimIndent() 926 ), 927 signature( 928 """ 929 // Signature format: 5.0 930 // - include-type-use-annotations=yes 931 // - kotlin-name-type-order=yes 932 // - kotlin-style-nulls=no 933 package test.pkg { 934 public class Foo { 935 method public platformString(): String; 936 method public nullableString(): @libcore.util.Nullable String; 937 method public nonNullString(): @libcore.util.NonNull String; 938 } 939 } 940 """ 941 .trimIndent() 942 ), 943 kotlin( 944 """ 945 package test.pkg 946 class Foo { 947 fun nullableString(): String? {} 948 fun nonNullString(): String {} 949 } 950 """ 951 .trimIndent() 952 ), 953 signature( 954 """ 955 // Signature format: 5.0 956 // - include-type-use-annotations=yes 957 // - kotlin-name-type-order=yes 958 package test.pkg { 959 public class Foo { 960 method public platformString(): String!; 961 method public nullableString(): String?; 962 method public nonNullString(): String; 963 } 964 } 965 """ 966 .trimIndent() 967 ) 968 ) { 969 val fooClass = codebase.assertClass("test.pkg.Foo") 970 971 // Platform nullability isn't possible from Kotlin 972 if (inputFormat != InputFormat.KOTLIN) { 973 val platformString = fooClass.assertMethod("platformString", "").returnType() 974 assertThat(platformString.modifiers.nullability()).isEqualTo(PLATFORM) 975 } 976 977 val nullableString = fooClass.assertMethod("nullableString", "").returnType() 978 nullableString.assertHasNullableNullability(nullabilityFromAnnotations) 979 980 val nonNullString = fooClass.assertMethod("nonNullString", "").returnType() 981 nonNullString.assertHasNonNullNullability(nullabilityFromAnnotations) 982 } 983 } 984 985 @Test 986 fun `Test nullability of arrays`() { 987 runNullabilityTest( 988 java( 989 """ 990 package test.pkg; 991 import libcore.util.NonNull; 992 import libcore.util.Nullable; 993 public class Foo { 994 public String[] platformStringPlatformArray() {} 995 public java.lang.@NonNull String[] nonNullStringPlatformArray() {} 996 public String @Nullable [] platformStringNullableArray() {} 997 public java.lang.@Nullable String @Nullable [] nullableStringNullableArray() {} 998 public java.lang.@Nullable String @NonNull [] nullableStringNonNullArray() {} 999 } 1000 """ 1001 .trimIndent() 1002 ), 1003 signature( 1004 """ 1005 // Signature format: 5.0 1006 // - include-type-use-annotations=yes 1007 // - kotlin-name-type-order=yes 1008 // - kotlin-style-nulls=no 1009 package test.pkg { 1010 public class Foo { 1011 method public nonNullStringPlatformArray(): @NonNull String[]; 1012 method public nullableStringNonNullArray(): @Nullable String @NonNull []; 1013 method public nullableStringNullableArray(): @Nullable String @Nullable []; 1014 method public platformStringNullableArray(): String @Nullable []; 1015 method public platformStringPlatformArray(): String[]; 1016 } 1017 } 1018 """ 1019 .trimIndent() 1020 ), 1021 kotlin( 1022 """ 1023 package test.pkg 1024 class Foo { 1025 fun nullableStringNullableArray(): Array<String?>? {} 1026 fun nullableStringNonNullArray(): Array<String?> {} 1027 } 1028 """ 1029 .trimIndent() 1030 ), 1031 signature( 1032 """ 1033 // Signature format: 5.0 1034 // - include-type-use-annotations=yes 1035 // - kotlin-name-type-order=yes 1036 package test.pkg { 1037 public class Foo { 1038 method public nonNullStringPlatformArray(): String[]!; 1039 method public nullableStringNonNullArray(): String?[]; 1040 method public nullableStringNullableArray(): String?[]?; 1041 method public platformStringNullableArray(): String![]?; 1042 method public platformStringPlatformArray(): String![]!; 1043 } 1044 } 1045 """ 1046 .trimIndent() 1047 ) 1048 ) { 1049 val fooClass = codebase.assertClass("test.pkg.Foo") 1050 1051 // Platform nullability isn't possible from Kotlin 1052 if (inputFormat != InputFormat.KOTLIN) { 1053 val platformStringPlatformArray = 1054 fooClass.assertMethod("platformStringPlatformArray", "").returnType() 1055 platformStringPlatformArray.assertArrayTypeItem { 1056 assertHasPlatformNullability() 1057 componentType.assertHasPlatformNullability() 1058 } 1059 } 1060 1061 // Platform nullability isn't possible from Kotlin 1062 if (inputFormat != InputFormat.KOTLIN) { 1063 val platformStringNullableArray = 1064 fooClass.assertMethod("platformStringNullableArray", "").returnType() 1065 platformStringNullableArray.assertArrayTypeItem { 1066 assertHasNullableNullability(nullabilityFromAnnotations) 1067 componentType.assertHasPlatformNullability() 1068 } 1069 } 1070 1071 // Platform nullability isn't possible from Kotlin 1072 if (inputFormat != InputFormat.KOTLIN) { 1073 val nonNullStringPlatformArray = 1074 fooClass.assertMethod("nonNullStringPlatformArray", "").returnType() 1075 nonNullStringPlatformArray.assertArrayTypeItem { 1076 assertHasPlatformNullability() 1077 componentType.assertHasNonNullNullability(nullabilityFromAnnotations) 1078 } 1079 } 1080 1081 val nullableStringNonNullArray = 1082 fooClass.assertMethod("nullableStringNonNullArray", "").returnType() 1083 nullableStringNonNullArray.assertArrayTypeItem { 1084 assertHasNonNullNullability(nullabilityFromAnnotations) 1085 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1086 } 1087 1088 val nullableStringNullableArray = 1089 fooClass.assertMethod("nullableStringNullableArray", "").returnType() 1090 nullableStringNullableArray.assertArrayTypeItem { 1091 assertHasNullableNullability(nullabilityFromAnnotations) 1092 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1093 } 1094 } 1095 } 1096 1097 @Test 1098 fun `Test nullability of multi-dimensional arrays`() { 1099 runNullabilityTest( 1100 java( 1101 """ 1102 package test.pkg; 1103 import libcore.util.NonNull; 1104 import libcore.util.Nullable; 1105 public class Foo { 1106 public java.lang.@Nullable String @NonNull [] @Nullable [] @NonNull [] foo() {} 1107 } 1108 """ 1109 .trimIndent() 1110 ), 1111 signature( 1112 """ 1113 // Signature format: 5.0 1114 // - include-type-use-annotations=yes 1115 // - kotlin-name-type-order=yes 1116 // - kotlin-style-nulls=no 1117 package test.pkg { 1118 public class Foo { 1119 ctor public Foo(); 1120 method public foo(): @Nullable String @NonNull [] @Nullable [] @NonNull []; 1121 } 1122 } 1123 """ 1124 .trimIndent() 1125 ), 1126 kotlin( 1127 """ 1128 package test.pkg 1129 class Foo { 1130 fun foo(): Array<Array<Array<String?>>?> 1131 } 1132 """ 1133 .trimIndent() 1134 ), 1135 signature( 1136 """ 1137 // Signature format: 5.0 1138 // - include-type-use-annotations=yes 1139 // - kotlin-name-type-order=yes 1140 package test.pkg { 1141 public class Foo { 1142 ctor public Foo(); 1143 method public foo(): String?[][]?[]; 1144 } 1145 } 1146 """ 1147 .trimIndent() 1148 ) 1149 ) { 1150 val fooClass = codebase.assertClass("test.pkg.Foo") 1151 1152 val array3d = fooClass.methods().single().returnType() 1153 array3d.assertArrayTypeItem { 1154 assertHasNonNullNullability(nullabilityFromAnnotations) 1155 1156 componentType.assertArrayTypeItem { 1157 assertHasNullableNullability(nullabilityFromAnnotations) 1158 1159 componentType.assertArrayTypeItem { 1160 assertHasNonNullNullability(nullabilityFromAnnotations) 1161 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1162 } 1163 } 1164 } 1165 } 1166 } 1167 1168 @Test 1169 fun `Test nullability of varargs`() { 1170 runNullabilityTest( 1171 java( 1172 """ 1173 package test.pkg; 1174 import libcore.util.NonNull; 1175 import libcore.util.Nullable; 1176 public class Foo { 1177 public void platformStringPlatformVararg(String... arg) {} 1178 public void nullableStringPlatformVararg(java.lang.@Nullable String... arg) {} 1179 public void platformStringNullableVararg(String @Nullable ... arg) {} 1180 public void nullableStringNullableVararg(java.lang.@Nullable String @Nullable ... arg) {} 1181 public void nullableStringNonNullVararg(java.lang.@Nullable String @NonNull ... arg) {} 1182 } 1183 """ 1184 .trimIndent() 1185 ), 1186 signature( 1187 """ 1188 // Signature format: 5.0 1189 // - include-type-use-annotations=yes 1190 // - kotlin-name-type-order=yes 1191 // - kotlin-style-nulls=no 1192 package test.pkg { 1193 public class Foo { 1194 method public platformStringPlatformVararg(arg: String...): void; 1195 method public nullableStringPlatformVararg(arg: @Nullable String...): void; 1196 method public platformStringNullableVararg(arg: String @Nullable ...): void; 1197 method public nullableStringNullableVararg(arg: @Nullable String @Nullable ...): void; 1198 method public nullableStringNonNullVararg(arg: @Nullable String @NonNull ...): void; 1199 } 1200 } 1201 """ 1202 .trimIndent() 1203 ), 1204 kotlin( 1205 """ 1206 package test.pkg 1207 class Foo { 1208 // Platform nullability isn't possible 1209 // Nullable varargs aren't possible 1210 fun nullableStringNonNullVararg(vararg arg: String?) = Unit 1211 } 1212 """ 1213 .trimIndent() 1214 ), 1215 signature( 1216 """ 1217 // Signature format: 5.0 1218 // - include-type-use-annotations=yes 1219 // - kotlin-name-type-order=yes 1220 package test.pkg { 1221 public class Foo { 1222 method public platformStringPlatformVararg(arg: String!...!): void; 1223 method public nullableStringPlatformVararg(arg: String?...!): void; 1224 method public platformStringNullableVararg(arg: String!...?): void; 1225 method public nullableStringNullableVararg(arg: String?...?): void; 1226 method public nullableStringNonNullVararg(arg: String?...): void; 1227 } 1228 } 1229 """ 1230 .trimIndent() 1231 ) 1232 ) { 1233 val fooClass = codebase.assertClass("test.pkg.Foo") 1234 1235 if (inputFormat != InputFormat.KOTLIN) { 1236 val platformStringPlatformVararg = 1237 fooClass 1238 .assertMethod("platformStringPlatformVararg", "java.lang.String[]") 1239 .parameters() 1240 .single() 1241 .type() 1242 platformStringPlatformVararg.assertArrayTypeItem { 1243 assertHasPlatformNullability() 1244 componentType.assertHasPlatformNullability() 1245 } 1246 } 1247 1248 if (inputFormat != InputFormat.KOTLIN) { 1249 val nullableStringPlatformVararg = 1250 fooClass 1251 .assertMethod("nullableStringPlatformVararg", "java.lang.String[]") 1252 .parameters() 1253 .single() 1254 .type() 1255 nullableStringPlatformVararg.assertArrayTypeItem { 1256 assertHasPlatformNullability() 1257 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1258 } 1259 } 1260 1261 if (inputFormat != InputFormat.KOTLIN) { 1262 val platformStringNullableVararg = 1263 fooClass 1264 .assertMethod("platformStringNullableVararg", "java.lang.String[]") 1265 .parameters() 1266 .single() 1267 .type() 1268 platformStringNullableVararg.assertArrayTypeItem { 1269 assertHasNullableNullability(nullabilityFromAnnotations) 1270 componentType.assertHasPlatformNullability() 1271 } 1272 } 1273 1274 if (inputFormat != InputFormat.KOTLIN) { 1275 val nullableStringNullableVararg = 1276 fooClass 1277 .assertMethod("nullableStringNullableVararg", "java.lang.String[]") 1278 .parameters() 1279 .single() 1280 .type() 1281 nullableStringNullableVararg.assertArrayTypeItem { 1282 assertHasNullableNullability(nullabilityFromAnnotations) 1283 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1284 } 1285 } 1286 1287 // The only version that exists for Kotlin 1288 val nullableStringNonNullVararg = 1289 fooClass 1290 .assertMethod("nullableStringNonNullVararg", "java.lang.String[]") 1291 .parameters() 1292 .single() 1293 .type() 1294 nullableStringNonNullVararg.assertHasNonNullNullability(nullabilityFromAnnotations) 1295 nullableStringNonNullVararg.assertArrayTypeItem { 1296 componentType.assertHasNullableNullability(nullabilityFromAnnotations) 1297 } 1298 } 1299 } 1300 1301 @Test 1302 fun `Test nullability of classes with parameters`() { 1303 runNullabilityTest( 1304 java( 1305 """ 1306 package test.pkg; 1307 import java.util.List; 1308 import java.util.Map; 1309 import libcore.util.NonNull; 1310 import libcore.util.Nullable; 1311 public class Foo { 1312 public @Nullable List<String> nullableListPlatformString() {} 1313 public @NonNull List<@Nullable String> nonNullListNullableString() {} 1314 public @Nullable Map<@NonNull Integer, @Nullable String> nullableMap() {} 1315 } 1316 """ 1317 .trimIndent() 1318 ), 1319 signature( 1320 """ 1321 // Signature format: 5.0 1322 // - include-type-use-annotations=yes 1323 // - kotlin-name-type-order=yes 1324 // - kotlin-style-nulls=no 1325 package test.pkg { 1326 public class Foo { 1327 method public nullableListPlatformString(): java.util.@Nullable List<java.lang.String>; 1328 method public nonNullListNullableString(): java.util.@NonNull List<java.lang.@Nullable String>; 1329 method public nullableMap(): java.util.@Nullable Map<java.lang.@NonNull Integer, java.lang.@Nullable String>; 1330 } 1331 } 1332 """ 1333 .trimIndent() 1334 ), 1335 kotlin( 1336 """ 1337 package test.pkg 1338 class Foo { 1339 fun nonNullListNullableString(): List<String?> {} 1340 fun nullableMap(): Map<Int, String?>? {} 1341 } 1342 """ 1343 .trimIndent() 1344 ), 1345 signature( 1346 """ 1347 // Signature format: 5.0 1348 // - include-type-use-annotations=yes 1349 // - kotlin-name-type-order=yes 1350 package test.pkg { 1351 public class Foo { 1352 method public nullableListPlatformString(): java.util.List<java.lang.String!>?; 1353 method public nonNullListNullableString(): java.util.List<java.lang.String?>; 1354 method public nullableMap(): java.util.Map<java.lang.Integer, java.lang.String?>?; 1355 } 1356 } 1357 """ 1358 .trimIndent() 1359 ) 1360 ) { 1361 val fooClass = codebase.assertClass("test.pkg.Foo") 1362 1363 // Platform type doesn't exist in Kotlin 1364 if (inputFormat != InputFormat.KOTLIN) { 1365 val nullableListPlatformString = 1366 fooClass.assertMethod("nullableListPlatformString", "").returnType() 1367 nullableListPlatformString.assertClassTypeItem { 1368 assertHasNullableNullability(nullabilityFromAnnotations) 1369 arguments.single().assertHasPlatformNullability() 1370 } 1371 } 1372 1373 val nonNullListNullableString = 1374 fooClass.assertMethod("nonNullListNullableString", "").returnType() 1375 nonNullListNullableString.assertClassTypeItem { 1376 assertHasNonNullNullability(nullabilityFromAnnotations) 1377 arguments.single().assertHasNullableNullability(nullabilityFromAnnotations) 1378 } 1379 1380 val nullableMap = fooClass.assertMethod("nullableMap", "").returnType() 1381 nullableMap.assertClassTypeItem { 1382 assertHasNullableNullability(nullabilityFromAnnotations) 1383 // Non-null Integer 1384 arguments[0].assertHasNonNullNullability(nullabilityFromAnnotations) 1385 // Nullable String 1386 arguments[1].assertHasNullableNullability(nullabilityFromAnnotations) 1387 } 1388 } 1389 } 1390 1391 @Test 1392 fun `Test nullability of outer classes`() { 1393 runNullabilityTest( 1394 java( 1395 """ 1396 package test.pkg; 1397 import libcore.util.NonNull; 1398 import libcore.util.Nullable; 1399 public class Foo { 1400 public Outer<@Nullable String>.@Nullable Inner<@NonNull String> foo(); 1401 } 1402 public class Outer<P1> { 1403 public class Inner<P2> {} 1404 } 1405 """ 1406 .trimIndent() 1407 ), 1408 signature( 1409 """ 1410 // Signature format: 5.0 1411 // - include-type-use-annotations=yes 1412 // - kotlin-name-type-order=yes 1413 // - kotlin-style-nulls=no 1414 package test.pkg { 1415 public class Foo { 1416 method public foo(): test.pkg.Outer<java.lang.@libcore.util.Nullable String>.@libcore.util.Nullable Inner<java.lang.@libcore.util.NonNull String>; 1417 } 1418 } 1419 """ 1420 .trimIndent() 1421 ), 1422 kotlin( 1423 """ 1424 package test.pkg 1425 class Foo { 1426 fun foo(): Outer<String?>.Inner<String>? {} 1427 } 1428 class Outer<P1> { 1429 inner class Inner<P2> 1430 } 1431 """ 1432 .trimIndent() 1433 ), 1434 signature( 1435 """ 1436 // Signature format: 5.0 1437 // - include-type-use-annotations=yes 1438 // - kotlin-name-type-order=yes 1439 package test.pkg { 1440 public class Foo { 1441 method public foo(): test.pkg.Outer<java.lang.String?>.Inner<java.lang.String>?; 1442 } 1443 } 1444 """ 1445 .trimIndent() 1446 ), 1447 ) { 1448 val innerClass = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1449 innerClass.assertClassTypeItem { 1450 assertHasNullableNullability(nullabilityFromAnnotations) 1451 arguments.single().assertHasNonNullNullability(nullabilityFromAnnotations) 1452 1453 // Outer class types can't be null and don't need to be annotated. 1454 outerClassType.assertNotNullTypeItem { 1455 assertHasNonNullNullability(expectAnnotation = false) 1456 arguments.single().assertHasNullableNullability(nullabilityFromAnnotations) 1457 } 1458 } 1459 } 1460 } 1461 1462 @Test 1463 fun `Test nullability of wildcards`() { 1464 runNullabilityTest( 1465 java( 1466 """ 1467 package test.pkg; 1468 import libcore.util.NonNull; 1469 import libcore.util.Nullable; 1470 import java.util.List; 1471 public class Foo<T> { 1472 public @NonNull Foo<? extends @Nullable String> extendsBound() {} 1473 public @NonNull Foo<? super @NonNull String> superBound() {} 1474 public @NonNull Foo<?> unbounded() {} 1475 } 1476 """ 1477 .trimIndent() 1478 ), 1479 signature( 1480 """ 1481 // Signature format: 5.0 1482 // - kotlin-name-type-order=yes 1483 // - include-type-use-annotations=yes 1484 // - kotlin-style-nulls=no 1485 package test.pkg { 1486 public class Foo<T> { 1487 method public extendsBound(): test.pkg.@NonNull Foo<? extends java.lang.@Nullable String>; 1488 method public superBound(): test.pkg.@NonNull Foo<? super java.lang.@NonNull String>; 1489 method public unbounded(): test.pkg.@NonNull Foo<?>; 1490 } 1491 } 1492 """ 1493 .trimIndent() 1494 ), 1495 kotlin( 1496 """ 1497 package test.pkg 1498 class Foo<T> { 1499 fun extendsBound(): Foo<out String?> {} 1500 fun superBound(): Foo<in String> {} 1501 fun unbounded(): Foo<*> {} 1502 } 1503 """ 1504 .trimIndent() 1505 ), 1506 signature( 1507 """ 1508 // Signature format: 5.0 1509 // - kotlin-name-type-order=yes 1510 // - include-type-use-annotations=yes 1511 package test.pkg { 1512 public class Foo<T> { 1513 method public extendsBound(): test.pkg.Foo<? extends java.lang.String?>; 1514 method public superBound(): test.pkg.Foo<? super java.lang.String>; 1515 method public unbounded(): test.pkg.Foo<?>; 1516 } 1517 } 1518 """ 1519 .trimIndent() 1520 ) 1521 ) { 1522 val fooClass = codebase.assertClass("test.pkg.Foo") 1523 1524 val extendsBoundReturnType = fooClass.assertMethod("extendsBound", "").returnType() 1525 extendsBoundReturnType.assertClassTypeItem { 1526 assertHasNonNullNullability(nullabilityFromAnnotations) 1527 1528 val argumentType = arguments.single() 1529 argumentType.assertWildcardItem { 1530 assertHasUndefinedNullability() 1531 extendsBound.assertNotNullTypeItem { 1532 assertHasNullableNullability(nullabilityFromAnnotations) 1533 } 1534 } 1535 } 1536 1537 val superBoundReturnType = fooClass.assertMethod("superBound", "").returnType() 1538 superBoundReturnType.assertClassTypeItem { 1539 assertHasNonNullNullability(nullabilityFromAnnotations) 1540 1541 val argumentType = arguments.single() 1542 argumentType.assertWildcardItem { 1543 assertHasUndefinedNullability() 1544 superBound.assertNotNullTypeItem { 1545 assertHasNonNullNullability(nullabilityFromAnnotations) 1546 } 1547 } 1548 } 1549 1550 val unboundedReturnType = fooClass.assertMethod("unbounded", "").returnType() 1551 unboundedReturnType.assertClassTypeItem { 1552 assertHasNonNullNullability(nullabilityFromAnnotations) 1553 1554 val argumentType = arguments.single() 1555 argumentType.assertHasUndefinedNullability() 1556 } 1557 } 1558 } 1559 1560 @Test 1561 fun `Test resetting nullability`() { 1562 // Mutating modifiers isn't supported for a text codebase due to type caching. 1563 val javaSource = 1564 inputSet( 1565 java( 1566 """ 1567 package test.pkg; 1568 import libcore.util.Nullable; 1569 public class Foo { 1570 public java.lang.@Nullable String foo() {} 1571 } 1572 """ 1573 .trimIndent() 1574 ), 1575 KnownSourceFiles.libcoreNullableSource 1576 ) 1577 val kotlinSource = 1578 kotlin( 1579 """ 1580 package test.pkg 1581 class Foo { 1582 fun foo(): String? {} 1583 } 1584 """ 1585 .trimIndent() 1586 ) 1587 val nullabilityTest = { codebase: Codebase, annotations: Boolean -> 1588 val stringType = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1589 // The type is originally nullable 1590 stringType.assertHasNullableNullability(annotations) 1591 1592 // Set to platform 1593 stringType.modifiers.setNullability(PLATFORM) 1594 stringType.assertHasPlatformNullability() 1595 // The annotation was not removed 1596 if (annotations) { 1597 assertThat(stringType.annotationNames().single()).endsWith("Nullable") 1598 } 1599 1600 // Set to non-null 1601 stringType.modifiers.setNullability(NONNULL) 1602 assertThat(stringType.modifiers.nullability()).isEqualTo(NONNULL) 1603 // The nullable annotation was not removed, a nonnull annotation was not added 1604 if (annotations) { 1605 assertThat(stringType.annotationNames().single()).endsWith("Nullable") 1606 } 1607 } 1608 1609 runCodebaseTest(javaSource) { nullabilityTest(codebase, true) } 1610 runCodebaseTest(kotlinSource) { nullabilityTest(codebase, false) } 1611 } 1612 1613 @Test 1614 fun `Test nullability set through item annotations`() { 1615 runCodebaseTest( 1616 inputSet( 1617 java( 1618 """ 1619 package test.pkg; 1620 import org.jetbrains.annotations.Nullable; 1621 public class Foo { 1622 public @Nullable String foo() {} 1623 } 1624 """ 1625 .trimIndent() 1626 ), 1627 java( 1628 """ 1629 package org.jetbrains.annotations; 1630 import java.lang.annotation.ElementType; 1631 import java.lang.annotation.Target; 1632 @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) 1633 public @interface Nullable {} 1634 """ 1635 .trimIndent() 1636 ) 1637 ), 1638 inputSet( 1639 signature( 1640 """ 1641 // Signature format: 5.0 1642 // - kotlin-name-type-order=yes 1643 // - include-type-use-annotations=yes 1644 // - kotlin-style-nulls=no 1645 package test.pkg { 1646 public class Foo { 1647 method @Nullable public foo(): String; 1648 } 1649 } 1650 """ 1651 .trimIndent() 1652 ) 1653 ) 1654 ) { 1655 val strType = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1656 // The annotation is on the item, not the type. 1657 strType.assertHasNullableNullability(expectAnnotation = false) 1658 } 1659 } 1660 1661 @Test 1662 fun `Test implicit nullability of constants`() { 1663 runCodebaseTest( 1664 java( 1665 """ 1666 package test.pkg; 1667 public class Foo { 1668 public final String nonNullStringConstant = "non null value"; 1669 public final String nullStringConstant = null; 1670 public String nonConstantString = "non null value"; 1671 } 1672 """ 1673 .trimIndent() 1674 ), 1675 signature( 1676 """ 1677 // Signature format: 2.0 1678 package test.pkg { 1679 public class Foo { 1680 field public final String nonNullStringConstant = "non null value"; 1681 field public final String nullStringConstant; 1682 field public String nonConstantString; 1683 } 1684 } 1685 """ 1686 .trimIndent() 1687 ) 1688 ) { 1689 val fooClass = codebase.assertClass("test.pkg.Foo") 1690 1691 val nonNullConstantType = 1692 fooClass.fields().single { it.name() == "nonNullStringConstant" }.type() 1693 // Nullability not set through an annotation. 1694 nonNullConstantType.assertHasNonNullNullability(expectAnnotation = false) 1695 1696 val nullConstantType = 1697 fooClass.fields().single { it.name() == "nullStringConstant" }.type() 1698 nullConstantType.assertHasPlatformNullability() 1699 1700 val nonConstantType = 1701 fooClass.fields().single { it.name() == "nullStringConstant" }.type() 1702 nonConstantType.assertHasPlatformNullability() 1703 } 1704 } 1705 1706 @Test 1707 fun `Test implicit nullability of constructor returns`() { 1708 runNullabilityTest( 1709 java( 1710 """ 1711 package test.pkg; 1712 public class Foo {} 1713 """ 1714 .trimIndent() 1715 ), 1716 signature( 1717 """ 1718 // Signature format: 2.0 1719 package test.pkg { 1720 public class Foo { 1721 ctor public Foo(); 1722 } 1723 } 1724 """ 1725 .trimIndent() 1726 ), 1727 kotlin( 1728 """ 1729 package test.pkg 1730 class Foo 1731 """ 1732 .trimIndent() 1733 ), 1734 signature( 1735 """ 1736 // Signature format: 5.0 1737 package test.pkg { 1738 public class Foo { 1739 ctor public Foo(); 1740 } 1741 } 1742 """ 1743 .trimIndent() 1744 ) 1745 ) { 1746 val ctorReturn = 1747 codebase.assertClass("test.pkg.Foo").constructors().single().returnType() 1748 // Constructor returns are always non-null without needing an annotation 1749 ctorReturn.assertHasNonNullNullability(expectAnnotation = false) 1750 } 1751 } 1752 1753 @Test 1754 fun `Test implicit nullability of equals parameter`() { 1755 runCodebaseTest( 1756 java( 1757 """ 1758 package test.pkg; 1759 public class Foo { 1760 @Override 1761 public boolean equals(Object other) {} 1762 } 1763 """ 1764 .trimIndent() 1765 ), 1766 signature( 1767 """ 1768 // Signature format: 5.0 1769 // - kotlin-name-type-order=yes 1770 // - include-type-use-annotations=yes 1771 // - kotlin-style-nulls=no 1772 package test.pkg { 1773 public class Foo { 1774 method public equals(other: Object): boolean; 1775 } 1776 } 1777 """ 1778 .trimIndent() 1779 ) 1780 ) { 1781 val equals = codebase.assertClass("test.pkg.Foo").methods().single() 1782 val objType = equals.parameters().single().type() 1783 // equals must accept null 1784 objType.assertHasNullableNullability(expectAnnotation = false) 1785 } 1786 } 1787 1788 @Test 1789 fun `Test implicit nullability of toString`() { 1790 runCodebaseTest( 1791 java( 1792 """ 1793 package test.pkg; 1794 public class Foo { 1795 @Override 1796 public String toString() {} 1797 } 1798 """ 1799 .trimIndent() 1800 ), 1801 signature( 1802 """ 1803 // Signature format: 5.0 1804 // - kotlin-name-type-order=yes 1805 // - include-type-use-annotations=yes 1806 // - kotlin-style-nulls=no 1807 package test.pkg { 1808 public class Foo { 1809 method public toString(): String; 1810 } 1811 } 1812 """ 1813 .trimIndent() 1814 ) 1815 ) { 1816 val strType = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1817 // toString must not return null 1818 strType.assertHasNonNullNullability(expectAnnotation = false) 1819 } 1820 } 1821 1822 @Test 1823 fun `Test implicit nullability of annotation members`() { 1824 runCodebaseTest( 1825 java( 1826 """ 1827 package test.pkg; 1828 public @interface Foo { 1829 String[] values(); 1830 } 1831 """ 1832 .trimIndent() 1833 ), 1834 kotlin( 1835 """ 1836 package test.pkg 1837 annotation class Foo { 1838 fun values(): Array<String> 1839 } 1840 """ 1841 .trimIndent() 1842 ), 1843 signature( 1844 """ 1845 // Signature format: 5.0 1846 // - kotlin-name-type-order=yes 1847 // - include-type-use-annotations=yes 1848 // - kotlin-style-nulls=no 1849 package test.pkg { 1850 public @interface Foo { 1851 method public values(): String[]; 1852 } 1853 } 1854 """ 1855 .trimIndent() 1856 ) 1857 ) { 1858 val strArray = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1859 strArray.assertArrayTypeItem { 1860 assertHasNonNullNullability(expectAnnotation = false) 1861 componentType.assertHasNonNullNullability(false) 1862 } 1863 } 1864 } 1865 1866 @Test 1867 fun `Test nullness of Kotlin enum members`() { 1868 runCodebaseTest( 1869 kotlin( 1870 """ 1871 package test.pkg 1872 enum class Foo { 1873 A 1874 } 1875 """ 1876 .trimIndent() 1877 ) 1878 ) { 1879 val fooEnum = codebase.assertClass("test.pkg.Foo") 1880 1881 // enum_constant public static final A: test.pkg.Foo; 1882 val enumConstant = fooEnum.fields().single() 1883 assertThat(enumConstant.isEnumConstant()).isTrue() 1884 enumConstant.type().assertHasNonNullNullability(expectAnnotation = false) 1885 } 1886 } 1887 1888 @Test 1889 fun `Test nullness of companion object`() { 1890 runCodebaseTest( 1891 kotlin( 1892 """ 1893 package test.pkg 1894 class Foo { 1895 companion object 1896 } 1897 """ 1898 .trimIndent() 1899 ) 1900 ) { 1901 val fooClass = codebase.assertClass("test.pkg.Foo") 1902 val companionType = fooClass.fields().single().type() 1903 companionType.assertHasNonNullNullability(expectAnnotation = false) 1904 } 1905 } 1906 1907 @Test 1908 fun `Test nullness of Kotlin lambda type`() { 1909 runCodebaseTest( 1910 kotlin( 1911 """ 1912 package test.pkg 1913 class Foo { 1914 fun noParamToString(): () -> String {} 1915 fun oneParamToString(): (String?) -> String {} 1916 fun twoParamToString(): (String, Int?) -> String? {} 1917 fun oneParamToUnit(): (String) -> Unit {} 1918 } 1919 """ 1920 .trimIndent() 1921 ) 1922 ) { 1923 val fooClass = codebase.assertClass("test.pkg.Foo") 1924 // () -> String 1925 val noParamToString = fooClass.assertMethod("noParamToString", "").returnType() 1926 noParamToString.assertClassTypeItem { 1927 assertHasNonNullNullability(expectAnnotation = false) 1928 assertThat(arguments).hasSize(1) 1929 arguments.single().assertHasNonNullNullability(expectAnnotation = false) 1930 } 1931 1932 // (String?) -> String 1933 val oneParamToString = fooClass.assertMethod("oneParamToString", "").returnType() 1934 oneParamToString.assertClassTypeItem { 1935 assertHasNonNullNullability(expectAnnotation = false) 1936 assertThat(arguments).hasSize(2) 1937 arguments[0].assertHasNullableNullability(expectAnnotation = false) 1938 arguments[1].assertHasNonNullNullability(expectAnnotation = false) 1939 } 1940 1941 // (String, Int?) -> String? 1942 val twoParamToString = fooClass.assertMethod("twoParamToString", "").returnType() 1943 twoParamToString.assertClassTypeItem { 1944 assertHasNonNullNullability(expectAnnotation = false) 1945 assertThat(arguments).hasSize(3) 1946 arguments[0].assertHasNonNullNullability(expectAnnotation = false) 1947 arguments[1].assertHasNullableNullability(expectAnnotation = false) 1948 arguments[2].assertHasNullableNullability(expectAnnotation = false) 1949 } 1950 1951 // (String) -> Unit 1952 val oneParamToUnit = fooClass.assertMethod("oneParamToUnit", "").returnType() 1953 oneParamToUnit.assertClassTypeItem { 1954 assertHasNonNullNullability(expectAnnotation = false) 1955 assertThat(arguments).hasSize(2) 1956 arguments[0].assertHasNonNullNullability(expectAnnotation = false) 1957 arguments[1].assertHasNonNullNullability(expectAnnotation = false) 1958 } 1959 } 1960 } 1961 1962 @Test 1963 fun `Test inherited nullability of unbounded Kotlin type variables - usage is not null`() { 1964 runCodebaseTest( 1965 kotlin( 1966 """ 1967 package test.pkg 1968 class Foo<T> { 1969 fun foo(): T {} 1970 } 1971 """ 1972 .trimIndent() 1973 ) 1974 ) { 1975 // T is unbounded, so it has an implicit `Any?` bound, making it possibly nullable, but 1976 // not necessarily. That means the usage of the variable without any nullable suffix 1977 // doesn't have a nullability on its own, it depends on what type is used as the 1978 // parameter. 1979 val tVar = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 1980 tVar.assertHasUndefinedNullability() 1981 } 1982 } 1983 1984 @Test 1985 fun `Test inherited nullability of unbounded Kotlin type variables - usage is nullable`() { 1986 runCodebaseTest( 1987 kotlin( 1988 """ 1989 package test.pkg 1990 class Foo<T> { 1991 fun foo(): T? {} 1992 } 1993 """ 1994 .trimIndent() 1995 ) 1996 ) { 1997 // T is unbounded, so it has an implicit `Any?` bound, making it possibly nullable, but 1998 // not necessarily. That means the usage of the variable without any nullable suffix 1999 // doesn't have a nullability on its own, it depends on what type is used as the 2000 // parameter. However, when it has a nullable suffix then it is nullable. 2001 val tVar = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 2002 tVar.assertHasNullableNullability() 2003 } 2004 } 2005 2006 @Test 2007 fun `Test inherited nullability of bounded Kotlin type variables - bound is not nullable`() { 2008 runCodebaseTest( 2009 kotlin( 2010 """ 2011 package test.pkg 2012 class Foo<T : Any> { 2013 fun foo(): T {} 2014 } 2015 """ 2016 .trimIndent() 2017 ) 2018 ) { 2019 // T is bounded by `Any` so it cannot be nullable which means that the variable on its 2020 // own is not nullable. 2021 val tVar = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 2022 tVar.assertHasNonNullNullability() 2023 } 2024 } 2025 2026 @Test 2027 fun `Test inherited nullability of bounded Kotlin type variables - bound is nullable`() { 2028 runCodebaseTest( 2029 kotlin( 2030 """ 2031 package test.pkg 2032 class Foo<T : Number?> { 2033 fun foo(): T {} 2034 } 2035 """ 2036 .trimIndent() 2037 ) 2038 ) { 2039 // T is bounded by `Number?`, making it possibly nullable, but not necessarily. That 2040 // means the usage of the variable without any nullable suffix doesn't have a 2041 // nullability on its own, it depends on what type is used as the parameter. 2042 val tVar = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 2043 tVar.assertHasUndefinedNullability() 2044 } 2045 } 2046 2047 @Test 2048 fun `Test nullability of Kotlin properties and accessors`() { 2049 runCodebaseTest( 2050 kotlin( 2051 """ 2052 package test.pkg 2053 class Foo { 2054 var nullableString: String? 2055 var nonNullListNullableString: List<String?> 2056 } 2057 """ 2058 .trimIndent() 2059 ) 2060 ) { 2061 val fooClass = codebase.assertClass("test.pkg.Foo") 2062 2063 val nullableStringProp = fooClass.properties().single { it.name() == "nullableString" } 2064 nullableStringProp.type().assertHasNullableNullability(expectAnnotation = false) 2065 nullableStringProp.getter!! 2066 .returnType() 2067 .assertHasNullableNullability(expectAnnotation = false) 2068 nullableStringProp.setter!! 2069 .parameters() 2070 .single() 2071 .type() 2072 .assertHasNullableNullability(expectAnnotation = false) 2073 2074 val nonNullListProp = 2075 fooClass.properties().single { it.name() == "nonNullListNullableString" } 2076 val propType = nonNullListProp.type() 2077 val getterType = nonNullListProp.getter!!.returnType() 2078 val setterType = nonNullListProp.setter!!.parameters().single().type() 2079 propType.assertClassTypeItem { 2080 assertHasNonNullNullability(expectAnnotation = false) 2081 arguments.single().assertHasNullableNullability(expectAnnotation = false) 2082 } 2083 getterType.assertClassTypeItem { 2084 assertHasNonNullNullability(expectAnnotation = false) 2085 arguments.single().assertHasNullableNullability(expectAnnotation = false) 2086 } 2087 setterType.assertClassTypeItem { 2088 assertHasNonNullNullability(expectAnnotation = false) 2089 arguments.single().assertHasNullableNullability(expectAnnotation = false) 2090 } 2091 } 2092 } 2093 2094 @Test 2095 fun `Test nullability of extension function type`() { 2096 runCodebaseTest( 2097 kotlin( 2098 """ 2099 package test.pkg 2100 class Foo { 2101 fun foo(): String?.(Int, Int?) -> String {} 2102 } 2103 """ 2104 .trimIndent() 2105 ) 2106 ) { 2107 val extensionFunctionType = 2108 codebase.assertClass("test.pkg.Foo").methods().single().returnType() 2109 extensionFunctionType.assertClassTypeItem { 2110 assertHasNonNullNullability(expectAnnotation = false) 2111 val receiverType = arguments[0] 2112 receiverType.assertHasNullableNullability(expectAnnotation = false) 2113 val typeArgument1 = arguments[1] 2114 typeArgument1.assertHasNonNullNullability(expectAnnotation = false) 2115 val typeArgument2 = arguments[2] 2116 typeArgument2.assertHasNullableNullability(expectAnnotation = false) 2117 val returnType = arguments[3] 2118 returnType.assertHasNonNullNullability(expectAnnotation = false) 2119 } 2120 } 2121 } 2122 2123 @Test 2124 fun `Test nullability of typealias`() { 2125 runCodebaseTest( 2126 kotlin( 2127 """ 2128 package test.pkg 2129 class Foo { 2130 fun foo(): FunctionType? 2131 } 2132 typealias FunctionType = (String) -> Int? 2133 """ 2134 .trimIndent() 2135 ) 2136 ) { 2137 val functionType = codebase.assertClass("test.pkg.Foo").methods().single().returnType() 2138 functionType.assertClassTypeItem { 2139 assertHasNullableNullability(expectAnnotation = false) 2140 val typeArgument = arguments[0] 2141 typeArgument.assertHasNonNullNullability(expectAnnotation = false) 2142 val returnType = arguments[1] 2143 returnType.assertHasNullableNullability(expectAnnotation = false) 2144 } 2145 } 2146 } 2147 2148 @Test 2149 fun `Test nullability of super class type`() { 2150 runCodebaseTest( 2151 java( 2152 """ 2153 package test.pkg; 2154 public class Foo extends Number {} 2155 """ 2156 ), 2157 kotlin( 2158 """ 2159 package test.pkg 2160 class Foo: Number { 2161 } 2162 """ 2163 ), 2164 signature( 2165 """ 2166 // Signature format: 2.0 2167 package test.pkg { 2168 public class Foo extends Number { 2169 } 2170 } 2171 """ 2172 ), 2173 ) { 2174 val superClassType = codebase.assertClass("test.pkg.Foo").superClassType()!! 2175 superClassType.assertHasNonNullNullability(expectAnnotation = false) 2176 } 2177 } 2178 2179 @Test 2180 fun `Test nullability of super interface type`() { 2181 runCodebaseTest( 2182 java( 2183 """ 2184 package test.pkg; 2185 import java.util.Map; 2186 public abstract class Foo implements Map.Entry<String, String> {} 2187 """ 2188 ), 2189 kotlin( 2190 """ 2191 package test.pkg 2192 import java.util.Map 2193 abstract class Foo: Map.Entry<String, String> { 2194 } 2195 """ 2196 ), 2197 signature( 2198 """ 2199 // Signature format: 2.0 2200 package test.pkg { 2201 public abstract class Foo implements java.util.Map.Entry<java.lang.String, java.lang.String> { 2202 } 2203 } 2204 """ 2205 ), 2206 ) { 2207 val superInterfaceType = codebase.assertClass("test.pkg.Foo").interfaceTypes().single() 2208 2209 // The outer class type must be non-null. 2210 val outerClassType = superInterfaceType.outerClassType!! 2211 outerClassType.assertHasNonNullNullability(expectAnnotation = false) 2212 2213 // As must the nested class. 2214 superInterfaceType.assertHasNonNullNullability(expectAnnotation = false) 2215 } 2216 } 2217 2218 @Test 2219 fun `Test nullability of generic super class and interface type`() { 2220 runCodebaseTest( 2221 java( 2222 """ 2223 package test.pkg; 2224 import java.util.List; 2225 public abstract class Foo<E> extends Number implements List<E> {} 2226 """ 2227 ), 2228 kotlin( 2229 """ 2230 package test.pkg 2231 import java.util.List 2232 abstract class Foo<E>: List<E> { 2233 } 2234 """ 2235 ), 2236 signature( 2237 """ 2238 // Signature format: 2.0 2239 package test.pkg { 2240 public abstract class Foo<E> extends Number implements java.util.List<E> { 2241 } 2242 } 2243 """ 2244 ), 2245 ) { 2246 val fooClass = codebase.assertClass("test.pkg.Foo") 2247 2248 // The super class type must be non-null. 2249 val superClassType = codebase.assertClass("test.pkg.Foo").superClassType()!! 2250 superClassType.assertHasNonNullNullability(expectAnnotation = false) 2251 2252 // The super interface types must be non-null. 2253 val superInterfaceType = fooClass.interfaceTypes().single() 2254 superInterfaceType.assertHasNonNullNullability(expectAnnotation = false) 2255 } 2256 } 2257 2258 @Test 2259 fun `Test nullability of class type parameter from constructor`() { 2260 runCodebaseTest( 2261 java( 2262 """ 2263 package test.pkg; 2264 public class Foo<F> { 2265 public class Bar<B> {} 2266 } 2267 """ 2268 .trimIndent() 2269 ), 2270 kotlin( 2271 """ 2272 package test.pkg 2273 class Foo<F> { 2274 inner class Bar<B> 2275 } 2276 """ 2277 .trimIndent() 2278 ), 2279 signature( 2280 """ 2281 // Signature format: 5.0 2282 package test.pkg { 2283 public class Foo<F> { 2284 ctor public Foo(); 2285 } 2286 public class Foo.Bar<B> { 2287 ctor public Foo.Bar(); 2288 } 2289 } 2290 """ 2291 .trimIndent() 2292 ), 2293 ) { 2294 val foo = codebase.assertClass("test.pkg.Foo").constructors().single().returnType() 2295 foo.assertHasNonNullNullability() 2296 val f = (foo as ClassTypeItem).arguments.single() 2297 f.assertHasUndefinedNullability() 2298 2299 val bar = codebase.assertClass("test.pkg.Foo.Bar").constructors().single().returnType() 2300 bar.assertHasNonNullNullability() 2301 val b = (bar as ClassTypeItem).arguments.single() 2302 b.assertHasUndefinedNullability() 2303 val outerFoo = bar.outerClassType!! 2304 outerFoo.assertHasNonNullNullability() 2305 val outerF = outerFoo.arguments.single() 2306 outerF.assertHasUndefinedNullability() 2307 } 2308 } 2309 2310 @Test 2311 fun `Test nullness of unbounded kotlin wildcard`() { 2312 runCodebaseTest( 2313 kotlin( 2314 """ 2315 package test.pkg 2316 class Foo { 2317 fun foo(): List<*> 2318 } 2319 """ 2320 .trimIndent() 2321 ) 2322 ) { 2323 val fooMethod = codebase.assertClass("test.pkg.Foo").methods().single() 2324 val wildcardType = (fooMethod.returnType() as ClassTypeItem).arguments.single() 2325 2326 wildcardType.assertHasUndefinedNullability() 2327 wildcardType.assertWildcardItem { 2328 extendsBound.assertNotNullTypeItem { assertHasNullableNullability() } 2329 } 2330 } 2331 } 2332 } 2333