added different errors instead of ERROR_COMPILE_TIME_VALUE with different text

check type for constants in DataFlowUtils
This commit is contained in:
Svetlana Isakova
2013-09-12 17:25:59 +04:00
parent d556ceedc1
commit 96db2ecabd
30 changed files with 258 additions and 158 deletions
@@ -462,7 +462,8 @@ public class JetControlFlowProcessor {
}
boolean conditionIsTrueConstant = false;
if (condition instanceof JetConstantExpression && condition.getNode().getElementType() == JetNodeTypes.BOOLEAN_CONSTANT) {
if (BooleanValue.TRUE == new CompileTimeConstantResolver().getBooleanValue(condition.getText(), KotlinBuiltIns.getInstance().getBooleanType())) {
if (BooleanValue.TRUE == new CompileTimeConstantResolver().getBooleanValue(
(JetConstantExpression) condition, KotlinBuiltIns.getInstance().getBooleanType())) {
conditionIsTrueConstant = true;
}
}
@@ -462,7 +462,14 @@ public interface Errors {
// Compile-time values
DiagnosticFactory1<PsiElement, String> ERROR_COMPILE_TIME_VALUE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetConstantExpression> INT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetConstantExpression> FLOAT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory2<JetConstantExpression, String, JetType> CONSTANT_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<JetConstantExpression> INCORRECT_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetConstantExpression> EMPTY_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetConstantExpression, JetConstantExpression> TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetElement, JetElement> ILLEGAL_ESCAPE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetConstantExpression, JetType> NULL_FOR_NONNULL_TYPE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetEscapeStringTemplateEntry> ILLEGAL_ESCAPE_SEQUENCE = DiagnosticFactory0.create(ERROR);
// Casts and is-checks
@@ -292,7 +292,15 @@ public class DefaultErrorMessages {
MAP.put(CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS, "Class object upper bounds of {0} have empty intersection", NAME);
MAP.put(TOO_MANY_ARGUMENTS, "Too many arguments for {0}", DescriptorRenderer.TEXT);
MAP.put(ERROR_COMPILE_TIME_VALUE, "{0}", TO_STRING);
MAP.put(CONSTANT_EXPECTED_TYPE_MISMATCH, "An {0} literal does not conform to the expected type {1}", TO_STRING, RENDER_TYPE);
MAP.put(INT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(FLOAT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(INCORRECT_CHARACTER_LITERAL, "Incorrect character literal");
MAP.put(EMPTY_CHARACTER_LITERAL, "Empty character literal");
MAP.put(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL, "Too many characters in a character literal ''{0}''", ELEMENT_TEXT);
MAP.put(ILLEGAL_ESCAPE, "Illegal escape: ''{0}''", ELEMENT_TEXT);
MAP.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type {0}", RENDER_TYPE);
MAP.put(ELSE_MISPLACED_IN_WHEN, "'else' entry must be the last one in a when-expression");
@@ -42,7 +42,6 @@ import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
import org.jetbrains.jet.lang.resolve.constants.ErrorValue;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
@@ -441,14 +440,6 @@ public class CandidateResolver {
JetExpression expression = argument.getArgumentExpression();
if (expression == null) return;
if (expression instanceof JetConstantExpression && !KotlinBuiltIns.getInstance().isUnit(context.expectedType)) {
CompileTimeConstant<?> value =
new CompileTimeConstantResolver().getCompileTimeConstant((JetConstantExpression) expression, context.expectedType);
if (value instanceof ErrorValue) {
context.trace.report(ERROR_COMPILE_TIME_VALUE.on(expression, ((ErrorValue) value).getMessage()));
}
return;
}
DataFlowInfo dataFlowInfoForValueArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(argument);
ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(dataFlowInfoForValueArgument);
DataFlowUtils.checkType(type, expression, newContext);
@@ -17,11 +17,15 @@
package org.jetbrains.jet.lang.resolve.constants;
import com.google.common.base.Function;
import com.google.common.collect.Sets;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetConstantExpression;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
@@ -29,40 +33,58 @@ import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.constants.ErrorValue.ErrorValueWithDiagnostic;
public class CompileTimeConstantResolver {
public static final ErrorValue OUT_OF_RANGE = new ErrorValue("The value is out of range");
private final KotlinBuiltIns builtIns;
public CompileTimeConstantResolver() {
this.builtIns = KotlinBuiltIns.getInstance();
}
@Nullable
public Diagnostic checkConstantExpressionType(
@NotNull JetConstantExpression expression,
@NotNull JetType expectedType
) {
CompileTimeConstant<?> compileTimeConstant = getCompileTimeConstant(expression, expectedType);
Set<AbstractDiagnosticFactory> errorsThatDependOnExpectedType =
Sets.<AbstractDiagnosticFactory>newHashSet(CONSTANT_EXPECTED_TYPE_MISMATCH, NULL_FOR_NONNULL_TYPE);
if (compileTimeConstant instanceof ErrorValueWithDiagnostic) {
Diagnostic diagnostic = ((ErrorValueWithDiagnostic) compileTimeConstant).getDiagnostic();
if (errorsThatDependOnExpectedType.contains(diagnostic.getFactory())) {
return diagnostic;
}
}
return null;
}
@NotNull
public CompileTimeConstant<?> getCompileTimeConstant(
@NotNull JetConstantExpression expression,
@NotNull JetType expectedType
) {
IElementType elementType = expression.getNode().getElementType();
String text = expression.getNode().getText();
CompileTimeConstant<?> value;
if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
value = getIntegerValue(text, expectedType);
value = getIntegerValue(expression, expectedType);
}
else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
value = getFloatValue(text, expectedType);
value = getFloatValue(expression, expectedType);
}
else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
value = getBooleanValue(text, expectedType);
value = getBooleanValue(expression, expectedType);
}
else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
value = getCharValue(text, expectedType);
value = getCharValue(expression, expectedType);
}
else if (elementType == JetNodeTypes.NULL) {
value = getNullValue(expectedType);
value = getNullValue(expression, expectedType);
}
else {
throw new IllegalArgumentException("Unsupported constant: " + expression);
@@ -70,16 +92,22 @@ public class CompileTimeConstantResolver {
return value;
}
@NotNull
public CompileTimeConstant<?> getIntegerValue(@NotNull String text, @NotNull JetType expectedType) {
return getIntegerValue(parseLongValue(text), expectedType);
public CompileTimeConstant<?> getIntegerValue(
@NotNull JetConstantExpression expression, @NotNull JetType expectedType
) {
String text = expression.getText();
return getIntegerValue(parseLongValue(text), expectedType, expression);
}
@NotNull
public CompileTimeConstant<?> getIntegerValue(@Nullable Long value, @NotNull JetType expectedType) {
public CompileTimeConstant<?> getIntegerValue(
@Nullable Long value,
@NotNull JetType expectedType,
@NotNull JetConstantExpression expression
) {
if (value == null) {
return OUT_OF_RANGE;
return ErrorValue.create(INT_LITERAL_OUT_OF_RANGE.on(expression));
}
if (noExpectedTypeOrUnitOrError(expectedType)) {
if (Integer.MIN_VALUE <= value && value <= Integer.MAX_VALUE) {
@@ -116,20 +144,20 @@ public class CompileTimeConstantResolver {
JetType intType = builtIns.getIntType();
JetType longType = builtIns.getLongType();
if (typeChecker.isSubtypeOf(intType, expectedType)) {
return getIntegerValue(value, intType);
return getIntegerValue(value, intType, expression);
}
else if (typeChecker.isSubtypeOf(longType, expectedType)) {
return getIntegerValue(value, longType);
return getIntegerValue(value, longType, expression);
}
else {
return new ErrorValue("An integer literal does not conform to the expected type " + expectedType);
return ErrorValue.create(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType));
}
}
if (value != null && lowerBound <= value && value <= upperBound) {
return create.apply(value);
}
return new ErrorValue("An integer literal does not conform to the expected type " + expectedType);
return ErrorValue.create(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType));
}
@Nullable
@@ -165,41 +193,48 @@ public class CompileTimeConstantResolver {
}
@NotNull
public CompileTimeConstant<?> getFloatValue(@NotNull String text, @NotNull JetType expectedType) {
if (noExpectedTypeOrUnitOrError(expectedType)
|| JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getDoubleType(), expectedType)) {
try {
public CompileTimeConstant<?> getFloatValue(
@NotNull JetConstantExpression expression, @NotNull JetType expectedType
) {
String text = expression.getText();
try {
if (noExpectedTypeOrUnitOrError(expectedType)
|| JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getDoubleType(), expectedType)) {
return new DoubleValue(Double.parseDouble(text));
}
catch (NumberFormatException e) {
return OUT_OF_RANGE;
}
}
else if (JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getFloatType(), expectedType)) {
try {
else if (JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getFloatType(), expectedType)) {
return new FloatValue(Float.parseFloat(text));
}
catch (NumberFormatException e) {
return OUT_OF_RANGE;
else {
return ErrorValue.create(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "floating-point", expectedType));
}
}
else {
return new ErrorValue("A floating-point literal does not conform to the expected type " + expectedType);
catch (NumberFormatException e) {
return ErrorValue.create(FLOAT_LITERAL_OUT_OF_RANGE.on(expression));
}
}
@Nullable
private CompileTimeConstant<?> checkNativeType(String text, JetType expectedType, String title, JetType nativeType) {
private CompileTimeConstant<?> checkNativeType(
JetType expectedType,
String title,
JetType nativeType,
JetConstantExpression expression
) {
if (!noExpectedTypeOrUnitOrError(expectedType)
&& !JetTypeChecker.INSTANCE.isSubtypeOf(nativeType, expectedType)) {
return new ErrorValue("A " + title + " literal " + text + " does not conform to the expected type " + expectedType);
return ErrorValue.create(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, title, expectedType));
}
return null;
}
@NotNull
public CompileTimeConstant<?> getBooleanValue(@NotNull String text, @NotNull JetType expectedType) {
CompileTimeConstant<?> error = checkNativeType(text, expectedType, "boolean", builtIns.getBooleanType());
public CompileTimeConstant<?> getBooleanValue(
@NotNull JetConstantExpression expression, @NotNull JetType expectedType
) {
String text = expression.getText();
CompileTimeConstant<?> error = checkNativeType(expectedType, "boolean", builtIns.getBooleanType(), expression);
if (error != null) {
return error;
}
@@ -213,20 +248,23 @@ public class CompileTimeConstantResolver {
}
@NotNull
public CompileTimeConstant<?> getCharValue(@NotNull String text, @NotNull JetType expectedType) {
CompileTimeConstant<?> error = checkNativeType(text, expectedType, "character", builtIns.getCharType());
public CompileTimeConstant<?> getCharValue(
@NotNull JetConstantExpression expression, @NotNull JetType expectedType
) {
String text = expression.getText();
CompileTimeConstant<?> error = checkNativeType(expectedType, "character", builtIns.getCharType(), expression);
if (error != null) {
return error;
}
// Strip the quotes
if (text.length() < 2 || text.charAt(0) != '\'' || text.charAt(text.length() - 1) != '\'') {
return new ErrorValue("Incorrect character literal");
return ErrorValue.create(INCORRECT_CHARACTER_LITERAL.on(expression));
}
text = text.substring(1, text.length() - 1); // now there're no quotes
if (text.length() == 0) {
return new ErrorValue("Empty character literal");
return ErrorValue.create(EMPTY_CHARACTER_LITERAL.on(expression));
}
if (text.charAt(0) != '\\') {
@@ -234,13 +272,16 @@ public class CompileTimeConstantResolver {
if (text.length() == 1) {
return new CharValue(text.charAt(0));
}
return new ErrorValue("Too many characters in a character literal '" + text + "'");
return ErrorValue.create(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL.on(expression, expression));
}
return escapedStringToCharValue(text);
return escapedStringToCharValue(text, expression);
}
@NotNull
public static CompileTimeConstant<?> escapedStringToCharValue(@NotNull String text) {
public static CompileTimeConstant<?> escapedStringToCharValue(
@NotNull String text,
@NotNull JetElement expression
) {
assert text.length() > 0 && text.charAt(0) == '\\' : "Only escaped sequences must be passed to this routine: " + text;
// Escape
@@ -248,12 +289,12 @@ public class CompileTimeConstantResolver {
switch (escape.length()) {
case 0:
// bare slash
return illegalEscape(text);
return illegalEscape(expression);
case 1:
// one-char escape
Character escaped = translateEscape(escape.charAt(0));
if (escaped == null) {
return illegalEscape(text);
return illegalEscape(expression);
}
return new CharValue(escaped);
case 5:
@@ -268,11 +309,14 @@ public class CompileTimeConstantResolver {
}
break;
}
return illegalEscape(text);
return illegalEscape(expression);
}
private static ErrorValue illegalEscape(String text) {
return new ErrorValue("Illegal escape: " + text);
@NotNull
private static CompileTimeConstant<?> illegalEscape(
@NotNull JetElement expression
) {
return ErrorValue.create(ILLEGAL_ESCAPE.on(expression, expression));
}
@Nullable
@@ -299,11 +343,13 @@ public class CompileTimeConstantResolver {
}
@NotNull
public CompileTimeConstant<?> getNullValue(@NotNull JetType expectedType) {
public CompileTimeConstant<?> getNullValue(
@NotNull JetConstantExpression expression, @NotNull JetType expectedType
) {
if (noExpectedTypeOrUnitOrError(expectedType) || expectedType.isNullable()) {
return NullValue.NULL;
}
return new ErrorValue("Null can not be a value of a non-null type " + expectedType);
return ErrorValue.create(NULL_FOR_NONNULL_TYPE.on(expression, expectedType));
}
private static boolean noExpectedTypeOrUnitOrError(JetType expectedType) {
@@ -18,16 +18,13 @@ package org.jetbrains.jet.lang.resolve.constants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lang.types.JetType;
public class ErrorValue implements CompileTimeConstant<Void> {
private final String message;
public ErrorValue(@NotNull String message) {
this.message = message;
}
public abstract class ErrorValue implements CompileTimeConstant<Void> {
@Override
@Deprecated // Should not be called, for this is not a real value, but a indication of an error
@@ -35,24 +32,62 @@ public class ErrorValue implements CompileTimeConstant<Void> {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public JetType getType(@NotNull KotlinBuiltIns kotlinBuiltIns) {
return ErrorUtils.createErrorType(message);
}
@Override
public <R, D> R accept(AnnotationArgumentVisitor<R, D> visitor, D data) {
return visitor.visitErrorValue(this, data);
}
@NotNull
public String getMessage() {
return message;
public static ErrorValue create(@NotNull String message) {
return new ErrorValueWithMessage(message);
}
@Override
public String toString() {
return message;
public static ErrorValue create(@NotNull Diagnostic diagnostic) {
return new ErrorValueWithDiagnostic(diagnostic);
}
public static class ErrorValueWithMessage extends ErrorValue {
private final String message;
public ErrorValueWithMessage(@NotNull String message) {
this.message = message;
}
public String getMessage() {
return message;
}
@NotNull
@Override
public JetType getType(@NotNull KotlinBuiltIns kotlinBuiltIns) {
return ErrorUtils.createErrorType(message);
}
@Override
public String toString() {
return getMessage();
}
}
public static class ErrorValueWithDiagnostic extends ErrorValue {
private final Diagnostic diagnostic;
public ErrorValueWithDiagnostic(@NotNull Diagnostic diagnostic) {
this.diagnostic = diagnostic;
}
public Diagnostic getDiagnostic() {
return diagnostic;
}
@NotNull
@Override
public JetType getType(@NotNull KotlinBuiltIns kotlinBuiltIns) {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return DefaultErrorMessages.RENDERER.render(diagnostic);
}
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
@@ -68,6 +69,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
import static org.jetbrains.jet.lang.resolve.constants.ErrorValue.ErrorValueWithDiagnostic;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
@@ -145,10 +147,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
CompileTimeConstant<?> value = compileTimeConstantResolver.getCompileTimeConstant(expression, context.expectedType);
if (value instanceof ErrorValue) {
// 'checkType' for 'ContextDependency.DEPENDENT' will take place in 'completeInferenceForArgument'
if (context.contextDependency == INDEPENDENT) {
context.trace.report(ERROR_COMPILE_TIME_VALUE.on(expression, ((ErrorValue) value).getMessage()));
}
assert value instanceof ErrorValueWithDiagnostic;
//noinspection CastConflictsWithInstanceof
context.trace.report(((ErrorValueWithDiagnostic)value).getDiagnostic());
return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo);
}
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, value);
@@ -1106,9 +1107,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
final StringBuilder builder = new StringBuilder();
final CompileTimeConstant<?>[] value = new CompileTimeConstant<?>[1];
final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[1];
dataFlowInfo[0] = context.dataFlowInfo;
final boolean[] isCompileTimeValue = new boolean[] { true };
final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[] { context.dataFlowInfo };
for (JetStringTemplateEntry entry : expression.getEntries()) {
entry.accept(new JetVisitorVoid() {
@@ -1120,7 +1120,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
dataFlowInfo[0] = typeInfo.getDataFlowInfo();
}
value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
isCompileTimeValue[0] = false;
}
@Override
@@ -1130,12 +1130,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public void visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry) {
String text = entry.getText();
CompileTimeConstant<?> character = CompileTimeConstantResolver.escapedStringToCharValue(text);
CompileTimeConstant<?> character = CompileTimeConstantResolver.escapedStringToCharValue(entry.getText(), entry);
if (character instanceof ErrorValue) {
context.trace.report(ILLEGAL_ESCAPE_SEQUENCE.on(entry));
value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
assert character instanceof ErrorValueWithDiagnostic;
//noinspection CastConflictsWithInstanceof
context.trace.report(((ErrorValueWithDiagnostic) character).getDiagnostic());
isCompileTimeValue[0] = false;
}
else {
builder.append(((CharValue) character).getValue());
@@ -1143,7 +1143,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
});
}
if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) {
if (isCompileTimeValue[0]) {
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new StringValue(builder.toString()));
}
return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
@@ -20,13 +20,16 @@ import com.intellij.openapi.util.Ref;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
@@ -168,6 +171,15 @@ public class DataFlowUtils {
return expressionType;
}
if (expression instanceof JetConstantExpression) {
Diagnostic diagnostic =
new CompileTimeConstantResolver().checkConstantExpressionType((JetConstantExpression) expression, expectedType);
if (diagnostic != null) {
trace.report(diagnostic);
}
return expressionType;
}
DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, expressionType, trace.getBindingContext());
for (JetType possibleType : dataFlowInfo.getPossibleTypes(dataFlowValue)) {
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
@@ -462,7 +462,7 @@ public class ExpressionTypingUtils {
@Override
public void report(@NotNull Diagnostic diagnostic) {
AbstractDiagnosticFactory factory = diagnostic.getFactory();
if ((factory == TYPE_MISMATCH || factory == ERROR_COMPILE_TIME_VALUE)
if ((factory == TYPE_MISMATCH || factory == CONSTANT_EXPECTED_TYPE_MISMATCH)
&& diagnostic.getPsiElement() == expressionToWatch) {
mismatchFound[0] = true;
}