Merge "Add a comment explaining --proguard option usage"
diff --git a/src/main/java/com/android/tools/metalava/AnnotationFilter.kt b/src/main/java/com/android/tools/metalava/AnnotationFilter.kt
index 172c32a..89b0edf 100644
--- a/src/main/java/com/android/tools/metalava/AnnotationFilter.kt
+++ b/src/main/java/com/android/tools/metalava/AnnotationFilter.kt
@@ -1,8 +1,10 @@
 package com.android.tools.metalava
 
 import com.android.SdkConstants.ATTR_VALUE
+import com.android.tools.metalava.model.AnnotationArrayAttributeValue
 import com.android.tools.metalava.model.AnnotationAttribute
 import com.android.tools.metalava.model.AnnotationItem
+import com.android.tools.metalava.model.AnnotationSingleAttributeValue
 import com.android.tools.metalava.model.DefaultAnnotationAttribute
 
 interface AnnotationFilter {
@@ -93,9 +95,29 @@
             return false
         }
         for (attribute in filter.attributes) {
-            val existingValue = existingAnnotation.findAttribute(attribute.name)?.value?.toSource()
-            if (existingValue != attribute.value.toSource()) {
-                return false
+            val existingValue = existingAnnotation.findAttribute(attribute.name)?.value
+            val existingValueSource = existingValue?.toSource()
+            val attributeValueSource = attribute.value.toSource()
+            if (attribute.name == "value") {
+                // Special-case where varargs value annotation attribute can be specified with
+                // either @Foo(BAR) or @Foo({BAR}) and they are equivalent.
+                when {
+                    attribute.value is AnnotationSingleAttributeValue &&
+                        existingValue is AnnotationArrayAttributeValue -> {
+                        if (existingValueSource != "{$attributeValueSource}") return false
+                    }
+                    attribute.value is AnnotationArrayAttributeValue &&
+                        existingValue is AnnotationSingleAttributeValue -> {
+                        if ("{$existingValueSource}" != attributeValueSource) return false
+                    }
+                    else -> {
+                        if (existingValueSource != attributeValueSource) return false
+                    }
+                }
+            } else {
+                if (existingValueSource != attributeValueSource) {
+                    return false
+                }
             }
         }
         return true
diff --git a/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt b/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
index 44323b2..83b58b9 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
@@ -37,6 +37,7 @@
 import com.intellij.psi.PsiTypeCastExpression
 import com.intellij.psi.PsiVariable
 import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.Name
 import org.jetbrains.uast.UAnnotation
 import org.jetbrains.uast.UBinaryExpression
 import org.jetbrains.uast.UBinaryExpressionWithType
@@ -439,8 +440,15 @@
 
                 is Pair<*, *> -> {
                     val first = value.first
+                    val second = value.second
                     if (first is ClassId) {
-                        return first.packageFqName.asString() + "." + first.relativeClassName.asString()
+                        val qualifiedName = first.packageFqName.asString() + "." +
+                            first.relativeClassName.asString()
+                        return if (second is Name) {
+                            qualifiedName + "." + second.asString()
+                        } else {
+                            qualifiedName
+                        }
                     }
                 }
             }
