Snap for 11274022 from f52e38e184cc2d9d07f38da9df774fd9b8918bba to studio-iguana-release

Change-Id: I86fcead7cecf48cd896600e07cd9661807078899
diff --git a/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemon.kt b/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemon.kt
index bf6db2c..800c76e 100644
--- a/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemon.kt
+++ b/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemon.kt
@@ -222,10 +222,8 @@
     var numUpdates = 0
     var numOther = 0
     addAll(project.modules.flatMap { module ->
-      module.dependencies.libraries.map {
-        getSdkIndexIssueFor(it.spec, it.path, it.parent.rootDir)
-      }.flatten()
-        .onEach { issue ->
+      module.dependencies.libraries.mapNotNull {
+        getSdkIndexIssueFor(it.spec, it.path, it.parent.rootDir)?.also { issue->
           when (issue.severity) {
             ERROR -> numErrors++
             WARNING -> numWarnings++
@@ -235,6 +233,7 @@
             else -> numOther++
           }
         }
+      }
     }, now = false)
     LOG.debug("Issues recreated: $numErrors errors, $numWarnings warnings, $numInfo information, $numUpdates updates, $numOther other")
     notifyRunning()
@@ -242,60 +241,78 @@
 }
 
 /**
- * Returns the list of issues from the Google Play SDK Index that the given library has.
+ * Checks if the dependency has issues in the Google Play SDK Index and if it does, returns the one with higher severity.
  *
  * @param dependencySpec: dependency being checked
- * @param libraryPath: path of the library dependency, used for generating the issues
+ * @param libraryPath: path of the library dependency, used generating the issues
  * @param parentModuleRootDir: root dir of the parent module of this dependency
  *
- * @return The list of issues from the SDK index for the given library, empty if no issues are present
+ * @return The issue with the higher severity from the SDK index, or null if there are no issues
  */
 fun getSdkIndexIssueFor(dependencySpec: PsArtifactDependencySpec,
                         libraryPath: PsPath,
                         parentModuleRootDir: File?,
-                        sdkIndex: GooglePlaySdkIndex = IdeGooglePlaySdkIndex): List<PsGeneralIssue> {
-  val groupId = dependencySpec.group ?: return emptyList()
-  val versionString = dependencySpec.version ?: return emptyList()
+                        sdkIndex: GooglePlaySdkIndex = IdeGooglePlaySdkIndex): PsGeneralIssue? {
+  val groupId = dependencySpec.group ?: return null
+  val versionString = dependencySpec.version ?: return null
   val artifactId = dependencySpec.name
 
-  // Report all SDK Index issues without grouping them(b/316038712):
-  val isBlocking = sdkIndex.hasLibraryBlockingIssues(groupId, artifactId, versionString)
   val isNonCompliant = sdkIndex.isLibraryNonCompliant(groupId, artifactId, versionString, parentModuleRootDir)
   val isCritical = sdkIndex.hasLibraryCriticalIssues(groupId, artifactId, versionString, parentModuleRootDir)
   val isOutdated = sdkIndex.isLibraryOutdated(groupId, artifactId, versionString, parentModuleRootDir)
+  val numberOfTypes = listOf(isNonCompliant, isCritical, isOutdated).count { it }
 
-  val foundIssues: MutableList<PsGeneralIssue> = mutableListOf()
+  if (numberOfTypes == 0) {
+    return null
+  }
+
+  val isBlocking = sdkIndex.hasLibraryBlockingIssues(groupId, artifactId, versionString)
+  val message: String
+  val severity: PsIssue.Severity
   if (isBlocking) {
-    if (isNonCompliant) {
-      sdkIndex.generateBlockingPolicyMessages(groupId, artifactId, versionString).forEach { message->
-        foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, ERROR, sdkIndex))
+    severity = ERROR
+    message = if (numberOfTypes == 1) {
+      when {
+        isNonCompliant -> sdkIndex.generateBlockingPolicyMessage(groupId, artifactId, versionString)
+        isCritical -> sdkIndex.generateBlockingCriticalMessage(groupId, artifactId, versionString)
+        isOutdated -> sdkIndex.generateBlockingOutdatedMessage(groupId, artifactId, versionString)
+        else -> sdkIndex.generateBlockingGenericIssueMessage(groupId, artifactId, versionString)
       }
     }
-    if (isCritical) {
-      val message = sdkIndex.generateBlockingCriticalMessage(groupId, artifactId, versionString)
-      foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, ERROR, sdkIndex))
-    }
-    if (isOutdated) {
-      val message = sdkIndex.generateBlockingOutdatedMessage(groupId, artifactId, versionString)
-      foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, ERROR, sdkIndex))
+    else {
+      sdkIndex.generateBlockingGenericIssueMessage(groupId, artifactId, versionString)
     }
   }
   else {
-    if (isNonCompliant) {
-      sdkIndex.generatePolicyMessages(groupId, artifactId, versionString).forEach { message->
-        foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, WARNING, sdkIndex))
+    if (numberOfTypes == 1) {
+      when {
+        isNonCompliant -> {
+          message = sdkIndex.generatePolicyMessage(groupId, artifactId, versionString)
+          severity = WARNING
+        }
+
+        isCritical -> {
+          message = sdkIndex.generateCriticalMessage(groupId, artifactId, versionString)
+          severity = INFO
+        }
+
+        isOutdated -> {
+          message = sdkIndex.generateOutdatedMessage(groupId, artifactId, versionString)
+          severity = WARNING
+        }
+
+        else -> {
+          message = sdkIndex.generateGenericIssueMessage(groupId, artifactId, versionString)
+          severity = WARNING
+        }
       }
     }
-    if (isOutdated) {
-      val message = sdkIndex.generateOutdatedMessage(groupId, artifactId, versionString)
-      foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, WARNING, sdkIndex))
-    }
-    if (isCritical) {
-      val message = sdkIndex.generateCriticalMessage(groupId, artifactId, versionString)
-      foundIssues.add(createIndexIssue(message, groupId, artifactId, versionString, libraryPath, INFO, sdkIndex))
+    else {
+      message = sdkIndex.generateGenericIssueMessage(groupId, artifactId, versionString)
+      severity = WARNING
     }
   }
