KT-1041 Add check that thrown/catched expression is of Throwable type

This commit is contained in:
Svetlana Isakova
2012-02-20 13:46:34 +04:00
parent 3d3b41da4f
commit 046c13a264
12 changed files with 47 additions and 13 deletions
@@ -842,6 +842,8 @@ public class JetTypeMapper {
knowTypes.put(standardLibrary.getNullableStringType(),JL_STRING_TYPE);
knowTypes.put(standardLibrary.getCharSequenceType(),JL_CHAR_SEQUENCE_TYPE);
knowTypes.put(standardLibrary.getNullableCharSequenceType(),JL_CHAR_SEQUENCE_TYPE);
knowTypes.put(standardLibrary.getThrowableType(), TYPE_THROWABLE);
knowTypes.put(standardLibrary.getNullableThrowableType(), TYPE_THROWABLE);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
@@ -204,10 +204,11 @@ public class JavaTypeTransformer {
classTypesMap.put("java.lang.Object", JetStandardClasses.getNullableAnyType());
classTypesMap.put("java.lang.String", standardLibrary.getNullableStringType());
classTypesMap.put("java.lang.CharSequence", standardLibrary.getNullableCharSequenceType());
classTypesMap.put("java.lang.Throwable", standardLibrary.getThrowableType());
}
return classTypesMap;
}
public Map<String, ClassDescriptor> getPrimitiveWrappersClassDescriptorMap() {
if (classDescriptorMap == null) {
classDescriptorMap = new HashMap<String, ClassDescriptor>();
@@ -217,6 +218,7 @@ public class JavaTypeTransformer {
}
classDescriptorMap.put("java.lang.String", standardLibrary.getString());
classDescriptorMap.put("java.lang.CharSequence", standardLibrary.getCharSequence());
classDescriptorMap.put("java.lang.Throwable", standardLibrary.getThrowable());
}
return classDescriptorMap;
}
+6
View File
@@ -59,3 +59,9 @@ class String() : Comparable<String>, CharSequence {
fun equals(other : Any?) : Boolean
}
class Throwable(message : String? = null, cause: Throwable? = null) {
fun getMessage() : String?
fun getCause() : Throwable?
fun printStackTrace() : Unit
}
@@ -72,14 +72,16 @@ public class JetStandardLibrary {
private ClassDescriptor iterableClass;
private ClassDescriptor comparableClass;
private ClassDescriptor volatileClass;
private ClassDescriptor throwableClass;
private JetType stringType;
private JetType volatileType;
private JetType nullableStringType;
private JetType charSequenceType;
private JetType nullableCharSequenceType;
private JetType nullableTuple0Type;
private JetType throwableType;
private JetType nullableThrowableType;
private JetType tuple0Type;
@@ -143,6 +145,7 @@ public class JetStandardLibrary {
this.charSequenceClass = (ClassDescriptor) libraryScope.getClassifier("CharSequence");
this.arrayClass = (ClassDescriptor) libraryScope.getClassifier("Array");
this.volatileClass = (ClassDescriptor) libraryScope.getClassifier("volatile");
this.throwableClass = (ClassDescriptor) libraryScope.getClassifier("Throwable");
this.iterableClass = (ClassDescriptor) libraryScope.getClassifier("Iterable");
this.comparableClass = (ClassDescriptor) libraryScope.getClassifier("Comparable");
@@ -153,6 +156,8 @@ public class JetStandardLibrary {
this.nullableCharSequenceType = TypeUtils.makeNullable(charSequenceType);
this.nullableStringType = TypeUtils.makeNullable(stringType);
this.volatileType = new JetTypeImpl(getVolatile());
this.throwableType = new JetTypeImpl(getThrowable());
this.nullableThrowableType = TypeUtils.makeNullable(throwableType);
this.tuple0Type = new JetTypeImpl(JetStandardClasses.getTuple(0));
this.nullableTuple0Type = TypeUtils.makeNullable(tuple0Type);
@@ -270,6 +275,12 @@ public class JetStandardLibrary {
return comparableClass;
}
@NotNull
public ClassDescriptor getThrowable() {
initStdClasses();
return throwableClass;
}
public Set<FunctionDescriptor> getTypeInfoFunctions() {
initStdClasses();
return typeInfoFunction;
@@ -393,6 +404,17 @@ public class JetStandardLibrary {
initStdClasses();
return nullableCharSequenceType;
}
@NotNull
public JetType getThrowableType() {
initStdClasses();
return throwableType;
}
public JetType getNullableThrowableType() {
initStdClasses();
return nullableThrowableType;
}
@NotNull
public JetType getNullablePrimitiveJetType(PrimitiveType primitiveType) {
@@ -400,6 +400,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
JetExpression catchBody = catchClause.getCatchBody();
if (catchParameter != null) {
VariableDescriptor variableDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), context.scope, catchParameter);
JetType throwableType = context.semanticServices.getStandardLibrary().getThrowable().getDefaultType();
DataFlowUtils.checkType(variableDescriptor.getOutType(), catchParameter, context.replaceExpectedType(throwableType));
if (catchBody != null) {
WritableScope catchScope = newWritableScopeImpl(context).setDebugName("Catch scope");
catchScope.addVariableDescriptor(variableDescriptor);
@@ -433,8 +435,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) {
JetExpression thrownExpression = expression.getThrownExpression();
if (thrownExpression != null) {
JetType type = facade.getType(thrownExpression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(context.scope));
// TODO : check that it inherits Throwable
JetType throwableType = context.semanticServices.getStandardLibrary().getThrowable().getDefaultType();
facade.getType(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope));
}
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
}
@@ -23,6 +23,6 @@ public object SomeClass {
public fun box():String {
if(SomeClass.bug is Throwable)
throw SomeClass.bug
throw SomeClass.bug as Throwable
return "OK"
}
@@ -162,7 +162,7 @@ fun illegalReturnIf(): Char {
}
fun returnNothing(): Nothing {
throw 1
throw <!ERROR_COMPILE_TIME_VALUE!>1<!>
}
fun f(): Int {
if (1 < 2) { return 1 } else returnNothing()
@@ -109,7 +109,7 @@ fun t7() : Int {
return 1
<!UNREACHABLE_CODE!>2<!>
}
catch (e : Any) {
catch (<!TYPE_MISMATCH!>e : Any<!>) {
<!UNUSED_EXPRESSION!>2<!>
}
return 1 // this is OK, like in Java
@@ -120,7 +120,7 @@ fun t8() : Int {
return 1
<!UNREACHABLE_CODE!>2<!>
}
catch (e : Any) {
catch (<!TYPE_MISMATCH!>e : Any<!>) {
return 1
<!UNREACHABLE_CODE!>2<!>
}
@@ -7,7 +7,7 @@ public class Throwables() {
public fun propagateIfInstanceOf<X : Throwable?>(throwable : Throwable?, declaredType : Class<X?>?) {
if (((throwable != null) && declaredType?.isInstance(throwable).sure()))
{
throw declaredType?.cast(throwable)
throw declaredType?.cast(throwable).sure()
}
}
public fun propagateIfPossible(throwable : Throwable?) {
@@ -157,7 +157,7 @@ fun illegalReturnIf(): Char {
}
fun returnNothing(): Nothing {
throw 1
throw <error>1</error>
}
fun f(): Int {
if (1 < 2) { return 1 } else returnNothing()
+2 -2
View File
@@ -107,7 +107,7 @@ fun t7() : Int {
return 1
<error>2</error>
}
catch (e : Any) {
catch (<error>e : Any</error>) {
<warning>2</warning>
}
return 1 // this is OK, like in Java
@@ -118,7 +118,7 @@ fun t8() : Int {
return 1
<error>2</error>
}
catch (e : Any) {
catch (<error>e : Any</error>) {
return 1
<error>2</error>
}
+1 -1
View File
@@ -135,7 +135,7 @@ fun <T: Exception> failsWith(block: ()-> Any) {
}
fun todo(block: ()-> Any) {
println("TODO at " + Exception().getStackTrace()?.get(1) + " for " + block)
println("TODO at " + (Exception() as java.lang.Throwable).getStackTrace()?.get(1) + " for " + block)
}
/*