From 62f639f92b34ea0ef4034b8e8f2331cc9de2b436 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 19 Nov 2017 14:36:04 +0300 Subject: [PATCH] Properly report missing virtual methods --- .../model/util/MissingItemsProcessor.java | 36 +++++++++++++++---- .../org/teavm/classlib/java/io/FileTest.java | 36 ++++--------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/core/src/main/java/org/teavm/model/util/MissingItemsProcessor.java b/core/src/main/java/org/teavm/model/util/MissingItemsProcessor.java index 7fa49e852..a4899aed0 100644 --- a/core/src/main/java/org/teavm/model/util/MissingItemsProcessor.java +++ b/core/src/main/java/org/teavm/model/util/MissingItemsProcessor.java @@ -31,16 +31,16 @@ public class MissingItemsProcessor { private List instructionsToAdd = new ArrayList<>(); private MethodHolder methodHolder; private Program program; - private Collection achievableClasses; + private Collection reachableClasses; private Collection reachableMethods; - private Collection achievableFields; + private Collection reachableFields; public MissingItemsProcessor(DependencyInfo dependencyInfo, Diagnostics diagnostics) { this.dependencyInfo = dependencyInfo; this.diagnostics = diagnostics; - achievableClasses = dependencyInfo.getReachableClasses(); + reachableClasses = dependencyInfo.getReachableClasses(); reachableMethods = dependencyInfo.getReachableMethods(); - achievableFields = dependencyInfo.getReachableFields(); + reachableFields = dependencyInfo.getReachableFields(); } public void processClass(ClassHolder cls) { @@ -126,7 +126,7 @@ public class MissingItemsProcessor { } private boolean checkClass(TextLocation location, String className) { - if (!achievableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) { + if (!reachableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) { return true; } diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Class {{c0}} was not found", @@ -163,11 +163,29 @@ public class MissingItemsProcessor { return true; } + private boolean checkVirtualMethod(TextLocation location, MethodReference method) { + if (!checkClass(location, method.getClassName())) { + return false; + } + if (!reachableMethods.contains(method)) { + return true; + } + + if (dependencyInfo.getClassSource().resolve(method) != null) { + return true; + } + + diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Method {{m0}} was not found", + method); + emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method); + return true; + } + private boolean checkField(TextLocation location, FieldReference field) { if (!checkClass(location, field.getClassName())) { return false; } - if (!achievableFields.contains(field) || !dependencyInfo.getField(field).isMissing()) { + if (!reachableFields.contains(field) || !dependencyInfo.getField(field).isMissing()) { return true; } diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Field {{f0}} was not found", @@ -193,7 +211,11 @@ public class MissingItemsProcessor { @Override public void visit(InvokeInstruction insn) { - checkMethod(insn.getLocation(), insn.getMethod()); + if (insn.getType() != InvocationType.VIRTUAL) { + checkMethod(insn.getLocation(), insn.getMethod()); + } else { + checkVirtualMethod(insn.getLocation(), insn.getMethod()); + } } @Override diff --git a/tests/src/test/java/org/teavm/classlib/java/io/FileTest.java b/tests/src/test/java/org/teavm/classlib/java/io/FileTest.java index 6941a474a..b10de6a75 100644 --- a/tests/src/test/java/org/teavm/classlib/java/io/FileTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/io/FileTest.java @@ -33,6 +33,7 @@ import java.net.URISyntaxException; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; +import org.teavm.interop.PlatformMarker; import org.teavm.junit.TeaVMTestRunner; @RunWith(TeaVMTestRunner.class) @@ -1079,34 +1080,6 @@ public class FileTest { f.delete(); } - @Test - public void isHidden() throws IOException, InterruptedException { - boolean onUnix = File.separatorChar == '/'; - File f = File.createTempFile("harmony-test-FileTest_isHidden_", ".tmp"); - // On Unix hidden files are marked with a "." at the beginning - // of the file name. - if (onUnix) { - File f2 = new File(".test.tst" + platformId); - FileOutputStream fos2 = new FileOutputStream(f2); - fos2.close(); - assertTrue("File returned hidden on Unix", !f.isHidden()); - assertTrue("File returned visible on Unix", f2.isHidden()); - assertTrue("File did not delete.", f2.delete()); - } else { - // For windows, the file is being set hidden by the attrib - // command. - Runtime r = Runtime.getRuntime(); - assertTrue("File returned hidden", !f.isHidden()); - Process p = r.exec("attrib +h \"" + f.getAbsolutePath() + "\""); - p.waitFor(); - assertTrue("File returned visible", f.isHidden()); - p = r.exec("attrib -h \"" + f.getAbsolutePath() + "\""); - p.waitFor(); - assertTrue("File returned hidden", !f.isHidden()); - } - f.delete(); - } - @Test public void lastModified() throws IOException { File f = new File(System.getProperty("java.io.tmpdir"), platformId + "lModTest.tst"); @@ -1283,7 +1256,7 @@ public class FileTest { // Test to make sure that listFiles can read hidden files. boolean onUnix = File.separatorChar == '/'; boolean onWindows = File.separatorChar == '\\'; - if (onWindows) { + if (!isTeaVM() && onWindows) { files[3] = "4.tst"; File f = new File(dir, "4.tst"); FileOutputStream fos = new FileOutputStream(f); @@ -1951,4 +1924,9 @@ public class FileTest { } assertTrue(exist); } + + @PlatformMarker + private static boolean isTeaVM() { + return false; + } }