177439519: warningsAsErrors should not turn on issues

This CL special cases the -Werror and -w modes such that instead of
using the severity in the overriding configuration, they use the
severity from more specific configurations to decide whether it's a
warning that should be promoted to error or disabled.

Test: New unit test added
Fixes: 177439519
Change-Id: Iec720c782ccdd16103010af8fc860d33d5b2af89
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/FlagConfiguration.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/FlagConfiguration.kt
index 5bcaf38..b63a7e0 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/FlagConfiguration.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/FlagConfiguration.kt
@@ -75,17 +75,28 @@
         ) {
             return Severity.IGNORE
         }
-        val impliedSeverity = severity ?: getDefaultSeverity(issue)
-        if (isWarningsAsErrors() && impliedSeverity === Severity.WARNING) {
-            if (issue === IssueRegistry.BASELINE) {
-                // Don't promote the baseline informational issue
-                // (number of issues promoted) to error
-                return severity
+        if (isWarningsAsErrors() || isIgnoreWarnings()) {
+            // If the severity is defined in this configuration, use it, otherwise
+            // if we're in an override configuration, use the fallback value,
+            // and finally if severity is not configured by either use the
+            // default. This ensures that for example we set warningsAsErrors
+            // in lintOptions, this will not turn issues ignored in a lint.xml
+            // file back on, and similarly it ensures that issues not mentioned
+            // in lint.xml will use the default.
+            val impliedSeverity = severity
+                ?: configurations.getDefinedSeverityWithoutOverride(source, issue)
+                ?: getDefaultSeverity(issue)
+            if (isWarningsAsErrors() && impliedSeverity === Severity.WARNING) {
+                if (issue === IssueRegistry.BASELINE) {
+                    // Don't promote the baseline informational issue
+                    // (number of issues promoted) to error
+                    return severity
+                }
+                severity = Severity.ERROR
             }
-            severity = Severity.ERROR
-        }
-        if (isIgnoreWarnings() && impliedSeverity === Severity.WARNING) {
-            severity = Severity.IGNORE
+            if (isIgnoreWarnings() && impliedSeverity === Severity.WARNING) {
+                severity = Severity.IGNORE
+            }
         }
         return severity
     }
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java
index a3618f2..b84fcd7 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java
@@ -40,6 +40,8 @@
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
 import java.util.stream.Collectors;
+import kotlin.io.FilesKt;
+import kotlin.text.Charsets;
 import kotlin.text.StringsKt;
 import org.intellij.lang.annotations.Language;
 
@@ -716,6 +718,53 @@
                 });
     }
 
+    public void testWarningsAsErrors() throws Exception {
+        // Regression test for 177439519
+        // The scenario is that we have warningsAsErrors turned on in an override
+        // configuration, and then lintConfig pointing to a lint.xml file which
+        // ignores some lint checks. We want the ignored lint checks to NOT be
+        // turned on on as errors. We also want any warning-severity issue not
+        // otherwise mentioned to turn into errors.
+        File project =
+                getProjectDir(
+                        null,
+                        java("class Test {\n    String s = \"/sdcard/path\";\n}"),
+                        xml(
+                                "res/layout/foo.xml",
+                                ""
+                                        + "<merge xmlns:android=\"http://schemas.android.com/apk/res/android\">\n"
+                                        + "    <Button android:text=\"Button\" android:id=\"@+id/button1\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"></Button>\n"
+                                        + "</merge>\n"));
+        File lintXml = new File(project, "res" + File.separator + "lint.xml");
+        FilesKt.writeText(
+                lintXml,
+                ""
+                        + "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
+                        + "<lint>\n"
+                        + "    <issue id=\"HardcodedText\" severity=\"ignore\"/>\n"
+                        + "</lint>",
+                Charsets.UTF_8);
+        checkDriver(
+                ""
+                        + "src/Test.java:2: Error: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n"
+                        + "    String s = \"/sdcard/path\";\n"
+                        + "               ~~~~~~~~~~~~~~\n"
+                        + "1 errors, 0 warnings",
+                "",
+
+                // Expected exit code
+                ERRNO_SUCCESS,
+
+                // Args
+                new String[] {
+                    "-Werror",
+                    "--quiet",
+                    "--disable",
+                    "LintError,UsesMinSdkAttributes,UnusedResources",
+                    project.getPath()
+                });
+    }
+
     public void testWrongThreadOff() throws Exception {
         // Make sure the wrong thread interprocedural check is not included with -Wall
         File project =