Resolve compileTimeInitializer for variable in lazy resolve

This commit is contained in:
Natalia Ukhorskaya
2014-02-21 13:54:57 +04:00
parent 89d99d2848
commit 4a8bcc614a
13 changed files with 133 additions and 32 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.resolve.DescriptorFactory;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
@@ -196,7 +197,7 @@ public class DescriptorSerializer {
}
}
hasConstant = !propertyDescriptor.isVar() && propertyDescriptor.getCompileTimeInitializer() != null;
hasConstant = propertyDescriptor.getCompileTimeInitializer() != null;
}
builder.setFlags(Flags.getCallableFlags(
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCacheImpl;
import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
@@ -565,7 +566,10 @@ public class BodyResolver {
JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace);
CompileTimeConstant<?> compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer();
if (compileTimeInitializer == null) {
expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace);
}
}
@NotNull
@@ -959,7 +959,7 @@ public class DescriptorResolver {
@Override
public JetType invoke() {
JetType initializerType = resolveInitializerType(scope, initializer, dataFlowInfo, trace);
setConstantForVariableIfNeeded(variableDescriptor, initializer, initializerType, trace);
setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, initializerType, trace);
return transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace);
}
}
@@ -967,40 +967,45 @@ public class DescriptorResolver {
}
else {
JetType initializerType = resolveInitializerType(scope, initializer, dataFlowInfo, trace);
setConstantForVariableIfNeeded(variableDescriptor, initializer, initializerType, trace);
setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, initializerType, trace);
return initializerType;
}
}
}
else {
JetType type = typeResolver.resolveType(scope, propertyTypeRef, trace, true);
JetExpression initializer = variable.getInitializer();
if (initializer != null) {
setConstantForVariableIfNeeded(variableDescriptor, initializer, type, trace);
}
setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, type, trace);
return type;
}
}
private void setConstantForVariableIfNeeded(
@NotNull VariableDescriptorImpl variableDescriptor,
@NotNull final JetExpression initializer,
@NotNull final JetType initializerType,
@NotNull final JetScope scope,
@NotNull JetVariableDeclaration variable,
@NotNull final DataFlowInfo dataFlowInfo,
@NotNull final JetType variableType,
@NotNull final BindingTrace trace
) {
if (variableDescriptor.isVar()) return;
if (!shouldRecordInitializerForProperty(variableDescriptor, variableType)) return;
variableDescriptor.setCompileTimeInitializer(storageManager.createRecursionTolerantNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
@Nullable
@Override
public CompileTimeConstant<?> invoke() {
CompileTimeConstant<?> constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType);
if ((constant instanceof IntegerValueTypeConstant)) {
return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType);
final JetExpression initializer = variable.getInitializer();
if (initializer == null) return;
variableDescriptor.setCompileTimeInitializer(
storageManager.createRecursionTolerantNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
@Nullable
@Override
public CompileTimeConstant<?> invoke() {
JetType initializerType = expressionTypingServices.safeGetType(scope, initializer, variableType, dataFlowInfo, trace);
CompileTimeConstant<?> constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType);
if (constant instanceof IntegerValueTypeConstant) {
return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType);
}
return constant;
}
return constant;
}
}, null));
}, null)
);
}
@NotNull
@@ -0,0 +1,45 @@
package test
// val prop1: 1
val prop1: Int = 1
// val prop2: 1
val prop2: Int? = 1
// val prop3: 1
val prop3: Number? = 1
// val prop4: 1
val prop4: Any? = 1
// val prop5: 1
val prop5: Number = 1
// val prop6: 1
val prop6: Any = 1
// val prop7: \"a\"
val prop7: String = "a"
// val prop8: \"a\"
val prop8: String? = "a"
// val prop9: \"a\"
val prop9: Any? = "a"
// val prop10: \"a\"
val prop10: Any = "a"
// val prop11: null
val prop11: aaa = 1
// val prop14: null
val prop14: aaa? = 1
class A
// val prop15: null
val prop15: A = 1
// val prop16: 1
val prop16: A? = 1
@@ -1,34 +1,34 @@
package test
// val prop1: Division by zero
// val prop1: null
val prop1 = 1 / 0
// val prop2: Division by zero
// val prop2: null
val prop2 = 1 / 0.0
// val prop3: Division by zero
// val prop3: null
val prop3 = 1.0 / 0
// val prop4: 10.0.toDouble()
val prop4 = 1 / 0.1
// val prop5: Division by zero
// val prop5: null
val prop5 = 1 / 0.toLong()
// val prop6: Division by zero
// val prop6: null
val prop6 = 1.0 / 0.toInt()
// val prop7: Division by zero
// val prop7: null
val prop7 = 1.0 / 0.toLong()
// val prop8: Division by zero
// val prop8: null
val prop8 = 1.0 / 0.toByte()
// val prop9: Division by zero
// val prop9: null
val prop9 = 1.0 / 0.toShort()
// val prop10: Division by zero
// val prop10: null
val prop10 = 1.0 / 0.toFloat()
// val prop11: Division by zero
// val prop11: null
val prop11 = 1.0 / 0.toDouble()
@@ -0,0 +1,6 @@
package test;
public final class ClassWithConstVal {
public final int f = 1;
public final int f2 = f;
}
@@ -0,0 +1,6 @@
package test
public class ClassWithConstVal() : java.lang.Object() {
public val f: Int = 1
public val f2: Int = f
}
@@ -0,0 +1,7 @@
package test
public final class ClassWithConstVal : java.lang.Object {
public constructor ClassWithConstVal()
public final val f: kotlin.Int = 1
public final val f2: kotlin.Int = 1
}
@@ -48,6 +48,11 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT
doConstantTest("compiler/testData/evaluate/constant/compareTo.kt");
}
@TestMetadata("differentTypes.kt")
public void testDifferentTypes() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/differentTypes.kt");
}
@TestMetadata("divideByZero.kt")
public void testDivideByZero() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/divideByZero.kt");
@@ -546,6 +546,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassDoesNotOverrideMethod.java");
}
@TestMetadata("ClassWithConstVal.java")
public void testClassWithConstVal() throws Exception {
doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.java");
}
@TestMetadata("ClassWithTypeP.java")
public void testClassWithTypeP() throws Exception {
doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithTypeP.java");
@@ -1509,6 +1509,11 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassDoesNotOverrideMethod.kt");
}
@TestMetadata("ClassWithConstVal.kt")
public void testClassWithConstVal() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.kt");
}
@TestMetadata("ClassWithTypeP.kt")
public void testClassWithTypeP() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithTypeP.kt");
@@ -266,7 +266,7 @@ public abstract class LazyJavaMemberScope(
propertyDescriptor.setType(effectiveSignature.getReturnType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()), null : JetType?)
if (!propertyDescriptor.isVar()) {
if (DescriptorUtils.shouldRecordInitializerForProperty(propertyDescriptor, propertyDescriptor.getType())) {
propertyDescriptor.setCompileTimeInitializer(
c.storageManager.createNullableLazyValue {
JavaPropertyInitializerEvaluator.getInstance().getInitializerConstant(field, propertyDescriptor)
@@ -495,4 +495,16 @@ public class DescriptorUtils {
}
return false;
}
public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) {
if (variable.isVar() || type.isError()) return false;
if (type instanceof LazyType || type.isNullable()) return true;
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
return builtIns.isPrimitiveType(type) ||
builtIns.getStringType().equals(type) ||
builtIns.getNumber().getDefaultType().equals(type) ||
builtIns.getAnyType().equals(type);
}
}