npe() renamed to sure()
This commit is contained in:
@@ -35,18 +35,10 @@ import java.util.*;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
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_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> myBreakTargets = new Stack<Label>();
|
||||
|
||||
@@ -574,10 +566,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
|
||||
: entry.getText();
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -972,7 +964,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
||||
v.checkcast(typeMapper.mapType(typeParameterDescriptor.getClassObjectType()));
|
||||
|
||||
return StackValue.onStack(OBJECT_TYPE);
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
else {
|
||||
// receiver
|
||||
@@ -1693,7 +1685,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
private StackValue generateNullSafeEquals(IElementType opToken, boolean leftNullable, boolean rightNullable) {
|
||||
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) {
|
||||
v.iconst(1);
|
||||
v.xor(Type.INT_TYPE);
|
||||
@@ -1706,7 +1698,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.ifnull(rightNull);
|
||||
Label leftNull = new Label();
|
||||
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) {
|
||||
v.iconst(1);
|
||||
v.xor(Type.INT_TYPE);
|
||||
@@ -1731,7 +1723,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.pop();
|
||||
Label leftNull = new Label();
|
||||
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) {
|
||||
v.iconst(1);
|
||||
v.xor(Type.INT_TYPE);
|
||||
@@ -1796,7 +1788,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
private StackValue compareExpressionsOnStack(IElementType opToken, Type operandType) {
|
||||
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);
|
||||
operandType = Type.INT_TYPE;
|
||||
}
|
||||
@@ -1865,7 +1857,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
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) {
|
||||
@@ -1885,7 +1877,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
public void invokeAppendMethod(Type exprType) {
|
||||
Method appendDescriptor = new Method("append", JetTypeMapper.JL_STRING_BUILDER,
|
||||
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
|
||||
@@ -2331,7 +2323,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||
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();
|
||||
v.ifne(isInstance);
|
||||
v.pop();
|
||||
@@ -2353,7 +2345,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2376,7 +2368,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(subjectType, v);
|
||||
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);
|
||||
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 lblDone = new Label();
|
||||
expressionToMatch.dupReceiver(v);
|
||||
expressionToMatch.put(OBJECT_TYPE, v);
|
||||
expressionToMatch.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
v.dup();
|
||||
final String tupleClassName = "jet/Tuple" + entries.size();
|
||||
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);
|
||||
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);
|
||||
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) {
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (!hasTypeInfoForInstanceOf(jetType)) {
|
||||
expressionToGen.put(OBJECT_TYPE, v);
|
||||
expressionToGen.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
@@ -2491,7 +2483,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
}
|
||||
else {
|
||||
generateTypeInfo(jetType);
|
||||
expressionToGen.put(OBJECT_TYPE, v);
|
||||
expressionToGen.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dupX1();
|
||||
}
|
||||
@@ -2718,7 +2710,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
v.dup();
|
||||
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
|
||||
for (JetExpression entry : entries) {
|
||||
gen(entry, OBJECT_TYPE);
|
||||
gen(entry, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
v.invokespecial(className, "<init>", signature.toString());
|
||||
return StackValue.onStack(tupleType);
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Concat implements IntrinsicMethod {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import sun.tools.tree.NewArrayExpression;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -87,7 +86,7 @@ public class IntrinsicMethods {
|
||||
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
|
||||
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
|
||||
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("ShortIterator", "next", 0, ITERATOR_NEXT);
|
||||
|
||||
+2
-2
@@ -13,11 +13,11 @@ import java.util.List;
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class NPE implements IntrinsicMethod {
|
||||
public class Sure implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
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);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
|
||||
// Returns "null" for null
|
||||
fun Any?.toString() : String// = this === other
|
||||
|
||||
fun <T : Any> T?.npe() : T
|
||||
fun <T : Any> T?.sure() : T
|
||||
|
||||
fun String?.plus(other: Any?) : String
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//KT-600 Problem with 'sure' extension function type inference
|
||||
// +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() {
|
||||
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;
|
||||
|
||||
import jet.runtime.Intrinsics;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.jet.codegen.CodegenTestCase;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -9,8 +8,8 @@ import java.lang.reflect.Method;
|
||||
public class JetNpeTest extends CodegenTestCase {
|
||||
public void testStackTrace () {
|
||||
try {
|
||||
Intrinsics.npe(null);
|
||||
fail("No NPE thrown");
|
||||
Intrinsics.sure(null);
|
||||
fail("No Sure thrown");
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
StackTraceElement stackTraceElement = e.getStackTrace()[0];
|
||||
@@ -20,12 +19,13 @@ public class JetNpeTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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");
|
||||
assertThrows(box, NullPointerException.class, null);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package jet.runtime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
@@ -11,7 +13,7 @@ public class Intrinsics {
|
||||
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)
|
||||
return throwNpe();
|
||||
return self;
|
||||
@@ -20,4 +22,30 @@ public class Intrinsics {
|
||||
private static Object throwNpe() {
|
||||
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