Uniform language feature error messages

This commit is contained in:
Roman Shevchenko
2012-05-28 20:54:36 +04:00
parent eba132876e
commit fd7212ec69
4 changed files with 110 additions and 90 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -21,6 +21,7 @@
package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.SourcePosition;
@@ -160,7 +161,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
final PsiType unboxedLType = PsiPrimitiveType.getUnboxedType(lType);
if (unboxedLType != null) {
if (rType instanceof PsiPrimitiveType && !PsiPrimitiveType.NULL.equals(rType)) {
if (rType instanceof PsiPrimitiveType && !PsiType.NULL.equals(rType)) {
if (!rType.equals(unboxedLType)) {
rEvaluator = new TypeCastEvaluator(rEvaluator, unboxedLType.getCanonicalText(), true);
}
@@ -175,7 +176,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
}
final PsiPrimitiveType unboxedRType = PsiPrimitiveType.getUnboxedType(rType);
final PsiType _rType = unboxedRType != null? unboxedRType : rType;
if (_rType instanceof PsiPrimitiveType && !PsiPrimitiveType.NULL.equals(_rType)) {
if (_rType instanceof PsiPrimitiveType && !PsiType.NULL.equals(_rType)) {
if (!lType.equals(_rType)) {
rEvaluator = new TypeCastEvaluator(rEvaluator, lType.getCanonicalText(), true);
}
@@ -988,9 +989,9 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
@Override
public void visitLiteralExpression(PsiLiteralExpression expression) {
final String parsingError = HighlightUtil.getLiteralExpressionParsingError(expression);
final HighlightInfo parsingError = HighlightUtil.checkLiteralExpressionParsingError(expression);
if (parsingError != null) {
throwEvaluateException(parsingError);
throwEvaluateException(parsingError.description);
return;
}
@@ -1219,9 +1220,9 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
myResult = new ArrayInitializerEvaluator(evaluators);
}
@Nullable
private static PsiClass getOuterClass(PsiClass aClass) {
if(aClass == null) return null;
return PsiTreeUtil.getContextOfType(aClass, PsiClass.class, true);
return aClass == null ? null : PsiTreeUtil.getContextOfType(aClass, PsiClass.class, true);
}
private PsiClass getContainingClass(PsiVariable variable) {
@@ -883,42 +883,30 @@ public class HighlightUtil {
return null;
}
@Nullable
static HighlightInfo checkLiteralExpressionParsingError(final PsiLiteralExpression expression) {
final String error = getLiteralExpressionParsingError(expression);
if (error != null) {
final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, error);
QuickFixAction.registerQuickFixActions(info, getLiteralExpressionQuickFixes(expression));
return info;
}
return null;
}
private static final Key<Boolean> TOO_BIG_CHAR_LITERAL_KEY = Key.create("too.big.char.literal");
@Nullable
public static String getLiteralExpressionParsingError(final PsiLiteralExpression expression) {
public static HighlightInfo checkLiteralExpressionParsingError(final PsiLiteralExpression expression) {
final Object value = expression.getValue();
final PsiElement literal = expression.getFirstChild();
assert literal instanceof PsiJavaToken : literal;
final IElementType type = ((PsiJavaToken)literal).getTokenType();
String text = PsiLiteralExpressionImpl.NUMERIC_LITERALS.contains(type) ? literal.getText().toLowerCase() : literal.getText();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(expression);
if (PsiLiteralExpressionImpl.REAL_LITERALS.contains(type)) {
if (text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) {
return JavaErrorMessages.message("hex.FP.literals.not.supported");
if (text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX)) {
final HighlightInfo info = checkFeature(expression, Feature.HEX_FP_LITERALS);
if (info != null) return info;
}
}
if (PsiLiteralExpressionImpl.INTEGER_LITERALS.contains(type)) {
if (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
return JavaErrorMessages.message("binary.literals.not.supported");
if (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX)) {
final HighlightInfo info = checkFeature(expression, Feature.BIN_LITERALS);
if (info != null) return info;
}
}
if (PsiLiteralExpressionImpl.NUMERIC_LITERALS.contains(type)) {
if (text.contains("_") && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
return JavaErrorMessages.message("underscores.in.literals.not.supported");
if (text.contains("_")) {
final HighlightInfo info = checkFeature(expression, Feature.UNDERSCORES);
if (info != null) return info;
}
}
@@ -929,13 +917,16 @@ public class HighlightUtil {
parent instanceof PsiPrefixExpression &&
((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) {
if (text.equals(PsiLiteralExpressionImpl.HEX_PREFIX)) {
return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
final String message = JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (text.equals(PsiLiteralExpressionImpl.BIN_PREFIX)) {
return JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
final String message = JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (value == null || text.equals(PsiLiteralExpressionImpl._2_IN_31)) {
return JavaErrorMessages.message("integer.number.too.large");
final String message = JavaErrorMessages.message("integer.number.too.large");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
}
@@ -946,19 +937,23 @@ public class HighlightUtil {
parent instanceof PsiPrefixExpression &&
((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) {
if (mText.equals(PsiLiteralExpressionImpl.HEX_PREFIX)) {
return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
final String message = JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (mText.equals(PsiLiteralExpressionImpl.BIN_PREFIX)) {
return JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
final String message = JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (value == null || mText.equals(PsiLiteralExpressionImpl._2_IN_63)) {
return JavaErrorMessages.message("long.number.too.large");
final String message = JavaErrorMessages.message("long.number.too.large");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
}
else if (type == JavaTokenType.FLOAT_LITERAL || type == JavaTokenType.DOUBLE_LITERAL) {
if (value == null) {
return JavaErrorMessages.message("malformed.floating.point.literal");
final String message = JavaErrorMessages.message("malformed.floating.point.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
else if (type == JavaTokenType.TRUE_KEYWORD || type == JavaTokenType.FALSE_KEYWORD || type == JavaTokenType.NULL_KEYWORD) {
@@ -967,28 +962,41 @@ public class HighlightUtil {
else if (type == JavaTokenType.CHARACTER_LITERAL) {
// todo[r.sh] clean this mess up
if (value != null) {
if (!StringUtil.endsWithChar(text, '\'')) return JavaErrorMessages.message("unclosed.char.literal");
if (!StringUtil.endsWithChar(text, '\'')) {
final String message = JavaErrorMessages.message("unclosed.char.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
else {
if (!StringUtil.startsWithChar(text, '\'')) return null;
if (StringUtil.endsWithChar(text, '\'')) {
if (text.length() == 1) return JavaErrorMessages.message("illegal.line.end.in.character.literal");
if (text.length() == 1) {
final String message = JavaErrorMessages.message("illegal.line.end.in.character.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
text = text.substring(1, text.length() - 1);
}
else {
return JavaErrorMessages.message("illegal.line.end.in.character.literal");
final String message = JavaErrorMessages.message("illegal.line.end.in.character.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
final StringBuilder chars = StringBuilderSpinAllocator.alloc();
final boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null);
if (!success) return JavaErrorMessages.message("illegal.escape.character.in.character.literal");
if (!success) {
final String message = JavaErrorMessages.message("illegal.escape.character.in.character.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
final int length = chars.length();
StringBuilderSpinAllocator.dispose(chars);
if (length > 1) {
literal.putUserData(TOO_BIG_CHAR_LITERAL_KEY, Boolean.TRUE);
return JavaErrorMessages.message("too.many.characters.in.character.literal");
final String message = JavaErrorMessages.message("too.many.characters.in.character.literal");
final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
QuickFixAction.registerQuickFixAction(info, new ConvertToStringLiteralAction());
return info;
}
else if (length == 0) {
return JavaErrorMessages.message("empty.character.literal");
final String message = JavaErrorMessages.message("empty.character.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
}
@@ -1002,27 +1010,46 @@ public class HighlightUtil {
if (!StringUtil.startsWithChar(text, '\"')) return null;
if (StringUtil.endsWithChar(text, '\"')) {
if (text.length() == 1) return JavaErrorMessages.message("illegal.line.end.in.string.literal");
if (text.length() == 1) {
final String message = JavaErrorMessages.message("illegal.line.end.in.string.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
text = text.substring(1, text.length() - 1);
}
else {
return JavaErrorMessages.message("illegal.line.end.in.string.literal");
final String message = JavaErrorMessages.message("illegal.line.end.in.string.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
StringBuilder chars = new StringBuilder();
boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null);
if (!success) return JavaErrorMessages.message("illegal.escape.character.in.string.literal");
if (!success) {
final String message = JavaErrorMessages.message("illegal.escape.character.in.string.literal");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
}
if (value instanceof Float) {
final Float number = (Float)value;
if (number.isInfinite()) return JavaErrorMessages.message("floating.point.number.too.large");
if (number.floatValue() == 0 && !isFPZero(text)) return JavaErrorMessages.message("floating.point.number.too.small");
if (number.isInfinite()) {
final String message = JavaErrorMessages.message("floating.point.number.too.large");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (number.floatValue() == 0 && !isFPZero(text)) {
final String message = JavaErrorMessages.message("floating.point.number.too.small");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
else if (value instanceof Double) {
final Double number = (Double)value;
if (number.isInfinite()) return JavaErrorMessages.message("floating.point.number.too.large");
if (number.doubleValue() == 0 && !isFPZero(text)) return JavaErrorMessages.message("floating.point.number.too.small");
if (number.isInfinite()) {
final String message = JavaErrorMessages.message("floating.point.number.too.large");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
if (number.doubleValue() == 0 && !isFPZero(text)) {
final String message = JavaErrorMessages.message("floating.point.number.too.small");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
}
return null;
@@ -1038,33 +1065,6 @@ public class HighlightUtil {
return true;
}
private static Collection<? extends IntentionAction> getLiteralExpressionQuickFixes(final PsiLiteralExpression expression) {
final PsiElement literal = expression.getFirstChild();
assert literal instanceof PsiJavaToken : literal;
final String text = literal.getText().toLowerCase();
final IElementType type = ((PsiJavaToken)literal).getTokenType();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(expression);
if (PsiLiteralExpressionImpl.REAL_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX)) {
return Collections.singletonList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
}
}
if (PsiLiteralExpressionImpl.NUMERIC_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX) || text.contains("_"))) {
return Collections.singletonList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_7));
}
}
if (type == JavaTokenType.CHARACTER_LITERAL) {
if (Boolean.TRUE.equals(literal.getUserData(TOO_BIG_CHAR_LITERAL_KEY))) {
return Collections.singletonList(new ConvertToStringLiteralAction());
}
}
return Collections.emptyList();
}
@Nullable
static HighlightInfo checkMustBeBoolean(@NotNull PsiExpression expr, PsiType type) {
PsiElement parent = expr.getParent();
@@ -2525,9 +2525,12 @@ public class HighlightUtil {
STATIC_IMPORTS(LanguageLevel.JDK_1_5, "feature.static.imports"),
FOR_EACH(LanguageLevel.JDK_1_5, "feature.for.each"),
VARARGS(LanguageLevel.JDK_1_5, "feature.varargs"),
HEX_FP_LITERALS(LanguageLevel.JDK_1_5, "feature.hex.fp.literals"),
DIAMOND_TYPES(LanguageLevel.JDK_1_7, "feature.diamond.types"),
MULTI_CATCH(LanguageLevel.JDK_1_7, "feature.multi.catch"),
TRY_WITH_RESOURCES(LanguageLevel.JDK_1_7, "feature.try.with.resources"),
BIN_LITERALS(LanguageLevel.JDK_1_7, "feature.binary.literals"),
UNDERSCORES(LanguageLevel.JDK_1_7, "feature.underscores.in.literals"),
EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods");
private final LanguageLevel level;
@@ -273,9 +273,6 @@ unclosed.char.literal=Unclosed character literal
illegal.escape.character.in.string.literal=Illegal escape character in string literal
floating.point.number.too.large=Floating point number too large
floating.point.number.too.small=Floating point number too small
hex.FP.literals.not.supported=Hexadecimal floating point literals are only supported in JDK 5 or higher
binary.literals.not.supported=Binary literals are only supported in JDK 7 or higher
underscores.in.literals.not.supported=Underscores in literals are only supported in JDK 7 or higher
import.statement.identifier.or.asterisk.expected.=Identifier or '*' expected
@@ -349,8 +346,11 @@ feature.annotations=Annotations
feature.static.imports=Static imports
feature.for.each=For-each loops
feature.varargs=Variable arity methods
feature.hex.fp.literals=Hexadecimal floating point literals
feature.diamond.types=Diamond types
feature.multi.catch=Multi-catches
feature.try.with.resources=Try-with-resources
feature.binary.literals=Binary literals
feature.underscores.in.literals=Underscores in literals
feature.extension.methods=Extension methods
insufficient.language.level={0} are not supported at this language level
@@ -1,3 +1,19 @@
/*
* Copyright 2000-2012 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.
*/
/// assignment compatible types
import java.io.*;
import java.net.*;
@@ -23,9 +39,9 @@ public class a {
int i14 = 020000000000;
int i15 = <error descr="Integer number too large">0xf044332211</error>;
int octale = 017777777777; // negative
int bi1 = <error descr="Binary literals are only supported in JDK 7 or higher">0b0010</error>;
int bi2 = <error descr="Binary literals are only supported in JDK 7 or higher">0B0010</error>;
int bi3 = <error descr="Underscores in literals are only supported in JDK 7 or higher">1_2</error>;
int bi1 = <error descr="Binary literals are not supported at this language level">0b0010</error>;
int bi2 = <error descr="Binary literals are not supported at this language level">0B0010</error>;
int bi3 = <error descr="Underscores in literals are not supported at this language level">1_2</error>;
long l1 = -<error descr="Long number too large">9223372036854775809L</error>;
long l2 = <error descr="Long number too large">9223372036854775808L</error>;
@@ -39,20 +55,20 @@ public class a {
long l10 = 0x8000000000000000L;
long octalValue = 01777777777777777777600L;
long octalValua = 01777777777777777777777L;
long bl1 = <error descr="Binary literals are only supported in JDK 7 or higher">0b0010l</error>;
long bl2 = <error descr="Binary literals are only supported in JDK 7 or higher">0B0010L</error>;
long bl3 = <error descr="Underscores in literals are only supported in JDK 7 or higher">10_24L</error>;
long bl1 = <error descr="Binary literals are not supported at this language level">0b0010l</error>;
long bl2 = <error descr="Binary literals are not supported at this language level">0B0010L</error>;
long bl3 = <error descr="Underscores in literals are not supported at this language level">10_24L</error>;
float f1= <error descr="Floating point number too small">1e-46f</error>;
float f2 = <error descr="Floating point number too large">1e39f</error>;
float f3 = 0E1F;
float f4 = <error descr="Hexadecimal floating point literals are only supported in JDK 5 or higher">0xabc.defP2f</error>;
float bf1 = <error descr="Underscores in literals are only supported in JDK 7 or higher">3.141_592f</error>;
float f4 = <error descr="Hexadecimal floating point literals are not supported at this language level">0xabc.defP2f</error>;
float bf1 = <error descr="Underscores in literals are not supported at this language level">3.141_592f</error>;
double dd1 = <error descr="Floating point number too small">1e-324</error>;
double dd2 = <error descr="Floating point number too large">1e309</error>;
double dd3 = 0E1;
double dd4 = <error descr="Hexadecimal floating point literals are only supported in JDK 5 or higher">0x1.fffffffffffffP1023</error>;
double dd4 = <error descr="Hexadecimal floating point literals are not supported at this language level">0x1.fffffffffffffP1023</error>;
double d1 = <error descr="Malformed floating point literal">1.E</error>;
double d2 = <error descr="Malformed floating point literal">1.e</error>;
double d3 = <error descr="Malformed floating point literal">1.E+</error>;
@@ -64,6 +80,6 @@ public class a {
double d9 = <error descr="Malformed floating point literal">1e-d</error>;
double d10 = <error descr="Malformed floating point literal">1e-F</error>;
double d11 = <error descr="Malformed floating point literal">1e-f</error>;
double d12 = <error descr="Underscores in literals are only supported in JDK 7 or higher">3.141_592_653_589_793d</error>;
double d12 = <error descr="Underscores in literals are not supported at this language level">3.141_592_653_589_793d</error>;
}
}