-  return foundIssues
+  return createIndexIssue(message, groupId, artifactId, versionString, libraryPath, severity, sdkIndex)
 }
 
 private fun createIndexIssue(
diff --git a/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/analysis/PsAndroidModuleAnalyzer.kt b/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/analysis/PsAndroidModuleAnalyzer.kt
index 678ba08..39d3f63 100644
--- a/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/analysis/PsAndroidModuleAnalyzer.kt
+++ b/project-system-gradle-psd/src/com/android/tools/idea/gradle/structure/daemon/analysis/PsAndroidModuleAnalyzer.kt
@@ -129,8 +129,7 @@
       }
       .filter { it.path != null && it.spec.group != null }
       .distinct()
-      .map { getSdkIndexIssueFor(it.spec, it.path!!, it.rootDir) }
-      .flatten()
+      .mapNotNull { getSdkIndexIssueFor(it.spec, it.path!!, it.rootDir) }
   }
 
   private data class PathSpecAndRoot(val path: PsPath?, val spec: PsArtifactDependencySpec, val rootDir: File?) {
diff --git a/project-system-gradle-psd/testSrc/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemonKtTest.kt b/project-system-gradle-psd/testSrc/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemonKtTest.kt
index 1001fb6..4aad53f 100644
--- a/project-system-gradle-psd/testSrc/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemonKtTest.kt
+++ b/project-system-gradle-psd/testSrc/com/android/tools/idea/gradle/structure/daemon/PsAnalyzerDaemonKtTest.kt
@@ -8,7 +8,6 @@
 import com.android.tools.lint.checks.LibraryIdentifier
 import com.android.tools.lint.checks.LibraryVersion
 import com.android.tools.lint.checks.LibraryVersionLabels
-import com.android.tools.lint.checks.LibraryVersionLabels.PolicyIssuesInfo.SdkPolicy
 import com.android.tools.lint.checks.Sdk
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
@@ -24,18 +23,21 @@
                                private val nonCompliant: Boolean,
                                private val outdated: Boolean,
                                private val critical: Boolean,
-                               private val violations: List<SdkPolicy>,
-                               private val expectedMessages: List<String>) {
+                               private val expectedMessage: String?) {
 
     @Test
     fun `Expected issue`() {
-      val sdkIndex = TestGooglePlaySdkIndex(blocking, nonCompliant, outdated, critical, violations)
+      val sdkIndex = TestGooglePlaySdkIndex(blocking, nonCompliant, outdated, critical)
       sdkIndex.prepareForTest()
-      val issues = getSdkIndexIssueFor(PsArtifactDependencySpec.Companion.create(LIBRARY_GROUP, LIBRARY_ARTIFACT, LIBRARY_VERSION),
+      val issue = getSdkIndexIssueFor(PsArtifactDependencySpec.Companion.create(LIBRARY_GROUP, LIBRARY_ARTIFACT, LIBRARY_VERSION),
                                       TestPath("testPath"), parentModuleRootDir = null, sdkIndex = sdkIndex)
-      assertThat(issues).hasSize(expectedMessages.size)
-      issues.forEachIndexed {index, issue ->
-        assertThat(issue.text.replace("\n<br>", " ")).endsWith(expectedMessages[index])
+      if (expectedMessage == null) {
+        assertThat(issue).isNull()
+      }
+      else {
+        assertThat(issue).isNotNull()
+        val unwrappedText = issue!!.text.replace("\n<br>", " ")
+        assertThat(unwrappedText).endsWith(expectedMessage)
       }
     }
 
@@ -49,40 +51,34 @@
       private const val MESSAGE_OUTDATED_BLOCKING = "has been marked as outdated by its author and will block publishing of your app to Play Console"
       private const val MESSAGE_CRITICAL = "has an associated message from its author"
       private const val MESSAGE_CRITICAL_BLOCKING = "has been reported as problematic by its author and will block publishing of your app to Play Console"
-      private const val MESSAGE_POLICY_USER = "has User Data policy issues that will block publishing of your app to Play Console in the future"
-      private const val MESSAGE_POLICY_USER_BLOCKING = "has User Data policy issues that will block publishing of your app to Play Console"
-      private const val MESSAGE_POLICY_PERMISSIONS = "has Permissions policy issues that will block publishing of your app to Play Console in the future"
-      private const val MESSAGE_POLICY_PERMISSIONS_BLOCKING = "has Permissions policy issues that will block publishing of your app to Play Console"
+      private const val MESSAGE_MULTIPLE_ISSUES = "has one or more issues that could block publishing of your app to Play Console in the future"
+      private const val MESSAGE_MULTIPLE_ISSUES_BLOCKING = "has one or more issues that will block publishing of your app to Play Console"
 
       @JvmStatic
       @Parameterized.Parameters(name = "{index}: blocking={0}, nonComplaint={1}, outdated={2}, critical={3}, message={4}")
       fun data() = listOf(
         // No issues
-        arrayOf(false, false, false, false, emptyList<SdkPolicy>(), emptyList<String>()),
+        arrayOf(false, false, false, false, null),
         // Policy
-        arrayOf(false, true, false, false, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY)),
+        arrayOf(false, true, false, false, MESSAGE_POLICY),
         // Outdated
-        arrayOf(false, false, true, false, emptyList<SdkPolicy>(), listOf(MESSAGE_OUTDATED)),
+        arrayOf(false, false, true, false, MESSAGE_OUTDATED),
         // Critical
-        arrayOf(false, false, false, true, emptyList<SdkPolicy>(), listOf(MESSAGE_CRITICAL)),
+        arrayOf(false, false, false, true, MESSAGE_CRITICAL),
         // Two types
-        arrayOf(false, true, true, false, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY, MESSAGE_OUTDATED)),
+        arrayOf(false, true, true, false, MESSAGE_MULTIPLE_ISSUES),
         // Three types
-        arrayOf(false, true, true, true, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY, MESSAGE_OUTDATED, MESSAGE_CRITICAL)),
-        // Two policies
-        arrayOf(false, true, false, false, listOf(SdkPolicy.SDK_POLICY_USER_DATA, SdkPolicy.SDK_POLICY_PERMISSIONS), listOf(MESSAGE_POLICY_USER, MESSAGE_POLICY_PERMISSIONS)),
+        arrayOf(false, true, true, true, MESSAGE_MULTIPLE_ISSUES),
         // Policy BLOCKING
-        arrayOf(true, true, false, false, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY_BLOCKING)),
+        arrayOf(true, true, false, false, MESSAGE_POLICY_BLOCKING),
         // Outdated BLOCKING
