mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-23 23:04:50 -08:00
Makes JCL compatibility report in HTML
This commit is contained in:
parent
a29318668e
commit
43b41b3a66
|
@ -82,40 +82,10 @@
|
||||||
<argument>java.util.logging</argument>
|
<argument>java.util.logging</argument>
|
||||||
<argument>java.util.concurrent</argument>
|
<argument>java.util.concurrent</argument>
|
||||||
<argument>-output</argument>
|
<argument>-output</argument>
|
||||||
<argument>${project.build.directory}/jcl-report/jcl-comparision.json</argument>
|
<argument>${project.build.directory}/jcl-report</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<!--This plugin's configuration is used to store Eclipse m2e settings only.
|
|
||||||
It has no influence on the Maven build itself.-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.eclipse.m2e</groupId>
|
|
||||||
<artifactId>lifecycle-mapping</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<configuration>
|
|
||||||
<lifecycleMappingMetadata>
|
|
||||||
<pluginExecutions>
|
|
||||||
<pluginExecution>
|
|
||||||
<pluginExecutionFilter>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-maven-plugin</artifactId>
|
|
||||||
<versionRange>[0.0.1-SNAPSHOT,)</versionRange>
|
|
||||||
<goals>
|
|
||||||
<goal>build-test-javascript</goal>
|
|
||||||
</goals>
|
|
||||||
</pluginExecutionFilter>
|
|
||||||
<action>
|
|
||||||
<ignore></ignore>
|
|
||||||
</action>
|
|
||||||
</pluginExecution>
|
|
||||||
</pluginExecutions>
|
|
||||||
</lifecycleMappingMetadata>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
class JCLClass {
|
||||||
|
public final String name;
|
||||||
|
public JCLStatus status;
|
||||||
|
public final List<JCLItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
public JCLClass(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,10 @@ package org.teavm.classlib.impl;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarInputStream;
|
import java.util.jar.JarInputStream;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||||
|
|
||||||
|
@ -32,10 +32,11 @@ public class JCLComparisonBuilder {
|
||||||
private static final String JAR_PREFIX = "jar:file:";
|
private static final String JAR_PREFIX = "jar:file:";
|
||||||
private static final String JAR_SUFFIX = "!/java/lang/Object.class";
|
private static final String JAR_SUFFIX = "!/java/lang/Object.class";
|
||||||
private static final String CLASS_SUFFIX = ".class";
|
private static final String CLASS_SUFFIX = ".class";
|
||||||
|
private static final String TEMPLATE_PLACEHOLDER = "${CONTENT}";
|
||||||
private Set<String> packages = new HashSet<>();
|
private Set<String> packages = new HashSet<>();
|
||||||
private ClassLoader classLoader = JCLComparisonBuilder.class.getClassLoader();
|
private ClassLoader classLoader = JCLComparisonBuilder.class.getClassLoader();
|
||||||
private JCLComparisonVisitor visitor;
|
private JCLComparisonVisitor visitor;
|
||||||
private String outputFile;
|
private String outputDirectory;
|
||||||
|
|
||||||
public ClassLoader getClassLoader() {
|
public ClassLoader getClassLoader() {
|
||||||
return classLoader;
|
return classLoader;
|
||||||
|
@ -49,24 +50,24 @@ public class JCLComparisonBuilder {
|
||||||
return packages;
|
return packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOutputFile() {
|
public String getOutputDirectory() {
|
||||||
return outputFile;
|
return outputDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputFile(String outputFile) {
|
public void setOutputDirectory(String outputDirectory) {
|
||||||
this.outputFile = outputFile;
|
this.outputDirectory = outputDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
System.err.println("Usage: package.name [package.name2 ...]");
|
System.err.println("Usage: package.name [package.name2 ...] [-output directory]");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
JCLComparisonBuilder builder = new JCLComparisonBuilder();
|
JCLComparisonBuilder builder = new JCLComparisonBuilder();
|
||||||
|
|
||||||
for (int i = 0; i < args.length; ++i) {
|
for (int i = 0; i < args.length; ++i) {
|
||||||
if (args[i].equals("-output")) {
|
if (args[i].equals("-output")) {
|
||||||
builder.setOutputFile(args[++i]);
|
builder.setOutputDirectory(args[++i]);
|
||||||
} else {
|
} else {
|
||||||
builder.getPackages().add(args[i].replace('.', '/'));
|
builder.getPackages().add(args[i].replace('.', '/'));
|
||||||
}
|
}
|
||||||
|
@ -76,6 +77,24 @@ public class JCLComparisonBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildComparisonReport() throws IOException {
|
public void buildComparisonReport() throws IOException {
|
||||||
|
List<JCLPackage> packages = buildModel();
|
||||||
|
processModel(packages);
|
||||||
|
new File(outputDirectory).mkdirs();
|
||||||
|
copyResource("html/class_obj.png");
|
||||||
|
copyResource("html/field_protected_obj.png");
|
||||||
|
copyResource("html/field_public_obj.png");
|
||||||
|
copyResource("html/jcl.css");
|
||||||
|
copyResource("html/methpro_obj.png");
|
||||||
|
copyResource("html/methpub_obj.png");
|
||||||
|
copyResource("html/package_obj.png");
|
||||||
|
try (Writer out = new OutputStreamWriter(new FileOutputStream(new File(
|
||||||
|
outputDirectory, "jcl.html")), "UTF-8")) {
|
||||||
|
generateHtml(out, packages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<JCLPackage> buildModel() throws IOException {
|
||||||
|
Map<String, JCLPackage> packageMap = new HashMap<>();
|
||||||
URL url = classLoader.getResource("java/lang/Object" + CLASS_SUFFIX);
|
URL url = classLoader.getResource("java/lang/Object" + CLASS_SUFFIX);
|
||||||
String path = url.toString();
|
String path = url.toString();
|
||||||
if (!path.startsWith(JAR_PREFIX) || !path.endsWith(JAR_SUFFIX)) {
|
if (!path.startsWith(JAR_PREFIX) || !path.endsWith(JAR_SUFFIX)) {
|
||||||
|
@ -83,14 +102,12 @@ public class JCLComparisonBuilder {
|
||||||
}
|
}
|
||||||
ClasspathClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
|
ClasspathClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
|
||||||
path = path.substring(JAR_PREFIX.length(), path.length() - JAR_SUFFIX.length());
|
path = path.substring(JAR_PREFIX.length(), path.length() - JAR_SUFFIX.length());
|
||||||
File outDir = new File(outputFile).getParentFile();
|
File outDir = new File(outputDirectory).getParentFile();
|
||||||
if (!outDir.exists()) {
|
if (!outDir.exists()) {
|
||||||
outDir.mkdirs();
|
outDir.mkdirs();
|
||||||
}
|
}
|
||||||
try (JarInputStream jar = new JarInputStream(new FileInputStream(path));
|
try (JarInputStream jar = new JarInputStream(new FileInputStream(path))) {
|
||||||
PrintStream out = new PrintStream(new FileOutputStream(outputFile))) {
|
visitor = new JCLComparisonVisitor(classSource, packageMap);
|
||||||
out.println("{");
|
|
||||||
visitor = new JCLComparisonVisitor(classSource, out);
|
|
||||||
while (true) {
|
while (true) {
|
||||||
JarEntry entry = jar.getNextJarEntry();
|
JarEntry entry = jar.getNextJarEntry();
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
|
@ -101,8 +118,22 @@ public class JCLComparisonBuilder {
|
||||||
}
|
}
|
||||||
jar.closeEntry();
|
jar.closeEntry();
|
||||||
}
|
}
|
||||||
out.println();
|
}
|
||||||
out.println("}");
|
return new ArrayList<>(packageMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processModel(List<JCLPackage> packages) {
|
||||||
|
Collections.sort(packages, new Comparator<JCLPackage>() {
|
||||||
|
@Override public int compare(JCLPackage o1, JCLPackage o2) {
|
||||||
|
return o1.name.compareTo(o2.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (JCLPackage pkg : packages) {
|
||||||
|
Collections.sort(pkg.classes, new Comparator<JCLClass>() {
|
||||||
|
@Override public int compare(JCLClass o1, JCLClass o2) {
|
||||||
|
return o1.name.compareTo(o2.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +146,121 @@ public class JCLComparisonBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compareClass(InputStream input) throws IOException {
|
private void compareClass(InputStream input) throws IOException {
|
||||||
ClassReader reader = new ClassReader(input);
|
byte[] buffer = IOUtils.toByteArray(input);
|
||||||
|
ClassReader reader = new ClassReader(buffer);
|
||||||
reader.accept(visitor, 0);
|
reader.accept(visitor, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyResource(String name) throws IOException {
|
||||||
|
String simpleName = name.substring(name.lastIndexOf('/') + 1);
|
||||||
|
try (InputStream input = classLoader.getResourceAsStream(name);
|
||||||
|
OutputStream output = new FileOutputStream(new File(outputDirectory, simpleName))) {
|
||||||
|
IOUtils.copy(input, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateHtml(Writer out, List<JCLPackage> packages) throws IOException {
|
||||||
|
String template;
|
||||||
|
try (Reader reader = new InputStreamReader(classLoader.getResourceAsStream("html/jcl.html"), "UTF-8")) {
|
||||||
|
template = IOUtils.toString(reader);
|
||||||
|
}
|
||||||
|
int placeholderIndex = template.indexOf(TEMPLATE_PLACEHOLDER);
|
||||||
|
String header = template.substring(0, placeholderIndex);
|
||||||
|
String footer = template.substring(placeholderIndex + TEMPLATE_PLACEHOLDER.length());
|
||||||
|
out.write(header);
|
||||||
|
for (JCLPackage pkg : packages) {
|
||||||
|
int totalClasses = pkg.classes.size();
|
||||||
|
int fullClasses = 0;
|
||||||
|
int partialClasses = 0;
|
||||||
|
for (JCLClass cls : pkg.classes) {
|
||||||
|
switch (cls.status) {
|
||||||
|
case FOUND:
|
||||||
|
fullClasses++;
|
||||||
|
partialClasses++;
|
||||||
|
break;
|
||||||
|
case PARTIAL:
|
||||||
|
partialClasses++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeRow(out, "package", pkg.status, pkg.name,
|
||||||
|
totalClasses > 0 ? fullClasses * 100 / totalClasses : null,
|
||||||
|
totalClasses > 0 ? partialClasses * 100 / totalClasses : null);
|
||||||
|
for (JCLClass cls : pkg.classes) {
|
||||||
|
int implemented = 0;
|
||||||
|
for (JCLItem item : cls.items) {
|
||||||
|
if (item.status != JCLStatus.MISSING) {
|
||||||
|
++implemented;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeRow(out, "class", cls.status, cls.name,
|
||||||
|
!cls.items.isEmpty() ? implemented * 100 / cls.items.size() : null, null);
|
||||||
|
for (JCLItem item : cls.items) {
|
||||||
|
String type;
|
||||||
|
switch (item.type) {
|
||||||
|
case FIELD:
|
||||||
|
type = "field";
|
||||||
|
break;
|
||||||
|
case METHOD:
|
||||||
|
type = "method";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writeRow(out, type, item.status, item.name, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.write(footer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeRow(Writer out, String type, JCLStatus status, String name, Integer percent,
|
||||||
|
Integer partialPercent) throws IOException {
|
||||||
|
out.write("<tr class=\"");
|
||||||
|
switch (status) {
|
||||||
|
case FOUND:
|
||||||
|
out.write("full");
|
||||||
|
break;
|
||||||
|
case MISSING:
|
||||||
|
out.write("missing");
|
||||||
|
break;
|
||||||
|
case PARTIAL:
|
||||||
|
out.write("partial");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.write("\">\n");
|
||||||
|
out.write("<td><div class=\"");
|
||||||
|
out.write(type);
|
||||||
|
out.write("\">");
|
||||||
|
out.write(escape(name));
|
||||||
|
out.write("</div></td>\n");
|
||||||
|
out.write("<td class=\"percent\">" + (partialPercent != null ? partialPercent.toString() : "") + "</td>");
|
||||||
|
out.write("<td class=\"percent\">" + (percent != null ? percent.toString() : "") + "</td>");
|
||||||
|
out.write("</tr>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escape(String string) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < string.length(); ++i) {
|
||||||
|
char ch = string.charAt(i);
|
||||||
|
switch (ch) {
|
||||||
|
case '<':
|
||||||
|
sb.append("<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
sb.append(">");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
sb.append(""");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sb.append(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.impl;
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.util.Map;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
|
@ -25,84 +25,103 @@ import org.teavm.model.ClassReader;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class JCLComparisonVisitor implements ClassVisitor {
|
class JCLComparisonVisitor implements ClassVisitor {
|
||||||
private PrintStream out;
|
private Map<String, JCLPackage> packageMap;
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private boolean first = true;
|
|
||||||
private boolean firstItem;
|
|
||||||
private boolean pass;
|
|
||||||
private boolean ended;
|
|
||||||
private ClassReader classReader;
|
private ClassReader classReader;
|
||||||
|
private JCLPackage jclPackage;
|
||||||
|
private JCLClass jclClass;
|
||||||
|
|
||||||
public JCLComparisonVisitor(ClassReaderSource classSource, PrintStream out) {
|
public JCLComparisonVisitor(ClassReaderSource classSource, Map<String, JCLPackage> packageMap) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.out = out;
|
this.packageMap = packageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||||
if ((access & Opcodes.ACC_PUBLIC) == 0) {
|
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
||||||
|
jclClass = null;
|
||||||
|
classReader = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String javaName = name.replace('/', '.');
|
String javaName = name.replace('/', '.');
|
||||||
if (!first) {
|
int dotIndex = javaName.lastIndexOf('.');
|
||||||
out.println(",");
|
String packageName = javaName.substring(0, dotIndex);
|
||||||
|
String simpleName = javaName.substring(dotIndex + 1);
|
||||||
|
jclPackage = packageMap.get(packageName);
|
||||||
|
if (jclPackage == null) {
|
||||||
|
jclPackage = new JCLPackage(packageName);
|
||||||
|
jclPackage.status = JCLStatus.FOUND;
|
||||||
|
packageMap.put(packageName, jclPackage);
|
||||||
}
|
}
|
||||||
first = false;
|
|
||||||
out.println(" \"" + javaName + "\" : {");
|
|
||||||
classReader = classSource.get(javaName);
|
classReader = classSource.get(javaName);
|
||||||
if (classReader == null) {
|
jclClass = new JCLClass(simpleName);
|
||||||
out.println(" \"implemented\" : false");
|
jclClass.status = classReader != null ? JCLStatus.FOUND : JCLStatus.MISSING;
|
||||||
pass = true;
|
jclPackage.classes.add(jclClass);
|
||||||
} else {
|
|
||||||
out.println(" \"implemented\" : true,");
|
|
||||||
out.println(" \"items\" : [");
|
|
||||||
pass = false;
|
|
||||||
}
|
|
||||||
ended = false;
|
|
||||||
firstItem = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
||||||
if (pass) {
|
if (classReader == null || (access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
JCLItem item = new JCLItem(JCLItemType.FIELD, name + " : " + desc);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!firstItem) {
|
|
||||||
out.println(",");
|
|
||||||
}
|
|
||||||
firstItem = false;
|
|
||||||
out.println(" {");
|
|
||||||
out.println(" \"type\" : \"field\",");
|
|
||||||
out.println(" \"name\" : \"" + name + "\",");
|
|
||||||
out.println(" \"descriptor\" : \"" + desc + "\",");
|
|
||||||
FieldReader field = classReader.getField(name);
|
FieldReader field = classReader.getField(name);
|
||||||
out.println(" \"implemented\" : \"" + (field != null ? "true" : "false") + "\",");
|
item.status = field != null ? JCLStatus.FOUND : JCLStatus.MISSING;
|
||||||
out.print(" }");
|
jclClass.items.add(item);
|
||||||
|
if (item.status == JCLStatus.MISSING) {
|
||||||
|
jclClass.status = JCLStatus.PARTIAL;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
if (pass) {
|
if (classReader == null || (access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
|
||||||
|
JCLItem item = new JCLItem(JCLItemType.METHOD, name + desc);
|
||||||
|
MethodReader method = findMethod(classReader, MethodDescriptor.parse(name + desc));
|
||||||
|
if (method == null) {
|
||||||
|
item.status = JCLStatus.MISSING;
|
||||||
|
} else {
|
||||||
|
if ((access & Opcodes.ACC_ABSTRACT) == 0 && method.hasModifier(ElementModifier.ABSTRACT)) {
|
||||||
|
item.status = JCLStatus.MISSING;
|
||||||
|
} else {
|
||||||
|
item.status = method.getOwnerName().equals(classReader.getName()) ?
|
||||||
|
JCLStatus.FOUND : JCLStatus.PARTIAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jclClass.items.add(item);
|
||||||
|
if (item.status == JCLStatus.MISSING) {
|
||||||
|
jclClass.status = JCLStatus.PARTIAL;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!firstItem) {
|
|
||||||
out.println(",");
|
private MethodReader findMethod(ClassReader cls, MethodDescriptor desc) {
|
||||||
|
MethodReader method = cls.getMethod(desc);
|
||||||
|
if (method != null) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
if (cls.getParent() != null) {
|
||||||
|
ClassReader parent = classSource.get(cls.getParent());
|
||||||
|
if (parent != null) {
|
||||||
|
method = findMethod(parent, desc);
|
||||||
|
if (method != null) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String ifaceName : cls.getInterfaces()) {
|
||||||
|
ClassReader iface = classSource.get(ifaceName);
|
||||||
|
if (iface != null) {
|
||||||
|
method = findMethod(iface, desc);
|
||||||
|
if (method != null) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
firstItem = false;
|
|
||||||
out.println(" {");
|
|
||||||
out.println(" \"type\" : \"method\",");
|
|
||||||
out.println(" \"name\" : \"" + name + "\",");
|
|
||||||
out.println(" \"descriptor\" : \"" + desc + "\",");
|
|
||||||
MethodReader method = classReader.getMethod(MethodDescriptor.parse(name + desc));
|
|
||||||
out.println(" \"implemented\" : \"" + (method != null ? "true" : "false") + "\",");
|
|
||||||
out.print(" }");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,15 +148,8 @@ class JCLComparisonVisitor implements ClassVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEnd() {
|
public void visitEnd() {
|
||||||
if (!ended) {
|
if (jclClass == null || jclClass.status != JCLStatus.FOUND) {
|
||||||
if (!pass) {
|
jclPackage.status = JCLStatus.PARTIAL;
|
||||||
if (!firstItem) {
|
|
||||||
out.println();
|
|
||||||
}
|
|
||||||
out.println(" ]");
|
|
||||||
}
|
|
||||||
out.print(" }");
|
|
||||||
ended = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
class JCLItem {
|
||||||
|
public final JCLItemType type;
|
||||||
|
public final String name;
|
||||||
|
public JCLStatus status;
|
||||||
|
|
||||||
|
public JCLItem(JCLItemType type, String name) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
enum JCLItemType {
|
||||||
|
FIELD,
|
||||||
|
METHOD
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
class JCLPackage {
|
||||||
|
public final String name;
|
||||||
|
public JCLStatus status;
|
||||||
|
public final List<JCLClass> classes = new ArrayList<>();
|
||||||
|
|
||||||
|
public JCLPackage(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
enum JCLStatus {
|
||||||
|
FOUND,
|
||||||
|
MISSING,
|
||||||
|
PARTIAL
|
||||||
|
}
|
BIN
teavm-classlib/src/main/resources/html/class_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/class_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 774 B |
BIN
teavm-classlib/src/main/resources/html/field_protected_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/field_protected_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 222 B |
BIN
teavm-classlib/src/main/resources/html/field_public_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/field_public_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 221 B |
46
teavm-classlib/src/main/resources/html/jcl-test.html
Normal file
46
teavm-classlib/src/main/resources/html/jcl-test.html
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>JCL emulation information</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
|
||||||
|
<link rel="stylesheet" href="jcl.css" type="text/css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<th>% of partially implemented</th>
|
||||||
|
<th>% of fully implemented</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="full">
|
||||||
|
<td><div class="package">java.lang</div></td>
|
||||||
|
<td class="percent">100%</td>
|
||||||
|
<td class="percent">0%</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="partial">
|
||||||
|
<td><div class="class">Object</div></td>
|
||||||
|
<td class="percent"></td>
|
||||||
|
<td class="percent">50%</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="full">
|
||||||
|
<td><div class="field">$id</div></td>
|
||||||
|
<td class="percent"></td>
|
||||||
|
<td class="percent"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="full">
|
||||||
|
<td><div class="method">clone()</div></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="missing">
|
||||||
|
<td><div class="method">getClass()</div></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
74
teavm-classlib/src/main/resources/html/jcl.css
Normal file
74
teavm-classlib/src/main/resources/html/jcl.css
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
* {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14pt;
|
||||||
|
line-height: 125%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1em;
|
||||||
|
border-color: rgb(160,160,160);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
padding-top: 0.25em;
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: rgb(160,160,160);
|
||||||
|
border-top-style: solid;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
background-color: rgb(220,220,220);
|
||||||
|
}
|
||||||
|
|
||||||
|
.full {
|
||||||
|
background-color: rgb(200,255,200);
|
||||||
|
}
|
||||||
|
.missing {
|
||||||
|
background-color: rgb(255,200,200);
|
||||||
|
}
|
||||||
|
.partial {
|
||||||
|
background-color: rgb(255,255,200);
|
||||||
|
}
|
||||||
|
.percent {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package, .class, .protected-class, .field, .protected-field, .method, .protected-method {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
padding-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package {
|
||||||
|
padding-left: 35px;
|
||||||
|
background-position: 16px 50%;
|
||||||
|
}
|
||||||
|
.class {
|
||||||
|
padding-left: 51px;
|
||||||
|
background-position: 32px 50%;
|
||||||
|
}
|
||||||
|
.field, .protected-field, .method, .protected-method {
|
||||||
|
padding-left: 67px;
|
||||||
|
background-position: 48px 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package {
|
||||||
|
background-image: url(package_obj.png);
|
||||||
|
}
|
||||||
|
.class {
|
||||||
|
background-image: url(class_obj.png);
|
||||||
|
}
|
||||||
|
.field {
|
||||||
|
background-image: url(field_public_obj.png);
|
||||||
|
}
|
||||||
|
.protected-field {
|
||||||
|
background-image: url(field_protected_obj.png);
|
||||||
|
}
|
||||||
|
.method {
|
||||||
|
background-image: url(methpub_obj.png);
|
||||||
|
}
|
||||||
|
.protected-method {
|
||||||
|
background-image: url(methpro_obj.png);
|
||||||
|
}
|
22
teavm-classlib/src/main/resources/html/jcl.html
Normal file
22
teavm-classlib/src/main/resources/html/jcl.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>JCL emulation information</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
|
||||||
|
<link rel="stylesheet" href="jcl.css" type="text/css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<th>% of partially implemented</th>
|
||||||
|
<th>% of fully implemented</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${CONTENT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
teavm-classlib/src/main/resources/html/methpro_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/methpro_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 B |
BIN
teavm-classlib/src/main/resources/html/methpub_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/methpub_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 325 B |
BIN
teavm-classlib/src/main/resources/html/package_obj.png
Normal file
BIN
teavm-classlib/src/main/resources/html/package_obj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 345 B |
|
@ -62,7 +62,10 @@ class ClassRefsRenamer implements InstructionVisitor {
|
||||||
}
|
}
|
||||||
rename(cls.getAnnotations(), renamedCls.getAnnotations());
|
rename(cls.getAnnotations(), renamedCls.getAnnotations());
|
||||||
for (String iface : cls.getInterfaces()) {
|
for (String iface : cls.getInterfaces()) {
|
||||||
renamedCls.getInterfaces().add(classNameMapper.map(iface));
|
String mappedIfaceName = classNameMapper.map(iface);
|
||||||
|
if (!mappedIfaceName.equals(renamedCls.getName())) {
|
||||||
|
renamedCls.getInterfaces().add(mappedIfaceName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return renamedCls;
|
return renamedCls;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,31 +114,6 @@
|
||||||
<skip>true</skip>
|
<skip>true</skip>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.eclipse.m2e</groupId>
|
|
||||||
<artifactId>lifecycle-mapping</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<configuration>
|
|
||||||
<lifecycleMappingMetadata>
|
|
||||||
<pluginExecutions>
|
|
||||||
<pluginExecution>
|
|
||||||
<pluginExecutionFilter>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-maven-plugin</artifactId>
|
|
||||||
<versionRange>[0.0.1-SNAPSHOT,)</versionRange>
|
|
||||||
<goals>
|
|
||||||
<goal>build-test-javascript</goal>
|
|
||||||
</goals>
|
|
||||||
</pluginExecutionFilter>
|
|
||||||
<action>
|
|
||||||
<ignore></ignore>
|
|
||||||
</action>
|
|
||||||
</pluginExecution>
|
|
||||||
</pluginExecutions>
|
|
||||||
</lifecycleMappingMetadata>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user