npe() renamed to sure()
This commit is contained in:
@@ -35,18 +35,10 @@ import java.util.*;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||||
private static final String CLASS_OBJECT = "java/lang/Object";
|
|
||||||
private static final String CLASS_STRING = "java/lang/String";
|
|
||||||
public static final String CLASS_STRING_BUILDER = "java/lang/StringBuilder";
|
|
||||||
private static final String CLASS_COMPARABLE = "java/lang/Comparable";
|
|
||||||
|
|
||||||
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
|
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
|
||||||
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
|
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
|
||||||
|
|
||||||
private static final Type OBJECT_TYPE = Type.getType(Object.class);
|
|
||||||
private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
|
|
||||||
private static final Type STRING_TYPE = Type.getObjectType(CLASS_STRING);
|
|
||||||
|
|
||||||
private final Stack<Label> myContinueTargets = new Stack<Label>();
|
private final Stack<Label> myContinueTargets = new Stack<Label>();
|
||||||
private final Stack<Label> myBreakTargets = new Stack<Label>();
|
private final Stack<Label> myBreakTargets = new Stack<Label>();
|
||||||
|
|
||||||
@@ -574,10 +566,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
|
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
|
||||||
: entry.getText();
|
: entry.getText();
|
||||||
v.aconst(text);
|
v.aconst(text);
|
||||||
invokeAppendMethod(STRING_TYPE);
|
invokeAppendMethod(JetTypeMapper.JL_STRING_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.invokevirtual(CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
|
||||||
return StackValue.onStack(expressionType(expression));
|
return StackValue.onStack(expressionType(expression));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -972,7 +964,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
||||||
v.checkcast(typeMapper.mapType(typeParameterDescriptor.getClassObjectType()));
|
v.checkcast(typeMapper.mapType(typeParameterDescriptor.getClassObjectType()));
|
||||||
|
|
||||||
return StackValue.onStack(OBJECT_TYPE);
|
return StackValue.onStack(JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// receiver
|
// receiver
|
||||||
@@ -1693,7 +1685,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private StackValue generateNullSafeEquals(IElementType opToken, boolean leftNullable, boolean rightNullable) {
|
private StackValue generateNullSafeEquals(IElementType opToken, boolean leftNullable, boolean rightNullable) {
|
||||||
if(!leftNullable) {
|
if(!leftNullable) {
|
||||||
v.invokevirtual(CLASS_OBJECT, "equals", "(Ljava/lang/Object;)Z");
|
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||||
if (opToken == JetTokens.EXCLEQ) {
|
if (opToken == JetTokens.EXCLEQ) {
|
||||||
v.iconst(1);
|
v.iconst(1);
|
||||||
v.xor(Type.INT_TYPE);
|
v.xor(Type.INT_TYPE);
|
||||||
@@ -1706,7 +1698,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.ifnull(rightNull);
|
v.ifnull(rightNull);
|
||||||
Label leftNull = new Label();
|
Label leftNull = new Label();
|
||||||
v.ifnull(leftNull);
|
v.ifnull(leftNull);
|
||||||
v.invokevirtual(CLASS_OBJECT, "equals", "(Ljava/lang/Object;)Z");
|
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||||
v.iconst(1);
|
v.iconst(1);
|
||||||
v.xor(Type.INT_TYPE);
|
v.xor(Type.INT_TYPE);
|
||||||
@@ -1731,7 +1723,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.pop();
|
v.pop();
|
||||||
Label leftNull = new Label();
|
Label leftNull = new Label();
|
||||||
v.ifnull(leftNull);
|
v.ifnull(leftNull);
|
||||||
v.invokevirtual(CLASS_OBJECT, "equals", "(Ljava/lang/Object;)Z");
|
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||||
v.iconst(1);
|
v.iconst(1);
|
||||||
v.xor(Type.INT_TYPE);
|
v.xor(Type.INT_TYPE);
|
||||||
@@ -1796,7 +1788,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private StackValue compareExpressionsOnStack(IElementType opToken, Type operandType) {
|
private StackValue compareExpressionsOnStack(IElementType opToken, Type operandType) {
|
||||||
if (operandType.getSort() == Type.OBJECT) {
|
if (operandType.getSort() == Type.OBJECT) {
|
||||||
v.invokeinterface(CLASS_COMPARABLE, "compareTo", "(Ljava/lang/Object;)I");
|
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
|
||||||
v.iconst(0);
|
v.iconst(0);
|
||||||
operandType = Type.INT_TYPE;
|
operandType = Type.INT_TYPE;
|
||||||
}
|
}
|
||||||
@@ -1865,7 +1857,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
||||||
v.invokespecial(CLASS_STRING_BUILDER, method.getName(), method.getDescriptor());
|
v.invokespecial("java/lang/StringBuilder", method.getName(), method.getDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invokeAppend(final JetExpression expr) {
|
public void invokeAppend(final JetExpression expr) {
|
||||||
@@ -1885,7 +1877,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
public void invokeAppendMethod(Type exprType) {
|
public void invokeAppendMethod(Type exprType) {
|
||||||
Method appendDescriptor = new Method("append", JetTypeMapper.JL_STRING_BUILDER,
|
Method appendDescriptor = new Method("append", JetTypeMapper.JL_STRING_BUILDER,
|
||||||
new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType});
|
new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType});
|
||||||
v.invokevirtual(CLASS_STRING_BUILDER, "append", appendDescriptor.getDescriptor());
|
v.invokevirtual("java/lang/StringBuilder", "append", appendDescriptor.getDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2331,7 +2323,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||||
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
||||||
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
|
generateInstanceOf(StackValue.expression(JetTypeMapper.TYPE_OBJECT, expression.getLeft(), this), jetType, true);
|
||||||
Label isInstance = new Label();
|
Label isInstance = new Label();
|
||||||
v.ifne(isInstance);
|
v.ifne(isInstance);
|
||||||
v.pop();
|
v.pop();
|
||||||
@@ -2353,7 +2345,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitIsExpression(final JetIsExpression expression, StackValue receiver) {
|
public StackValue visitIsExpression(final JetIsExpression expression, StackValue receiver) {
|
||||||
final StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this);
|
final StackValue match = StackValue.expression(JetTypeMapper.TYPE_OBJECT, expression.getLeftHandSide(), this);
|
||||||
return generatePatternMatch(expression.getPattern(), expression.isNegated(), match, null);
|
return generatePatternMatch(expression.getPattern(), expression.isNegated(), match, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2376,7 +2368,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
expressionToMatch.dupReceiver(v);
|
expressionToMatch.dupReceiver(v);
|
||||||
expressionToMatch.put(subjectType, v);
|
expressionToMatch.put(subjectType, v);
|
||||||
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
|
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
|
||||||
Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE;
|
Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : JetTypeMapper.TYPE_OBJECT;
|
||||||
gen(condExpression, condType);
|
gen(condExpression, condType);
|
||||||
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, false, false);
|
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, false, false);
|
||||||
}
|
}
|
||||||
@@ -2407,7 +2399,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
Label lblFail = new Label();
|
Label lblFail = new Label();
|
||||||
Label lblDone = new Label();
|
Label lblDone = new Label();
|
||||||
expressionToMatch.dupReceiver(v);
|
expressionToMatch.dupReceiver(v);
|
||||||
expressionToMatch.put(OBJECT_TYPE, v);
|
expressionToMatch.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
v.dup();
|
v.dup();
|
||||||
final String tupleClassName = "jet/Tuple" + entries.size();
|
final String tupleClassName = "jet/Tuple" + entries.size();
|
||||||
Type tupleType = Type.getObjectType(tupleClassName);
|
Type tupleType = Type.getObjectType(tupleClassName);
|
||||||
@@ -2421,7 +2413,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
|
|
||||||
v.mark(lblCheck);
|
v.mark(lblCheck);
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
final StackValue tupleField = StackValue.field(OBJECT_TYPE, tupleClassName, "_" + (i + 1), false);
|
final StackValue tupleField = StackValue.field(JetTypeMapper.TYPE_OBJECT, tupleClassName, "_" + (i + 1), false);
|
||||||
final StackValue stackValue = generatePatternMatch(entries.get(i).getPattern(), false, tupleField, nextEntry);
|
final StackValue stackValue = generatePatternMatch(entries.get(i).getPattern(), false, tupleField, nextEntry);
|
||||||
stackValue.condJump(lblPopAndFail, true, v);
|
stackValue.condJump(lblPopAndFail, true, v);
|
||||||
}
|
}
|
||||||
@@ -2467,7 +2459,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
|
private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
|
||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if (!hasTypeInfoForInstanceOf(jetType)) {
|
if (!hasTypeInfoForInstanceOf(jetType)) {
|
||||||
expressionToGen.put(OBJECT_TYPE, v);
|
expressionToGen.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
if (leaveExpressionOnStack) {
|
if (leaveExpressionOnStack) {
|
||||||
v.dup();
|
v.dup();
|
||||||
}
|
}
|
||||||
@@ -2491,7 +2483,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generateTypeInfo(jetType);
|
generateTypeInfo(jetType);
|
||||||
expressionToGen.put(OBJECT_TYPE, v);
|
expressionToGen.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
if (leaveExpressionOnStack) {
|
if (leaveExpressionOnStack) {
|
||||||
v.dupX1();
|
v.dupX1();
|
||||||
}
|
}
|
||||||
@@ -2718,7 +2710,7 @@ If finally block is present, its last expression is the value of try expression.
|
|||||||
v.dup();
|
v.dup();
|
||||||
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
|
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
|
||||||
for (JetExpression entry : entries) {
|
for (JetExpression entry : entries) {
|
||||||
gen(entry, OBJECT_TYPE);
|
gen(entry, JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
v.invokespecial(className, "<init>", signature.toString());
|
v.invokespecial(className, "<init>", signature.toString());
|
||||||
return StackValue.onStack(tupleType);
|
return StackValue.onStack(tupleType);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class Concat implements IntrinsicMethod {
|
|||||||
codegen.invokeAppend(arguments.get(1));
|
codegen.invokeAppend(arguments.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
|
||||||
return StackValue.onStack(Type.getObjectType("java/lang/String"));
|
return StackValue.onStack(Type.getObjectType("java/lang/String"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
|||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import sun.tools.tree.NewArrayExpression;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -87,7 +86,7 @@ public class IntrinsicMethods {
|
|||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
|
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
|
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
|
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("npe"), 0, new NPE());
|
declareOverload(myStdLib.getLibraryScope().getFunctions("sure"), 0, new Sure());
|
||||||
|
|
||||||
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
|
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
|
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
|
||||||
|
|||||||
+2
-2
@@ -13,11 +13,11 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class NPE implements IntrinsicMethod {
|
public class Sure implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
v.invokestatic("jet/runtime/Intrinsics", "npe", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
v.invokestatic("jet/runtime/Intrinsics", "sure", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v);
|
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v);
|
||||||
return StackValue.onStack(expectedType);
|
return StackValue.onStack(expectedType);
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
|
|||||||
// Returns "null" for null
|
// Returns "null" for null
|
||||||
fun Any?.toString() : String// = this === other
|
fun Any?.toString() : String// = this === other
|
||||||
|
|
||||||
fun <T : Any> T?.npe() : T
|
fun <T : Any> T?.sure() : T
|
||||||
|
|
||||||
fun String?.plus(other: Any?) : String
|
fun String?.plus(other: Any?) : String
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
//KT-600 Problem with 'sure' extension function type inference
|
//KT-600 Problem with 'sure' extension function type inference
|
||||||
// +JDK
|
// +JDK
|
||||||
|
|
||||||
fun <T : Any> T?.sure() : T { if (this != null) return this else throw NullPointerException() }
|
fun <T : Any> T?._sure() : T { if (this != null) return this else throw NullPointerException() }
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val i : Int? = 10
|
val i : Int? = 10
|
||||||
val <!UNUSED_VARIABLE!>i2<!> : Int = i.sure() // inferred type is Int? but Int was excepted
|
val <!UNUSED_VARIABLE!>i2<!> : Int = i._sure() // inferred type is Int? but Int was excepted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.jet.runtime;
|
package org.jetbrains.jet.runtime;
|
||||||
|
|
||||||
import jet.runtime.Intrinsics;
|
import jet.runtime.Intrinsics;
|
||||||
import junit.framework.TestCase;
|
|
||||||
import org.jetbrains.jet.codegen.CodegenTestCase;
|
import org.jetbrains.jet.codegen.CodegenTestCase;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@@ -9,8 +8,8 @@ import java.lang.reflect.Method;
|
|||||||
public class JetNpeTest extends CodegenTestCase {
|
public class JetNpeTest extends CodegenTestCase {
|
||||||
public void testStackTrace () {
|
public void testStackTrace () {
|
||||||
try {
|
try {
|
||||||
Intrinsics.npe(null);
|
Intrinsics.sure(null);
|
||||||
fail("No NPE thrown");
|
fail("No Sure thrown");
|
||||||
}
|
}
|
||||||
catch (NullPointerException e) {
|
catch (NullPointerException e) {
|
||||||
StackTraceElement stackTraceElement = e.getStackTrace()[0];
|
StackTraceElement stackTraceElement = e.getStackTrace()[0];
|
||||||
@@ -20,12 +19,13 @@ public class JetNpeTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testNotNull () throws Exception {
|
public void testNotNull () throws Exception {
|
||||||
loadText("fun box() = if(10.npe() == 10) \"OK\" else \"fail\"");
|
loadText("fun box() = if(10.sure() == 10) \"OK\" else \"fail\"");
|
||||||
blackBox();
|
blackBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNull () throws Exception {
|
public void testNull () throws Exception {
|
||||||
loadText("fun box() = if(null.npe() == 10) \"OK\" else \"fail\"");
|
loadText("fun box() = if(null.sure() == 10) \"OK\" else \"fail\"");
|
||||||
|
System.out.println(generateToText());
|
||||||
Method box = generateFunction("box");
|
Method box = generateFunction("box");
|
||||||
assertThrows(box, NullPointerException.class, null);
|
assertThrows(box, NullPointerException.class, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package jet.runtime;
|
package jet.runtime;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
@@ -11,7 +13,7 @@ public class Intrinsics {
|
|||||||
return ((self == null) ? "null" : self) + ((other == null) ? "null" : other.toString());
|
return ((self == null) ? "null" : self) + ((other == null) ? "null" : other.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object npe(Object self) {
|
public static Object sure(Object self) {
|
||||||
if(self == null)
|
if(self == null)
|
||||||
return throwNpe();
|
return throwNpe();
|
||||||
return self;
|
return self;
|
||||||
@@ -20,4 +22,30 @@ public class Intrinsics {
|
|||||||
private static Object throwNpe() {
|
private static Object throwNpe() {
|
||||||
throw new JetNullPointerException();
|
throw new JetNullPointerException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Throwable sanitizeStackTrace(Throwable throwable) {
|
||||||
|
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
||||||
|
ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
|
||||||
|
boolean skip = true;
|
||||||
|
for(StackTraceElement ste : stackTrace) {
|
||||||
|
if(!skip) {
|
||||||
|
list.add(ste);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if("jet.runtime.Intrinsics".equals(ste.getClassName()) && "sure".equals(ste.getMethodName())) {
|
||||||
|
skip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throwable.setStackTrace(list.toArray(new StackTraceElement[list.size()]));
|
||||||
|
return throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class JetNullPointerException extends NullPointerException {
|
||||||
|
@Override
|
||||||
|
public synchronized Throwable fillInStackTrace() {
|
||||||
|
super.fillInStackTrace();
|
||||||
|
return sanitizeStackTrace(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package jet.runtime;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author alex.tkachman
|
|
||||||
*/
|
|
||||||
class JetNullPointerException extends NullPointerException {
|
|
||||||
@Override
|
|
||||||
public synchronized Throwable fillInStackTrace() {
|
|
||||||
super.fillInStackTrace();
|
|
||||||
StackTraceElement[] stackTrace = getStackTrace();
|
|
||||||
ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
|
|
||||||
boolean skip = true;
|
|
||||||
for(StackTraceElement ste : stackTrace) {
|
|
||||||
if(!skip) {
|
|
||||||
list.add(ste);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if("jet.runtime.Intrinsics".equals(ste.getClassName()) && "npe".equals(ste.getMethodName())) {
|
|
||||||
skip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setStackTrace(list.toArray(new StackTraceElement[list.size()]));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Intrinsics.npe(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user