-        arrayOf(true, false, true, false, emptyList<SdkPolicy>(), listOf(MESSAGE_OUTDATED_BLOCKING)),
+        arrayOf(true, false, true, false, MESSAGE_OUTDATED_BLOCKING),
         // Critical BLOCKING
-        arrayOf(true, false, false, true, emptyList<SdkPolicy>(), listOf(MESSAGE_CRITICAL_BLOCKING)),
+        arrayOf(true, false, false, true, MESSAGE_CRITICAL_BLOCKING),
         // Two types BLOCKING
-        arrayOf(true, true, true, false, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY_BLOCKING, MESSAGE_OUTDATED_BLOCKING)),
+        arrayOf(true, true, true, false, MESSAGE_MULTIPLE_ISSUES_BLOCKING),
         // Three types BLOCKING
-        arrayOf(true, true, true, true, emptyList<SdkPolicy>(), listOf(MESSAGE_POLICY_BLOCKING, MESSAGE_CRITICAL_BLOCKING, MESSAGE_OUTDATED_BLOCKING)),
-        // Two policies BLOCKING
-        arrayOf(true, true, false, false, listOf(SdkPolicy.SDK_POLICY_USER_DATA, SdkPolicy.SDK_POLICY_PERMISSIONS), listOf(MESSAGE_POLICY_USER_BLOCKING, MESSAGE_POLICY_PERMISSIONS_BLOCKING)),
+        arrayOf(true, true, true, true, MESSAGE_MULTIPLE_ISSUES_BLOCKING),
       )
     }
 