diff --git a/src/test/java/com/android/tools/metalava/ApiFileTest.kt b/src/test/java/com/android/tools/metalava/ApiFileTest.kt
index 36cbd0a..1a04de5 100644
--- a/src/test/java/com/android/tools/metalava/ApiFileTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiFileTest.kt
@@ -4595,4 +4595,55 @@
             """
         )
     }
+
+    @Test
+    fun `Constants in a file scope annotation`() {
+        check(
+            format = FileFormat.V4,
+            sourceFiles = arrayOf(
+                kotlin(
+                    """
+                    @file:RestrictTo(RestrictTo.Scope.LIBRARY)
+                    package test.pkg
+                    import androidx.annotation.RestrictTo
+                    private fun veryFun(): Boolean = true
+                """
+                ),
+                restrictToSource
+            ),
+            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
+            api = """
+                // Signature format: 4.0
+                package test.pkg {
+                  @RestrictTo({androidx.annotation.RestrictTo.Scope.LIBRARY}) public final class TestKt {
+                  }
+                }
+            """
+        )
+    }
+
+    @Test
+    fun `RestrictTo on a file hiding it`() {
+        check(
+            format = FileFormat.V4,
+            sourceFiles = arrayOf(
+                kotlin(
+                    """
+                    @file:RestrictTo(RestrictTo.Scope.LIBRARY)
+                    package test.pkg
+                    import androidx.annotation.RestrictTo
+                    private fun veryFun(): Boolean = true
+                """
+                ),
+                restrictToSource
+            ),
+            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation", "--show-unannotated"),
+            hideAnnotations = arrayOf(
+                "androidx.annotation.RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY)"
+            ),
+            api = """
+                // Signature format: 4.0
+            """
+        )
+    }
 }
diff --git a/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt b/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
index 0fdfad6..d578242 100644
--- a/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
+++ b/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
@@ -2326,6 +2326,7 @@
                     enum_constant @Deprecated public static final androidx.annotation.RestrictTo.Scope GROUP_ID;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP;
+                    enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP_PREFIX;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope SUBCLASSES;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope TESTS;
                   }
@@ -2432,6 +2433,7 @@
                     enum_constant public static final deprecated androidx.annotation.RestrictTo.Scope GROUP_ID;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP;
+                    enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP_PREFIX;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope SUBCLASSES;
                     enum_constant public static final androidx.annotation.RestrictTo.Scope TESTS;
                   }
diff --git a/src/test/java/com/android/tools/metalava/DriverTest.kt b/src/test/java/com/android/tools/metalava/DriverTest.kt
index caea8ad..cf24bb2 100644
--- a/src/test/java/com/android/tools/metalava/DriverTest.kt
+++ b/src/test/java/com/android/tools/metalava/DriverTest.kt
@@ -1942,22 +1942,35 @@
     """
 ).indented()
 
-val restrictToSource: TestFile = java(
+val restrictToSource: TestFile = kotlin(
     """
-    package androidx.annotation;
-    import java.lang.annotation.*;
-    import static java.lang.annotation.ElementType.*;
-    import static java.lang.annotation.RetentionPolicy.*;
-    @SuppressWarnings("WeakerAccess")
-    @Retention(CLASS)
-    @Target({ANNOTATION_TYPE, TYPE, METHOD, CONSTRUCTOR, FIELD, PACKAGE})
-    public @interface RestrictTo {
-        Scope[] value();
-        enum Scope {
+    package androidx.annotation
+
+    import androidx.annotation.RestrictTo.Scope
+    import java.lang.annotation.ElementType.*
+
+    @MustBeDocumented
+    @kotlin.annotation.Retention(AnnotationRetention.BINARY)
+    @Target(
+        AnnotationTarget.ANNOTATION_CLASS,
+        AnnotationTarget.CLASS,
+        AnnotationTarget.FUNCTION,
+        AnnotationTarget.PROPERTY_GETTER,
+        AnnotationTarget.PROPERTY_SETTER,
+        AnnotationTarget.CONSTRUCTOR,
+        AnnotationTarget.FIELD,
+        AnnotationTarget.FILE
+    )
+    // Needed due to Kotlin's lack of PACKAGE annotation target
+    // https://youtrack.jetbrains.com/issue/KT-45921
+    @Suppress("DEPRECATED_JAVA_ANNOTATION")
+    @java.lang.annotation.Target(ANNOTATION_TYPE, TYPE, METHOD, CONSTRUCTOR, FIELD, PACKAGE)
+    public annotation class RestrictTo(vararg val value: Scope) {
+        public enum class Scope {
             LIBRARY,
             LIBRARY_GROUP,
-            /** @deprecated */
-            @Deprecated
+            LIBRARY_GROUP_PREFIX,
+            @Deprecated("Use LIBRARY_GROUP_PREFIX instead.")
             GROUP_ID,
             TESTS,
             SUBCLASSES,
diff --git a/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt b/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt
index 47d04d9..f448e49 100644
--- a/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt
+++ b/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt
@@ -144,4 +144,39 @@
                 """
         )
     }
+
+    @Test
+    fun `Using hide annotation on file scope`() {
+        check(
+            sourceFiles = arrayOf(
+                kotlin(
+                    """
+                        package test.pkg
+                        @Target(AnnotationTarget.FILE)
+                        annotation class HideFile
+                    """
+                ),
+                kotlin(
+                    """
+                        @file:HideFile
+                        package test.pkg
+
+                        fun hiddenTopLevelFunction() = 1
+                        var hiddenTopLevelProperty = 2
+                        class VisibleTopLevelClass
+                    """
+                )
+            ),
+            hideAnnotations = arrayOf("test.pkg.HideFile"),
+            api = """
+                package test.pkg {
+                  @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FILE) public @interface HideFile {
+                  }
+                  public final class VisibleTopLevelClass {
+                    ctor public VisibleTopLevelClass();
+                  }
+                }
+                """
+        )
+    }
 }