npe() runtime intrinsic method.

This commit is contained in:
Alex Tkachman
2011-11-26 09:30:24 +02:00
parent a6eeb01b64
commit 2cbd072478
6 changed files with 100 additions and 3 deletions
@@ -87,6 +87,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());
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
@@ -0,0 +1,24 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class NPE 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;");
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
+1 -3
View File
@@ -42,9 +42,7 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
// Returns "null" for null
fun Any?.toString() : String// = this === other
// fun <T> array(vararg elements : T) : Array<T>
// fun array(vararg elements : Int) : IntArray
fun <T : Any> T?.npe() : T
fun String?.plus(other: Any?) : String
@@ -0,0 +1,32 @@
package org.jetbrains.jet.runtime;
import jet.runtime.Intrinsics;
import junit.framework.TestCase;
import org.jetbrains.jet.codegen.CodegenTestCase;
import java.lang.reflect.Method;
public class JetNpeTest extends CodegenTestCase {
public void testStackTrace () {
try {
Intrinsics.npe(null);
fail("No NPE thrown");
}
catch (NullPointerException e) {
StackTraceElement stackTraceElement = e.getStackTrace()[0];
assertEquals(stackTraceElement.getMethodName(), "testStackTrace");
assertEquals(stackTraceElement.getClassName(), "org.jetbrains.jet.runtime.JetNpeTest");
}
}
public void testNotNull () throws Exception {
loadText("fun box() = if(10.npe() == 10) \"OK\" else \"fail\"");
blackBox();
}
public void testNull () throws Exception {
loadText("fun box() = if(null.npe() == 10) \"OK\" else \"fail\"");
Method box = generateFunction("box");
assertThrows(box, NullPointerException.class, null);
}
}
+10
View File
@@ -10,4 +10,14 @@ public class Intrinsics {
public static String stringPlus(String self, Object other) {
return ((self == null) ? "null" : self) + ((other == null) ? "null" : other.toString());
}
public static Object npe(Object self) {
if(self == null)
return throwNpe();
return self;
}
private static Object throwNpe() {
throw new JetNullPointerException();
}
}
@@ -0,0 +1,32 @@
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);
}
}