mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Compute constant expression as an inspection; minor improvements
Works for unary operation Do not suggested if replacement is the same as the original code Replacement is displayed in the quick-fix name
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Allows you to replace compile-time constant expression with its actual value (e.g. "2 + 2" with "4").
|
||||
<!-- tooltip end -->
|
||||
<small>New in 2018.1</small>
|
||||
</body>
|
||||
</html>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Compute constant value of '"The quick brown fox jumps " + 100000 + " times" + " over the lazy dog"'" "true"
|
||||
class Test {
|
||||
void test() {
|
||||
// Do not display the result in action name
|
||||
String foo = "The quick brown fox jumps 100000 times over the lazy dog";
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Replace '2 * 2' with constant value '4'" "true"
|
||||
class Test {
|
||||
int x = 4;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Fix all 'Constant expression can be evaluated' problems in file" "true"
|
||||
class Test {
|
||||
void test() {
|
||||
String[] squares = new String[10];
|
||||
squares[0] = "0*0=0";
|
||||
squares[1] = "1*1=1";
|
||||
squares[2] = "2*2=4";
|
||||
squares[3] = "3*3=9";
|
||||
squares[4] = "4*4=16";
|
||||
squares[5] = "5*5=25";
|
||||
squares[6] = "6*6=36";
|
||||
squares[7] = "7*7=49";
|
||||
squares[8] = "8*8=64";
|
||||
squares[9] = "9*9=81";
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Replace '~2' with constant value '-3'" "true"
|
||||
class Test {
|
||||
int x = -3;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Compute constant value of '"The quick brown fox jumps " + 100000 + " times" + " over the lazy dog"'" "true"
|
||||
class Test {
|
||||
void test() {
|
||||
// Do not display the result in action name
|
||||
String foo = "The quick brown fox jumps " + 10<caret>0000 + " times" + " over the lazy dog";
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Replace '2 * 2' with constant value '4'" "true"
|
||||
class Test {
|
||||
int x = 2*<caret>2;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Fix all 'Constant expression can be evaluated' problems in file" "true"
|
||||
class Test {
|
||||
void test() {
|
||||
String[] squares = new String[10];
|
||||
squares[0] = 0 <caret>+ "*" + 0 + "=" + 0 * 0;
|
||||
squares[1] = 1 + "*" + 1 + "=" + 1 * 1;
|
||||
squares[2] = 2 + "*" + 2 + "=" + 2 * 2;
|
||||
squares[3] = 3 + "*" + 3 + "=" + 3 * 3;
|
||||
squares[4] = 4 + "*" + 4 + "=" + 4 * 4;
|
||||
squares[5] = 5 + "*" + 5 + "=" + 5 * 5;
|
||||
squares[6] = 6 + "*" + 6 + "=" + 6 * 6;
|
||||
squares[7] = 7 + "*" + 7 + "=" + 7 * 7;
|
||||
squares[8] = 8 + "*" + 8 + "=" + 8 * 8;
|
||||
squares[9] = 9 + "*" + 9 + "=" + 9 * 9;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Replace '~2' with constant value '-3'" "true"
|
||||
class Test {
|
||||
int x = ~<caret>2;
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Fix all 'Constant expression can be evaluated' problems in file" "false"
|
||||
class Test {
|
||||
int x = -<caret>2;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Fix all 'Constant expression can be evaluated' problems in file" "false"
|
||||
class Test {
|
||||
void test() {
|
||||
// Do not suggest to compute for performance reasons
|
||||
String foo = "The quick brown fox jumps " + 10<caret>0000 + "times" + "over the lazy dog"+
|
||||
"The quick brown fox jumps " + 100000 + "times" + "over the lazy dog"+
|
||||
"The quick brown fox jumps " + 100000 + "times" + "over the lazy dog"+
|
||||
"The quick brown fox jumps " + 100000 + "times" + "over the lazy dog"+
|
||||
"The quick brown fox jumps " + 100000 + "times" + "over the lazy dog";
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -2261,4 +2261,9 @@ copy.constructor.misses.field.problem.descriptor.3=Copy constructor does not cop
|
||||
copy.constructor.misses.field.problem.descriptor.many=Copy constructor does not copy {0} fields
|
||||
|
||||
fix.add.argument.family.name=Add argument
|
||||
fix.add.argument.name=Add ''{0}'' argument
|
||||
fix.add.argument.name=Add ''{0}'' argument
|
||||
|
||||
inspection.constant.expression.display.name=Constant expression can be evaluated
|
||||
inspection.constant.expression.fix.name=Compute constant value of ''{0}''
|
||||
inspection.constant.expression.fix.name.with.value=Replace ''{0}'' with constant value ''{1}''
|
||||
inspection.constant.expression.fix.family.name=Compute constant value
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ConstantEvaluationOverflowException;
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ConstantExpressionInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitUnaryExpression(PsiUnaryExpression expression) {
|
||||
handle(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPolyadicExpression(PsiPolyadicExpression expression) {
|
||||
handle(expression);
|
||||
}
|
||||
|
||||
void handle(PsiExpression expression) {
|
||||
// intention disabled for long expressions because of performance issues on
|
||||
// relatively common large string expressions.
|
||||
if (expression.getTextLength() > 200) return;
|
||||
if (expression.getType() == null) return;
|
||||
if (!PsiUtil.isConstantExpression(expression)) return;
|
||||
final PsiElement parent = expression.getParent();
|
||||
if (parent instanceof PsiExpression && PsiUtil.isConstantExpression((PsiExpression)parent)) return;
|
||||
try {
|
||||
final Object value = ExpressionUtils.computeConstantExpression(expression, true);
|
||||
if (value != null) {
|
||||
String valueText = getValueText(value);
|
||||
if (!expression.textMatches(valueText)) {
|
||||
holder.registerProblem(expression, InspectionGadgetsBundle.message("inspection.constant.expression.display.name"),
|
||||
new ComputeConstantValueFix(expression, valueText));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ConstantEvaluationOverflowException ignore) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class ComputeConstantValueFix implements LocalQuickFix {
|
||||
private final String myText;
|
||||
private String myValueText;
|
||||
|
||||
public ComputeConstantValueFix(PsiExpression expression, String valueText) {
|
||||
myText = PsiExpressionTrimRenderer.render(expression);
|
||||
myValueText = valueText;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
if (myValueText.length() > 50) {
|
||||
return InspectionGadgetsBundle.message("inspection.constant.expression.fix.name", myText);
|
||||
}
|
||||
return InspectionGadgetsBundle.message("inspection.constant.expression.fix.name.with.value", myText, myValueText);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("inspection.constant.expression.fix.family.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiExpression expression = (PsiExpression)descriptor.getStartElement();
|
||||
final Object value = ExpressionUtils.computeConstantExpression(expression);
|
||||
@NonNls final String newExpression = getValueText(value);
|
||||
PsiReplacementUtil.replaceExpression(expression, newExpression, new CommentTracker());
|
||||
}
|
||||
}
|
||||
|
||||
private static String getValueText(Object value) {
|
||||
@NonNls final String newExpression;
|
||||
if (value instanceof String) {
|
||||
final String string = (String)value;
|
||||
newExpression = '"' + StringUtil.escapeStringCharacters(string) + '"';
|
||||
}
|
||||
else if (value instanceof Character) {
|
||||
newExpression = '\'' + StringUtil.escapeStringCharacters(value.toString()) + '\'';
|
||||
}
|
||||
else if (value instanceof Long) {
|
||||
newExpression = value.toString() + 'L';
|
||||
}
|
||||
else if (value instanceof Double) {
|
||||
final double v = ((Double)value).doubleValue();
|
||||
if (Double.isNaN(v)) {
|
||||
newExpression = "java.lang.Double.NaN";
|
||||
}
|
||||
else if (Double.isInfinite(v)) {
|
||||
if (v > 0.0) {
|
||||
newExpression = "java.lang.Double.POSITIVE_INFINITY";
|
||||
}
|
||||
else {
|
||||
newExpression = "java.lang.Double.NEGATIVE_INFINITY";
|
||||
}
|
||||
}
|
||||
else {
|
||||
newExpression = Double.toString(v);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Float) {
|
||||
final float v = ((Float)value).floatValue();
|
||||
if (Float.isNaN(v)) {
|
||||
newExpression = "java.lang.Float.NaN";
|
||||
}
|
||||
else if (Float.isInfinite(v)) {
|
||||
if (v > 0.0F) {
|
||||
newExpression = "java.lang.Float.POSITIVE_INFINITY";
|
||||
}
|
||||
else {
|
||||
newExpression = "java.lang.Float.NEGATIVE_INFINITY";
|
||||
}
|
||||
}
|
||||
else {
|
||||
newExpression = Float.toString(v) + 'f';
|
||||
}
|
||||
}
|
||||
else if (value == null) {
|
||||
newExpression = "null";
|
||||
}
|
||||
else {
|
||||
newExpression = String.valueOf(value);
|
||||
}
|
||||
return newExpression;
|
||||
}
|
||||
}
|
||||
@@ -2788,6 +2788,10 @@
|
||||
bundle="com.siyeh.InspectionGadgetsBundle" key="variable.type.can.be.explicit.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.language.level.specific.issues.and.migration.aids10"
|
||||
implementationClass="com.intellij.codeInspection.VariableTypeCanBeExplicitInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ConstantExpression" enabledByDefault="true" level="INFORMATION"
|
||||
bundle="com.siyeh.InspectionGadgetsBundle" key="inspection.constant.expression.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
|
||||
implementationClass="com.siyeh.ig.style.ConstantExpressionInspection"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ConstantExpressionInspectionTest extends LightQuickFixParameterizedTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{
|
||||
new ConstantExpressionInspection()
|
||||
};
|
||||
}
|
||||
|
||||
public void test() { doAllTests(); }
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/constantExpression";
|
||||
}
|
||||
}
|
||||
@@ -435,11 +435,6 @@
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.other</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.constant.ConstantExpressionIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.other</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.constant.ConstantSubexpressionIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
|
||||
@@ -169,7 +169,6 @@ negate.comparison.intention.name=Negate ''{0}''
|
||||
negate.comparison.intention.name1=Negate ''{0}'' to ''{1}''
|
||||
flip.commutative.method.call.intention.name=Flip ''.{0}()''
|
||||
flip.commutative.method.call.intention.name1=Flip ''.{0}()'' (may change semantics)
|
||||
constant.expression.intention.name=Compute constant value of ''{0}''
|
||||
status.bar.escape.highlighting.message=Press Escape to remove the highlighting
|
||||
1.fully.qualified.name.status.bar.escape.highlighting.message=1 fully qualified name replaced with import (press Escape to remove highlighting)
|
||||
multiple.fully.qualified.names.status.bar.escape.highlighting.message={0} fully qualified names replaced with import (press Escape to remove highlighting)
|
||||
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2018 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ipp.constant;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ipp.base.MutablyNamedIntention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import com.siyeh.ipp.psiutils.HighlightUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ConstantExpressionIntention extends MutablyNamedIntention {
|
||||
|
||||
@Override
|
||||
protected String getTextForElement(PsiElement element) {
|
||||
final String text = HighlightUtil.getPresentableText(element);
|
||||
return IntentionPowerPackBundle.message("constant.expression.intention.name", text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected PsiElementPredicate getElementPredicate() {
|
||||
return new ConstantExpressionPredicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIntention(PsiElement element) {
|
||||
final PsiExpression expression = (PsiExpression)element;
|
||||
final Object value = ExpressionUtils.computeConstantExpression(expression);
|
||||
@NonNls final String newExpression;
|
||||
if (value instanceof String) {
|
||||
final String string = (String)value;
|
||||
newExpression = '"' + StringUtil.escapeStringCharacters(string) + '"';
|
||||
}
|
||||
else if (value instanceof Character) {
|
||||
newExpression = '\'' + StringUtil.escapeStringCharacters(value.toString()) + '\'';
|
||||
}
|
||||
else if (value instanceof Long) {
|
||||
newExpression = value.toString() + 'L';
|
||||
}
|
||||
else if (value instanceof Double) {
|
||||
final double v = ((Double)value).doubleValue();
|
||||
if (Double.isNaN(v)) {
|
||||
newExpression = "java.lang.Double.NaN";
|
||||
}
|
||||
else if (Double.isInfinite(v)) {
|
||||
if (v > 0.0) {
|
||||
newExpression = "java.lang.Double.POSITIVE_INFINITY";
|
||||
}
|
||||
else {
|
||||
newExpression = "java.lang.Double.NEGATIVE_INFINITY";
|
||||
}
|
||||
}
|
||||
else {
|
||||
newExpression = Double.toString(v);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Float) {
|
||||
final float v = ((Float)value).floatValue();
|
||||
if (Float.isNaN(v)) {
|
||||
newExpression = "java.lang.Float.NaN";
|
||||
}
|
||||
else if (Float.isInfinite(v)) {
|
||||
if (v > 0.0F) {
|
||||
newExpression = "java.lang.Float.POSITIVE_INFINITY";
|
||||
}
|
||||
else {
|
||||
newExpression = "java.lang.Float.NEGATIVE_INFINITY";
|
||||
}
|
||||
}
|
||||
else {
|
||||
newExpression = Float.toString(v) + 'f';
|
||||
}
|
||||
}
|
||||
else if (value == null) {
|
||||
newExpression = "null";
|
||||
}
|
||||
else {
|
||||
newExpression = String.valueOf(value);
|
||||
}
|
||||
PsiReplacementUtil.replaceExpression(expression, newExpression, new CommentTracker());
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ipp.constant;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ConstantEvaluationOverflowException;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
|
||||
class ConstantExpressionPredicate implements PsiElementPredicate {
|
||||
|
||||
public boolean satisfiedBy(PsiElement element) {
|
||||
if (!(element instanceof PsiPolyadicExpression)) {
|
||||
return false;
|
||||
}
|
||||
if (element instanceof PsiLiteralExpression || element instanceof PsiClassObjectAccessExpression) {
|
||||
return false;
|
||||
}
|
||||
final PsiPolyadicExpression expression = (PsiPolyadicExpression)element;
|
||||
final PsiType expressionType = expression.getType();
|
||||
if (expressionType == null || expressionType.equalsToText(JAVA_LANG_STRING)) {
|
||||
// intention disabled for string concatenations because of performance issues on
|
||||
// relatively common large string expressions.
|
||||
return false;
|
||||
}
|
||||
final PsiExpression[] operands = expression.getOperands();
|
||||
for (PsiExpression operand : operands) {
|
||||
if (operand == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType type = operand.getType();
|
||||
if (type == null || type.equalsToText(JAVA_LANG_STRING)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!PsiUtil.isConstantExpression(expression)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
final Object value = ExpressionUtils.computeConstantExpression(expression, true);
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (ConstantEvaluationOverflowException ignore) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement parent = element.getParent();
|
||||
return !(parent instanceof PsiExpression) || !PsiUtil.isConstantExpression((PsiExpression)parent);
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
void f() {
|
||||
int i = 3600;
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
void f() {
|
||||
int i = <spot>60 * 60</spot>;
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention calculates the value of a compile
|
||||
time constant expression, and replaces it with an equivalent literal expression.
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user