Project Coin numeric literals (IDEA-64808)

This commit is contained in:
Roman Shevchenko
2011-02-08 12:16:20 +01:00
parent 473c8cda31
commit e75d85ba43
14 changed files with 1232 additions and 885 deletions
@@ -29,6 +29,7 @@ import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.IntentionProvider;
import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.lang.StdLanguages;
@@ -813,10 +814,14 @@ public class HighlightUtil {
@Nullable
static HighlightInfo checkLiteralExpressionParsingError(PsiLiteralExpression expression) {
String error = expression.getParsingError();
static HighlightInfo checkLiteralExpressionParsingError(final PsiLiteralExpression expression) {
final String error = expression.getParsingError();
if (error != null) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, error);
final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, error);
if (expression instanceof IntentionProvider) {
QuickFixAction.registerQuickFixActions(info, ((IntentionProvider)expression).getIntentions());
}
return info;
}
return null;
}
@@ -4,6 +4,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.tree.IElementType;
@SuppressWarnings({"ALL"})
%%
%{
@@ -31,9 +32,6 @@ import com.intellij.psi.tree.IElementType;
%eof{ return;
%eof}
DIGIT=[0-9]
OCTAL_DIGIT=[0-7]
HEX_DIGIT=[0-9A-Fa-f]
WHITE_SPACE_CHAR=[\ \n\r\t\f]
IDENTIFIER=[:jletter:] [:jletterdigit:]*
@@ -43,23 +41,38 @@ DOC_COMMENT="/*""*"+("/"|([^"/""*"]{COMMENT_TAIL}))?
COMMENT_TAIL=([^"*"]*("*"+[^"*""/"])?)*("*"+"/")?
END_OF_LINE_COMMENT="/""/"[^\r\n]*
INTEGER_LITERAL={DECIMAL_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}|{OCTAL_INTEGER_LITERAL}
DECIMAL_INTEGER_LITERAL=(0|([1-9]({DIGIT})*))
HEX_INTEGER_LITERAL=0[Xx]({HEX_DIGIT})*
OCTAL_INTEGER_LITERAL=0({OCTAL_DIGIT})+
LONG_LITERAL=({INTEGER_LITERAL})[Ll]
DIGIT=[0-9]
DIGIT_OR_UNDERSCORE=[_0-9]
OCTAL_DIGIT=[0-7]
OCTAL_DIGIT_OR_UNDERSCORE=[_0-7]
HEX_DIGIT=[0-9A-Fa-f]
HEX_DIGIT_OR_UNDERSCORE=[_0-9A-Fa-f]
BINARY_DIGIT=[01]
BINARY_DIGIT_OR_UNDERSCORE=[_01]
DIGITS={DIGIT}|({DIGIT}{DIGIT_OR_UNDERSCORE}*{DIGIT})
HEX_DIGITS={HEX_DIGIT}|({HEX_DIGIT}{HEX_DIGIT_OR_UNDERSCORE}*{HEX_DIGIT})
BINARY_DIGITS={BINARY_DIGIT}|({BINARY_DIGIT}{BINARY_DIGIT_OR_UNDERSCORE}*{BINARY_DIGIT})
INTEGER_LITERAL={DECIMAL_INTEGER_LITERAL}|{OCTAL_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}|{BINARY_INTEGER_LITERAL}
DECIMAL_INTEGER_LITERAL=0|([1-9]({DIGIT_OR_UNDERSCORE}*{DIGIT})?)
OCTAL_INTEGER_LITERAL=0{OCTAL_DIGIT_OR_UNDERSCORE}*{OCTAL_DIGIT}
HEX_INTEGER_LITERAL=0[Xx]{HEX_DIGITS}?
BINARY_INTEGER_LITERAL=0[Bb]{BINARY_DIGITS}?
LONG_LITERAL={INTEGER_LITERAL}[Ll]
FLOAT_LITERAL=({FLOATING_POINT_LITERAL1}|{FLOATING_POINT_LITERAL2}|{FLOATING_POINT_LITERAL3}|{FLOATING_POINT_LITERAL4})[Ff]
DOUBLE_LITERAL=(({FLOATING_POINT_LITERAL1}|{FLOATING_POINT_LITERAL2}|{FLOATING_POINT_LITERAL3})[Dd]?)|({FLOATING_POINT_LITERAL4}[Dd])
FLOATING_POINT_LITERAL1={DIGITS}"."{DIGITS}?{EXPONENT_PART}?
FLOATING_POINT_LITERAL2="."{DIGITS}{EXPONENT_PART}?
FLOATING_POINT_LITERAL3={DIGITS}{EXPONENT_PART}
FLOATING_POINT_LITERAL4={DIGITS}
EXPONENT_PART=[Ee]["+""-"]?{DIGITS}?
FLOAT_LITERAL=(({FLOATING_POINT_LITERAL1})[Ff])|(({FLOATING_POINT_LITERAL2})[Ff])|(({FLOATING_POINT_LITERAL3})[Ff])|(({FLOATING_POINT_LITERAL4})[Ff])
DOUBLE_LITERAL=(({FLOATING_POINT_LITERAL1})[Dd]?)|(({FLOATING_POINT_LITERAL2})[Dd]?)|(({FLOATING_POINT_LITERAL3})[Dd]?)|(({FLOATING_POINT_LITERAL4})[Dd])
FLOATING_POINT_LITERAL1=({DIGIT})+"."({DIGIT})*({EXPONENT_PART})?
FLOATING_POINT_LITERAL2="."({DIGIT})+({EXPONENT_PART})?
FLOATING_POINT_LITERAL3=({DIGIT})+({EXPONENT_PART})
FLOATING_POINT_LITERAL4=({DIGIT})+
EXPONENT_PART=[Ee]["+""-"]?({DIGIT})*
HEX_FLOAT_LITERAL={HEX_SIGNIFICAND}{BINARY_EXPONENT}[Ff]
HEX_DOUBLE_LITERAL={HEX_SIGNIFICAND}{BINARY_EXPONENT}[Dd]?
BINARY_EXPONENT=[Pp][+-]?{DIGIT}+
HEX_SIGNIFICAND={HEX_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}.|0[Xx]{HEX_DIGIT}*.{HEX_DIGIT}+
BINARY_EXPONENT=[Pp][+-]?{DIGITS}
HEX_SIGNIFICAND={HEX_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}.|0[Xx]{HEX_DIGITS}?.{HEX_DIGITS}
CHARACTER_LITERAL="'"([^\\\'\r\n]|{ESCAPE_SEQUENCE})*("'"|\\)?
STRING_LITERAL=\"([^\\\"\r\n]|{ESCAPE_SEQUENCE})*(\"|\\)?
@@ -76,9 +89,9 @@ ESCAPE_SEQUENCE=\\[^\r\n]
<YYINITIAL> {LONG_LITERAL} { return JavaTokenType.LONG_LITERAL; }
<YYINITIAL> {INTEGER_LITERAL} { return JavaTokenType.INTEGER_LITERAL; }
<YYINITIAL> {FLOAT_LITERAL} { return JavaTokenType.FLOAT_LITERAL; }
<YYINITIAL> {HEX_FLOAT_LITERAL} { if (myJdk15Enabled) return JavaTokenType.FLOAT_LITERAL; }
<YYINITIAL> {HEX_FLOAT_LITERAL} { return JavaTokenType.FLOAT_LITERAL; }
<YYINITIAL> {DOUBLE_LITERAL} { return JavaTokenType.DOUBLE_LITERAL; }
<YYINITIAL> {HEX_DOUBLE_LITERAL} { if (myJdk15Enabled) return JavaTokenType.DOUBLE_LITERAL; }
<YYINITIAL> {HEX_DOUBLE_LITERAL} { return JavaTokenType.DOUBLE_LITERAL; }
<YYINITIAL> {CHARACTER_LITERAL} { return JavaTokenType.CHARACTER_LITERAL; }
<YYINITIAL> {STRING_LITERAL} { return JavaTokenType.STRING_LITERAL; }
File diff suppressed because it is too large Load Diff
@@ -16,9 +16,13 @@
package com.intellij.psi.impl.source.tree.java;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.IntentionProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.Constants;
import com.intellij.psi.impl.source.tree.LeafElement;
@@ -27,66 +31,94 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.injected.StringLiteralEscaper;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.text.LiteralFormatUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements PsiLiteralExpression,PsiLanguageInjectionHost, Constants, ContributedReferenceHost {
public class PsiLiteralExpressionImpl
extends ExpressionPsiElement
implements PsiLiteralExpression, PsiLanguageInjectionHost, Constants, ContributedReferenceHost, IntentionProvider {
@NonNls private static final String QUOT = "&quot;";
@NonNls private static final String HEXPREFIX = "0x";
@NonNls private static final String HEXPREFIX2 = "0X";
@NonNls private static final String LHEX_PREFIX = "0xl";
@NonNls private static final String HEX_PREFIX = "0x";
@NonNls private static final String HEX_PREFIX2 = "0X";
@NonNls private static final String LONG_HEX_EMPTY = "0xl";
@NonNls private static final String BIN_PREFIX = "0b";
@NonNls private static final String BIN_PREFIX2 = "0B";
@NonNls private static final String LONG_BIN_EMPTY = "0bl";
@NonNls private static final String _2_IN_63 = Long.toString(-1L << 63).substring(1);
@NonNls private static final String _2_IN_31 = Long.toString(-1L << 31).substring(1);
@NonNls private static final String _2_IN_63_L = _2_IN_63 + "l";
private static final TokenSet INTEGER_LITERALS = TokenSet.create(INTEGER_LITERAL, LONG_LITERAL);
private static final TokenSet REAL_LITERALS = TokenSet.create(FLOAT_LITERAL, DOUBLE_LITERAL);
private static final TokenSet NUMERIC_LITERALS = TokenSet.orSet(INTEGER_LITERALS, REAL_LITERALS);
public PsiLiteralExpressionImpl() {
super(LITERAL_EXPRESSION);
}
public PsiType getType() {
IElementType i = getFirstChildNode().getElementType();
if (i == INTEGER_LITERAL) {
final IElementType type = getFirstChildNode().getElementType();
if (type == INTEGER_LITERAL) {
return PsiType.INT;
}
if (i == LONG_LITERAL) {
if (type == LONG_LITERAL) {
return PsiType.LONG;
}
if (i == FLOAT_LITERAL) {
if (type == FLOAT_LITERAL) {
return PsiType.FLOAT;
}
if (i == DOUBLE_LITERAL) {
if (type == DOUBLE_LITERAL) {
return PsiType.DOUBLE;
}
if (i == CHARACTER_LITERAL) {
if (type == CHARACTER_LITERAL) {
return PsiType.CHAR;
}
if (i == STRING_LITERAL) {
if (type == STRING_LITERAL) {
return PsiType.getJavaLangString(getManager(), getResolveScope());
}
if (i == TRUE_KEYWORD || i == FALSE_KEYWORD) {
if (type == TRUE_KEYWORD || type == FALSE_KEYWORD) {
return PsiType.BOOLEAN;
}
if (i == NULL_KEYWORD) {
if (type == NULL_KEYWORD) {
return PsiType.NULL;
}
return null;
}
@NonNls private static final String _2_IN_63 = Long.toString(-1L << 63).substring(1);
@NonNls private static final String _2_IN_31 = Long.toString(-1L << 31).substring(1);
@NonNls private static final String _2_IN_63_L = _2_IN_63 + "l";
public String getCanonicalText() {
final TreeElement literal = getFirstChildNode();
final IElementType type = literal.getElementType();
return NUMERIC_LITERALS.contains(type) ? LiteralFormatUtil.removeUnderscores(literal.getText()) : literal.getText();
}
public Object getValue() {
String text = getFirstChildNode().getText();
int textLength = text.length();
IElementType i = getFirstChildNode().getElementType();
if (i == INTEGER_LITERAL) {
final TreeElement literal = getFirstChildNode();
final IElementType type = literal.getElementType();
String text = getCanonicalText();
final int textLength = text.length();
if (type == INTEGER_LITERAL) {
try {
if (text.startsWith(HEXPREFIX) || text.startsWith(HEXPREFIX2)) {
if (text.startsWith(HEX_PREFIX) || text.startsWith(HEX_PREFIX2)) {
// should fit in 32 bits
final long value = parseDigits(text.substring(2), 4, 32);
return Integer.valueOf((int)value);
}
if (text.startsWith(BIN_PREFIX) || text.startsWith(BIN_PREFIX2)) {
// should fit in 32 bits
final long value = parseDigits(text.substring(2), 1, 32);
return Integer.valueOf((int)value);
}
if (StringUtil.startsWithChar(text, '0')) {
// should fit in 32 bits
final long value = parseDigits(text, 3, 32);
@@ -101,14 +133,17 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
return null;
}
}
if (i == LONG_LITERAL) {
if (type == LONG_LITERAL) {
if (StringUtil.endsWithChar(text, 'L') || StringUtil.endsWithChar(text, 'l')) {
text = text.substring(0, textLength - 1);
}
try {
if (text.startsWith(HEXPREFIX) || text.startsWith(HEXPREFIX2)) {
if (text.startsWith(HEX_PREFIX) || text.startsWith(HEX_PREFIX2)) {
return parseDigits(text.substring(2), 4, 64);
}
if (text.startsWith(BIN_PREFIX) || text.startsWith(BIN_PREFIX2)) {
return parseDigits(text.substring(2), 1, 64);
}
if (StringUtil.startsWithChar(text, '0')) {
// should fit in 64 bits
return parseDigits(text, 3, 64);
@@ -120,7 +155,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
return null;
}
}
if (i == FLOAT_LITERAL) {
if (type == FLOAT_LITERAL) {
try {
return Float.valueOf(text);
}
@@ -128,7 +163,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
return null;
}
}
if (i == DOUBLE_LITERAL) {
if (type == DOUBLE_LITERAL) {
try {
return Double.valueOf(text);
}
@@ -136,7 +171,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
return null;
}
}
if (i == CHARACTER_LITERAL) {
if (type == CHARACTER_LITERAL) {
if (StringUtil.endsWithChar(text, '\'')) {
if (textLength == 1) return null;
text = text.substring(1, textLength - 1);
@@ -150,7 +185,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
if (chars.length() != 1) return null;
return Character.valueOf(chars.charAt(0));
}
if (i == STRING_LITERAL) {
if (type == STRING_LITERAL) {
if (StringUtil.endsWithChar(text, '\"')) {
if (textLength == 1) return null;
text = text.substring(1, textLength - 1);
@@ -165,23 +200,21 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
}
return internedParseStringCharacters(text);
}
if (i == TRUE_KEYWORD) {
if (type == TRUE_KEYWORD) {
return Boolean.TRUE;
}
if (i == FALSE_KEYWORD) {
if (type == FALSE_KEYWORD) {
return Boolean.FALSE;
}
if (i == NULL_KEYWORD) {
return null;
}
return null;
}
// convert text to number according to radix specified
// if number is more than maxbits bits long, throws NumberFormatException
private static long parseDigits(String text, int bitsInRadix, int maxBits) throws NumberFormatException {
// if number is more than maxBits bits long, throws NumberFormatException
private static long parseDigits(final String text, final int bitsInRadix, final int maxBits) throws NumberFormatException {
final int radix = 1 << bitsInRadix;
int textLength = text.length();
final int textLength = text.length();
if (textLength == 0) {
throw new NumberFormatException(text);
}
@@ -189,7 +222,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
if ((integer & (-1L << (maxBits - bitsInRadix))) != 0) {
throw new NumberFormatException(text);
}
int lastDigit = Character.digit(text.charAt(textLength - 1), radix);
final int lastDigit = Character.digit(text.charAt(textLength - 1), radix);
if (lastDigit == -1) {
throw new NumberFormatException(text);
}
@@ -200,42 +233,68 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
public String getParsingError() {
final Object value = getValue();
TreeElement firstChildNode = getFirstChildNode();
String text = firstChildNode.getText();
IElementType i = firstChildNode.getElementType();
if (i == INTEGER_LITERAL) {
text = text.toLowerCase();
final TreeElement literal = getFirstChildNode();
final IElementType type = literal.getElementType();
String text = NUMERIC_LITERALS.contains(type) ? literal.getText().toLowerCase() : literal.getText();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(this);
if (REAL_LITERALS.contains(type)) {
if (text.startsWith(HEX_PREFIX) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) {
return JavaErrorMessages.message("hex.FP.literals.not.supported");
}
}
if (INTEGER_LITERALS.contains(type)) {
if (text.startsWith(BIN_PREFIX) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
return JavaErrorMessages.message("binary.literals.not.supported");
}
}
if (NUMERIC_LITERALS.contains(type)) {
if (text.contains("_") && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
return JavaErrorMessages.message("underscores.in.literals.not.supported");
}
}
if (type == INTEGER_LITERAL) {
//literal 2147483648 may appear only as the operand of the unary negation operator -.
if (!(text.equals(_2_IN_31)
&& getParent() instanceof PsiPrefixExpression
&& ((PsiPrefixExpression)getParent()).getOperationSign().getTokenType() == MINUS)) {
if (text.equals(HEXPREFIX)) return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
if (text.equals(HEX_PREFIX)) {
return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
}
if (text.equals(BIN_PREFIX)) {
return JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
}
if (value == null || text.equals(_2_IN_31)) {
return JavaErrorMessages.message("integer.number.too.large");
}
}
}
else if (i == LONG_LITERAL) {
text = text.toLowerCase();
else if (type == LONG_LITERAL) {
//literal 9223372036854775808L may appear only as the operand of the unary negation operator -.
if (!(text.equals(_2_IN_63_L)
&& getParent() instanceof PsiPrefixExpression
&& ((PsiPrefixExpression)getParent()).getOperationSign().getTokenType() == MINUS)) {
if (text.equals(HEXPREFIX) || text.equals(LHEX_PREFIX)) return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
if (text.equals(LONG_HEX_EMPTY)) {
return JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
}
if (text.equals(LONG_BIN_EMPTY)) {
return JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
}
if (value == null || text.equals(_2_IN_63_L)) {
return JavaErrorMessages.message("long.number.too.large");
}
}
}
else if (i == FLOAT_LITERAL || i == DOUBLE_LITERAL) {
else if (type == FLOAT_LITERAL || type == DOUBLE_LITERAL) {
if (value == null) {
return JavaErrorMessages.message("malformed.floating.point.literal");
}
}
else if (i == TRUE_KEYWORD || i == FALSE_KEYWORD || i == NULL_KEYWORD) {
// TODO
else if (type == TRUE_KEYWORD || type == FALSE_KEYWORD || type == NULL_KEYWORD) {
return null;
}
else if (i == CHARACTER_LITERAL) {
else if (type == CHARACTER_LITERAL) {
if (value == null) {
if (!StringUtil.startsWithChar(text, '\'')) return null;
if (StringUtil.endsWithChar(text, '\'')) {
@@ -254,7 +313,7 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
else if (chars.length() == 0) return JavaErrorMessages.message("empty.character.literal");
}
}
else if (i == STRING_LITERAL) {
else if (type == STRING_LITERAL) {
if (value == null) {
for (final PsiElement element : getChildren()) {
if (element instanceof OuterLanguageElement) {
@@ -281,30 +340,54 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
if (number.isInfinite()) return JavaErrorMessages.message("floating.point.number.too.large");
if (number.floatValue() == 0 && !isFPZero()) return JavaErrorMessages.message("floating.point.number.too.small");
}
if (value instanceof Double) {
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()) return JavaErrorMessages.message("floating.point.number.too.small");
}
return null;
}
@NotNull
@Override
public Collection<? extends IntentionAction> getIntentions() {
final TreeElement literal = getFirstChildNode();
final String text = literal.getText().toLowerCase();
final IElementType type = literal.getElementType();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(this);
if (REAL_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && text.startsWith(HEX_PREFIX)) {
return Arrays.asList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
}
}
if (NUMERIC_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && (text.startsWith(BIN_PREFIX) || text.contains("_"))) {
return Arrays.asList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_7));
}
}
return Collections.emptyList();
}
/**
* @return true if floating point literal consists of zeros only
*/
private boolean isFPZero() {
String text = getFirstChildNode().getText();
final String text = getFirstChildNode().getText();
for(int i = 0; i < text.length(); i++){
char c = text.charAt(i);
final char c = text.charAt(i);
if (Character.isDigit(c) && c != '0') return false;
if (Character.toUpperCase(c) == 'E') break;
}
return true;
}
private static String internedParseStringCharacters(String chars) {
StringBuilder outChars = new StringBuilder(chars.length());
boolean success = parseStringCharacters(chars, outChars, null);
@Nullable
private static String internedParseStringCharacters(final String chars) {
final StringBuilder outChars = new StringBuilder(chars.length());
final boolean success = parseStringCharacters(chars, outChars, null);
return success ? outChars.toString() : null;
}
@@ -471,4 +554,3 @@ public class PsiLiteralExpressionImpl extends ExpressionPsiElement implements Ps
InjectedLanguageUtil.enumerate(this, visitor);
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2011 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 com.intellij.util.text;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
public class LiteralFormatUtil {
private LiteralFormatUtil() { }
@NotNull
public static String removeUnderscores(@NotNull final String text) {
return StringUtil.cleanString(text, "_");
}
}
@@ -1,64 +1,69 @@
/// assignment compatible types
import java.io.*;
import java.net.*;
public class a {
final int FI = 2;
final int FIBIG = 200000000;
void f() {
int i1=-<error descr="Integer number too large">2147483649</error>;
int i2=<error descr="Integer number too large">2147483648</error>;
int i3 = -2147483648;
int i4 = -0x7fffffff;
int i5 = -017777777777;
int i6 = <error descr="Hexadecimal numbers must contain at least one hexadecimal digit">0x</error>;
int i7 = 0xdeadbeef;
int i8 = 0xffffffff;
int i9=<error descr="Integer number too large">0xffffffff9</error>;
int i10= 0x80000000;
int i11=0000000000000+0x000000000;
int i12=0x00000000000000000000000;
int i13= <error descr="Integer number too large">040000000000</error>;
int i14= 020000000000;
int i15 = <error descr="Integer number too large">0xf044332211</error>;
int octale = 017777777777; // negative
int i1= -<error descr="Integer number too large">2147483649</error>;
int i2= <error descr="Integer number too large">2147483648</error>;
int i3 = -2147483648;
int i4 = -0x7fffffff;
int i5 = -017777777777;
int i6 = <error descr="Hexadecimal numbers must contain at least one hexadecimal digit">0x</error>;
int i7 = 0xdeadbeef;
int i8 = 0xffffffff;
int i9 = <error descr="Integer number too large">0xffffffff9</error>;
int i10 = 0x80000000;
int i11 = 0000000000000+0x000000000;
int i12 = 0x00000000000000000000000;
int i13 = <error descr="Integer number too large">040000000000</error>;
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>;
long l1 = -<error descr="Long number too large">9223372036854775809L</error>;
long l2 = <error descr="Long number too large">9223372036854775808L</error>;
long l3 = -9223372036854775808L;
long l4 = -<error descr="Integer number too large">2147483649</error>;
long l5 = <error descr="Integer number too large">2147483648</error>;
long l6 = <error descr="Hexadecimal numbers must contain at least one hexadecimal digit">0xL</error>;
long l7 = 0xdeadbeefffffffffL;
long l8 = 0xffffffffffffffffL;
long l9 = <error descr="Long number too large">0xffffffffffffffff9L</error>;
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>;
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>;
long l1=-<error descr="Long number too large">9223372036854775809L</error>;
long l2=<error descr="Long number too large">9223372036854775808L</error>;
long l3=-9223372036854775808L;
long l4=-<error descr="Integer number too large">2147483649</error>;
long l5=<error descr="Integer number too large">2147483648</error>;
long l6 = <error descr="Hexadecimal numbers must contain at least one hexadecimal digit">0xL</error>;
long l7= 0xdeadbeefffffffffL;
long l8= 0xffffffffffffffffL;
long l9=<error descr="Long number too large">0xffffffffffffffff9L</error>;
long l10=0x8000000000000000L;
long octalValue = 01777777777777777777600L;
long octalValua = 01777777777777777777777L;
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;
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 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>;
double d4=<error descr="Malformed floating point literal">1.E-</error>;
double d5=<error descr="Malformed floating point literal">.1eD</error>;
double d6=<error descr="Malformed floating point literal">.1e+D</error>;
double d7=<error descr="Malformed floating point literal">1e+D</error>;
double d8=<error descr="Malformed floating point literal">1e-D</error>;
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 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 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>;
double d4 = <error descr="Malformed floating point literal">1.E-</error>;
double d5 = <error descr="Malformed floating point literal">.1eD</error>;
double d6 = <error descr="Malformed floating point literal">.1e+D</error>;
double d7 = <error descr="Malformed floating point literal">1e+D</error>;
double d8 = <error descr="Malformed floating point literal">1e-D</error>;
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>;
}
}
@@ -0,0 +1,45 @@
public class NumericLiterals {
void f() {
int i1 = 1_2;
int i2 = 012__34;
int i3 = 0x1_2_3_4;
int i4 = 0B0;
int i5 = 0b0001_0010_0100_1000;
int i6 = <error descr="Binary numbers must contain at least one binary digit">0b</error>;
int i7 = <error descr="Integer number too large">0b1_1111_1111_1111_1111_1111_1111_1111_1111</error>;
long l1 = 1_2L;
long l2 = 012__34l;
long l3 = 0x1_2_3_4L;
long l4 = 0B0L;
long l5 = 0b0001_0010_0100_1000l;
long l6 = <error descr="Binary numbers must contain at least one binary digit">0Bl</error>;
long l7 = <error descr="Long number too large">0B1_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L</error>;
float f1 = 1_0f;
float f2 = 1e1_2f;
float f3 = 2_2.f;
float f4 = .3_3f;
float f5 = 3.14_16f;
float f6 = 6.022___137e+2_3f;
float f7 = 0xa_ap1_0f;
float f8 = 0xa_b.p22F;
float f9 = 0x.ab__cP0f;
float f10 = 0xa_bc.d_efP0F;
float f11= <error descr="Floating point number too small">1e-4__6f</error>;
float f12 = <error descr="Floating point number too large">1e3_9f</error>;
double d1 = 0_0d;
double d2 = 1e1_1;
double d3 = 2_2.;
double d4 = .3_3;
double d5 = 3.141_592;
double d6 = 1e-9_9d;
double d7 = 1e1__3_7;
double d8 = 0xa_ap1;
double d9 = 0xa_b.P1_2;
double d10 = 0x.a_bcP1___23d;
double d11 = <error descr="Floating point number too small">1e-3_2_4</error>;
double d12 = <error descr="Floating point number too large">0xa_bc.de_fP1_234D</error>;
}
}
@@ -145,4 +145,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
}
}
public void testNumericLiterals() throws Exception {
doTest(false, false);
}
}
@@ -0,0 +1,139 @@
/*
* Copyright 2000-2011 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 com.intellij.lang.java.lexer;
import com.intellij.lexer.JavaLexer;
import com.intellij.lexer.Lexer;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.LexerTestCase;
public class JavaLexerTest extends LexerTestCase {
public void testClassicNumericLiterals() {
doTest("0 1234 01234 0x1234",
"INTEGER_LITERAL ('0')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('1234')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('01234')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0x1234')");
doTest("0L 1234l 01234L 0x1234l",
"LONG_LITERAL ('0L')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('1234l')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('01234L')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('0x1234l')");
doTest("0f 1e1f 2.f .3f 0f 3.14f 6.022137e+23f",
"FLOAT_LITERAL ('0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('1e1f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('2.f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('.3f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('3.14f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('6.022137e+23f')");
doTest("0d 1e1 2. .3 0.0 3.14 1e-9d 1e137",
"DOUBLE_LITERAL ('0d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e1')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('2.')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('.3')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0.0')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('3.14')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e-9d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e137')");
}
public void testTigerNumericLiterals() throws Exception {
doTest("0xap0f 0xab.p0F 0x.abcP0f 0xabc.defP0F",
"FLOAT_LITERAL ('0xap0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0xab.p0F')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0x.abcP0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0xabc.defP0F')");
doTest("0xap1 0xab.P12 0x.abcP123d 0xabc.defP1234D",
"DOUBLE_LITERAL ('0xap1')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0xab.P12')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0x.abcP123d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0xabc.defP1234D')");
}
public void testCoinNumericLiterals() {
doTest("1_2 0_1 012__34 0x1_2_3_4 0B0 0b0001_0010_0100_1000",
"INTEGER_LITERAL ('1_2')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0_1')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('012__34')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0x1_2_3_4')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0B0')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0b0001_0010_0100_1000')");
doTest("1_2L 0_7l 012__34l 0x1_2_3_4L 0B0L 0b0001_0010_0100_1000l",
"LONG_LITERAL ('1_2L')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('0_7l')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('012__34l')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('0x1_2_3_4L')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('0B0L')\nWHITE_SPACE (' ')\n" +
"LONG_LITERAL ('0b0001_0010_0100_1000l')");
doTest("1_0f 1e1_2f 2_2.f .3_3f 3.14_16f 6.022___137e+2_3f",
"FLOAT_LITERAL ('1_0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('1e1_2f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('2_2.f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('.3_3f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('3.14_16f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('6.022___137e+2_3f')");
doTest("0_0d 1e1_1 2_2. .3_3 3.141_592 1e-9_9d 1e1__3_7",
"DOUBLE_LITERAL ('0_0d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e1_1')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('2_2.')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('.3_3')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('3.141_592')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e-9_9d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1e1__3_7')");
doTest("0xa_ap1_0f 0xa_b.p22F 0x.ab__cP0f 0xa_bc.d_efP0F",
"FLOAT_LITERAL ('0xa_ap1_0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0xa_b.p22F')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0x.ab__cP0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0xa_bc.d_efP0F')");
doTest("0xa_ap1 0xa_b.P1_2 0x.a_bcP1___23d 0xa_bc.de_fP1_234D",
"DOUBLE_LITERAL ('0xa_ap1')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0xa_b.P1_2')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0x.a_bcP1___23d')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('0xa_bc.de_fP1_234D')");
}
public void testMalformedCoinLiterals() throws Exception {
doTest("0_ _1 0_8 0x_f 0b_1 0B2 0x1.0_p-1 1.0e_1022",
"INTEGER_LITERAL ('0')\nIDENTIFIER ('_')\nWHITE_SPACE (' ')\n" +
"IDENTIFIER ('_1')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0')\nIDENTIFIER ('_8')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0x')\nIDENTIFIER ('_f')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0b')\nIDENTIFIER ('_1')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0B')\nINTEGER_LITERAL ('2')\nWHITE_SPACE (' ')\n" +
"INTEGER_LITERAL ('0x1')\nDOUBLE_LITERAL ('.0')\nIDENTIFIER ('_p')\nMINUS ('-')\nINTEGER_LITERAL ('1')\nWHITE_SPACE (' ')\n" +
"DOUBLE_LITERAL ('1.0e')\nIDENTIFIER ('_1022')");
}
@Override
protected Lexer createLexer() {
return new JavaLexer(LanguageLevel.HIGHEST);
}
@Override
protected String getDirPath() {
return "";
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2011 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 com.intellij.codeInspection;
import com.intellij.codeInsight.intention.IntentionAction;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface IntentionProvider {
@NotNull
Collection<? extends IntentionAction> getIntentions();
}
@@ -34,6 +34,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -51,6 +52,12 @@ public final class QuickFixAction {
registerQuickFixAction(info, null, action, null);
}
public static void registerQuickFixActions(final HighlightInfo info, final Collection<? extends IntentionAction> actions) {
for (IntentionAction action : actions) {
registerQuickFixAction(info, action);
}
}
@Deprecated
public static void registerQuickFixAction(HighlightInfo info, IntentionAction action, List<IntentionAction> options, String displayName) {
doRegister(info, action, options, displayName, null, null);
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -31,6 +32,10 @@ import java.io.IOException;
public abstract class LexerTestCase extends UsefulTestCase {
protected void doTest(@NonNls String text) {
doTest(text, null);
}
protected void doTest(@NonNls String text, @Nullable String expected) {
Lexer lexer = createLexer();
lexer.start(text);
String result = "";
@@ -45,7 +50,13 @@ public abstract class LexerTestCase extends UsefulTestCase {
result += line;
lexer.advance();
}
assertSameLinesWithFile(PathManager.getHomePath() + "/" + getDirPath() + "/" + getTestName(true) + ".txt", result);
if (expected != null) {
assertSameLines(expected, result);
}
else {
assertSameLinesWithFile(PathManager.getHomePath() + "/" + getDirPath() + "/" + getTestName(true) + ".txt", result);
}
}
protected void doFileTest(@NonNls String fileExt) {
@@ -1842,4 +1842,16 @@ public class StringUtil {
}
return true;
}
public static String cleanString(@NotNull final String original, final String charsToRemove) {
if (original.length() == 0) return original;
final StringBuilder builder = new StringBuilder(original.length());
for (int i = 0; i < original.length(); i++) {
final char ch = original.charAt(i);
if (charsToRemove.indexOf(ch) < 0) builder.append(ch);
}
return builder.toString();
}
}
@@ -261,6 +261,7 @@ uidesigned.field.is.overwritten.by.generated.code=Field ''{0}'' is overwritten b
uidesigner.bound.field.type.mismatch=Types of GUI component (''{0}'') and bound field (''{1}'') do not match
hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit=Hexadecimal numbers must contain at least one hexadecimal digit
binary.numbers.must.contain.at.least.one.hexadecimal.digit=Binary numbers must contain at least one binary digit
integer.number.too.large=Integer number too large
long.number.too.large=Long number too large
malformed.floating.point.literal=Malformed floating point literal
@@ -272,6 +273,9 @@ illegal.line.end.in.string.literal=Illegal line end in string 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