1 /*
2  * 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
18 
19 import com.android.tools.metalava.model.provider.Capability
20 import com.android.tools.metalava.model.testing.FilterAction.EXCLUDE
21 import com.android.tools.metalava.model.testing.FilterByProvider
22 import com.android.tools.metalava.model.testing.RequiresCapabilities
23 import com.android.tools.metalava.model.text.FileFormat
24 import com.android.tools.metalava.testing.java
25 import com.android.tools.metalava.testing.kotlin
26 import org.junit.Test
27 
28 /** Base class to collect test inputs whose behaviors (API/lint) vary depending on UAST versions. */
29 @RequiresCapabilities(Capability.KOTLIN)
30 abstract class UastTestBase : DriverTest() {
31 
32     @Test
Test RequiresOptIn and OptInnull33     fun `Test RequiresOptIn and OptIn`() {
34         // See http://b/248341155 for more details
35         val klass = if (isK2) "Class" else "kotlin.reflect.KClass"
36         check(
37             sourceFiles =
38                 arrayOf(
39                     kotlin(
40                         """
41                     package test.pkg
42 
43                     @RequiresOptIn
44                     @Retention(AnnotationRetention.BINARY)
45                     @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
46                     annotation class ExperimentalBar
47 
48                     @ExperimentalBar
49                     class FancyBar
50 
51                     @OptIn(FancyBar::class) // @OptIn should not be tracked as it is not API
52                     class SimpleClass {
53                         fun methodUsingFancyBar() {
54                             val fancyBar = FancyBar()
55                         }
56                     }
57 
58                     @androidx.annotation.experimental.UseExperimental(FancyBar::class) // @UseExperimental should not be tracked as it is not API
59                     class AnotherSimpleClass {
60                         fun methodUsingFancyBar() {
61                             val fancyBar = FancyBar()
62                         }
63                     }
64                 """
65                     ),
66                     kotlin(
67                         """
68                     package androidx.annotation.experimental
69 
70                     import kotlin.annotation.Retention
71                     import kotlin.annotation.Target
72                     import kotlin.reflect.KClass
73 
74                     @Retention(AnnotationRetention.BINARY)
75                     @Target(
76                         AnnotationTarget.CLASS,
77                         AnnotationTarget.PROPERTY,
78                         AnnotationTarget.LOCAL_VARIABLE,
79                         AnnotationTarget.VALUE_PARAMETER,
80                         AnnotationTarget.CONSTRUCTOR,
81                         AnnotationTarget.FUNCTION,
82                         AnnotationTarget.PROPERTY_GETTER,
83                         AnnotationTarget.PROPERTY_SETTER,
84                         AnnotationTarget.FILE,
85                         AnnotationTarget.TYPEALIAS
86                     )
87                     annotation class UseExperimental(
88                         /**
89                          * Defines the experimental API(s) whose usage this annotation allows.
90                          */
91                         vararg val markerClass: KClass<out Annotation>
92                     )
93                 """
94                     )
95                 ),
96             format = FileFormat.V3,
97             api =
98                 """
99                 // Signature format: 3.0
100                 package androidx.annotation.experimental {
101                   @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.LOCAL_VARIABLE, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER, kotlin.annotation.AnnotationTarget.CONSTRUCTOR, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.PROPERTY_SETTER, kotlin.annotation.AnnotationTarget.FILE, kotlin.annotation.AnnotationTarget.TYPEALIAS}) public @interface UseExperimental {
102                     method public abstract $klass<? extends java.lang.annotation.Annotation>[] markerClass();
103                     property public abstract $klass<? extends java.lang.annotation.Annotation>[] markerClass;
104                   }
105                 }
106                 package test.pkg {
107                   public final class AnotherSimpleClass {
108                     ctor public AnotherSimpleClass();
109                     method public void methodUsingFancyBar();
110                   }
111                   @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalBar {
112                   }
113                   @test.pkg.ExperimentalBar public final class FancyBar {
114                     ctor public FancyBar();
115                   }
116                   public final class SimpleClass {
117                     ctor public SimpleClass();
118                     method public void methodUsingFancyBar();
119                   }
120                 }
121             """
122         )
123     }
124 
125     @Test
renamed via @JvmNamenull126     fun `renamed via @JvmName`() {
127         val api =
128             if (isK2) {
129                 // NB: getInterpolated -> isInterpolated
130                 """
131                     // Signature format: 4.0
132                     package test.pkg {
133                       public final class ColorRamp {
134                         ctor public ColorRamp(int[] colors, boolean interpolated);
135                         method public int[] getColors();
136                         method public int[] getOtherColors();
137                         method public boolean isInitiallyEnabled();
138                         method public boolean isInterpolated();
139                         method public void updateOtherColors(int[]);
140                         property public final int[] colors;
141                         property public final boolean initiallyEnabled;
142                         property public final boolean interpolated;
143                         property public final int[] otherColors;
144                       }
145                     }
146                 """
147             } else {
148                 """
149                     // Signature format: 4.0
150                     package test.pkg {
151                       public final class ColorRamp {
152                         ctor public ColorRamp(int[] colors, boolean interpolated);
153                         method public int[] getColors();
154                         method public boolean getInterpolated();
155                         method public int[] getOtherColors();
156                         method public boolean isInitiallyEnabled();
157                         method public void updateOtherColors(int[]);
158                         property public final int[] colors;
159                         property public final boolean initiallyEnabled;
160                         property public final boolean interpolated;
161                         property public final int[] otherColors;
162                       }
163                     }
164                 """
165             }
166         // Regression test from http://b/257444932: @get:JvmName on constructor property
167         check(
168             sourceFiles =
169                 arrayOf(
170                     kotlin(
171                         """
172                         package test.pkg
173 
174                         class ColorRamp(
175                             val colors: IntArray,
176                             @get:JvmName("isInterpolated")
177                             val interpolated: Boolean,
178                         ) {
179                             @get:JvmName("isInitiallyEnabled")
180                             val initiallyEnabled: Boolean
181 
182                             @set:JvmName("updateOtherColors")
183                             var otherColors: IntArray
184                         }
185                     """
186                     )
187                 ),
188             format = FileFormat.V4,
189             api = api,
190         )
191     }
192 
193     @Test
Kotlin Reified Methodsnull194     fun `Kotlin Reified Methods`() {
195         // TODO: once fix for https://youtrack.jetbrains.com/issue/KT-39209 is available (231),
196         //  FE1.0 UAST will have implicit nullability too.
197         //  Put this back to ApiFileTest, before `Kotlin Reified Methods 2`
198         val n = if (isK2) " @Nullable" else ""
199         check(
200             format = FileFormat.V2,
201             sourceFiles =
202                 arrayOf(
203                     java(
204                         """
205                     package test.pkg;
206 
207                     public class Context {
208                         @SuppressWarnings("unchecked")
209                         public final <T> T getSystemService(Class<T> serviceClass) {
210                             return null;
211                         }
212                     }
213                     """
214                     ),
215                     kotlin(
216                         """
217                     package test.pkg
218 
219                     inline fun <reified T> Context.systemService1() = getSystemService(T::class.java)
220                     inline fun Context.systemService2() = getSystemService(String::class.java)
221                     """
222                     )
223                 ),
224             api =
225                 """
226                 package test.pkg {
227                   public class Context {
228                     ctor public Context();
229                     method public final <T> T getSystemService(Class<T>);
230                   }
231                   public final class TestKt {
232                     method$n public static inline <reified T> T systemService1(@NonNull test.pkg.Context);
233                     method public static inline String systemService2(@NonNull test.pkg.Context);
234                   }
235                 }
236                 """
237         )
238     }
239 
240     @Test
Annotation on parameters of data class synthetic copynull241     fun `Annotation on parameters of data class synthetic copy`() {
242         // https://youtrack.jetbrains.com/issue/KT-57003
243         check(
244             sourceFiles =
245                 arrayOf(
246                     kotlin(
247                         """
248                         package test.pkg
249                         annotation class MyAnnotation
250 
251                         data class Foo(@MyAnnotation val p1: Int, val p2: String)
252                     """
253                     )
254                 ),
255             api =
256                 """
257                 package test.pkg {
258                   public final class Foo {
259                     ctor public Foo(@test.pkg.MyAnnotation int p1, String p2);
260                     method public int component1();
261                     method public String component2();
262                     method public test.pkg.Foo copy(@test.pkg.MyAnnotation int p1, String p2);
263                     method public int getP1();
264                     method public String getP2();
265                     property public final int p1;
266                     property public final String p2;
267                   }
268                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface MyAnnotation {
269                   }
270                 }
271             """
272         )
273     }
274 
275     @Test
declarations with value class in its signaturenull276     fun `declarations with value class in its signature`() {
277         // https://youtrack.jetbrains.com/issue/KT-57546
278         // https://youtrack.jetbrains.com/issue/KT-57577
279         val mod = if (isK2) "" else " final"
280         check(
281             sourceFiles =
282                 arrayOf(
283                     kotlin(
284                         """
285                         package test.pkg
286                         @kotlin.jvm.JvmInline
287                         value class AnchorType internal constructor(internal val ratio: Float) {
288                             companion object {
289                                 val Start = AnchorType(0f)
290                                 val Center = AnchorType(0.5f)
291                                 val End = AnchorType(1f)
292                             }
293                         }
294                         class User(
295                           val p : AnchorType,
296                           var q : AnchorType,
297                         ) {
298                           fun foo() = p
299                           fun bar(): () -> AnchorType = { foo() }
300                         }
301 
302                         class Alignment(val horizontal: Horizontal, val vertical: Vertical) {
303                           @kotlin.jvm.JvmInline
304                           value class Horizontal private constructor(private val value: Int) {
305                             companion object {
306                               val Start: Horizontal = Horizontal(0)
307                               val CenterHorizontally: Horizontal = Horizontal(1)
308                               val End: Horizontal = Horizontal(2)
309                             }
310                           }
311 
312                           @kotlin.jvm.JvmInline
313                           value class Vertical private constructor(private val value: Int) {
314                             companion object {
315                               val Top: Vertical = Vertical(0)
316                               val CenterVertically: Vertical = Vertical(1)
317                               val Bottom: Vertical = Vertical(2)
318                             }
319                           }
320 
321                           companion object {
322                             val TopStart: Alignment = Alignment(Horizontal.Start, Vertical.Top)
323                             val Top: Vertical = Vertical.Top
324                             val Start: Horizontal = Horizontal.Start
325                           }
326                         }
327                     """
328                     )
329                 ),
330             api =
331                 """
332                 package test.pkg {
333                   public final class Alignment {
334                     ctor public Alignment(int horizontal, int vertical);
335                     method public int getHorizontal();
336                     method public int getVertical();
337                     property public$mod int horizontal;
338                     property public$mod int vertical;
339                     field public static final test.pkg.Alignment.Companion Companion;
340                   }
341                   public static final class Alignment.Companion {
342                     method public int getStart();
343                     method public int getTop();
344                     method public test.pkg.Alignment getTopStart();
345                     property public$mod int Start;
346                     property public$mod int Top;
347                     property public final test.pkg.Alignment TopStart;
348                   }
349                   @kotlin.jvm.JvmInline public static final value class Alignment.Horizontal {
350                     field public static final test.pkg.Alignment.Horizontal.Companion Companion;
351                   }
352                   public static final class Alignment.Horizontal.Companion {
353                     method public int getCenterHorizontally();
354                     method public int getEnd();
355                     method public int getStart();
356                     property public$mod int CenterHorizontally;
357                     property public$mod int End;
358                     property public$mod int Start;
359                   }
360                   @kotlin.jvm.JvmInline public static final value class Alignment.Vertical {
361                     field public static final test.pkg.Alignment.Vertical.Companion Companion;
362                   }
363                   public static final class Alignment.Vertical.Companion {
364                     method public int getBottom();
365                     method public int getCenterVertically();
366                     method public int getTop();
367                     property public$mod int Bottom;
368                     property public$mod int CenterVertically;
369                     property public$mod int Top;
370                   }
371                   @kotlin.jvm.JvmInline public final value class AnchorType {
372                     field public static final test.pkg.AnchorType.Companion Companion;
373                   }
374                   public static final class AnchorType.Companion {
375                     method public float getCenter();
376                     method public float getEnd();
377                     method public float getStart();
378                     property public final float Center;
379                     property public final float End;
380                     property public final float Start;
381                   }
382                   public final class User {
383                     ctor public User(float p, float q);
384                     method public kotlin.jvm.functions.Function0<test.pkg.AnchorType> bar();
385                     method public float foo();
386                     method public float getP();
387                     method public float getQ();
388                     method public void setQ(float);
389                     property public$mod float p;
390                     property public$mod float q;
391                   }
392                 }
393         """
394         )
395     }
396 
397     @Test
non-last vararg typenull398     fun `non-last vararg type`() {
399         // https://youtrack.jetbrains.com/issue/KT-57547
400         check(
401             sourceFiles =
402                 arrayOf(
403                     kotlin(
404                         """
405                         package test.pkg
406                         fun foo(vararg vs: String, b: Boolean = true) {
407                         }
408                     """
409                     )
410                 ),
411             api =
412                 """
413                 package test.pkg {
414                   public final class TestKt {
415                     method public static void foo(String[] vs, optional boolean b);
416                   }
417                 }
418             """
419         )
420     }
421 
422     @Test
implements Comparatornull423     fun `implements Comparator`() {
424         // https://youtrack.jetbrains.com/issue/KT-57548
425         check(
426             sourceFiles =
427                 arrayOf(
428                     kotlin(
429                         """
430                         package test.pkg
431                         class Foo(val x : Int)
432                         class FooComparator : Comparator<Foo> {
433                           override fun compare(firstFoo: Foo, secondFoo: Foo): Int =
434                             firstFoo.x - secondFoo.x
435                         }
436                     """
437                     )
438                 ),
439             api =
440                 """
441                 package test.pkg {
442                   public final class Foo {
443                     ctor public Foo(int x);
444                     method public int getX();
445                     property public final int x;
446                   }
447                   public final class FooComparator implements java.util.Comparator<test.pkg.Foo> {
448                     ctor public FooComparator();
449                     method public int compare(test.pkg.Foo firstFoo, test.pkg.Foo secondFoo);
450                   }
451                 }
452             """
453         )
454     }
455 
456     @Test
constant in file-level annotationnull457     fun `constant in file-level annotation`() {
458         // https://youtrack.jetbrains.com/issue/KT-57550
459         check(
460             sourceFiles =
461                 arrayOf(
462                     kotlin(
463                         """
464                         @file:RequiresApi(31)
465                         package test.pkg
466                         import androidx.annotation.RequiresApi
467 
468                         @RequiresApi(31)
469                         fun foo(p: Int) {}
470                     """
471                     ),
472                     requiresApiSource
473                 ),
474             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
475             api =
476                 """
477                 package test.pkg {
478                   @RequiresApi(31) public final class TestKt {
479                     method @RequiresApi(31) public static void foo(int p);
480                   }
481                 }
482             """
483         )
484     }
485 
486     @Test
final modifier in enum membersnull487     fun `final modifier in enum members`() {
488         // https://youtrack.jetbrains.com/issue/KT-57567
489         check(
490             sourceFiles =
491                 arrayOf(
492                     kotlin(
493                         """
494                         package test.pkg
495                         enum class Event {
496                           ON_CREATE, ON_START, ON_STOP, ON_DESTROY;
497                           companion object {
498                             @JvmStatic
499                             fun upTo(state: State): Event? {
500                               return when(state) {
501                                 State.ENQUEUED -> ON_CREATE
502                                 State.RUNNING -> ON_START
503                                 State.BLOCKED -> ON_STOP
504                                 else -> null
505                               }
506                             }
507                           }
508                         }
509                         enum class State {
510                           ENQUEUED, RUNNING, SUCCEEDED, FAILED, BLOCKED, CANCELLED;
511                           val isFinished: Boolean
512                             get() = this == SUCCEEDED || this == FAILED || this == CANCELLED
513                           fun isAtLeast(state: State): Boolean {
514                             return compareTo(state) >= 0
515                           }
516                         }
517                     """
518                     )
519                 ),
520             api =
521                 """
522                 package test.pkg {
523                   public enum Event {
524                     method public static test.pkg.Event? upTo(test.pkg.State state);
525                     enum_constant public static final test.pkg.Event ON_CREATE;
526                     enum_constant public static final test.pkg.Event ON_DESTROY;
527                     enum_constant public static final test.pkg.Event ON_START;
528                     enum_constant public static final test.pkg.Event ON_STOP;
529                     field public static final test.pkg.Event.Companion Companion;
530                   }
531                   public static final class Event.Companion {
532                     method public test.pkg.Event? upTo(test.pkg.State state);
533                   }
534                   public enum State {
535                     method public boolean isAtLeast(test.pkg.State state);
536                     method public boolean isFinished();
537                     property public final boolean isFinished;
538                     enum_constant public static final test.pkg.State BLOCKED;
539                     enum_constant public static final test.pkg.State CANCELLED;
540                     enum_constant public static final test.pkg.State ENQUEUED;
541                     enum_constant public static final test.pkg.State FAILED;
542                     enum_constant public static final test.pkg.State RUNNING;
543                     enum_constant public static final test.pkg.State SUCCEEDED;
544                   }
545                 }
546             """
547         )
548     }
549 
550     @Test
lateinit var as mutable bare fieldnull551     fun `lateinit var as mutable bare field`() {
552         // https://youtrack.jetbrains.com/issue/KT-57569
553         check(
554             sourceFiles =
555                 arrayOf(
556                     kotlin(
557                         """
558                         package test.pkg
559                         class Bar
560                         class Foo {
561                           lateinit var bars: List<Bar>
562                             private set
563                         }
564                     """
565                     )
566                 ),
567             api =
568                 """
569                 package test.pkg {
570                   public final class Bar {
571                     ctor public Bar();
572                   }
573                   public final class Foo {
574                     ctor public Foo();
575                     method public java.util.List<test.pkg.Bar> getBars();
576                     property public final java.util.List<test.pkg.Bar> bars;
577                   }
578                 }
579             """
580         )
581     }
582 
583     @Test
Upper bound wildcards -- enum membersnull584     fun `Upper bound wildcards -- enum members`() {
585         // https://youtrack.jetbrains.com/issue/KT-57578
586         val upperBound = "? extends "
587         check(
588             sourceFiles =
589                 arrayOf(
590                     kotlin(
591                         """
592                         package test.pkg
593                         enum class PowerCategoryDisplayLevel {
594                           BREAKDOWN, TOTAL
595                         }
596 
597                         enum class PowerCategory {
598                           CPU, MEMORY
599                         }
600 
601                         class PowerMetric {
602                           companion object {
603                             @JvmStatic
604                             fun Battery(): Type.Battery {
605                               return Type.Battery()
606                             }
607 
608                             @JvmStatic
609                             fun Energy(
610                               categories: Map<PowerCategory, PowerCategoryDisplayLevel> = emptyMap()
611                             ): Type.Energy {
612                               return Type.Energy(categories)
613                             }
614 
615                             @JvmStatic
616                             fun Power(
617                               categories: Map<PowerCategory, PowerCategoryDisplayLevel> = emptyMap()
618                             ): Type.Power {
619                               return Type.Power(categories)
620                             }
621                           }
622                           sealed class Type(var categories: Map<PowerCategory, PowerCategoryDisplayLevel> = emptyMap()) {
623                             class Power(
624                               powerCategories: Map<PowerCategory, PowerCategoryDisplayLevel> = emptyMap()
625                             ) : Type(powerCategories)
626 
627                             class Energy(
628                               energyCategories: Map<PowerCategory, PowerCategoryDisplayLevel> = emptyMap()
629                             ) : Type(energyCategories)
630 
631                             class Battery : Type()
632                           }
633                         }
634                     """
635                     )
636                 ),
637             api =
638                 """
639                 package test.pkg {
640                   public enum PowerCategory {
641                     enum_constant public static final test.pkg.PowerCategory CPU;
642                     enum_constant public static final test.pkg.PowerCategory MEMORY;
643                   }
644                   public enum PowerCategoryDisplayLevel {
645                     enum_constant public static final test.pkg.PowerCategoryDisplayLevel BREAKDOWN;
646                     enum_constant public static final test.pkg.PowerCategoryDisplayLevel TOTAL;
647                   }
648                   public final class PowerMetric {
649                     ctor public PowerMetric();
650                     method public static test.pkg.PowerMetric.Type.Battery Battery();
651                     method public static test.pkg.PowerMetric.Type.Energy Energy(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> categories);
652                     method public static test.pkg.PowerMetric.Type.Power Power(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> categories);
653                     field public static final test.pkg.PowerMetric.Companion Companion;
654                   }
655                   public static final class PowerMetric.Companion {
656                     method public test.pkg.PowerMetric.Type.Battery Battery();
657                     method public test.pkg.PowerMetric.Type.Energy Energy(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> categories);
658                     method public test.pkg.PowerMetric.Type.Power Power(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> categories);
659                   }
660                   public abstract static sealed class PowerMetric.Type {
661                     method public final java.util.Map<test.pkg.PowerCategory,test.pkg.PowerCategoryDisplayLevel> getCategories();
662                     method public final void setCategories(java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel>);
663                     property public final java.util.Map<test.pkg.PowerCategory,test.pkg.PowerCategoryDisplayLevel> categories;
664                   }
665                   public static final class PowerMetric.Type.Battery extends test.pkg.PowerMetric.Type {
666                     ctor public PowerMetric.Type.Battery();
667                   }
668                   public static final class PowerMetric.Type.Energy extends test.pkg.PowerMetric.Type {
669                     ctor public PowerMetric.Type.Energy(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> energyCategories);
670                   }
671                   public static final class PowerMetric.Type.Power extends test.pkg.PowerMetric.Type {
672                     ctor public PowerMetric.Type.Power(optional java.util.Map<test.pkg.PowerCategory,${upperBound}test.pkg.PowerCategoryDisplayLevel> powerCategories);
673                   }
674                 }
675             """
676         )
677     }
678 
679     @Test
Upper bound wildcards -- type aliasnull680     fun `Upper bound wildcards -- type alias`() {
681         // https://youtrack.jetbrains.com/issue/KT-61460
682         check(
683             sourceFiles =
684                 arrayOf(
685                     kotlin(
686                         """
687                         package test.pkg
688 
689                         class PerfettoSdkHandshake(
690                           private val targetPackage: String,
691                           private val parseJsonMap: (jsonString: String) -> Map<String, String>,
692                           private val executeShellCommand: ShellCommandExecutor,
693                         )
694 
695                         internal typealias ShellCommandExecutor = (command: String) -> String
696                         """
697                     )
698                 ),
699             api =
700                 """
701                 package test.pkg {
702                   public final class PerfettoSdkHandshake {
703                     ctor public PerfettoSdkHandshake(String targetPackage, kotlin.jvm.functions.Function1<? super java.lang.String,? extends java.util.Map<java.lang.String,java.lang.String>> parseJsonMap, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.String> executeShellCommand);
704                   }
705                 }
706                 """
707         )
708     }
709 
710     @Test
Upper bound wildcards -- extension function typenull711     fun `Upper bound wildcards -- extension function type`() {
712         // https://youtrack.jetbrains.com/issue/KT-61734
713         check(
714             sourceFiles =
715                 arrayOf(
716                     kotlin(
717                         """
718                         package test.pkg
719 
720                         interface NavGraphBuilder
721 
722                         interface AnimatedContentTransitionScope<S>
723 
724                         interface NavBackStackEntry
725 
726                         interface EnterTransition
727 
728                         fun NavGraphBuilder.compose(
729                           enterTransition: (@JvmSuppressWildcards
730                               AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = null,
731                         ) = TODO()
732                         """
733                     )
734                 ),
735             api =
736                 """
737                 package test.pkg {
738                   public interface AnimatedContentTransitionScope<S> {
739                   }
740                   public interface EnterTransition {
741                   }
742                   public interface NavBackStackEntry {
743                   }
744                   public interface NavGraphBuilder {
745                   }
746                   public final class NavGraphBuilderKt {
747                     method public static Void compose(test.pkg.NavGraphBuilder, optional kotlin.jvm.functions.Function1<test.pkg.AnimatedContentTransitionScope<test.pkg.NavBackStackEntry>,test.pkg.EnterTransition?>? enterTransition);
748                   }
749                 }
750                 """
751         )
752     }
753 
754     @Test
Upper bound wildcards -- extension function type -- deprecatednull755     fun `Upper bound wildcards -- extension function type -- deprecated`() {
756         // https://youtrack.jetbrains.com/issue/KT-61734
757         val wildcard1 = if (isK2) "" else "? super "
758         val wildcard2 = if (isK2) "" else "? extends "
759         check(
760             sourceFiles =
761                 arrayOf(
762                     kotlin(
763                         """
764                         package test.pkg
765 
766                         interface NavGraphBuilder
767 
768                         interface AnimatedContentTransitionScope<S>
769 
770                         interface NavBackStackEntry
771 
772                         interface EnterTransition
773 
774                         fun NavGraphBuilder.after(
775                           enterTransition: (@JvmSuppressWildcards
776                               AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = null,
777                         ) = TODO()
778 
779                         @Deprecated("no more composable", level = DeprecationLevel.HIDDEN)
780                         fun NavGraphBuilder.before(
781                           enterTransition: (@JvmSuppressWildcards
782                               AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = null,
783                         ) = TODO()
784                         """
785                     )
786                 ),
787             api =
788                 """
789                 package test.pkg {
790                   public interface AnimatedContentTransitionScope<S> {
791                   }
792                   public interface EnterTransition {
793                   }
794                   public interface NavBackStackEntry {
795                   }
796                   public interface NavGraphBuilder {
797                   }
798                   public final class NavGraphBuilderKt {
799                     method public static Void after(test.pkg.NavGraphBuilder, optional kotlin.jvm.functions.Function1<test.pkg.AnimatedContentTransitionScope<test.pkg.NavBackStackEntry>,test.pkg.EnterTransition?>? enterTransition);
800                     method @Deprecated public static Void before(test.pkg.NavGraphBuilder, optional kotlin.jvm.functions.Function1<${wildcard1}test.pkg.AnimatedContentTransitionScope<test.pkg.NavBackStackEntry>,${wildcard2}test.pkg.EnterTransition?>? enterTransition);
801                   }
802                 }
803                 """
804         )
805     }
806 
807     @Test
boxed type argument as method return typenull808     fun `boxed type argument as method return type`() {
809         // https://youtrack.jetbrains.com/issue/KT-57579
810         check(
811             sourceFiles =
812                 arrayOf(
813                     kotlin(
814                         """
815                         package test.pkg
816                         abstract class ActivityResultContract<I, O> {
817                           abstract fun parseResult(resultCode: Int, intent: Intent?): O
818                         }
819 
820                         interface Intent
821 
822                         class StartActivityForResult : ActivityResultContract<Intent, Boolean>() {
823                           override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
824                             return resultCode == 42
825                           }
826                         }
827                     """
828                     )
829                 ),
830             api =
831                 """
832                 package test.pkg {
833                   public abstract class ActivityResultContract<I, O> {
834                     ctor public ActivityResultContract();
835                     method public abstract O parseResult(int resultCode, test.pkg.Intent? intent);
836                   }
837                   public interface Intent {
838                   }
839                   public final class StartActivityForResult extends test.pkg.ActivityResultContract<test.pkg.Intent,java.lang.Boolean> {
840                     ctor public StartActivityForResult();
841                     method public Boolean parseResult(int resultCode, test.pkg.Intent? intent);
842                   }
843                 }
844             """
845         )
846     }
847 
848     @Test
setter returns this with type castnull849     fun `setter returns this with type cast`() {
850         // https://youtrack.jetbrains.com/issue/KT-61459
851         check(
852             sourceFiles =
853                 arrayOf(
854                     kotlin(
855                         """
856                         package test.pkg
857 
858                         interface Alarm {
859                           interface Builder<Self : Builder<Self>> {
860                             fun build(): Alarm
861                           }
862                         }
863 
864                         abstract class AbstractAlarm<
865                           Self : AbstractAlarm<Self, Builder>, Builder : AbstractAlarm.Builder<Builder, Self>>
866                         internal constructor(
867                           val identifier: String,
868                         ) : Alarm {
869                           abstract class Builder<Self : Builder<Self, Built>, Built : AbstractAlarm<Built, Self>> : Alarm.Builder<Self> {
870                             private var identifier: String = ""
871 
872                             fun setIdentifier(text: String): Self {
873                               this.identifier = text
874                               return this as Self
875                             }
876 
877                             final override fun build(): Built = TODO()
878                           }
879                         }
880                     """
881                     )
882                 ),
883             api =
884                 """
885                 package test.pkg {
886                   public abstract class AbstractAlarm<Self extends test.pkg.AbstractAlarm<Self, Builder>, Builder extends test.pkg.AbstractAlarm.Builder<Builder, Self>> implements test.pkg.Alarm {
887                     method public final String getIdentifier();
888                     property public final String identifier;
889                   }
890                   public abstract static class AbstractAlarm.Builder<Self extends test.pkg.AbstractAlarm.Builder<Self, Built>, Built extends test.pkg.AbstractAlarm<Built, Self>> implements test.pkg.Alarm.Builder<Self> {
891                     ctor public AbstractAlarm.Builder();
892                     method public final Built build();
893                     method public final Self setIdentifier(String text);
894                   }
895                   public interface Alarm {
896                   }
897                   public static interface Alarm.Builder<Self extends test.pkg.Alarm.Builder<Self>> {
898                     method public test.pkg.Alarm build();
899                   }
900                 }
901             """
902         )
903     }
904 
905     @Test
suspend fun in interfacenull906     fun `suspend fun in interface`() {
907         // https://youtrack.jetbrains.com/issue/KT-61544
908         check(
909             sourceFiles =
910                 arrayOf(
911                     kotlin(
912                         """
913                         package test.pkg
914 
915                         interface MyInterface
916 
917                         interface GattClientScope {
918                           suspend fun await(block: () -> Unit)
919                           suspend fun readCharacteristic(p: MyInterface): Result<ByteArray>
920                           suspend fun writeCharacteristic(p: MyInterface, value: ByteArray): Result<Unit>
921                         }
922                         """
923                     )
924                 ),
925             api =
926                 """
927                 package test.pkg {
928                   public interface GattClientScope {
929                     method public suspend Object? await(kotlin.jvm.functions.Function0<kotlin.Unit> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
930                     method public suspend Object? readCharacteristic(test.pkg.MyInterface p, kotlin.coroutines.Continuation<? super kotlin.Result<? extends byte[]>>);
931                     method public suspend Object? writeCharacteristic(test.pkg.MyInterface p, byte[] value, kotlin.coroutines.Continuation<? super kotlin.Result<? extends kotlin.Unit>>);
932                   }
933                   public interface MyInterface {
934                   }
935                 }
936                 """
937         )
938     }
939 
940     @Test
nullable return type via type aliasnull941     fun `nullable return type via type alias`() {
942         // https://youtrack.jetbrains.com/issue/KT-61460
943         check(
944             sourceFiles =
945                 arrayOf(
946                     kotlin(
947                         """
948                         package test.pkg
949 
950                         typealias HasAuthenticationResultsDelegate = () -> Boolean
951 
952                         class PrepareGetCredentialResponse private constructor(
953                           val hasAuthResultsDelegate: HasAuthenticationResultsDelegate?,
954                         )
955                         """
956                     )
957                 ),
958             api =
959                 """
960                 package test.pkg {
961                   public final class PrepareGetCredentialResponse {
962                     method public kotlin.jvm.functions.Function0<java.lang.Boolean>? getHasAuthResultsDelegate();
963                     property public final kotlin.jvm.functions.Function0<java.lang.Boolean>? hasAuthResultsDelegate;
964                   }
965                 }
966             """
967         )
968     }
969 
970     @Test
IntDef with constant in companion objectnull971     fun `IntDef with constant in companion object`() {
972         // https://youtrack.jetbrains.com/issue/KT-61497
973         check(
974             sourceFiles =
975                 arrayOf(
976                     kotlin(
977                         """
978                         package test.pkg
979 
980                         @Retention(AnnotationRetention.SOURCE)
981                         @Target(AnnotationTarget.ANNOTATION_CLASS)
982                         annotation class MyIntDef(
983                           vararg val value: Int = [],
984                           val flag: Boolean = false,
985                         )
986 
987                         class RemoteAuthClient internal constructor(
988                           private val packageName: String,
989                         ) {
990                           companion object {
991                             const val NO_ERROR: Int = -1
992                             const val ERROR_UNSUPPORTED: Int = 0
993                             const val ERROR_PHONE_UNAVAILABLE: Int = 1
994 
995                             @MyIntDef(NO_ERROR, ERROR_UNSUPPORTED, ERROR_PHONE_UNAVAILABLE)
996                             @Retention(AnnotationRetention.SOURCE)
997                             annotation class ErrorCode
998                           }
999                         }
1000                         """
1001                     ),
1002                 ),
1003             api =
1004                 """
1005                 package test.pkg {
1006                   @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS) public @interface MyIntDef {
1007                     method public abstract boolean flag() default false;
1008                     method public abstract int[] value();
1009                     property public abstract boolean flag;
1010                     property public abstract int[] value;
1011                   }
1012                   public final class RemoteAuthClient {
1013                     field public static final test.pkg.RemoteAuthClient.Companion Companion;
1014                     field public static final int ERROR_PHONE_UNAVAILABLE = 1; // 0x1
1015                     field public static final int ERROR_UNSUPPORTED = 0; // 0x0
1016                     field public static final int NO_ERROR = -1; // 0xffffffff
1017                   }
1018                   public static final class RemoteAuthClient.Companion {
1019                   }
1020                   @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @test.pkg.MyIntDef({test.pkg.RemoteAuthClient.NO_ERROR, test.pkg.RemoteAuthClient.ERROR_UNSUPPORTED, test.pkg.RemoteAuthClient.ERROR_PHONE_UNAVAILABLE}) public static @interface RemoteAuthClient.Companion.ErrorCode {
1021                   }
1022                 }
1023                 """
1024         )
1025     }
1026 
1027     @Test
APIs before and after @Deprecated(HIDDEN) on properties or accessorsnull1028     fun `APIs before and after @Deprecated(HIDDEN) on properties or accessors`() {
1029         val api =
1030             if (isK2) {
1031                 // NB: better tracking non-deprecated accessors (thanks to better use-site handling)
1032                 """
1033                     package test.pkg {
1034                       @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.PROPERTY_SETTER}) public @interface MyAnnotation {
1035                       }
1036                       public interface TestInterface {
1037                         method @Deprecated public int getPOld_deprecatedOnGetter();
1038                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnBoth();
1039                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnGetter();
1040                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnSetter();
1041                         method @Deprecated public int getPOld_deprecatedOnProperty();
1042                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnBoth();
1043                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnGetter();
1044                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnSetter();
1045                         method public int getPOld_deprecatedOnSetter();
1046                         method @test.pkg.MyAnnotation public int getPOld_deprecatedOnSetter_myAnnoOnBoth();
1047                         method @test.pkg.MyAnnotation public int getPOld_deprecatedOnSetter_myAnnoOnGetter();
1048                         method public int getPOld_deprecatedOnSetter_myAnnoOnSetter();
1049                         method public void setPOld_deprecatedOnGetter(int);
1050                         method @test.pkg.MyAnnotation public void setPOld_deprecatedOnGetter_myAnnoOnBoth(int);
1051                         method public void setPOld_deprecatedOnGetter_myAnnoOnGetter(int);
1052                         method @test.pkg.MyAnnotation public void setPOld_deprecatedOnGetter_myAnnoOnSetter(int);
1053                         method @Deprecated public void setPOld_deprecatedOnProperty(int);
1054                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnBoth(int);
1055                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnGetter(int);
1056                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnSetter(int);
1057                         method @Deprecated public void setPOld_deprecatedOnSetter(int);
1058                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnBoth(int);
1059                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnGetter(int);
1060                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnSetter(int);
1061                         property @Deprecated public int pOld_deprecatedOnGetter;
1062                         property @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnBoth;
1063                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnGetter;
1064                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnSetter;
1065                         property @Deprecated public int pOld_deprecatedOnProperty;
1066                         property @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnBoth;
1067                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnGetter;
1068                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnSetter;
1069                         property public abstract int pOld_deprecatedOnSetter;
1070                         property @test.pkg.MyAnnotation public abstract int pOld_deprecatedOnSetter_myAnnoOnBoth;
1071                         property @test.pkg.MyAnnotation public abstract int pOld_deprecatedOnSetter_myAnnoOnGetter;
1072                         property public abstract int pOld_deprecatedOnSetter_myAnnoOnSetter;
1073                       }
1074                       public final class Test_accessors {
1075                         ctor public Test_accessors();
1076                         method public String? getPNew_accessors();
1077                         method @Deprecated public String? getPOld_accessors_deprecatedOnGetter();
1078                         method public String? getPOld_accessors_deprecatedOnProperty();
1079                         method public String? getPOld_accessors_deprecatedOnSetter();
1080                         method public void setPNew_accessors(String?);
1081                         method public void setPOld_accessors_deprecatedOnGetter(String?);
1082                         method public void setPOld_accessors_deprecatedOnProperty(String?);
1083                         method @Deprecated public void setPOld_accessors_deprecatedOnSetter(String?);
1084                         property public final String? pNew_accessors;
1085                         property @Deprecated public String? pOld_accessors_deprecatedOnGetter;
1086                         property public String? pOld_accessors_deprecatedOnProperty;
1087                         property public final String? pOld_accessors_deprecatedOnSetter;
1088                       }
1089                       public final class Test_getter {
1090                         ctor public Test_getter();
1091                         method public String? getPNew_getter();
1092                         method @Deprecated public String? getPOld_getter_deprecatedOnGetter();
1093                         method public String? getPOld_getter_deprecatedOnProperty();
1094                         method public String? getPOld_getter_deprecatedOnSetter();
1095                         method public void setPNew_getter(String?);
1096                         method public void setPOld_getter_deprecatedOnGetter(String?);
1097                         method @Deprecated public void setPOld_getter_deprecatedOnProperty(String?);
1098                         method @Deprecated public void setPOld_getter_deprecatedOnSetter(String?);
1099                         property public final String? pNew_getter;
1100                         property @Deprecated public String? pOld_getter_deprecatedOnGetter;
1101                         property public String? pOld_getter_deprecatedOnProperty;
1102                         property public final String? pOld_getter_deprecatedOnSetter;
1103                       }
1104                       public final class Test_noAccessor {
1105                         ctor public Test_noAccessor();
1106                         method public String getPNew_noAccessor();
1107                         method @Deprecated public String getPOld_noAccessor_deprecatedOnGetter();
1108                         method @Deprecated public String getPOld_noAccessor_deprecatedOnProperty();
1109                         method public String getPOld_noAccessor_deprecatedOnSetter();
1110                         method public void setPNew_noAccessor(String);
1111                         method public void setPOld_noAccessor_deprecatedOnGetter(String);
1112                         method @Deprecated public void setPOld_noAccessor_deprecatedOnProperty(String);
1113                         method @Deprecated public void setPOld_noAccessor_deprecatedOnSetter(String);
1114                         property public final String pNew_noAccessor;
1115                         property @Deprecated public String pOld_noAccessor_deprecatedOnGetter;
1116                         property @Deprecated public String pOld_noAccessor_deprecatedOnProperty;
1117                         property public final String pOld_noAccessor_deprecatedOnSetter;
1118                       }
1119                       public final class Test_setter {
1120                         ctor public Test_setter();
1121                         method public String? getPNew_setter();
1122                         method @Deprecated public String? getPOld_setter_deprecatedOnGetter();
1123                         method @Deprecated public String? getPOld_setter_deprecatedOnProperty();
1124                         method public String? getPOld_setter_deprecatedOnSetter();
1125                         method public void setPNew_setter(String?);
1126                         method public void setPOld_setter_deprecatedOnGetter(String?);
1127                         method public void setPOld_setter_deprecatedOnProperty(String?);
1128                         method @Deprecated public void setPOld_setter_deprecatedOnSetter(String?);
1129                         property public final String? pNew_setter;
1130                         property @Deprecated public String? pOld_setter_deprecatedOnGetter;
1131                         property @Deprecated public String? pOld_setter_deprecatedOnProperty;
1132                         property public final String? pOld_setter_deprecatedOnSetter;
1133                       }
1134                     }
1135                 """
1136             } else {
1137                 """
1138                     package test.pkg {
1139                       @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.PROPERTY_GETTER, kotlin.annotation.AnnotationTarget.PROPERTY_SETTER}) public @interface MyAnnotation {
1140                       }
1141                       public interface TestInterface {
1142                         method @Deprecated public int getPOld_deprecatedOnGetter();
1143                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnBoth();
1144                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnGetter();
1145                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnGetter_myAnnoOnSetter();
1146                         method @Deprecated public int getPOld_deprecatedOnProperty();
1147                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnBoth();
1148                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnGetter();
1149                         method @Deprecated @test.pkg.MyAnnotation public int getPOld_deprecatedOnProperty_myAnnoOnSetter();
1150                         method @Deprecated public void setPOld_deprecatedOnProperty(int);
1151                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnBoth(int);
1152                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnGetter(int);
1153                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnProperty_myAnnoOnSetter(int);
1154                         method @Deprecated public void setPOld_deprecatedOnSetter(int);
1155                         method @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnBoth(int);
1156                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnGetter(int);
1157                         method @Deprecated @test.pkg.MyAnnotation public void setPOld_deprecatedOnSetter_myAnnoOnSetter(int);
1158                         property @Deprecated public int pOld_deprecatedOnGetter;
1159                         property @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnBoth;
1160                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnGetter;
1161                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnGetter_myAnnoOnSetter;
1162                         property @Deprecated public int pOld_deprecatedOnProperty;
1163                         property @Deprecated @test.pkg.MyAnnotation @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnBoth;
1164                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnGetter;
1165                         property @Deprecated @test.pkg.MyAnnotation public int pOld_deprecatedOnProperty_myAnnoOnSetter;
1166                       }
1167                       public final class Test_accessors {
1168                         ctor public Test_accessors();
1169                         method public String? getPNew_accessors();
1170                         method @Deprecated public String? getPOld_accessors_deprecatedOnGetter();
1171                         method public String? getPOld_accessors_deprecatedOnProperty();
1172                         method public void setPNew_accessors(String?);
1173                         method public void setPOld_accessors_deprecatedOnProperty(String?);
1174                         method @Deprecated public void setPOld_accessors_deprecatedOnSetter(String?);
1175                         property public final String? pNew_accessors;
1176                         property @Deprecated public String? pOld_accessors_deprecatedOnGetter;
1177                         property public String? pOld_accessors_deprecatedOnProperty;
1178                       }
1179                       public final class Test_getter {
1180                         ctor public Test_getter();
1181                         method public String? getPNew_getter();
1182                         method @Deprecated public String? getPOld_getter_deprecatedOnGetter();
1183                         method public String? getPOld_getter_deprecatedOnProperty();
1184                         method public void setPNew_getter(String?);
1185                         method @Deprecated public void setPOld_getter_deprecatedOnProperty(String?);
1186                         method @Deprecated public void setPOld_getter_deprecatedOnSetter(String?);
1187                         property public final String? pNew_getter;
1188                         property @Deprecated public String? pOld_getter_deprecatedOnGetter;
1189                         property public String? pOld_getter_deprecatedOnProperty;
1190                       }
1191                       public final class Test_noAccessor {
1192                         ctor public Test_noAccessor();
1193                         method public String getPNew_noAccessor();
1194                         method @Deprecated public String getPOld_noAccessor_deprecatedOnGetter();
1195                         method @Deprecated public String getPOld_noAccessor_deprecatedOnProperty();
1196                         method public void setPNew_noAccessor(String);
1197                         method @Deprecated public void setPOld_noAccessor_deprecatedOnProperty(String);
1198                         method @Deprecated public void setPOld_noAccessor_deprecatedOnSetter(String);
1199                         property public final String pNew_noAccessor;
1200                         property @Deprecated public String pOld_noAccessor_deprecatedOnGetter;
1201                         property @Deprecated public String pOld_noAccessor_deprecatedOnProperty;
1202                       }
1203                       public final class Test_setter {
1204                         ctor public Test_setter();
1205                         method public String? getPNew_setter();
1206                         method @Deprecated public String? getPOld_setter_deprecatedOnGetter();
1207                         method @Deprecated public String? getPOld_setter_deprecatedOnProperty();
1208                         method public void setPNew_setter(String?);
1209                         method public void setPOld_setter_deprecatedOnProperty(String?);
1210                         method @Deprecated public void setPOld_setter_deprecatedOnSetter(String?);
1211                         property public final String? pNew_setter;
1212                         property @Deprecated public String? pOld_setter_deprecatedOnGetter;
1213                         property @Deprecated public String? pOld_setter_deprecatedOnProperty;
1214                       }
1215                     }
1216                 """
1217             }
1218         // TODO: https://youtrack.jetbrains.com/issue/KTIJ-27244
1219         check(
1220             sourceFiles =
1221                 arrayOf(
1222                     kotlin(
1223                         """
1224                         package test.pkg
1225 
1226                         class Test_noAccessor {
1227                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1228                             var pOld_noAccessor_deprecatedOnProperty: String = "42"
1229 
1230                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1231                             var pOld_noAccessor_deprecatedOnGetter: String = "42"
1232 
1233                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1234                             var pOld_noAccessor_deprecatedOnSetter: String = "42"
1235 
1236                             var pNew_noAccessor: String = "42"
1237                         }
1238 
1239                         class Test_getter {
1240                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1241                             var pOld_getter_deprecatedOnProperty: String? = null
1242                                 get() = field ?: "null?"
1243 
1244                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1245                             var pOld_getter_deprecatedOnGetter: String? = null
1246                                 get() = field ?: "null?"
1247 
1248                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1249                             var pOld_getter_deprecatedOnSetter: String? = null
1250                                 get() = field ?: "null?"
1251 
1252                             var pNew_getter: String? = null
1253                                 get() = field ?: "null?"
1254                         }
1255 
1256                         class Test_setter {
1257                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1258                             var pOld_setter_deprecatedOnProperty: String? = null
1259                                 set(value) {
1260                                     if (field == null) {
1261                                         field = value
1262                                     }
1263                                 }
1264 
1265                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1266                             var pOld_setter_deprecatedOnGetter: String? = null
1267                                 set(value) {
1268                                     if (field == null) {
1269                                         field = value
1270                                     }
1271                                 }
1272 
1273                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1274                             var pOld_setter_deprecatedOnSetter: String? = null
1275                                 set(value) {
1276                                     if (field == null) {
1277                                         field = value
1278                                     }
1279                                 }
1280 
1281                             var pNew_setter: String? = null
1282                                 set(value) {
1283                                     if (field == null) {
1284                                         field = value
1285                                     }
1286                                 }
1287                         }
1288 
1289                         class Test_accessors {
1290                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1291                             var pOld_accessors_deprecatedOnProperty: String? = null
1292                                 get() = field ?: "null?"
1293                                 set(value) {
1294                                     if (field == null) {
1295                                         field = value
1296                                     }
1297                                 }
1298 
1299                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1300                             var pOld_accessors_deprecatedOnGetter: String? = null
1301                                 get() = field ?: "null?"
1302                                 set(value) {
1303                                     if (field == null) {
1304                                         field = value
1305                                     }
1306                                 }
1307 
1308                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1309                             var pOld_accessors_deprecatedOnSetter: String? = null
1310                                 get() = field ?: "null?"
1311                                 set(value) {
1312                                     if (field == null) {
1313                                         field = value
1314                                     }
1315                                 }
1316 
1317                             var pNew_accessors: String? = null
1318                                 get() = field ?: "null?"
1319                                 set(value) {
1320                                     if (field == null) {
1321                                         field = value
1322                                     }
1323                                 }
1324                         }
1325 
1326                         @Target(
1327                           AnnotationTarget.PROPERTY,
1328                           AnnotationTarget.PROPERTY_GETTER,
1329                           AnnotationTarget.PROPERTY_SETTER
1330                         )
1331                         annotation class MyAnnotation
1332 
1333                         interface TestInterface {
1334                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1335                             var pOld_deprecatedOnProperty: Int
1336 
1337                             @get:MyAnnotation
1338                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1339                             var pOld_deprecatedOnProperty_myAnnoOnGetter: Int
1340 
1341                             @set:MyAnnotation
1342                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1343                             var pOld_deprecatedOnProperty_myAnnoOnSetter: Int
1344 
1345                             @get:MyAnnotation
1346                             @set:MyAnnotation
1347                             @Deprecated("no more property", level = DeprecationLevel.HIDDEN)
1348                             var pOld_deprecatedOnProperty_myAnnoOnBoth: Int
1349 
1350                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1351                             var pOld_deprecatedOnGetter: Int
1352 
1353                             @get:MyAnnotation
1354                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1355                             var pOld_deprecatedOnGetter_myAnnoOnGetter: Int
1356 
1357                             @set:MyAnnotation
1358                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1359                             var pOld_deprecatedOnGetter_myAnnoOnSetter: Int
1360 
1361                             @get:MyAnnotation
1362                             @set:MyAnnotation
1363                             @get:Deprecated("no more getter", level = DeprecationLevel.HIDDEN)
1364                             var pOld_deprecatedOnGetter_myAnnoOnBoth: Int
1365 
1366                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1367                             var pOld_deprecatedOnSetter: Int
1368 
1369                             @get:MyAnnotation
1370                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1371                             var pOld_deprecatedOnSetter_myAnnoOnGetter: Int
1372 
1373                             @set:MyAnnotation
1374                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1375                             var pOld_deprecatedOnSetter_myAnnoOnSetter: Int
1376 
1377                             @get:MyAnnotation
1378                             @set:MyAnnotation
1379                             @set:Deprecated("no more setter", level = DeprecationLevel.HIDDEN)
1380                             var pOld_deprecatedOnSetter_myAnnoOnBoth: Int
1381                         }
1382                         """
1383                     )
1384                 ),
1385             api = api,
1386         )
1387     }
1388 
1389     @Test
actual typealias -- without value classnull1390     fun `actual typealias -- without value class`() {
1391         // https://youtrack.jetbrains.com/issue/KT-55085
1392         val typeAliasExpanded = if (isK2) "test.pkg.NativePointerKeyboardModifiers" else "int"
1393         val commonSource =
1394             kotlin(
1395                 "commonMain/src/test/pkg/PointerEvent.kt",
1396                 """
1397                         package test.pkg
1398 
1399                         expect class PointerEvent {
1400                             val keyboardModifiers: PointerKeyboardModifiers
1401                         }
1402 
1403                         expect class NativePointerKeyboardModifiers
1404 
1405                         class PointerKeyboardModifiers(internal val packedValue: NativePointerKeyboardModifiers)
1406                         """
1407             )
1408         check(
1409             sourceFiles =
1410                 arrayOf(
1411                     kotlin(
1412                         "androidMain/src/test/pkg/PointerEvent.android.kt",
1413                         """
1414                         package test.pkg
1415 
1416                         actual class PointerEvent {
1417                             actual val keyboardModifiers = PointerKeyboardModifiers(42)
1418                         }
1419 
1420                         internal actual typealias NativePointerKeyboardModifiers = Int
1421                         """
1422                     ),
1423                     commonSource,
1424                 ),
1425             commonSourceFiles = arrayOf(commonSource),
1426             api =
1427                 """
1428                 package test.pkg {
1429                   public final class PointerEvent {
1430                     ctor public PointerEvent();
1431                     method public test.pkg.PointerKeyboardModifiers getKeyboardModifiers();
1432                     property public final test.pkg.PointerKeyboardModifiers keyboardModifiers;
1433                   }
1434                   public final class PointerKeyboardModifiers {
1435                     ctor public PointerKeyboardModifiers($typeAliasExpanded packedValue);
1436                   }
1437                 }
1438                 """
1439         )
1440     }
1441 
1442     @Test
actual typealias -- without common splitnull1443     fun `actual typealias -- without common split`() {
1444         // https://youtrack.jetbrains.com/issue/KT-55085
1445         val typeAliasExpanded = if (isK2) "test.pkg.NativePointerKeyboardModifiers" else "int"
1446         check(
1447             sourceFiles =
1448                 arrayOf(
1449                     kotlin(
1450                         "androidMain/src/test/pkg/PointerEvent.android.kt",
1451                         """
1452                         package test.pkg
1453 
1454                         actual class PointerEvent {
1455                             actual val keyboardModifiers = PointerKeyboardModifiers(42)
1456                         }
1457 
1458                         internal actual typealias NativePointerKeyboardModifiers = Int
1459                         """
1460                     ),
1461                     kotlin(
1462                         "commonMain/src/test/pkg/PointerEvent.kt",
1463                         """
1464                         package test.pkg
1465 
1466                         expect class PointerEvent {
1467                             val keyboardModifiers: PointerKeyboardModifiers
1468                         }
1469 
1470                         expect class NativePointerKeyboardModifiers
1471 
1472                         @kotlin.jvm.JvmInline
1473                         value class PointerKeyboardModifiers(internal val packedValue: NativePointerKeyboardModifiers)
1474                         """
1475                     )
1476                 ),
1477             api =
1478                 """
1479                 package test.pkg {
1480                   public final class PointerEvent {
1481                     ctor public PointerEvent();
1482                     method public $typeAliasExpanded getKeyboardModifiers();
1483                     property public final $typeAliasExpanded keyboardModifiers;
1484                   }
1485                   @kotlin.jvm.JvmInline public final value class PointerKeyboardModifiers {
1486                     ctor public PointerKeyboardModifiers($typeAliasExpanded packedValue);
1487                   }
1488                 }
1489                 """
1490         )
1491     }
1492 
1493     // b/324521456: need to set kotlin-stdlib-common for common module
1494     @FilterByProvider("psi", "k2", action = EXCLUDE)
1495     @Test
actual typealiasnull1496     fun `actual typealias`() {
1497         // https://youtrack.jetbrains.com/issue/KT-55085
1498         // TODO: https://youtrack.jetbrains.com/issue/KTIJ-26853
1499         val typeAliasExpanded = if (isK2) "test.pkg.NativePointerKeyboardModifiers" else "int"
1500         val commonSource =
1501             kotlin(
1502                 "commonMain/src/test/pkg/PointerEvent.kt",
1503                 """
1504                         package test.pkg
1505 
1506                         expect class PointerEvent {
1507                             val keyboardModifiers: PointerKeyboardModifiers
1508                         }
1509 
1510                         expect class NativePointerKeyboardModifiers
1511 
1512                         @kotlin.jvm.JvmInline
1513                         value class PointerKeyboardModifiers(internal val packedValue: NativePointerKeyboardModifiers)
1514                         """
1515             )
1516         check(
1517             sourceFiles =
1518                 arrayOf(
1519                     kotlin(
1520                         "androidMain/src/test/pkg/PointerEvent.android.kt",
1521                         """
1522                         package test.pkg
1523 
1524                         actual class PointerEvent {
1525                             actual val keyboardModifiers = PointerKeyboardModifiers(42)
1526                         }
1527 
1528                         internal actual typealias NativePointerKeyboardModifiers = Int
1529                         """
1530                     ),
1531                     commonSource,
1532                 ),
1533             commonSourceFiles = arrayOf(commonSource),
1534             api =
1535                 """
1536                 package test.pkg {
1537                   public final class PointerEvent {
1538                     ctor public PointerEvent();
1539                     method public int getKeyboardModifiers();
1540                     property public final int keyboardModifiers;
1541                   }
1542                   @kotlin.jvm.JvmInline public final value class PointerKeyboardModifiers {
1543                     ctor public PointerKeyboardModifiers($typeAliasExpanded packedValue);
1544                   }
1545                 }
1546                 """
1547         )
1548     }
1549 
1550     @Test
actual inlinenull1551     fun `actual inline`() {
1552         // b/336816056
1553         val commonSource =
1554             kotlin(
1555                 "commonMain/src/pkg/TestClass.kt",
1556                 """
1557                     package pkg
1558                     public expect class TestClass {
1559                       public fun test1(a: Int = 0)
1560                     }
1561                     public expect inline fun TestClass.test2(a: Int = 0)
1562                 """
1563             )
1564         check(
1565             sourceFiles =
1566                 arrayOf(
1567                     kotlin(
1568                         "androidMain/src/pkg/TestClass.kt",
1569                         """
1570                             package pkg
1571                             public actual class TestClass {
1572                               public actual fun test1(a: Int) {}
1573                             }
1574                             public actual inline fun TestClass.test2(a: Int) {
1575                             }
1576                         """
1577                     ),
1578                     commonSource,
1579                 ),
1580             commonSourceFiles = arrayOf(commonSource),
1581             api =
1582                 """
1583                 package pkg {
1584                   public final class TestClass {
1585                     ctor public TestClass();
1586                     method public void test1(optional int a);
1587                   }
1588                   public final class TestClassKt {
1589                     method public static inline void test2(pkg.TestClass, optional int a);
1590                   }
1591                 }
1592                 """
1593         )
1594     }
1595 }
1596