Write constant initializer for java properties
This commit is contained in:
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPropertyInitializerEvaluatorImpl
|
||||
-14
@@ -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
|
||||
|
||||
+7
@@ -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<PsiField> implements JavaField
|
||||
public JavaType getType() {
|
||||
return JavaTypeImpl.create(getPsi().getType());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiExpression getInitializer() {
|
||||
return getPsi().getInitializer();
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -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;
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
@@ -13,5 +13,5 @@ public trait StringConstantInParam : java.lang.Object {
|
||||
}
|
||||
|
||||
package test.StringConstantInParam {
|
||||
public val HEL: kotlin.String
|
||||
public val HEL: kotlin.String = "hel"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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?
|
||||
}
|
||||
|
||||
+1
-1
@@ -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())
|
||||
|
||||
+5
@@ -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
|
||||
|
||||
+43
@@ -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<JavaPropertyInitializerEvaluator> 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);
|
||||
}
|
||||
+3
-1
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user