diff --git a/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.java.structure.JavaPropertyInitializerEvaluator b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.java.structure.JavaPropertyInitializerEvaluator new file mode 100644 index 00000000000..23de29d21b1 --- /dev/null +++ b/compiler/frontend.java/src/META-INF/services/org.jetbrains.jet.lang.resolve.java.structure.JavaPropertyInitializerEvaluator @@ -0,0 +1 @@ +org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPropertyInitializerEvaluatorImpl diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/TraceBasedJavaResolverCache.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/TraceBasedJavaResolverCache.java index 597531ce658..95cab5f8d51 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/TraceBasedJavaResolverCache.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/TraceBasedJavaResolverCache.java @@ -77,20 +77,6 @@ public class TraceBasedJavaResolverCache implements JavaResolverCache { public void recordField(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor) { PsiField psiField = ((JavaFieldImpl) field).getPsi(); trace.record(VARIABLE, psiField, descriptor); - - if (!descriptor.isVar()) { - PsiExpression initializer = psiField.getInitializer(); - Object evaluatedExpression = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false); - if (evaluatedExpression != null) { - CompileTimeConstant constant = - ResolverPackage.resolveCompileTimeConstantValue(evaluatedExpression, - CompileTimeConstantUtils.isPropertyCompileTimeConstant(descriptor), - descriptor.getType()); - if (constant != null) { - trace.record(COMPILE_TIME_INITIALIZER, descriptor, constant); - } - } - } } @Override diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaFieldImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaFieldImpl.java index b67a9730748..638377931a3 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaFieldImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaFieldImpl.java @@ -17,8 +17,10 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; import com.intellij.psi.PsiEnumConstant; +import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiField; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.structure.JavaField; import org.jetbrains.jet.lang.resolve.java.structure.JavaType; @@ -37,4 +39,9 @@ public class JavaFieldImpl extends JavaMemberImpl implements JavaField public JavaType getType() { return JavaTypeImpl.create(getPsi().getType()); } + + @Nullable + public PsiExpression getInitializer() { + return getPsi().getInitializer(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java new file mode 100644 index 00000000000..971b1072ad7 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java.structure.impl; + +import com.intellij.psi.PsiExpression; +import com.intellij.psi.impl.JavaConstantExpressionEvaluator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.ConstantUtils; +import org.jetbrains.jet.lang.resolve.java.structure.JavaField; +import org.jetbrains.jet.lang.resolve.java.structure.JavaPropertyInitializerEvaluator; + +public class JavaPropertyInitializerEvaluatorImpl extends JavaPropertyInitializerEvaluator { + @Nullable + @Override + public CompileTimeConstant getInitializerConstant(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor) { + PsiExpression initializer = ((JavaFieldImpl) field).getInitializer(); + Object evaluatedExpression = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false); + if (evaluatedExpression != null) { + return ConstantUtils.createCompileTimeConstant( + evaluatedExpression, + DescriptorUtils.isPropertyCompileTimeConstant(descriptor), + false, + descriptor.getType()); + } + return null; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index 12c6f423d10..752f2b28bc8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -82,17 +82,20 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet override fun visitConstantExpression(expression: JetConstantExpression, expectedType: JetType?): CompileTimeConstant<*>? { val text = expression.getText() if (text == null) return null - val result: Any? = when (expression.getNode().getElementType()) { + + val nodeElementType = expression.getNode().getElementType() + if (nodeElementType == JetNodeTypes.NULL) return NullValue.NULL + + val result: Any? = when (nodeElementType) { JetNodeTypes.INTEGER_CONSTANT -> parseLong(text) JetNodeTypes.FLOAT_CONSTANT -> parseFloatingLiteral(text) JetNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text) JetNodeTypes.CHARACTER_CONSTANT -> CompileTimeConstantChecker.parseChar(expression) - JetNodeTypes.NULL -> null else -> throw IllegalArgumentException("Unsupported constant: " + expression) } - if (result == null && expression.getNode().getElementType() == JetNodeTypes.NULL) return NullValue.NULL + if (result == null) return null - fun isLongWithSuffix() = expression.getNode().getElementType() == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) + fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) return createCompileTimeConstant(result, expectedType, !isLongWithSuffix()) } @@ -181,6 +184,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentsEntrySet = resolvedCall.getValueArguments().entrySet() if (argumentsEntrySet.isEmpty()) { val result = evaluateUnaryAndCheck(argumentForReceiver, resultingDescriptorName.asString(), callExpression) + if (result == null) return null val isArgumentPure = isPureConstant(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS @@ -197,6 +201,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } val result = evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression) + if (result == null) return null val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) @@ -303,7 +308,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet else compileTimeConstant.getValue() return createCompileTimeConstant(value, expectedType, isPure = false, - canBeUsedInAnnotation = CompileTimeConstantUtils.isPropertyCompileTimeConstant(callableDescriptor)) + canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor)) } } return null diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java index c350ba80023..fa0732638ae 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java @@ -120,17 +120,6 @@ public class CompileTimeConstantUtils { return "kotlin.javaClass.function".equals(getIntrinsicAnnotationArgument(resolvedCall.getResultingDescriptor().getOriginal())); } - public static boolean isPropertyCompileTimeConstant(@NotNull VariableDescriptor descriptor) { - if (descriptor.isVar()) { - return false; - } - if (isClassObject(descriptor.getContainingDeclaration()) || isTopLevelDeclaration(descriptor)) { - JetType type = descriptor.getType(); - return KotlinBuiltIns.getInstance().isPrimitiveType(type) || KotlinBuiltIns.getInstance().getStringType().equals(type); - } - return false; - } - public static boolean isJavaLangClass(ClassDescriptor descriptor) { return "java.lang.Class".equals(DescriptorUtils.getFqName(descriptor).asString()); } diff --git a/compiler/testData/lazyResolve/recursiveComparator/propertyClassFileDependencyRecursion.txt b/compiler/testData/lazyResolve/recursiveComparator/propertyClassFileDependencyRecursion.txt index 89c38cc124f..b358cbd7d18 100644 --- a/compiler/testData/lazyResolve/recursiveComparator/propertyClassFileDependencyRecursion.txt +++ b/compiler/testData/lazyResolve/recursiveComparator/propertyClassFileDependencyRecursion.txt @@ -1,6 +1,6 @@ package test -internal val checkTypeProp: test.PropType? +internal val checkTypeProp: test.PropType? = null internal final class PropType { /*primary*/ public constructor PropType() diff --git a/compiler/testData/loadJava/compiledJava/annotations/StringConstantInParam.txt b/compiler/testData/loadJava/compiledJava/annotations/StringConstantInParam.txt index 14824505cc8..796bb214515 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/StringConstantInParam.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/StringConstantInParam.txt @@ -13,5 +13,5 @@ public trait StringConstantInParam : java.lang.Object { } package test.StringConstantInParam { - public val HEL: kotlin.String + public val HEL: kotlin.String = "hel" } diff --git a/compiler/testData/loadJava/compiledJava/static/StaticFinal.txt b/compiler/testData/loadJava/compiledJava/static/StaticFinal.txt index 300b7404b48..5e30b50072f 100644 --- a/compiler/testData/loadJava/compiledJava/static/StaticFinal.txt +++ b/compiler/testData/loadJava/compiledJava/static/StaticFinal.txt @@ -5,5 +5,5 @@ public open class StaticFinal : java.lang.Object { } package test.StaticFinal { - public val foo: kotlin.String + public val foo: kotlin.String = "aaa" } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.txt index 6201759a2b1..b672df9e2ae 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/FinalFieldAsVal.txt @@ -2,5 +2,5 @@ package test public final class FinalFieldAsVal : java.lang.Object { public constructor FinalFieldAsVal() - public final val f: kotlin.Int + public final val f: kotlin.Int = 1.toInt() } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.kt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.kt index 95219dd537b..da04e75957f 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.kt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.kt @@ -4,5 +4,5 @@ import java.util.* public open class WrongFieldMutability : Object() { public var fooNotFinal : String? = "" - public val fooFinal : String? = "" + public val fooFinal : String? = "Test" } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.txt index 94c18385028..77b81eaefeb 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongFieldMutability.txt @@ -2,6 +2,6 @@ package test public open class WrongFieldMutability : java.lang.Object { public constructor WrongFieldMutability() - public final val fooFinal: kotlin.String? + public final val fooFinal: kotlin.String? = "Test" public final var fooNotFinal: kotlin.String? } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt index fefad77af62..4beba306054 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt @@ -109,7 +109,7 @@ class LazyJavaAnnotationDescriptor( private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): CompileTimeConstant<*>? { return when (argument) { - is JavaLiteralAnnotationArgument -> resolveCompileTimeConstantValue(argument.getValue(), true, null) + is JavaLiteralAnnotationArgument -> ConstantUtils.createCompileTimeConstant(argument.getValue(), true, false, null) is JavaReferenceAnnotationArgument -> resolveFromReference(argument.resolve()) is JavaArrayAnnotationArgument -> resolveFromArray(argument.getName() ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements()) is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation()) diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt index 9d15e352636..3791a8fcc53 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.ExternalSignatureResolver import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils import org.jetbrains.jet.utils.Printer import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPackageFragmentDescriptor +import org.jetbrains.jet.lang.resolve.java.structure.JavaPropertyInitializerEvaluator public abstract class LazyJavaMemberScope( protected val c: LazyJavaResolverContextWithTypes, @@ -265,6 +266,10 @@ public abstract class LazyJavaMemberScope( propertyDescriptor.setType(effectiveSignature.getReturnType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()), null : JetType?) + if (!propertyDescriptor.isVar()) { + propertyDescriptor.setCompileTimeInitializer(JavaPropertyInitializerEvaluator.getInstance().getInitializerConstant(field, propertyDescriptor)) + } + c.javaResolverCache.recordField(field, propertyDescriptor); return propertyDescriptor diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaPropertyInitializerEvaluator.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaPropertyInitializerEvaluator.java new file mode 100644 index 00000000000..66e7c75f59b --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaPropertyInitializerEvaluator.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java.structure; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; + +import java.util.Iterator; +import java.util.ServiceLoader; + +public abstract class JavaPropertyInitializerEvaluator { + private static JavaPropertyInitializerEvaluator instance; + + @NotNull + public static JavaPropertyInitializerEvaluator getInstance() { + if (instance == null) { + Iterator iterator = + ServiceLoader.load(JavaPropertyInitializerEvaluator.class, JavaPropertyInitializerEvaluator.class.getClassLoader()).iterator(); + assert iterator.hasNext() : "No service found: " + JavaPropertyInitializerEvaluator.class.getName(); + instance = iterator.next(); + } + return instance; + } + + @Nullable + public abstract CompileTimeConstant getInitializerConstant(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor); +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index 36a6d6b7cc0..4ee26553789 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl; import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationsImpl; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.ConstantUtils; import org.jetbrains.jet.lang.resolve.constants.EnumValue; import org.jetbrains.jet.lang.resolve.constants.ErrorValue; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; @@ -38,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.ResolverPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.lang.types.ErrorUtils; +import org.jetbrains.jet.lang.types.JetType; import javax.inject.Inject; import java.io.IOException; @@ -134,7 +136,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer @Override public void visit(@Nullable Name name, @Nullable Object value) { if (name != null) { - CompileTimeConstant argument = ResolverPackage.resolveCompileTimeConstantValue(value, true, null); + CompileTimeConstant argument = ConstantUtils.createCompileTimeConstant(value, true, false, null); setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name)); } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index e85426346b8..d6a748e2299 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -484,4 +484,15 @@ public class DescriptorUtils { } return descriptor; } + + public static boolean isPropertyCompileTimeConstant(@NotNull VariableDescriptor descriptor) { + if (descriptor.isVar()) { + return false; + } + if (isClassObject(descriptor.getContainingDeclaration()) || isTopLevelDeclaration(descriptor)) { + JetType type = descriptor.getType(); + return KotlinBuiltIns.getInstance().isPrimitiveType(type) || KotlinBuiltIns.getInstance().getStringType().equals(type); + } + return false; + } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java index c675fd9215f..2cb22a1699f 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java @@ -119,6 +119,9 @@ public class ConstantUtils { else if (value instanceof String) { return new StringValue((String) value, canBeUsedInAnnotations); } + else if (value == null) { + return NullValue.NULL; + } return null; }