Record compile time constants to trace
This commit is contained in:
+58
-61
@@ -42,39 +42,61 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.COMPILE_TIME_INITIAL
|
|||||||
|
|
||||||
@SuppressWarnings("StaticMethodReferencedViaSubclass")
|
@SuppressWarnings("StaticMethodReferencedViaSubclass")
|
||||||
public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<?>, Void> {
|
public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<?>, Void> {
|
||||||
@NotNull private final BindingTrace trace;
|
private final BindingTrace trace;
|
||||||
@NotNull private final JetType expectedType;
|
private final JetType expectedType;
|
||||||
|
|
||||||
public ConstantExpressionEvaluator(@NotNull BindingTrace trace, @NotNull JetType expectedType) {
|
private ConstantExpressionEvaluator(@NotNull BindingTrace trace, @NotNull JetType expectedType) {
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.expectedType = expectedType;
|
this.expectedType = expectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static CompileTimeConstant<?> evaluate(@NotNull JetExpression expression, @NotNull BindingTrace trace, @NotNull JetType expectedType) {
|
||||||
|
ConstantExpressionEvaluator evaluator = new ConstantExpressionEvaluator(trace, expectedType);
|
||||||
|
return evaluator.evaluate(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public CompileTimeConstant<?> evaluate(@NotNull JetExpression expression) {
|
||||||
|
CompileTimeConstant<?> recordedCompileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||||
|
if (recordedCompileTimeConstant != null) {
|
||||||
|
return recordedCompileTimeConstant;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompileTimeConstant<?> compileTimeConstant = expression.accept(this, null);
|
||||||
|
|
||||||
|
if (compileTimeConstant != null) {
|
||||||
|
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant);
|
||||||
|
return compileTimeConstant;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitConstantExpression(@NotNull JetConstantExpression expression, Void nothing) {
|
public CompileTimeConstant<?> visitConstantExpression(@NotNull JetConstantExpression expression, Void data) {
|
||||||
return trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
return trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void nothing) {
|
public CompileTimeConstant<?> visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void data) {
|
||||||
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression, nothing);
|
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression);
|
||||||
if (deparenthesizedExpression != null) {
|
if (deparenthesizedExpression != null) {
|
||||||
return deparenthesizedExpression.accept(this, nothing);
|
return evaluate(deparenthesizedExpression);
|
||||||
}
|
}
|
||||||
return super.visitParenthesizedExpression(expression, nothing);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) {
|
public CompileTimeConstant<?> visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) {
|
||||||
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression, data);
|
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression);
|
||||||
if (deparenthesizedExpression != null) {
|
if (deparenthesizedExpression != null) {
|
||||||
return deparenthesizedExpression.accept(this, data);
|
return evaluate(deparenthesizedExpression);
|
||||||
}
|
}
|
||||||
return super.visitPrefixExpression(expression, data);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetExpression getDeparenthesizedExpression(JetExpression expression, Void data) {
|
private static JetExpression getDeparenthesizedExpression(JetExpression expression) {
|
||||||
JetExpression deparenthesizedExpr = JetPsiUtil.deparenthesize(expression);
|
JetExpression deparenthesizedExpr = JetPsiUtil.deparenthesize(expression);
|
||||||
if (deparenthesizedExpr == expression) {
|
if (deparenthesizedExpr == expression) {
|
||||||
return null;
|
return null;
|
||||||
@@ -83,29 +105,26 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void nothing) {
|
public CompileTimeConstant<?> visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void data) {
|
||||||
CompileTimeConstant<?> compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
|
||||||
if (compileTimeConstant != null) {
|
|
||||||
return compileTimeConstant;
|
|
||||||
}
|
|
||||||
|
|
||||||
JetStringTemplateEntry[] stringTemplateEntries = expression.getEntries();
|
JetStringTemplateEntry[] stringTemplateEntries = expression.getEntries();
|
||||||
if (stringTemplateEntries.length == 1) {
|
if (stringTemplateEntries.length == 1) {
|
||||||
CompileTimeConstant singleEntry = stringTemplateEntries[0].accept(this, nothing);
|
CompileTimeConstant singleEntry = stringTemplateEntries[0].accept(this, null);
|
||||||
if (!(singleEntry instanceof StringValue) && singleEntry != null) {
|
if (!(singleEntry instanceof StringValue) && singleEntry != null) {
|
||||||
return new StringValue(singleEntry.getValue().toString());
|
return new StringValue(singleEntry.getValue().toString());
|
||||||
}
|
}
|
||||||
return singleEntry;
|
else {
|
||||||
|
return singleEntry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (stringTemplateEntries.length > 1) {
|
else if (stringTemplateEntries.length > 1) {
|
||||||
CompileTimeConstant<?> first = stringTemplateEntries[0].accept(this, nothing);
|
CompileTimeConstant<?> first = stringTemplateEntries[0].accept(this, null);
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
CompileTimeConstant<?> second;
|
CompileTimeConstant<?> second;
|
||||||
String tmpResult = null;
|
String tmpResult = null;
|
||||||
for (int i = 1; i < stringTemplateEntries.length; i++) {
|
for (int i = 1; i < stringTemplateEntries.length; i++) {
|
||||||
second = stringTemplateEntries[i].accept(this, nothing);
|
second = stringTemplateEntries[i].accept(this, null);
|
||||||
if (second == null) {
|
if (second == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -125,12 +144,12 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitBlockStringTemplateEntry(@NotNull JetBlockStringTemplateEntry entry, Void data) {
|
public CompileTimeConstant<?> visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry, Void data) {
|
||||||
JetExpression expression = entry.getExpression();
|
JetExpression expression = entry.getExpression();
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
return expression.accept(this, data);
|
return evaluate(expression);
|
||||||
}
|
}
|
||||||
return super.visitBlockStringTemplateEntry(entry, data);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -138,15 +157,6 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
return new StringValue(entry.getText());
|
return new StringValue(entry.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompileTimeConstant<?> visitSimpleNameStringTemplateEntry(@NotNull JetSimpleNameStringTemplateEntry entry, Void data) {
|
|
||||||
JetExpression expression = entry.getExpression();
|
|
||||||
if (expression != null) {
|
|
||||||
return expression.accept(this, data);
|
|
||||||
}
|
|
||||||
return super.visitSimpleNameStringTemplateEntry(entry, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry, Void data) {
|
public CompileTimeConstant<?> visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry, Void data) {
|
||||||
return new StringValue(entry.getUnescapedValue());
|
return new StringValue(entry.getUnescapedValue());
|
||||||
@@ -162,7 +172,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
IElementType operationToken = expression.getOperationToken();
|
IElementType operationToken = expression.getOperationToken();
|
||||||
if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) {
|
if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) {
|
||||||
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
||||||
CompileTimeConstant<?> leftConstant = leftExpression.accept(new ConstantExpressionEvaluator(trace, booleanType), null);
|
CompileTimeConstant<?> leftConstant = evaluate(leftExpression, trace, booleanType);
|
||||||
if (leftConstant == null) {
|
if (leftConstant == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -170,23 +180,17 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
if (rightExpression == null) {
|
if (rightExpression == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
CompileTimeConstant<?> rightConstant = rightExpression.accept(new ConstantExpressionEvaluator(trace, booleanType), null);
|
CompileTimeConstant<?> rightConstant = evaluate(rightExpression, trace, booleanType);
|
||||||
if (rightConstant == null) {
|
if (rightConstant == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Name operationName = operationToken == JetTokens.ANDAND ? Name.identifier("andand") : Name.identifier("oror");
|
Name operationName = operationToken == JetTokens.ANDAND ? Name.identifier("andand") : Name.identifier("oror");
|
||||||
Object result = EvaluatePackage.evaluateBinaryExpression(leftConstant, rightConstant, operationName);
|
Object result = EvaluatePackage.evaluateBinaryExpression(leftConstant, rightConstant, operationName);
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createCompileTimeConstant(result, expectedType);
|
return createCompileTimeConstant(result, expectedType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object result = evaluateCall(expression.getOperationReference(), leftExpression);
|
Object result = evaluateCall(expression.getOperationReference(), leftExpression);
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken)) {
|
if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken)) {
|
||||||
return createCompileTimeConstantForCompareTo(result, operationToken);
|
return createCompileTimeConstantForCompareTo(result, operationToken);
|
||||||
}
|
}
|
||||||
@@ -231,7 +235,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CompileTimeConstant<?> createCompileTimeConstantForEquals(
|
private static CompileTimeConstant<?> createCompileTimeConstantForEquals(
|
||||||
@NotNull Object result,
|
@Nullable Object result,
|
||||||
@NotNull IElementType operationToken
|
@NotNull IElementType operationToken
|
||||||
) {
|
) {
|
||||||
if (result instanceof Boolean) {
|
if (result instanceof Boolean) {
|
||||||
@@ -248,7 +252,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CompileTimeConstant<?> createCompileTimeConstantForCompareTo(
|
private static CompileTimeConstant<?> createCompileTimeConstantForCompareTo(
|
||||||
@NotNull Object result,
|
@Nullable Object result,
|
||||||
@NotNull IElementType operationToken
|
@NotNull IElementType operationToken
|
||||||
) {
|
) {
|
||||||
if (result instanceof Integer) {
|
if (result instanceof Integer) {
|
||||||
@@ -292,14 +296,15 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Object result = evaluateCall(expression.getOperationReference(), leftExpression);
|
Object result = evaluateCall(expression.getOperationReference(), leftExpression);
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createCompileTimeConstant(result, expectedType);
|
return createCompileTimeConstant(result, expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompileTimeConstant<?> createCompileTimeConstant(@NotNull Object value, @NotNull JetType expectedType) {
|
@Nullable
|
||||||
if (value instanceof Integer) {
|
public static CompileTimeConstant<?> createCompileTimeConstant(@Nullable Object value, @NotNull JetType expectedType) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (value instanceof Integer) {
|
||||||
return getIntegerValue(((Integer) value).longValue(), expectedType);
|
return getIntegerValue(((Integer) value).longValue(), expectedType);
|
||||||
}
|
}
|
||||||
else if (value instanceof Byte) {
|
else if (value instanceof Byte) {
|
||||||
@@ -399,11 +404,6 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
/* 1.toInt(); 1.plus(1); MyEnum.A */
|
/* 1.toInt(); 1.plus(1); MyEnum.A */
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
|
public CompileTimeConstant<?> visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
|
||||||
CompileTimeConstant wholeExpressionValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression);
|
|
||||||
if (wholeExpressionValue != null) {
|
|
||||||
return wholeExpressionValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||||
|
|
||||||
@@ -416,17 +416,14 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
|
|
||||||
if (((JetCallExpression) selectorExpression).getValueArguments().size() < 2) {
|
if (((JetCallExpression) selectorExpression).getValueArguments().size() < 2) {
|
||||||
Object result = evaluateCall(calleeExpression, receiverExpression);
|
Object result = evaluateCall(calleeExpression, receiverExpression);
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createCompileTimeConstant(result, expectedType);
|
return createCompileTimeConstant(result, expectedType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectorExpression != null) {
|
if (selectorExpression != null) {
|
||||||
return selectorExpression.accept(this, null);
|
return evaluate(selectorExpression);
|
||||||
}
|
}
|
||||||
return super.visitQualifiedExpression(expression, data);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -483,7 +480,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
for (ValueArgument argument : valueArguments) {
|
for (ValueArgument argument : valueArguments) {
|
||||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||||
if (argumentExpression != null) {
|
if (argumentExpression != null) {
|
||||||
CompileTimeConstant<?> constant = argumentExpression.accept(new ConstantExpressionEvaluator(trace, expectedType), null);
|
CompileTimeConstant<?> constant = evaluate(argumentExpression, trace, expectedType);
|
||||||
if (constant != null) {
|
if (constant != null) {
|
||||||
constants.add(constant);
|
constants.add(constant);
|
||||||
}
|
}
|
||||||
@@ -493,7 +490,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompileTimeConstant<?> visitJetElement(@NotNull JetElement element, Void nothing) {
|
public CompileTimeConstant<?> visitJetElement(@NotNull JetElement element, Void data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ public class AnnotationResolver {
|
|||||||
@NotNull JetType expectedType,
|
@NotNull JetType expectedType,
|
||||||
@NotNull BindingTrace trace
|
@NotNull BindingTrace trace
|
||||||
) {
|
) {
|
||||||
return expression.accept(new ConstantExpressionEvaluator(trace, expectedType), null);
|
return ConstantExpressionEvaluator.evaluate(expression, trace, expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user