Add common method to parse char value
This commit is contained in:
+1
-1
@@ -78,7 +78,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
|||||||
JetNodeTypes.INTEGER_CONSTANT -> CompileTimeConstantResolver.parseLong(text)
|
JetNodeTypes.INTEGER_CONSTANT -> CompileTimeConstantResolver.parseLong(text)
|
||||||
JetNodeTypes.FLOAT_CONSTANT -> CompileTimeConstantResolver.parseDouble(text)
|
JetNodeTypes.FLOAT_CONSTANT -> CompileTimeConstantResolver.parseDouble(text)
|
||||||
JetNodeTypes.BOOLEAN_CONSTANT -> CompileTimeConstantResolver.parseBoolean(text)
|
JetNodeTypes.BOOLEAN_CONSTANT -> CompileTimeConstantResolver.parseBoolean(text)
|
||||||
JetNodeTypes.CHARACTER_CONSTANT -> CompileTimeConstantResolver.parseChar(text)
|
JetNodeTypes.CHARACTER_CONSTANT -> CompileTimeConstantResolver.parseChar(expression)
|
||||||
JetNodeTypes.NULL -> null
|
JetNodeTypes.NULL -> null
|
||||||
else -> throw IllegalArgumentException("Unsupported constant: " + expression)
|
else -> throw IllegalArgumentException("Unsupported constant: " + expression)
|
||||||
}
|
}
|
||||||
|
|||||||
+101
-64
@@ -23,7 +23,10 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
|
||||||
import org.jetbrains.jet.lang.psi.JetConstantExpression;
|
import org.jetbrains.jet.lang.psi.JetConstantExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
@@ -120,31 +123,18 @@ public class CompileTimeConstantResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkCharValue(CompileTimeConstant<?> constant, JetType expectedType, JetConstantExpression expression) {
|
private boolean checkCharValue(CompileTimeConstant<?> constant, JetType expectedType, JetConstantExpression expression) {
|
||||||
String text = expression.getText();
|
|
||||||
if (!noExpectedTypeOrError(expectedType)
|
if (!noExpectedTypeOrError(expectedType)
|
||||||
&& !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getCharType(), expectedType)) {
|
&& !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getCharType(), expectedType)) {
|
||||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType));
|
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip the quotes
|
if (constant != null) {
|
||||||
if (text.length() < 2 || text.charAt(0) != '\'' || text.charAt(text.length() - 1) != '\'') {
|
return false;
|
||||||
return reportError(INCORRECT_CHARACTER_LITERAL.on(expression));
|
|
||||||
}
|
|
||||||
text = text.substring(1, text.length() - 1); // now there're no quotes
|
|
||||||
|
|
||||||
if (text.length() == 0) {
|
|
||||||
return reportError(EMPTY_CHARACTER_LITERAL.on(expression));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.charAt(0) != '\\') {
|
CompileTimeConstant<?> compileTimeConstant = parseCharValue(expression);
|
||||||
// No escape
|
if (compileTimeConstant instanceof ErrorCharValueWithDiagnostic) {
|
||||||
if (text.length() == 1) {
|
return reportError(((ErrorCharValueWithDiagnostic) compileTimeConstant).getDiagnostic());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return reportError(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL.on(expression, expression));
|
|
||||||
}
|
|
||||||
if (constant == null) {
|
|
||||||
return reportError(ILLEGAL_ESCAPE.on(expression, expression));
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -156,6 +146,95 @@ public class CompileTimeConstantResolver {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static CompileTimeConstant<?> parseCharValue(@NotNull JetConstantExpression expression) {
|
||||||
|
String text = expression.getText();
|
||||||
|
// Strip the quotes
|
||||||
|
if (text.length() < 2 || text.charAt(0) != '\'' || text.charAt(text.length() - 1) != '\'') {
|
||||||
|
return createErrorValue(INCORRECT_CHARACTER_LITERAL.on(expression));
|
||||||
|
}
|
||||||
|
text = text.substring(1, text.length() - 1); // now there're no quotes
|
||||||
|
|
||||||
|
if (text.length() == 0) {
|
||||||
|
return createErrorValue(EMPTY_CHARACTER_LITERAL.on(expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.charAt(0) != '\\') {
|
||||||
|
// No escape
|
||||||
|
if (text.length() == 1) {
|
||||||
|
return new CharValue(text.charAt(0));
|
||||||
|
}
|
||||||
|
return createErrorValue(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL.on(expression, expression));
|
||||||
|
}
|
||||||
|
return escapedStringToCharValue(text, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
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
|
||||||
|
String escape = text.substring(1); // strip the slash
|
||||||
|
switch (escape.length()) {
|
||||||
|
case 0:
|
||||||
|
// bare slash
|
||||||
|
return illegalEscape(expression);
|
||||||
|
case 1:
|
||||||
|
// one-char escape
|
||||||
|
Character escaped = translateEscape(escape.charAt(0));
|
||||||
|
if (escaped == null) {
|
||||||
|
return illegalEscape(expression);
|
||||||
|
}
|
||||||
|
return new CharValue(escaped);
|
||||||
|
case 5:
|
||||||
|
// unicode escape
|
||||||
|
if (escape.charAt(0) == 'u') {
|
||||||
|
try {
|
||||||
|
Integer intValue = Integer.valueOf(escape.substring(1), 16);
|
||||||
|
return new CharValue((char) intValue.intValue());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// Will be reported below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return illegalEscape(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static CompileTimeConstant<?> illegalEscape(@NotNull JetElement expression) {
|
||||||
|
return createErrorValue(ILLEGAL_ESCAPE.on(expression, expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ErrorValue createErrorValue(@NotNull Diagnostic diagnostic) {
|
||||||
|
return new ErrorCharValueWithDiagnostic(diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ErrorCharValueWithDiagnostic extends ErrorValue {
|
||||||
|
private final Diagnostic diagnostic;
|
||||||
|
|
||||||
|
public ErrorCharValueWithDiagnostic(@NotNull Diagnostic diagnostic) {
|
||||||
|
this.diagnostic = diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Long parseLong(String text) {
|
public static Long parseLong(String text) {
|
||||||
try {
|
try {
|
||||||
@@ -200,52 +279,10 @@ public class CompileTimeConstantResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Character parseChar(@NotNull String text) {
|
public static Character parseChar(@NotNull JetConstantExpression expression) {
|
||||||
// Strip the quotes
|
CompileTimeConstant<?> compileTimeConstant = parseCharValue(expression);
|
||||||
if (text.length() < 2 || text.charAt(0) != '\'' || text.charAt(text.length() - 1) != '\'') {
|
if (compileTimeConstant instanceof CharValue) {
|
||||||
return null;
|
return ((CharValue) compileTimeConstant).getValue();
|
||||||
}
|
|
||||||
text = text.substring(1, text.length() - 1); // now there're no quotes
|
|
||||||
|
|
||||||
if (text.length() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.charAt(0) != '\\') {
|
|
||||||
// No escape
|
|
||||||
if (text.length() == 1) {
|
|
||||||
return text.charAt(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return escapedStringToChar(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static Character escapedStringToChar(@NotNull String text) {
|
|
||||||
if (!(text.length() > 0 && text.charAt(0) == '\\')) return null;
|
|
||||||
|
|
||||||
// Escape
|
|
||||||
String escape = text.substring(1); // strip the slash
|
|
||||||
switch (escape.length()) {
|
|
||||||
case 0: return null;
|
|
||||||
case 1:
|
|
||||||
// one-char escape
|
|
||||||
Character escaped = translateEscape(escape.charAt(0));
|
|
||||||
if (escaped == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return escaped;
|
|
||||||
case 5:
|
|
||||||
// unicode escape
|
|
||||||
if (escape.charAt(0) == 'u') {
|
|
||||||
try {
|
|
||||||
Integer intValue = Integer.valueOf(escape.substring(1), 16);
|
|
||||||
return (char) intValue.intValue();
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// Will be reported below
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -71,6 +71,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.DescriptorUtils.getStaticNestedClassesScope;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
|
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.calls.context.ContextDependency.INDEPENDENT;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver.ErrorCharValueWithDiagnostic;
|
||||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
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.NO_EXPECTED_TYPE;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
|
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
|
||||||
@@ -1178,9 +1179,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
|
public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
|
||||||
Character character = CompileTimeConstantResolver.escapedStringToChar(entry.getText());
|
CompileTimeConstant<?> compileTimeConstant = CompileTimeConstantResolver.escapedStringToCharValue(entry.getText(), entry);
|
||||||
if (character == null) {
|
if (compileTimeConstant instanceof ErrorCharValueWithDiagnostic) {
|
||||||
context.trace.report(Errors.ILLEGAL_ESCAPE.on(entry, entry));
|
context.trace.report(((ErrorCharValueWithDiagnostic) compileTimeConstant).getDiagnostic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user