Report info diagnostics for duplicates in program and library
Bug: b/120884788
Change-Id: I5ab1e3c6f3ca90619725f63de88bb738e1762b5c
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index bbaa2b9..9c1ab31 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -265,6 +265,7 @@
System.out.println("R8 is running with free memory:" + runtime.freeMemory());
System.out.println("R8 is running with max memory:" + runtime.maxMemory());
}
+ options.prepareForReportingLibraryAndProgramDuplicates();
try {
AppView<AppInfoWithClassHierarchy> appView;
{
@@ -437,6 +438,8 @@
assert appView.appInfo().hasLiveness();
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+ options.reportLibraryAndProgramDuplicates(appViewWithLiveness);
+
new CfOpenClosedInterfacesAnalysis(appViewWithLiveness).run(executorService);
assert verifyNoJarApplicationReaders(appView.appInfo().classes());
diff --git a/src/main/java/com/android/tools/r8/errors/DuplicateTypeInProgramAndLibraryDiagnostic.java b/src/main/java/com/android/tools/r8/errors/DuplicateTypeInProgramAndLibraryDiagnostic.java
new file mode 100644
index 0000000..5af3923
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/DuplicateTypeInProgramAndLibraryDiagnostic.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.errors;
+
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.references.ClassReference;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+@Keep
+public class DuplicateTypeInProgramAndLibraryDiagnostic extends DuplicateTypesDiagnostic {
+
+ public DuplicateTypeInProgramAndLibraryDiagnostic(
+ ClassReference type, Origin programOrigin, Origin libraryOrigin) {
+ super(type, ImmutableList.of(programOrigin, libraryOrigin));
+ }
+
+ /** Get the origin of the program definition for the duplicated type. */
+ public Origin getProgramOrigin() {
+ return ((List<Origin>) getOrigins()).get(0);
+ }
+
+ /** Get the origin of the library definition for the duplicated type. */
+ public Origin getLibraryOrigin() {
+ return ((List<Origin>) getOrigins()).get(1);
+ }
+
+ @Override
+ public String getDiagnosticMessage() {
+ String typeName = getType().getTypeName();
+ return "Type "
+ + typeName
+ + " is defined by both the program: "
+ + getProgramOrigin()
+ + " and the library: "
+ + getLibraryOrigin();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index b5b28fd..8fedcdd 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -202,7 +202,12 @@
allLibraryClasses,
type -> {
DexProgramClass clazz = programClasses.get(type);
- return clazz != null ? clazz : classpathClasses.get(type);
+ if (clazz != null) {
+ options.recordLibraryAndProgramDuplicate(
+ type, clazz, allLibraryClasses.get(type));
+ return clazz;
+ }
+ return classpathClasses.get(type);
},
options);
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index ea3b56f..017b6a0 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -34,6 +34,7 @@
import com.android.tools.r8.dex.VirtualFile;
import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
import com.android.tools.r8.errors.IncompleteNestNestDesugarDiagnosic;
import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
import com.android.tools.r8.errors.InvalidDebugInfoException;
@@ -123,6 +124,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -882,8 +884,6 @@
return testing.readInputStackMaps ? testing.readInputStackMaps : isGeneratingClassFiles();
}
- public boolean printCfg = false;
- public String printCfgFile;
public boolean ignoreMissingClasses = false;
public boolean reportMissingClassesInEnclosingMethodAttribute = false;
public boolean reportMissingClassesInInnerClassAttributes = false;
@@ -1069,6 +1069,46 @@
private final Map<Origin, List<Pair<ProgramMethod, String>>> warningInvalidDebugInfo =
new HashMap<>();
+ private Map<DexType, Pair<DexProgramClass, DexLibraryClass>> warningLibraryProgramDuplicates;
+
+ public void recordLibraryAndProgramDuplicate(
+ DexType type, DexProgramClass programClass, DexLibraryClass libraryClass) {
+ if (warningLibraryProgramDuplicates != null) {
+ warningLibraryProgramDuplicates.computeIfAbsent(
+ type, k -> new Pair<>(programClass, libraryClass));
+ }
+ }
+
+ public void prepareForReportingLibraryAndProgramDuplicates() {
+ warningLibraryProgramDuplicates = new ConcurrentHashMap<>();
+ }
+
+ public void reportLibraryAndProgramDuplicates(AppView<AppInfoWithLiveness> appViewWithLiveness) {
+ assert warningLibraryProgramDuplicates != null;
+ if (warningLibraryProgramDuplicates.isEmpty()) {
+ warningLibraryProgramDuplicates = null;
+ return;
+ }
+ List<DexType> sortedKeys =
+ ListUtils.sort(warningLibraryProgramDuplicates.keySet(), DexType::compareTo);
+ for (DexType key : sortedKeys) {
+ // If the type has been pruned from the program then don't issue a diagnostic.
+ if (DexProgramClass.asProgramClassOrNull(
+ appViewWithLiveness.appInfo().definitionForWithoutExistenceAssert(key))
+ == null) {
+ continue;
+ }
+ Pair<DexProgramClass, DexLibraryClass> classes = warningLibraryProgramDuplicates.get(key);
+ reporter.info(
+ new DuplicateTypeInProgramAndLibraryDiagnostic(
+ key.asClassReference(),
+ classes.getFirst().getOrigin(),
+ classes.getSecond().getOrigin()));
+ }
+ warningLibraryProgramDuplicates = null;
+ reporter.failIfPendingErrors();
+ }
+
// Don't read code from dex files. Used to extract non-code information from vdex files where
// the code contains unsupported byte codes.
public boolean skipReadingDexCode = false;
diff --git a/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java b/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
index c58b9e1..f7f771f 100644
--- a/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
+++ b/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.classlookup;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -13,9 +14,12 @@
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -163,7 +167,9 @@
try {
builder.compileWithExpectedDiagnostics(
diagnostics -> {
- diagnostics.assertOnlyErrors();
+ diagnostics.assertNoWarnings();
+ diagnostics.assertAllInfosMatch(
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class));
checkDiagnostics(diagnostics.getErrors());
});
fail("Expected compilation failure");
@@ -180,11 +186,14 @@
.addProgramClassFileData(junitClasses)
.addKeepAllClassesRule()
.addOptionsModification(options -> options.lookupLibraryBeforeProgram = false)
- .allowDiagnosticWarningMessages(libraryContainsJUnit())
+ .applyIf(libraryContainsJUnit(), R8TestBuilder::allowDiagnosticMessages)
.compile()
.inspectDiagnosticMessages(
diagnostics -> {
if (libraryContainsJUnit()) {
+ diagnostics.assertNoErrors();
+ diagnostics.assertAllInfosMatch(
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class));
checkDiagnostics(diagnostics.getWarnings());
}
})
@@ -200,8 +209,12 @@
.addKeepAllClassesRule()
.applyIf(libraryContainsJUnit(), builder -> builder.addDontWarn("android.test.**"))
.addOptionsModification(options -> options.lookupLibraryBeforeProgram = false)
+ .allowDiagnosticInfoMessages(libraryContainsJUnit())
.compile()
- .assertNoMessages();
+ .applyIf(
+ libraryContainsJUnit(),
+ TestCompileResult::assertOnlyInfos,
+ TestCompileResult::assertNoMessages);
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaContextDuplicateInLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaContextDuplicateInLibraryTest.java
index c343ea8..5d5b969 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaContextDuplicateInLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaContextDuplicateInLibraryTest.java
@@ -3,11 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.StringUtils;
@@ -89,7 +91,11 @@
b.getBuilder()
.setDexClassChecksumFilter(
(desc, checksum) -> !desc.contains(binaryName(LIBRARY_CONTEXT))))
- .compile()
+ .allowDiagnosticInfoMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics.assertAllInfosMatch(
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class)))
.addRunClasspathClasses(LIBRARY)
.run(parameters.getRuntime(), MAIN)
.applyIf(
diff --git a/src/test/java/com/android/tools/r8/diagnostics/ProgramAndLibraryDuplicatesTest.java b/src/test/java/com/android/tools/r8/diagnostics/ProgramAndLibraryDuplicatesTest.java
new file mode 100644
index 0000000..e9b75b6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/diagnostics/ProgramAndLibraryDuplicatesTest.java
@@ -0,0 +1,91 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.diagnostics;
+
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
+import com.android.tools.r8.errors.DuplicateTypesDiagnostic;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ProgramAndLibraryDuplicatesTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters()
+ .withDefaultRuntimes()
+ .withMinimumApiLevel()
+ .enableApiLevelsForCf()
+ .build();
+ }
+
+ public ProgramAndLibraryDuplicatesTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addInnerClasses(ProgramAndLibraryDuplicatesTest.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addLibraryClasses(MyFunction.class)
+ .setMinApi(parameters)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(ProgramAndLibraryDuplicatesTest.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addLibraryClasses(MyFunction.class)
+ .setMinApi(parameters)
+ .addKeepMainRule(TestClass.class)
+ .allowDiagnosticInfoMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics
+ .assertOnlyInfos()
+ .assertInfosMatch(
+ allOf(
+ diagnosticType(DuplicateTypesDiagnostic.class),
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class),
+ diagnosticMessage(containsString(typeName(MyFunction.class))))))
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ interface MyFunction<T, R> {
+ R apply(T arg);
+ }
+
+ static class TestClass {
+
+ public static void run(MyFunction<String, String> fn) {
+ System.out.println(fn.apply("Hello"));
+ }
+
+ public static void main(String[] args) {
+ run(prefix -> prefix + ", world");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
index 79a7e19..2fafa0f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
@@ -4,10 +4,12 @@
package com.android.tools.r8.ir.optimize.logging;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -79,7 +81,16 @@
transformer(Log.class).setClassDescriptor("Landroid/util/Log;").transform())
.addKeepAllClassesRule()
.setMinApi(parameters)
- .compile()
+ .allowDiagnosticInfoMessages(parameters.isDexRuntime())
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ if (parameters.isDexRuntime()) {
+ diagnostics.assertAllInfosMatch(
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class));
+ } else {
+ diagnostics.assertNoMessages();
+ }
+ })
.writeToZip();
testForR8(parameters.getBackend())
diff --git a/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java b/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
index f7a8f50..d4b9204 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
@@ -3,33 +3,38 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.maindexlist.b72312389;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import com.android.tools.r8.BaseCommand;
-import com.android.tools.r8.CompatProguardCommandBuilder;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.Diagnostic;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GenerateMainDexList;
import com.android.tools.r8.GenerateMainDexListCommand;
-import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.errors.DuplicateTypeInProgramAndLibraryDiagnostic;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Box;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Paths;
-import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class B72312389 extends TestBase {
+
// TODO(120884788): Remove this when default is true.
private static boolean lookupLibraryBeforeProgram = false;
@@ -53,10 +58,19 @@
" *;",
"}");
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return TestParameters.builder().withNoneRuntime().build();
+ }
+
+ public B72312389(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
@Test
public void testGenerateMainDexList() throws Exception {
assumeFalse(ToolHelper.isWindows());
- CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
+ TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
GenerateMainDexListCommand.Builder builder = GenerateMainDexListCommand.builder(diagnostics);
buildInstrumentationTestCaseApplication(builder);
GenerateMainDexListCommand command = builder
@@ -68,7 +82,7 @@
} else {
assertTrue(mainDexList.contains("junit/framework/TestCase.class"));
}
- diagnostics.assertEmpty();
+ diagnostics.assertNoMessages();
}
@Test
@@ -77,27 +91,36 @@
Box<String> mainDexList = new Box<>();
// Build a app with a class extending InstrumentationTestCase and including both the junit
// and the Android library.
- CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
- R8Command.Builder builder = new CompatProguardCommandBuilder(true, diagnostics);
- buildInstrumentationTestCaseApplication(builder);
- R8Command command =
- builder
- .setMinApiLevel(AndroidApiLevel.K.getLevel())
- // TODO(72793900): This should not be required.
- .addProguardConfiguration(ImmutableList.of("-keep class ** { *; }"), Origin.unknown())
- .addProguardConfiguration(ImmutableList.of("-dontobfuscate"), Origin.unknown())
- .addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .setMainDexListConsumer(ToolHelper.consumeString(mainDexList::set))
- .build();
- CodeInspector inspector = new CodeInspector(ToolHelper.runR8(command));
- assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
- assertEquals(
- !lookupLibraryBeforeProgram, mainDexList.get().contains("junit/framework/TestCase.class"));
- assertEquals(
- lookupLibraryBeforeProgram ? 0 : 1,
- diagnostics.countLibraryClassExtendsProgramClassWarnings(
- "android.test.InstrumentationTestCase", "junit.framework.TestCase"));
+ testForR8Compat(Backend.DEX)
+ .apply(b -> buildInstrumentationTestCaseApplication(b.getBuilder()))
+ .setMinApi(AndroidApiLevel.K)
+ // TODO(72793900): This should not be required.
+ .addKeepRules(ImmutableList.of("-keep class ** { *; }"))
+ .addDontObfuscate()
+ .addMainDexRules(keepInstrumentationTestCaseRules)
+ .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+ .setMainDexListConsumer(ToolHelper.consumeString(mainDexList::set))
+ .allowDiagnosticMessages()
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ diagnostics
+ .assertNoErrors()
+ .assertAllInfosMatch(
+ diagnosticType(DuplicateTypeInProgramAndLibraryDiagnostic.class));
+ assertEquals(
+ lookupLibraryBeforeProgram ? 0 : 1,
+ countLibraryClassExtendsProgramClassWarnings(
+ diagnostics.getWarnings(),
+ "android.test.InstrumentationTestCase",
+ "junit.framework.TestCase"));
+ })
+ .inspect(
+ inspector -> {
+ assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
+ assertEquals(
+ !lookupLibraryBeforeProgram,
+ mainDexList.get().contains("junit/framework/TestCase.class"));
+ });
}
@Test
@@ -108,49 +131,23 @@
.setMinApi(AndroidApiLevel.B)
.addMainDexRules(keepInstrumentationTestCaseRules)
.compile()
- // Library types and method overrides are lazily enqueued, thus no longer causing failures.
+ // Library types and method overrides are lazily enqueued, thus no warnings/errors.
.assertNoMessages();
}
- private static class CollectingDiagnosticHandler implements DiagnosticsHandler {
- private final List<Diagnostic> infos = new ArrayList<>();
- private final List<Diagnostic> warnings = new ArrayList<>();
- private final List<Diagnostic> errors = new ArrayList<>();
+ private static boolean isLibraryClassExtendsProgramClassWarning(
+ String libraryClass, String programClass, Diagnostic diagnostic) {
+ return diagnostic
+ .getDiagnosticMessage()
+ .equals("Library class " + libraryClass + " extends program class " + programClass);
+ }
- @Override
- public void info(Diagnostic info) {
- infos.add(info);
- }
-
- @Override
- public void warning(Diagnostic warning) {
- warnings.add(warning);
- }
-
- @Override
- public void error(Diagnostic error) {
- errors.add(error);
- }
-
- public void assertEmpty() {
- assertEquals(0, errors.size());
- assertEquals(0, warnings.size());
- assertEquals(0, infos.size());
- }
-
- private boolean isLibraryClassExtendsProgramClassWarning(
- String libraryClass, String programClass, Diagnostic diagnostic) {
- return diagnostic.getDiagnosticMessage().equals(
- "Library class "+ libraryClass + " extends program class " + programClass);
- }
-
- public long countLibraryClassExtendsProgramClassWarnings(
- String libraryClass, String programClass) {
- return warnings.stream()
- .filter(
- diagnostics ->
- isLibraryClassExtendsProgramClassWarning(libraryClass, programClass, diagnostics))
- .count();
- }
+ public static long countLibraryClassExtendsProgramClassWarnings(
+ List<Diagnostic> diagnostics, String libraryClass, String programClass) {
+ return diagnostics.stream()
+ .filter(
+ diagnostic ->
+ isLibraryClassExtendsProgramClassWarning(libraryClass, programClass, diagnostic))
+ .count();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageObjectOnProgramPathTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageObjectOnProgramPathTest.java
index a4c60cd..da7342c 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageObjectOnProgramPathTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageObjectOnProgramPathTest.java
@@ -40,7 +40,7 @@
.addKeepMainRule(Main.class)
.addDontWarn("*")
.addKeepClassRules(Object.class)
- .allowDiagnosticWarningMessages()
+ .allowDiagnosticMessages()
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A::foo");
}