mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
IDEA-66564 (parse indeterminate FP literals in compiled annotations, ultimate fix)
This commit is contained in:
@@ -53,7 +53,7 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
}
|
||||
|
||||
public int getStubVersion() {
|
||||
return JavaFileElementType.STUB_VERSION + 2;
|
||||
return JavaFileElementType.STUB_VERSION + 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClsBinaryExpressionImpl extends ClsElementImpl implements PsiBinaryExpression {
|
||||
private final ClsElementImpl myParent;
|
||||
private final PsiExpression myLOperand;
|
||||
private final PsiJavaToken myOperation;
|
||||
private final PsiExpression myROperand;
|
||||
|
||||
public ClsBinaryExpressionImpl(ClsElementImpl parent,
|
||||
ClsLiteralExpressionImpl lOperand,
|
||||
ClsJavaTokenImpl operation,
|
||||
ClsLiteralExpressionImpl rOperand) {
|
||||
myParent = parent;
|
||||
myLOperand = lOperand;
|
||||
myOperation = operation;
|
||||
myROperand = rOperand;
|
||||
lOperand.setParent(this);
|
||||
operation.setParent(this);
|
||||
rOperand.setParent(this);
|
||||
}
|
||||
|
||||
public ClsBinaryExpressionImpl(ClsElementImpl parent,
|
||||
ClsPrefixExpressionImpl lOperand,
|
||||
ClsJavaTokenImpl operation,
|
||||
ClsLiteralExpressionImpl rOperand) {
|
||||
myParent = parent;
|
||||
myLOperand = lOperand;
|
||||
myOperation = operation;
|
||||
myROperand = rOperand;
|
||||
lOperand.setParent(this);
|
||||
operation.setParent(this);
|
||||
rOperand.setParent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendMirrorText(int indentLevel, StringBuilder buffer) {
|
||||
buffer.append(getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMirror(@NotNull TreeElement element) {
|
||||
setMirrorCheckingType(element, JavaElementType.BINARY_EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return StringUtil.join(myLOperand.getText(), " ", myOperation.getText(), " ", myROperand.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getChildren() {
|
||||
return new PsiElement[]{myLOperand, myOperation, myROperand};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitBinaryExpression(this);
|
||||
}
|
||||
else {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiExpression getLOperand() {
|
||||
return myLOperand;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiExpression getROperand() {
|
||||
return myROperand;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaToken getOperationSign() {
|
||||
return myOperation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IElementType getOperationTokenType() {
|
||||
return myOperation.getTokenType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return myLOperand.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiBinaryExpression:" + getText();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.psi.impl.compiled;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClsJavaTokenImpl extends ClsElementImpl implements PsiJavaToken {
|
||||
private ClsElementImpl myParent;
|
||||
private final IElementType myTokenType;
|
||||
private final String myTokenText;
|
||||
|
||||
public ClsJavaTokenImpl(ClsElementImpl parent, IElementType tokenType, String tokenText) {
|
||||
myParent = parent;
|
||||
myTokenType = tokenType;
|
||||
myTokenText = tokenText;
|
||||
}
|
||||
|
||||
void setParent(ClsElementImpl parent) {
|
||||
myParent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementType getTokenType() {
|
||||
return myTokenType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return myTokenText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getChildren() {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendMirrorText(final int indentLevel, final StringBuilder buffer) {
|
||||
buffer.append(getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMirror(@NotNull TreeElement element) {
|
||||
setMirrorCheckingType(element, myTokenType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitJavaToken(this);
|
||||
}
|
||||
else {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ClsLiteralExpressionImpl extends ClsElementImpl implements PsiLiter
|
||||
}
|
||||
|
||||
public void setMirror(@NotNull TreeElement element) {
|
||||
setMirrorCheckingType(element, ElementType.LITERAL_EXPRESSION);
|
||||
setMirrorCheckingType(element, JavaElementType.LITERAL_EXPRESSION);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -122,11 +122,10 @@ public class ClsParsingUtil {
|
||||
return new ClsLiteralExpressionImpl(parent, expr.getText(), expr.getType(), ((PsiLiteralExpression)expr).getValue());
|
||||
}
|
||||
else if (expr instanceof PsiPrefixExpression) {
|
||||
final PsiExpression operand = ((PsiPrefixExpression) expr).getOperand();
|
||||
final ClsLiteralExpressionImpl literal = (ClsLiteralExpressionImpl) psiToClsExpression(operand, null);
|
||||
final ClsPrefixExpressionImpl prefixExpression = new ClsPrefixExpressionImpl(parent, literal);
|
||||
literal.setParent(prefixExpression);
|
||||
return prefixExpression;
|
||||
final PsiPrefixExpression prefixExpr = (PsiPrefixExpression)expr;
|
||||
final ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, prefixExpr.getOperationTokenType(), prefixExpr.getOperationSign().getText());
|
||||
final ClsLiteralExpressionImpl literal = (ClsLiteralExpressionImpl) psiToClsExpression(prefixExpr.getOperand(), null);
|
||||
return new ClsPrefixExpressionImpl(parent, operation, literal);
|
||||
}
|
||||
else if (expr instanceof PsiClassObjectAccessExpression) {
|
||||
final String canonicalClassText = ((PsiClassObjectAccessExpression)expr).getOperand().getType().getCanonicalText();
|
||||
@@ -135,14 +134,27 @@ public class ClsParsingUtil {
|
||||
else if (expr instanceof PsiReferenceExpression) {
|
||||
return new ClsReferenceExpressionImpl(parent, (PsiReferenceExpression)expr);
|
||||
}
|
||||
else if (expr instanceof PsiBinaryExpression) {
|
||||
final PsiBinaryExpression binaryExpr = (PsiBinaryExpression)expr;
|
||||
final PsiExpression lOperand = psiToClsExpression(binaryExpr.getLOperand(), null);
|
||||
final ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, binaryExpr.getOperationTokenType(), binaryExpr.getOperationSign().getText());
|
||||
final PsiExpression rOperand = psiToClsExpression(binaryExpr.getROperand(), null);
|
||||
if (lOperand instanceof ClsLiteralExpressionImpl) {
|
||||
return new ClsBinaryExpressionImpl(parent, (ClsLiteralExpressionImpl)lOperand, operation, (ClsLiteralExpressionImpl)rOperand);
|
||||
}
|
||||
else if (lOperand instanceof ClsPrefixExpressionImpl) {
|
||||
return new ClsBinaryExpressionImpl(parent, (ClsPrefixExpressionImpl)lOperand, operation, (ClsLiteralExpressionImpl)rOperand);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiConstantEvaluationHelper evaluator = JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper();
|
||||
final Object value = evaluator.computeConstantExpression(expr);
|
||||
if (value != null) {
|
||||
return new ClsLiteralExpressionImpl(parent, expr.getText(), expr.getType(), value);
|
||||
}
|
||||
LOG.error("Unable to compute expression value: " + expr);
|
||||
return null;
|
||||
}
|
||||
|
||||
LOG.error("Unable to compute expression value: " + expr);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
@@ -22,55 +23,72 @@ import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClsPrefixExpressionImpl extends ClsElementImpl implements PsiPrefixExpression {
|
||||
private final ClsElementImpl myParent;
|
||||
private ClsElementImpl myParent;
|
||||
private final PsiJavaToken myOperation;
|
||||
private final PsiExpression myOperand;
|
||||
|
||||
private final MySign mySign = new MySign();
|
||||
|
||||
public ClsPrefixExpressionImpl(ClsElementImpl parent, PsiExpression operand) {
|
||||
public ClsPrefixExpressionImpl(ClsElementImpl parent, ClsJavaTokenImpl operation, ClsLiteralExpressionImpl operand) {
|
||||
myParent = parent;
|
||||
myOperation = operation;
|
||||
myOperand = operand;
|
||||
operation.setParent(this);
|
||||
operand.setParent(this);
|
||||
}
|
||||
|
||||
void setParent(ClsElementImpl parent) {
|
||||
myParent = parent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiExpression getOperand() {
|
||||
return myOperand;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaToken getOperationSign() {
|
||||
return mySign;
|
||||
return myOperation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IElementType getOperationTokenType() {
|
||||
return getOperationSign().getTokenType();
|
||||
return myOperation.getTokenType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return myOperand.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getChildren() {
|
||||
return new PsiElement[]{getOperationSign(), getOperand()};
|
||||
return new PsiElement[]{myOperation, myOperand};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "-" + myOperand.getText();
|
||||
return StringUtil.join(myOperation.getText(), myOperand.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendMirrorText(final int indentLevel, final StringBuilder buffer) {
|
||||
buffer.append(getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMirror(@NotNull TreeElement element) {
|
||||
setMirrorCheckingType(element, JavaElementType.PREFIX_EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitPrefixExpression(this);
|
||||
@@ -80,39 +98,8 @@ public class ClsPrefixExpressionImpl extends ClsElementImpl implements PsiPrefix
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiPrefixExpression:" + getText();
|
||||
}
|
||||
|
||||
private class MySign extends ClsElementImpl implements PsiJavaToken {
|
||||
public IElementType getTokenType() {
|
||||
return JavaTokenType.MINUS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getChildren() {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public PsiElement getParent() {
|
||||
return ClsPrefixExpressionImpl.this;
|
||||
}
|
||||
|
||||
public void appendMirrorText(final int indentLevel, final StringBuilder buffer) {
|
||||
buffer.append("-");
|
||||
}
|
||||
|
||||
public void setMirror(@NotNull TreeElement element) {
|
||||
setMirrorCheckingType(element, JavaTokenType.MINUS);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitJavaToken(this);
|
||||
}
|
||||
else {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,14 @@ import java.util.regex.Pattern;
|
||||
public class ClsStubBuilder {
|
||||
private static final Pattern REGEX_PATTERN = Pattern.compile("(?<=[^\\$])\\${1}(?=[^\\$])");
|
||||
|
||||
public static final String DOUBLE_POSITIVE_INF = "1.0 / 0.0";
|
||||
public static final String DOUBLE_NEGATIVE_INF = "-1.0 / 0.0";
|
||||
public static final String DOUBLE_NAN = "0.0d / 0.0";
|
||||
|
||||
public static final String FLOAT_POSITIVE_INF = "1.0f / 0.0";
|
||||
public static final String FLOAT_NEGATIVE_INF = "-1.0f / 0.0";
|
||||
public static final String FLOAT_NAN = "0.0f / 0.0";
|
||||
|
||||
private ClsStubBuilder() { }
|
||||
|
||||
@Nullable
|
||||
@@ -679,26 +687,28 @@ public class ClsStubBuilder {
|
||||
if (value instanceof Long) return value.toString() + "L";
|
||||
|
||||
if (value instanceof Double) {
|
||||
final double v = ((Double)value).doubleValue();
|
||||
if (Double.isInfinite(v)) {
|
||||
return StringUtil.join(CommonClassNames.JAVA_LANG_DOUBLE, ".", (v > 0 ? "POSITIVE_INFINITY" : "NEGATIVE_INFINITY"));
|
||||
final double d = ((Double)value).doubleValue();
|
||||
if (Double.isInfinite(d)) {
|
||||
return d > 0 ? DOUBLE_POSITIVE_INF : DOUBLE_NEGATIVE_INF;
|
||||
}
|
||||
else if (Double.isNaN(v)) {
|
||||
return StringUtil.join(CommonClassNames.JAVA_LANG_DOUBLE, ".", "NaN");
|
||||
else if (Double.isNaN(d)) {
|
||||
return DOUBLE_NAN;
|
||||
}
|
||||
return Double.toString(v);
|
||||
return Double.toString(d);
|
||||
}
|
||||
|
||||
if (value instanceof Float) {
|
||||
final float v = ((Float)value).floatValue();
|
||||
|
||||
if (Float.isInfinite(v)) {
|
||||
return StringUtil.join(CommonClassNames.JAVA_LANG_FLOAT, ".", (v > 0 ? "POSITIVE_INFINITY" : "NEGATIVE_INFINITY"));
|
||||
return v > 0 ? FLOAT_POSITIVE_INF : FLOAT_NEGATIVE_INF;
|
||||
}
|
||||
else if (Float.isNaN(v)) {
|
||||
return StringUtil.join(CommonClassNames.JAVA_LANG_FLOAT, ".", "NaN");
|
||||
return FLOAT_NAN;
|
||||
}
|
||||
else {
|
||||
return Float.toString(v) + "f";
|
||||
}
|
||||
return Float.toString(v) + "f";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -664,9 +664,9 @@ public class ClsRepositoryUseTest extends PsiTestCase{
|
||||
assert method instanceof PsiAnnotationMethod : method;
|
||||
try {
|
||||
final PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)method).getDefaultValue();
|
||||
assert defaultValue instanceof PsiReferenceExpression : defaultValue;
|
||||
final String type = method.getName().startsWith("f") ? "Float." : "Double";
|
||||
assert defaultValue.getText().contains(type) : defaultValue;
|
||||
assert defaultValue instanceof PsiBinaryExpression : defaultValue;
|
||||
final PsiPrimitiveType type = method.getName().startsWith("f") ? PsiType.FLOAT : PsiType.DOUBLE;
|
||||
assertEquals(type, ((PsiBinaryExpression)defaultValue).getType());
|
||||
}
|
||||
catch (Exception e) {
|
||||
final String valueText = ((PsiMethodStub)((StubBasedPsiElement)method).getStub()).getDefaultValueText();
|
||||
|
||||
Reference in New Issue
Block a user