@@ -91,7 +87,6 @@
       private val nonCompliant: Boolean,
       private val outdated: Boolean,
       private val critical: Boolean,
-      private val violations: List<SdkPolicy>,
     ) : GooglePlaySdkIndex(null) {
       override fun readUrlData(url: String, timeout: Int): ByteArray? {
         return null
@@ -104,7 +99,7 @@
         val labels = LibraryVersionLabels.newBuilder()
         labels.severity = if (blocking) LibraryVersionLabels.Severity.BLOCKING_SEVERITY else LibraryVersionLabels.Severity.NON_BLOCKING_SEVERITY
         if (nonCompliant) {
-          labels.setPolicyIssuesInfo(LibraryVersionLabels.PolicyIssuesInfo.newBuilder().addAllViolatedSdkPolicies(violations))
+          labels.setPolicyIssuesInfo(LibraryVersionLabels.PolicyIssuesInfo.newBuilder())
         }
         if (outdated) {
           labels.setOutdatedIssueInfo(LibraryVersionLabels.OutdatedIssueInfo.newBuilder())
diff --git a/project-system-gradle/src/com/android/tools/idea/projectsystem/gradle/IdeGooglePlaySdkIndex.kt b/project-system-gradle/src/com/android/tools/idea/projectsystem/gradle/IdeGooglePlaySdkIndex.kt
index fde9f1a..e6978aa 100644
--- a/project-system-gradle/src/com/android/tools/idea/projectsystem/gradle/IdeGooglePlaySdkIndex.kt
+++ b/project-system-gradle/src/com/android/tools/idea/projectsystem/gradle/IdeGooglePlaySdkIndex.kt
@@ -59,10 +59,12 @@
   override fun logNonCompliant(groupId: String, artifactId: String, versionString: String, file: File?) {
     super.logNonCompliant(groupId, artifactId, versionString, file)
     val isBlocking = hasLibraryBlockingIssues(groupId, artifactId, versionString)
-    if (isBlocking)
-      generateBlockingPolicyMessages(groupId, artifactId, versionString).forEach { logger.warn(it)}
-    else
-      generatePolicyMessages(groupId, artifactId, versionString).forEach { logger.warn(it)}
+    val warnMsg =
+      if (isBlocking)
+        generateBlockingPolicyMessage(groupId, artifactId, versionString)
+      else
+        generatePolicyMessage(groupId, artifactId, versionString)
+    logger.warn(warnMsg)
     logTrackerEventForLibraryVersion(groupId, artifactId, versionString, isBlocking, file, SDK_INDEX_LIBRARY_IS_NON_COMPLIANT)
   }
 
diff --git a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/PolicyIssuesPsdTest.kt b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/PolicyIssuesPsdTest.kt
index 49d2844..b647650 100644
--- a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/PolicyIssuesPsdTest.kt
+++ b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/PolicyIssuesPsdTest.kt
@@ -28,9 +28,8 @@
         openAndClosePSD(studio)
       },
       beforeClose = {
-        // Two errors and one warning should be shown:
+        // An error and one warning should be shown:
         //   - com.startapp:inapp-sdk:3.9.1 error (blocking critical)
-        //   - com.startapp:inapp-sdk:3.9.1 error (blocking outdated)
         //   - com.mopub:mopub-sdk:4.16.0 warning (outdated)
         verifyPsdIssues(numWarnings = 1)
       },
diff --git a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexPsdTest.kt b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexPsdTest.kt
index 134a753..9fb4019 100644
--- a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexPsdTest.kt
+++ b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexPsdTest.kt
@@ -26,9 +26,8 @@
         openAndClosePSD(studio)
       },
       beforeClose = {
-        // Two errors and two warnings should appear:
+        // One error and two warnings should appear:
         //   - com.startapp:inapp-sdk:3.9.1 blocking critical
-        //   - com.startapp:inapp-sdk:3.9.1 blocking outdated
         //   - com.stripe:stripe-android:9.3.2 warning (policy issues, not blocking)
         //   - com.mopub:mopub-sdk:4.16.0 warning (outdated)
         verifyPsdIssues(numWarnings = 2)
diff --git a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexTestBase.kt b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexTestBase.kt
index c433260..55ca5ef 100644
--- a/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexTestBase.kt
+++ b/project-system-integration-tests/testSrc/com/android/tools/idea/projectsystem/gradle/SdkIndexTestBase.kt
@@ -99,11 +99,11 @@
   protected fun verifyPsdIssues(numWarnings: Int) {
     val summaryRegex = ".*PsAnalyzerDaemon - Issues recreated: (.*)$"
     // The test project uses the following libraries:
-    //  - com.startapp:inapp-sdk: 3.9.1 error (blocking critical and outdated)
+    //  - com.startapp:inapp-sdk: 3.9.1 error (blocking critical)
     //  - com.stripe:stripe-android:9.3.2 error (if policy issues are enabled, not blocking)
     //  - com.mopub:mopub-sdk:4.16.0 warning (outdated)
     //  - com.snowplowanalytics:snowplow-android-tracker:1.4.1 info (critical, but not blocking)
-    val expectedSummary = "2 errors, $numWarnings warnings, 1 information, 0 updates, 0 other"
+    val expectedSummary = "1 errors, $numWarnings warnings, 1 information, 0 updates, 0 other"
     val foundSummary: String
     try {
       val matcher = system.installation.ideaLog.waitForMatchingLine(summaryRegex, timeoutBetweenIssuesSeconds, TimeUnit.SECONDS)