Add post-processor that reports references to missing items and replaces

these references with code that throws error.
This commit is contained in:
Alexey Andreev 2015-01-16 17:47:25 +04:00
parent 4299836ef4
commit 9154f4eff9
32 changed files with 587 additions and 182 deletions

View File

@ -18,7 +18,6 @@ package org.teavm.classlib.java.io;
import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TString;
import org.teavm.classlib.java.util.TArrays;
import org.teavm.javascript.ni.Rename;
/**
*
@ -62,9 +61,8 @@ public class TByteArrayOutputStream extends TOutputStream {
}
@Override
@Rename("toString")
public TString toString0() {
return new TString(buf, 0, count);
public String toString() {
return new String(buf, 0, count);
}
public TString toString(TString charsetName) throws TUnsupportedEncodingException {

View File

@ -204,6 +204,9 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
case "getDeclaringClass":
graph.getResult().propagate(agent.getType("java.lang.Class"));
break;
case "getName":
graph.getResult().propagate(agent.getType("java.lang.String"));
break;
case "newInstance":
agent.linkMethod(new MethodReference(InstantiationException.class, "<init>", void.class),
location).use();

View File

@ -18,8 +18,6 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.util.TArrays;
import org.teavm.javascript.ni.Remove;
import org.teavm.javascript.ni.Rename;
/**
*
@ -589,13 +587,6 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
return buffer.length;
}
@Override
@Rename("toString")
public TString toString0() {
return new TString(buffer, 0, length);
}
@Remove
@Override
public String toString() {
return new String(buffer, 0, length);

View File

@ -31,6 +31,6 @@ public class TArrayIndexOutOfBoundsException extends TIndexOutOfBoundsException
}
public TArrayIndexOutOfBoundsException(int index) {
super(TInteger.toString(index));
super(TString.wrap(Integer.toString(index)));
}
}

View File

@ -17,7 +17,6 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -71,13 +70,12 @@ public class TBoolean extends TObject implements TSerializable, TComparable<TBoo
return valueOf(parseBoolean(value));
}
public static TString toString(boolean value) {
return value ? TString.wrap("true") : TString.wrap("false");
public static String toString(boolean value) {
return value ? "true" : "false";
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -15,8 +15,6 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
@ -66,13 +64,12 @@ public class TByte extends TNumber implements TComparable<TByte> {
return new TByte(value);
}
public static TString toString(byte value) {
return TString.wrap(new StringBuilder().append(value).toString());
public static String toString(byte value) {
return new StringBuilder().append(value).toString();
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -15,8 +15,6 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
@ -28,6 +26,6 @@ public interface TCharSequence {
TCharSequence subSequence(int start, int end);
@Rename("toString")
TString toString0();
@Override
String toString();
}

View File

@ -19,7 +19,6 @@ import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.impl.unicode.UnicodeHelper;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -118,8 +117,7 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}
@ -136,8 +134,8 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
return value;
}
public static TString toString(char c) {
return new TString(new char[] { c });
public static String toString(char c) {
return new String(new char[] { c });
}
public static boolean isValidCodePoint(int codePoint) {

View File

@ -42,6 +42,7 @@ public class TClass<T> extends TObject {
@InjectedBy(ClassNativeGenerator.class)
public native boolean isAssignableFrom(TClass<?> obj);
@PluggableDependency(ClassNativeGenerator.class)
public TString getName() {
return name;
}

View File

@ -17,7 +17,6 @@ package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.InjectedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -68,8 +67,8 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
return new TDouble(d);
}
public static TString toString(double d) {
return TString.wrap(new TStringBuilder().append(d).toString());
public static String toString(double d) {
return new TStringBuilder().append(d).toString();
}
public static TDouble valueOf(TString string) {
@ -190,8 +189,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -40,9 +40,8 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
}
@Override
@Rename("toString")
public TString toString0() {
return name;
public String toString() {
return name.toString();
}
@Override

View File

@ -16,7 +16,6 @@
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -71,13 +70,12 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
return new TFloat(d);
}
public static TString toString(float d) {
return TString.wrap(new TStringBuilder().append(d).toString());
public static String toString(float d) {
return new TStringBuilder().append(d).toString();
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -15,8 +15,6 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
@ -37,26 +35,26 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
this(parseInt(s));
}
public static TString toString(int i, int radix) {
public static String toString(int i, int radix) {
if (radix < MIN_VALUE || radix > MAX_VALUE) {
radix = 10;
}
return TString.wrap(new TAbstractStringBuilder(20).append(i, radix).toString());
return new TAbstractStringBuilder(20).append(i, radix).toString();
}
public static TString toHexString(int i) {
public static String toHexString(int i) {
return toString(i, 16);
}
public static TString toOctalString(int i) {
public static String toOctalString(int i) {
return toString(i, 8);
}
public static TString toBinaryString(int i) {
public static String toBinaryString(int i) {
return toString(i, 2);
}
public static TString toString(int i) {
public static String toString(int i) {
return toString(i, 10);
}
@ -152,8 +150,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -16,7 +16,6 @@
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -174,29 +173,28 @@ public class TLong extends TNumber implements TComparable<TLong> {
return value;
}
public static TString toString(long i, int radix) {
return TString.wrap(new TStringBuilder().insert(0, i, radix).toString());
public static String toString(long i, int radix) {
return new TStringBuilder().insert(0, i, radix).toString();
}
public static TString toHexString(long i) {
public static String toHexString(long i) {
return toString(i, 16);
}
public static TString toOctalString(long i) {
public static String toOctalString(long i) {
return toString(i, 8);
}
public static TString toBinaryString(long i) {
public static String toBinaryString(long i) {
return toString(i, 2);
}
public static TString toString(long value) {
return TString.wrap(new TStringBuilder().append(value).toString());
public static String toString(long value) {
return new TStringBuilder().append(value).toString();
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2015 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.java.lang;
/**
*
* @author Alexey Andreev
*/
public class TNoClassDefFoundError extends TLinkageError {
private static final long serialVersionUID = -7662272618403764942L;
public TNoClassDefFoundError() {
super();
}
public TNoClassDefFoundError(TString message) {
super(message);
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.java.lang;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TNoSuchMethodError extends TIncompatibleClassChangeError {
private static final long serialVersionUID = 7907885242472547035L;
public TNoSuchMethodError() {
super();
}
public TNoSuchMethodError(TString message) {
super(message);
}
}

View File

@ -49,9 +49,9 @@ public class TObject {
return this == other;
}
@Rename("toString")
public TString toString0() {
return TString.wrap(getClass().getName() + "@" + TInteger.toHexString(identity()));
@Override
public String toString() {
return getClass().getName() + "@" + TInteger.toHexString(identity());
}
@GeneratedBy(ObjectNativeGenerator.class)

View File

@ -15,8 +15,6 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
@ -65,13 +63,12 @@ public class TShort extends TNumber implements TComparable<TShort> {
return new TShort(value);
}
public static TString toString(short value) {
return TString.wrap(new StringBuilder().append(value).toString());
public static String toString(short value) {
return new StringBuilder().append(value).toString();
}
@Override
@Rename("toString")
public TString toString0() {
public String toString() {
return toString(value);
}

View File

@ -25,7 +25,6 @@ import org.teavm.classlib.java.util.TMap;
import org.teavm.classlib.java.util.regex.TPattern;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.InjectedBy;
import org.teavm.javascript.ni.Rename;
/**
*
@ -458,9 +457,8 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
}
@Override
@Rename("toString")
public TString toString0() {
return this;
public String toString() {
return (String)(Object)this;
}
public char[] toCharArray() {

View File

@ -31,6 +31,7 @@ public class TStringIndexOutOfBoundsException extends TIndexOutOfBoundsException
}
public TStringIndexOutOfBoundsException(int index) {
super(new TStringBuilder().append(TString.wrap("String index out of bounds: ")).append(index).toString0());
super(TString.wrap(new TStringBuilder().append(TString.wrap("String index out of bounds: "))
.append(index).toString()));
}
}

View File

@ -482,9 +482,8 @@ public class TBitSet extends TObject implements TCloneable, TSerializable {
}
@Override
@Rename("toString")
public TString toString0() {
TStringBuilder sb = new TStringBuilder();
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('{');
boolean first = true;
for (int i = 0; i < data.length; ++i) {
@ -497,7 +496,7 @@ public class TBitSet extends TObject implements TCloneable, TSerializable {
int numZeros = TInteger.numberOfTrailingZeros(val);
bit += numZeros;
if (!first) {
sb.append(TString.wrap(", "));
sb.append(", ");
} else {
first = false;
}
@ -507,7 +506,7 @@ public class TBitSet extends TObject implements TCloneable, TSerializable {
}
}
sb.append('}');
return TString.wrap(sb.toString());
return sb.toString();
}
@Rename("clone")

View File

@ -18,38 +18,35 @@ package org.teavm.classlib.java.util.logging;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TInteger;
import org.teavm.classlib.java.lang.TObject;
import org.teavm.classlib.java.lang.TString;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TLevel extends TObject implements TSerializable {
public static final TLevel OFF = new TLevel(TString.wrap("OFF"), TInteger.MAX_VALUE);
public static final TLevel SEVERE = new TLevel(TString.wrap("SEVERE"), 1000);
public static final TLevel WARNING = new TLevel(TString.wrap("WARNING"), 900);
public static final TLevel INFO = new TLevel(TString.wrap("INFO"), 800);
public static final TLevel CONFIG = new TLevel(TString.wrap("CONFIG"), 700);
public static final TLevel FINE = new TLevel(TString.wrap("FINE"), 500);
public static final TLevel FINER = new TLevel(TString.wrap("FINER"), 400);
public static final TLevel FINEST = new TLevel(TString.wrap("FINEST"), 300);
public static final TLevel ALL = new TLevel(TString.wrap("FINEST"), TInteger.MIN_VALUE);
private TString name;
public static final TLevel OFF = new TLevel("OFF", TInteger.MAX_VALUE);
public static final TLevel SEVERE = new TLevel("SEVERE", 1000);
public static final TLevel WARNING = new TLevel("WARNING", 900);
public static final TLevel INFO = new TLevel("INFO", 800);
public static final TLevel CONFIG = new TLevel("CONFIG", 700);
public static final TLevel FINE = new TLevel("FINE", 500);
public static final TLevel FINER = new TLevel("FINER", 400);
public static final TLevel FINEST = new TLevel("FINEST", 300);
public static final TLevel ALL = new TLevel("ALL", TInteger.MIN_VALUE);
private String name;
private int value;
protected TLevel(TString name, int value) {
protected TLevel(String name, int value) {
this.name = name;
this.value = value;
}
public TString getName() {
public String getName() {
return name;
}
@Override
@Rename("toString")
public final TString toString0() {
public final String toString() {
return name;
}

View File

@ -24,7 +24,7 @@ import org.teavm.model.MethodReference;
* @author Alexey Andreev
*/
public class DefaultProblemTextConsumer implements ProblemTextConsumer {
private StringBuilder sb;
private StringBuilder sb = new StringBuilder();
public void clear() {
sb.setLength(0);

View File

@ -62,7 +62,11 @@ public class Problem {
break;
}
consumer.append(text.substring(index, next));
next = parseParameter(consumer, next);
index = parseParameter(consumer, next);
if (index == next) {
consumer.append("{{");
index += 2;
}
}
consumer.append(text.substring(index));
}
@ -89,7 +93,7 @@ public class Problem {
default:
return index;
}
int digitsEnd = passDigits(index);
int digitsEnd = passDigits(next);
if (digitsEnd == next) {
return index;
}

View File

@ -15,10 +15,7 @@
*/
package org.teavm.javascript.ni;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
/**
*

View File

@ -190,6 +190,17 @@ public class BasicBlock implements BasicBlockReader {
}
}
public void removeIncomingsFrom(BasicBlock predecessor) {
for (Phi phi : getPhis()) {
List<Incoming> incomings = phi.getIncomings();
for (int i = 0; i < incomings.size(); ++i) {
if (incomings.get(i).getSource() == predecessor) {
incomings.remove(i--);
}
}
}
}
private List<TryCatchBlock> immutableTryCatchBlocks = Collections.unmodifiableList(tryCatchBlocks);
@Override

View File

@ -0,0 +1,302 @@
/*
* Copyright 2015 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.model.util;
import java.util.ArrayList;
import java.util.List;
import org.teavm.dependency.DependencyInfo;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
/**
*
* @author Alexey Andreev
*/
public class MissingItemsProcessor {
private DependencyInfo dependencyInfo;
private Diagnostics diagnostics;
private List<Instruction> instructionsToAdd = new ArrayList<>();
private MethodHolder methodHolder;
private Program program;
public MissingItemsProcessor(DependencyInfo dependencyInfo, Diagnostics diagnostics) {
this.dependencyInfo = dependencyInfo;
this.diagnostics = diagnostics;
}
public void processClass(ClassHolder cls) {
for (MethodHolder method : cls.getMethods()) {
if (dependencyInfo.getAchievableMethods().contains(method.getReference()) && method.getProgram() != null) {
processMethod(method);
}
}
}
public void processMethod(MethodHolder method) {
this.methodHolder = method;
this.program = method.getProgram();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
instructionsToAdd.clear();
for (int j = 0; j < block.getInstructions().size(); ++j) {
Instruction insn = block.getInstructions().get(j);
insn.acceptVisitor(instructionProcessor);
if (!instructionsToAdd.isEmpty()) {
truncateBlock(block, j);
break;
}
}
}
}
private void truncateBlock(BasicBlock block, int index) {
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
if (block.getLastInstruction() != null) {
block.getLastInstruction().acceptVisitor(transitionExtractor);
}
for (BasicBlock successor : transitionExtractor.getTargets()) {
successor.removeIncomingsFrom(block);
}
block.getInstructions().subList(index, block.getInstructions().size()).clear();
block.getInstructions().addAll(instructionsToAdd);
}
private void emitExceptionThrow(InstructionLocation location, String exceptionName, String text) {
Variable exceptionVar = program.createVariable();
ConstructInstruction newExceptionInsn = new ConstructInstruction();
newExceptionInsn.setType(exceptionName);
newExceptionInsn.setReceiver(exceptionVar);
newExceptionInsn.setLocation(location);
instructionsToAdd.add(newExceptionInsn);
Variable constVar = program.createVariable();
StringConstantInstruction constInsn = new StringConstantInstruction();
constInsn.setConstant(text);
constInsn.setReceiver(constVar);
constInsn.setLocation(location);
instructionsToAdd.add(constInsn);
InvokeInstruction initExceptionInsn = new InvokeInstruction();
initExceptionInsn.setInstance(exceptionVar);
initExceptionInsn.setMethod(new MethodReference(exceptionName, "<init>", ValueType.object("java.lang.String"),
ValueType.VOID));
initExceptionInsn.setType(InvocationType.SPECIAL);
initExceptionInsn.getArguments().add(constVar);
initExceptionInsn.setLocation(location);
instructionsToAdd.add(initExceptionInsn);
RaiseInstruction raiseInsn = new RaiseInstruction();
raiseInsn.setException(exceptionVar);
raiseInsn.setLocation(location);
instructionsToAdd.add(raiseInsn);
}
private boolean checkClass(InstructionLocation location, String className) {
if (!dependencyInfo.getAchievableClasses().contains(className) ||
!dependencyInfo.getClass(className).isMissing()) {
return true;
}
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Class {{c0}} was not found",
className);
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
return false;
}
private boolean checkClass(InstructionLocation location, ValueType type) {
while (type instanceof ValueType.Array) {
type = ((ValueType.Array)type).getItemType();
}
if (type instanceof ValueType.Object) {
return checkClass(location, ((ValueType.Object)type).getClassName());
}
return true;
}
private boolean checkMethod(InstructionLocation location, MethodReference method) {
if (!checkClass(location, method.getClassName())) {
return false;
}
if (!dependencyInfo.getAchievableMethods().contains(method) || !dependencyInfo.getMethod(method).isMissing()) {
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(InstructionLocation location, FieldReference field) {
if (!checkClass(location, field.getClassName())) {
return false;
}
if (!dependencyInfo.getAchievableFields().contains(field) || !dependencyInfo.getField(field).isMissing()) {
return true;
}
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Field {{f0}} was not found",
field);
emitExceptionThrow(location, NoSuchFieldError.class.getName(), "Field not found: " + field);
return true;
}
private InstructionVisitor instructionProcessor = new InstructionVisitor() {
@Override
public void visit(NullCheckInstruction insn) {
}
@Override
public void visit(InitClassInstruction insn) {
checkClass(insn.getLocation(), insn.getClassName());
}
@Override
public void visit(IsInstanceInstruction insn) {
checkClass(insn.getLocation(), insn.getType());
}
@Override
public void visit(InvokeInstruction insn) {
checkMethod(insn.getLocation(), insn.getMethod());
}
@Override
public void visit(PutElementInstruction insn) {
}
@Override
public void visit(GetElementInstruction insn) {
}
@Override
public void visit(UnwrapArrayInstruction insn) {
}
@Override
public void visit(CloneArrayInstruction insn) {
}
@Override
public void visit(ArrayLengthInstruction insn) {
}
@Override
public void visit(PutFieldInstruction insn) {
checkField(insn.getLocation(), insn.getField());
}
@Override
public void visit(GetFieldInstruction insn) {
checkField(insn.getLocation(), insn.getField());
}
@Override
public void visit(ConstructMultiArrayInstruction insn) {
checkClass(insn.getLocation(), insn.getItemType());
}
@Override
public void visit(ConstructInstruction insn) {
checkClass(insn.getLocation(), insn.getType());
}
@Override
public void visit(ConstructArrayInstruction insn) {
checkClass(insn.getLocation(), insn.getItemType());
}
@Override
public void visit(RaiseInstruction insn) {
}
@Override
public void visit(ExitInstruction insn) {
}
@Override
public void visit(SwitchInstruction insn) {
}
@Override
public void visit(JumpInstruction insn) {
}
@Override
public void visit(BinaryBranchingInstruction insn) {
}
@Override
public void visit(BranchingInstruction insn) {
}
@Override
public void visit(CastIntegerInstruction insn) {
}
@Override
public void visit(CastNumberInstruction insn) {
}
@Override
public void visit(CastInstruction insn) {
checkClass(insn.getLocation(), insn.getTargetType());
}
@Override
public void visit(AssignInstruction insn) {
}
@Override
public void visit(NegateInstruction insn) {
}
@Override
public void visit(BinaryInstruction insn) {
}
@Override
public void visit(StringConstantInstruction insn) {
}
@Override
public void visit(DoubleConstantInstruction insn) {
}
@Override
public void visit(FloatConstantInstruction insn) {
}
@Override
public void visit(LongConstantInstruction insn) {
}
@Override
public void visit(IntegerConstantInstruction insn) {
}
@Override
public void visit(NullConstantInstruction insn) {
}
@Override
public void visit(ClassConstantInstruction insn) {
checkClass(insn.getLocation(), insn.getConstant());
}
@Override
public void visit(EmptyInstruction insn) {
}
};
}

View File

@ -0,0 +1,97 @@
/*
* Copyright 2015 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.tooling;
import java.util.Iterator;
import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite;
import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem;
import org.teavm.model.CallLocation;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
import org.teavm.vm.TeaVM;
/**
*
* @author Alexey Andreev
*/
public final class TeaVMProblemRenderer {
private TeaVMProblemRenderer() {
}
public static void describeProblems(TeaVM vm, TeaVMToolLog log) {
CallGraph cg = vm.getDependencyInfo().getCallGraph();
DefaultProblemTextConsumer consumer = new DefaultProblemTextConsumer();
for (Problem problem : vm.getProblemProvider().getProblems()) {
consumer.clear();
problem.render(consumer);
StringBuilder sb = new StringBuilder();
sb.append(consumer.getText());
renderCallStack(cg, problem.getLocation(), sb);
String problemText = sb.toString();
switch (problem.getSeverity()) {
case ERROR:
log.error(problemText);
break;
case WARNING:
log.warning(problemText);
break;
}
}
}
private static void renderCallStack(CallGraph cg, CallLocation location, StringBuilder sb) {
if (location == null) {
return;
}
sb.append("\n at ");
renderCallLocation(location.getMethod(), location.getSourceLocation(), sb);
if (location.getMethod() != null) {
CallGraphNode node = cg.getNode(location.getMethod());
while (true) {
Iterator<? extends CallSite> callSites = node.getCallerCallSites().iterator();
if (!callSites.hasNext()) {
break;
}
CallSite callSite = callSites.next();
sb.append("\n at ");
renderCallLocation(callSite.getCaller().getMethod(), callSite.getLocation(), sb);
node = callSite.getCaller();
}
}
}
private static void renderCallLocation(MethodReference method, InstructionLocation location, StringBuilder sb) {
if (method != null) {
sb.append(method);
} else {
sb.append("unknown method");
}
sb.append(' ');
if (location != null) {
sb.append("(");
String fileName = location.getFileName();
if (fileName != null) {
sb.append(fileName.substring(fileName.lastIndexOf('/') + 1));
sb.append(':');
}
sb.append(location.getLine());
sb.append(')');
}
}
}

View File

@ -372,6 +372,15 @@ public class TeaVMTestTool {
String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map";
innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName);
}
if (!vm.getProblemProvider().getProblems().isEmpty()) {
if (vm.getProblemProvider().getSevereProblems().isEmpty()) {
log.warning("Test built with warnings: " + methodRef);
TeaVMProblemRenderer.describeProblems(vm, log);
} else {
log.warning("Test built with errors: " + methodRef);
TeaVMProblemRenderer.describeProblems(vm, log);
}
}
}
if (sourceMapsGenerated) {
DebugInformation debugInfo = debugInfoBuilder.getDebugInformation();

View File

@ -22,13 +22,8 @@ import org.teavm.cache.DiskCachedClassHolderSource;
import org.teavm.cache.DiskProgramCache;
import org.teavm.cache.DiskRegularMethodNodeCache;
import org.teavm.cache.FileSymbolTable;
import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite;
import org.teavm.debugging.information.DebugInformation;
import org.teavm.debugging.information.DebugInformationBuilder;
import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem;
import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.RenderingContext;
import org.teavm.model.*;
@ -304,10 +299,10 @@ public class TeaVMTool {
log.info("JavaScript file successfully built");
} else if (problemProvider.getSevereProblems().isEmpty()) {
log.info("JavaScript file built with warnings");
describeProblems(vm);
TeaVMProblemRenderer.describeProblems(vm, log);
} else {
log.info("JavaScript file built with errors");
describeProblems(vm);
TeaVMProblemRenderer.describeProblems(vm, log);
}
if (debugInformationGenerated) {
DebugInformation debugInfo = debugEmitter.getDebugInformation();
@ -359,67 +354,6 @@ public class TeaVMTool {
}
}
private void describeProblems(TeaVM vm) {
CallGraph cg = vm.getDependencyInfo().getCallGraph();
DefaultProblemTextConsumer consumer = new DefaultProblemTextConsumer();
for (Problem problem : vm.getProblemProvider().getProblems()) {
consumer.clear();
problem.render(consumer);
StringBuilder sb = new StringBuilder();
sb.append(consumer.getText());
renderCallStack(cg, problem.getLocation(), sb);
String problemText = sb.toString();
switch (problem.getSeverity()) {
case ERROR:
log.error(problemText);
break;
case WARNING:
log.warning(problemText);
break;
}
}
}
private void renderCallStack(CallGraph cg, CallLocation location, StringBuilder sb) {
if (location == null) {
return;
}
sb.append("\n at ");
renderCallLocation(location.getMethod(), location.getSourceLocation(), sb);
if (location.getMethod() != null) {
CallGraphNode node = cg.getNode(location.getMethod());
while (true) {
Iterator<? extends CallSite> callSites = node.getCallerCallSites().iterator();
if (!callSites.hasNext()) {
break;
}
CallSite callSite = callSites.next();
sb.append("\n at ");
renderCallLocation(node.getMethod(), callSite.getLocation(), sb);
node = callSite.getCaller();
}
}
}
private void renderCallLocation(MethodReference method, InstructionLocation location, StringBuilder sb) {
if (method != null) {
sb.append(method);
} else {
sb.append("unknown method");
}
sb.append(' ');
if (location != null) {
sb.append("(");
String fileName = location.getFileName();
if (fileName != null) {
sb.append(fileName.substring(fileName.lastIndexOf('/') + 1));
sb.append(':');
}
sb.append(location.getLine());
sb.append(')');
}
}
private void copySourceFiles() {
if (vm.getWrittenClasses() == null) {
return;

View File

@ -29,10 +29,7 @@ import org.teavm.javascript.ast.ClassNode;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.Injector;
import org.teavm.model.*;
import org.teavm.model.util.ListingBuilder;
import org.teavm.model.util.ModelUtils;
import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.RegisterAllocator;
import org.teavm.model.util.*;
import org.teavm.optimization.*;
import org.teavm.vm.spi.RendererListener;
import org.teavm.vm.spi.TeaVMHost;
@ -344,6 +341,21 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
internDep.use();
dependencyChecker.linkMethod(new MethodReference(String.class, "length", int.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use();
MethodDependency exceptionCons = dependencyChecker.linkMethod(new MethodReference(
NoClassDefFoundError.class, "<init>", String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoClassDefFoundError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchFieldError.class, "<init>",
String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchFieldError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchMethodError.class, "<init>",
String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchMethodError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
dependencyChecker.processDependencies();
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
return;
@ -438,6 +450,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
reportPhase(TeaVMPhase.LINKING, dependency.getAchievableClasses().size());
Linker linker = new Linker();
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency, diagnostics);
if (wasCancelled()) {
return cutClasses;
}
@ -445,6 +458,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
for (String className : dependency.getAchievableClasses()) {
ClassHolder cls = ModelUtils.copyClass(dependency.getClassSource().get(className));
cutClasses.putClassHolder(cls);
missingItemsProcessor.processClass(cls);
linker.link(dependency, cls);
progressListener.progressReached(++index);
}

View File

@ -112,6 +112,9 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Parameter
private MethodAlias[] methodAliases;
@Parameter
private boolean stopOnErrors = true;
private TeaVMTool tool = new TeaVMTool();
public void setProject(MavenProject project) {
@ -198,6 +201,10 @@ public class BuildJavascriptMojo extends AbstractMojo {
this.incremental = incremental;
}
public void setStopOnErrors(boolean stopOnErrors) {
this.stopOnErrors = stopOnErrors;
}
public File getCacheDirectory() {
return cacheDirectory;
}
@ -247,7 +254,7 @@ public class BuildJavascriptMojo extends AbstractMojo {
tool.setSourceMapsFileGenerated(sourceMapsGenerated);
tool.setSourceFilesCopied(sourceFilesCopied);
tool.generate();
if (!tool.getProblemProvider().getSevereProblems().isEmpty()) {
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
throw new MojoExecutionException("Build error");
}
} catch (RuntimeException e) {