xref: /aosp_15_r20/tools/metalava/metalava/src/test/java/com/android/tools/metalava/doc/DocAnalyzerRangeTest.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
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.doc
18 
19 import com.android.tools.metalava.DriverTest
20 import com.android.tools.metalava.intDefAnnotationSource
21 import com.android.tools.metalava.intRangeAnnotationSource
22 import com.android.tools.metalava.testing.java
23 import org.junit.Test
24 
25 /** Tests for the [DocAnalyzer] which check the handling of ranges in the docs */
26 class DocAnalyzerRangeTest : DriverTest() {
27     @Test
Document rangesnull28     fun `Document ranges`() {
29         check(
30             sourceFiles =
31                 arrayOf(
32                     java(
33                         """
34                     package test.pkg;
35 
36                     import android.Manifest;
37                     import android.annotation.IntRange;
38 
39                     public class RangeTest {
40                         @IntRange(from = 10)
41                         public int test1(@IntRange(from = 20) int range2) { return 15; }
42 
43                         @IntRange(from = 10, to = 20)
44                         public int test2() { return 15; }
45 
46                         @IntRange(to = 100)
47                         public int test3() { return 50; }
48                     }
49                     """
50                     ),
51                     intRangeAnnotationSource
52                 ),
53             docStubs = true,
54             checkCompilation = true,
55             stubFiles =
56                 arrayOf(
57                     java(
58                         """
59                     package test.pkg;
60                     @SuppressWarnings({"unchecked", "deprecation", "all"})
61                     public class RangeTest {
62                     public RangeTest() { throw new RuntimeException("Stub!"); }
63                     /**
64                      * @param range2 Value is 20 or greater
65                      * @return Value is 10 or greater
66                      */
67                     public int test1(int range2) { throw new RuntimeException("Stub!"); }
68                     /**
69                      * @return Value is between 10 and 20 inclusive
70                      */
71                     public int test2() { throw new RuntimeException("Stub!"); }
72                     /**
73                      * @return Value is 100 or less
74                      */
75                     public int test3() { throw new RuntimeException("Stub!"); }
76                     }
77                     """
78                     )
79                 )
80         )
81     }
82 
83     @Test
Typedefsnull84     fun Typedefs() {
85         check(
86             sourceFiles =
87                 arrayOf(
88                     java(
89                         """
90                     package test.pkg;
91 
92                     import android.annotation.IntDef;
93                     import android.annotation.IntRange;
94 
95                     import java.lang.annotation.Retention;
96                     import java.lang.annotation.RetentionPolicy;
97 
98                     @SuppressWarnings({"UnusedDeclaration", "WeakerAccess"})
99                     public class TypedefTest {
100                         @IntDef({STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT})
101                         @Retention(RetentionPolicy.SOURCE)
102                         private @interface DialogStyle {}
103 
104                         public static final int STYLE_NORMAL = 0;
105                         public static final int STYLE_NO_TITLE = 1;
106                         public static final int STYLE_NO_FRAME = 2;
107                         public static final int STYLE_NO_INPUT = 3;
108                         public static final int STYLE_UNRELATED = 3;
109 
110                         public void setStyle(@DialogStyle int style, int theme) {
111                         }
112 
113                         @IntDef(value = {STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT, 2, 3 + 1},
114                         flag=true)
115                         @Retention(RetentionPolicy.SOURCE)
116                         private @interface DialogFlags {}
117 
118                         public void setFlags(Object first, @DialogFlags int flags) {
119                         }
120                     }
121                     """
122                     ),
123                     intRangeAnnotationSource,
124                     intDefAnnotationSource
125                 ),
126             checkCompilation = true,
127             docStubs = true,
128             stubFiles =
129                 arrayOf(
130                     java(
131                         """
132                     package test.pkg;
133                     @SuppressWarnings({"unchecked", "deprecation", "all"})
134                     public class TypedefTest {
135                     public TypedefTest() { throw new RuntimeException("Stub!"); }
136                     /**
137                      * @param flags Value is either <code>0</code> or a combination of {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, {@link test.pkg.TypedefTest#STYLE_NO_INPUT}, 2, and 3 + 1
138                      */
139                     public void setFlags(java.lang.Object first, int flags) { throw new RuntimeException("Stub!"); }
140                     /**
141                      * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or {@link test.pkg.TypedefTest#STYLE_NO_INPUT}
142                      */
143                     public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
144                     public static final int STYLE_NORMAL = 0; // 0x0
145                     public static final int STYLE_NO_FRAME = 2; // 0x2
146                     public static final int STYLE_NO_INPUT = 3; // 0x3
147                     public static final int STYLE_NO_TITLE = 1; // 0x1
148                     public static final int STYLE_UNRELATED = 3; // 0x3
149                     }
150                     """
151                     )
152                 )
153         )
154     }
155 
156     @Test
Typedefs combined with rangesnull157     fun `Typedefs combined with ranges`() {
158         check(
159             sourceFiles =
160                 arrayOf(
161                     java(
162                         """
163                     package test.pkg;
164 
165                     import android.annotation.IntDef;
166                     import android.annotation.IntRange;
167 
168                     import java.lang.annotation.Retention;
169                     import java.lang.annotation.RetentionPolicy;
170 
171                     @SuppressWarnings({"UnusedDeclaration", "WeakerAccess"})
172                     public class TypedefTest {
173                         @IntDef({STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT})
174                         @IntRange(from = 20)
175                         @Retention(RetentionPolicy.SOURCE)
176                         private @interface DialogStyle {}
177 
178                         public static final int STYLE_NORMAL = 0;
179                         public static final int STYLE_NO_TITLE = 1;
180                         public static final int STYLE_NO_FRAME = 2;
181 
182                         public void setStyle(@DialogStyle int style, int theme) {
183                         }
184                     }
185                     """
186                     ),
187                     intRangeAnnotationSource,
188                     intDefAnnotationSource
189                 ),
190             docStubs = true,
191             checkCompilation = true,
192             stubFiles =
193                 arrayOf(
194                     java(
195                         """
196                     package test.pkg;
197                     @SuppressWarnings({"unchecked", "deprecation", "all"})
198                     public class TypedefTest {
199                     public TypedefTest() { throw new RuntimeException("Stub!"); }
200                     /**
201                      * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or STYLE_NO_INPUT
202                      * Value is 20 or greater
203                      */
204                     public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
205                     public static final int STYLE_NORMAL = 0; // 0x0
206                     public static final int STYLE_NO_FRAME = 2; // 0x2
207                     public static final int STYLE_NO_TITLE = 1; // 0x1
208                     }
209                     """
210                     )
211                 )
212         )
213     }
214 
215     @Test
Add new parameter when no doc existsnull216     fun `Add new parameter when no doc exists`() {
217         check(
218             sourceFiles =
219                 arrayOf(
220                     java(
221                         """
222                     package test.pkg;
223                     import android.annotation.IntRange;
224                     public class RangeTest {
225                         public int test1(int parameter1, @IntRange(from = 10) int parameter2, int parameter3) { }
226                     }
227                     """
228                     ),
229                     intRangeAnnotationSource
230                 ),
231             checkCompilation = true,
232             docStubs = true,
233             stubFiles =
234                 arrayOf(
235                     java(
236                         """
237                     package test.pkg;
238                     @SuppressWarnings({"unchecked", "deprecation", "all"})
239                     public class RangeTest {
240                     public RangeTest() { throw new RuntimeException("Stub!"); }
241                     /**
242                      * @param parameter2 Value is 10 or greater
243                      */
244                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
245                     }
246                     """
247                     )
248                 )
249         )
250     }
251 
252     @Test
Add new parameter when doc exists but no param docnull253     fun `Add new parameter when doc exists but no param doc`() {
254         check(
255             sourceFiles =
256                 arrayOf(
257                     java(
258                         """
259                     package test.pkg;
260                     import android.annotation.IntRange;
261                     public class RangeTest {
262                         /**
263                         * This is the existing documentation.
264                         * @return return value documented here
265                         */
266                         public int test1(int parameter1, @IntRange(from = 10) int parameter2, int parameter3) { }
267                     }
268                     """
269                     ),
270                     intRangeAnnotationSource
271                 ),
272             checkCompilation = true,
273             docStubs = true,
274             stubFiles =
275                 arrayOf(
276                     java(
277                         """
278                     package test.pkg;
279                     @SuppressWarnings({"unchecked", "deprecation", "all"})
280                     public class RangeTest {
281                     public RangeTest() { throw new RuntimeException("Stub!"); }
282                     /**
283                      * This is the existing documentation.
284                      * @param parameter2 Value is 10 or greater
285                      * @return return value documented here
286                      */
287                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
288                     }
289                     """
290                     )
291                 )
292         )
293     }
294 
295     @Test
Add new parameter, sorted correctly between existing onesnull296     fun `Add new parameter, sorted correctly between existing ones`() {
297         check(
298             sourceFiles =
299                 arrayOf(
300                     java(
301                         """
302                     package test.pkg;
303                     import android.annotation.IntRange;
304                     public class RangeTest {
305                         /**
306                         * This is the existing documentation.
307                         * @param parameter1 docs for parameter1
308                         * @param parameter3 docs for parameter2
309                         * @return return value documented here
310                         */
311                         public int test1(int parameter1, @IntRange(from = 10) int parameter2, int parameter3) { }
312                     }
313                     """
314                     ),
315                     intRangeAnnotationSource
316                 ),
317             checkCompilation = true,
318             docStubs = true,
319             stubFiles =
320                 arrayOf(
321                     java(
322                         """
323                     package test.pkg;
324                     @SuppressWarnings({"unchecked", "deprecation", "all"})
325                     public class RangeTest {
326                     public RangeTest() { throw new RuntimeException("Stub!"); }
327                     /**
328                      * This is the existing documentation.
329                      * @param parameter1 docs for parameter1
330                      * @param parameter3 docs for parameter2
331                      * @param parameter2 Value is 10 or greater
332                      * @return return value documented here
333                      */
334                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
335                     }
336                     """
337                     )
338                 )
339         )
340     }
341 
342     @Test
Add to existing parameternull343     fun `Add to existing parameter`() {
344         check(
345             sourceFiles =
346                 arrayOf(
347                     java(
348                         """
349                     package test.pkg;
350                     import android.annotation.IntRange;
351                     public class RangeTest {
352                         /**
353                         * This is the existing documentation.
354                         * @param parameter1 docs for parameter1
355                         * @param parameter2 docs for parameter2
356                         * @param parameter3 docs for parameter2
357                         * @return return value documented here
358                         */
359                         public int test1(int parameter1, @IntRange(from = 10) int parameter2, int parameter3) { }
360                     }
361                     """
362                     ),
363                     intRangeAnnotationSource
364                 ),
365             checkCompilation = true,
366             docStubs = true,
367             stubFiles =
368                 arrayOf(
369                     java(
370                         """
371                     package test.pkg;
372                     @SuppressWarnings({"unchecked", "deprecation", "all"})
373                     public class RangeTest {
374                     public RangeTest() { throw new RuntimeException("Stub!"); }
375                     /**
376                      * This is the existing documentation.
377                      * @param parameter1 docs for parameter1
378                      * @param parameter2 docs for parameter2
379                      * Value is 10 or greater
380                      * @param parameter3 docs for parameter2
381                      * @return return value documented here
382                      */
383                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
384                     }
385                     """
386                     )
387                 )
388         )
389     }
390 
391     @Test
Add new return valuenull392     fun `Add new return value`() {
393         check(
394             sourceFiles =
395                 arrayOf(
396                     java(
397                         """
398                     package test.pkg;
399                     import android.annotation.IntRange;
400                     public class RangeTest {
401                         @IntRange(from = 10)
402                         public int test1(int parameter1, int parameter2, int parameter3) { }
403                     }
404                     """
405                     ),
406                     intRangeAnnotationSource
407                 ),
408             checkCompilation = true,
409             docStubs = true,
410             stubFiles =
411                 arrayOf(
412                     java(
413                         """
414                     package test.pkg;
415                     @SuppressWarnings({"unchecked", "deprecation", "all"})
416                     public class RangeTest {
417                     public RangeTest() { throw new RuntimeException("Stub!"); }
418                     /**
419                      * @return Value is 10 or greater
420                      */
421                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
422                     }
423                     """
424                     )
425                 )
426         )
427     }
428 
429     @Test
Add to existing return value (ensuring it appears last)null430     fun `Add to existing return value (ensuring it appears last)`() {
431         check(
432             sourceFiles =
433                 arrayOf(
434                     java(
435                         """
436                     package test.pkg;
437                     import android.annotation.IntRange;
438                     public class RangeTest {
439                         /**
440                         * This is the existing documentation.
441                         * @return return value documented here
442                         */
443                         @IntRange(from = 10)
444                         public int test1(int parameter1, int parameter2, int parameter3) { }
445                     }
446                     """
447                     ),
448                     intRangeAnnotationSource
449                 ),
450             checkCompilation = true,
451             docStubs = true,
452             stubFiles =
453                 arrayOf(
454                     java(
455                         """
456                     package test.pkg;
457                     @SuppressWarnings({"unchecked", "deprecation", "all"})
458                     public class RangeTest {
459                     public RangeTest() { throw new RuntimeException("Stub!"); }
460                     /**
461                      * This is the existing documentation.
462                      * @return return value documented here
463                      * Value is 10 or greater
464                      */
465                     public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
466                     }
467                     """
468                     )
469                 )
470         )
471     }
472 
473     @Test
Merge API levelsnull474     fun `Merge API levels`() {
475         check(
476             sourceFiles =
477                 arrayOf(
478                     java(
479                         """
480                     package android.widget;
481 
482                     public class Toolbar {
483                         /**
484                         * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
485                         * @return blah blah blah
486                         */
487                         public int getCurrentContentInsetEnd() {
488                             return 0;
489                         }
490                     }
491                     """
492                     ),
493                     intRangeAnnotationSource
494                 ),
495             checkCompilation = true,
496             docStubs = true,
497             applyApiLevelsXml =
498                 """
499                     <?xml version="1.0" encoding="utf-8"?>
500                     <api version="2">
501                         <class name="android/widget/Toolbar" since="21">
502                             <method name="&lt;init>(Landroid/content/Context;)V"/>
503                             <method name="collapseActionView()V"/>
504                             <method name="getContentInsetStartWithNavigation()I" since="24"/>
505                             <method name="getCurrentContentInsetEnd()I" since="24"/>
506                             <method name="getCurrentContentInsetLeft()I" since="24"/>
507                             <method name="getCurrentContentInsetRight()I" since="24"/>
508                             <method name="getCurrentContentInsetStart()I" since="24"/>
509                         </class>
510                     </api>
511                     """,
512             stubFiles =
513                 arrayOf(
514                     java(
515                         """
516                     package android.widget;
517                     /** @apiSince 21 */
518                     @SuppressWarnings({"unchecked", "deprecation", "all"})
519                     public class Toolbar {
520                     public Toolbar() { throw new RuntimeException("Stub!"); }
521                     /**
522                      * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
523                      * @return blah blah blah
524                      * @apiSince 24
525                      */
526                     public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
527                     }
528                     """
529                     )
530                 )
531         )
532     }
533 
534     @Test
Trailing comment closenull535     fun `Trailing comment close`() {
536         check(
537             sourceFiles =
538                 arrayOf(
539                     java(
540                         """
541                     package android.widget;
542 
543                     public class Toolbar {
544                         /**
545                         * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here. */
546                         public int getCurrentContentInsetEnd() {
547                             return 0;
548                         }
549                     }
550                     """
551                     ),
552                     intRangeAnnotationSource
553                 ),
554             checkCompilation = true,
555             docStubs = true,
556             applyApiLevelsXml =
557                 """
558                     <?xml version="1.0" encoding="utf-8"?>
559                     <api version="2">
560                         <class name="android/widget/Toolbar" since="21">
561                             <method name="getCurrentContentInsetEnd()I" since="24"/>
562                         </class>
563                     </api>
564                     """,
565             stubFiles =
566                 arrayOf(
567                     java(
568                         """
569                     package android.widget;
570                     /** @apiSince 21 */
571                     @SuppressWarnings({"unchecked", "deprecation", "all"})
572                     public class Toolbar {
573                     public Toolbar() { throw new RuntimeException("Stub!"); }
574                     /**
575                      * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
576                      * @apiSince 24
577                      */
578                     public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
579                     }
580                     """
581                     )
582                 )
583         )
584     }
585 }
586