moved to analysis

This commit is contained in:
Alexey Kudravtsev
2013-05-24 13:49:38 +04:00
parent 9d71b57425
commit 853c6c22e6
3 changed files with 174 additions and 139 deletions
@@ -0,0 +1,107 @@
/*
* Copyright 2000-2013 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.accessStaticViaInstance;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public class AccessStaticViaInstanceBase extends BaseJavaBatchLocalInspectionTool {
@NonNls public static final String ACCESS_STATIC_VIA_INSTANCE = "AccessStaticViaInstance";
@Override
@NotNull
public String getGroupDisplayName() {
return "";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionsBundle.message("access.static.via.instance");
}
@Override
@NotNull
@NonNls
public String getShortName() {
return ACCESS_STATIC_VIA_INSTANCE;
}
@Override
public String getAlternativeID() {
return "static-access";
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
checkAccessStaticMemberViaInstanceReference(expression, holder, isOnTheFly);
}
};
}
private void checkAccessStaticMemberViaInstanceReference(PsiReferenceExpression expr, ProblemsHolder holder, boolean onTheFly) {
JavaResolveResult result = expr.advancedResolve(false);
PsiElement resolved = result.getElement();
if (!(resolved instanceof PsiMember)) return;
PsiExpression qualifierExpression = expr.getQualifierExpression();
if (qualifierExpression == null) return;
if (qualifierExpression instanceof PsiReferenceExpression) {
final PsiElement qualifierResolved = ((PsiReferenceExpression)qualifierExpression).resolve();
if (qualifierResolved instanceof PsiClass || qualifierResolved instanceof PsiPackage) {
return;
}
}
if (!((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC)) return;
String description = JavaErrorMessages.message("static.member.accessed.via.instance.reference",
JavaHighlightUtil.formatType(qualifierExpression.getType()),
HighlightMessageUtil.getSymbolName(resolved, result.getSubstitutor()));
if (!onTheFly) {
if (RemoveUnusedVariableUtil.checkSideEffects(qualifierExpression, null, new ArrayList<PsiElement>())) {
holder.registerProblem(expr, description);
return;
}
}
holder.registerProblem(expr, description, createAccessStaticViaInstanceFix(expr, onTheFly, result));
}
protected LocalQuickFix createAccessStaticViaInstanceFix(PsiReferenceExpression expr,
boolean onTheFly,
JavaResolveResult result) {
return null;
}
}
@@ -21,8 +21,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -96,7 +94,7 @@ public class AccessStaticViaInstanceFix extends LocalQuickFixAndIntentionActionO
final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
if (qualifierExpression != null) {
if (!checkSideEffects(project, containingClass, qualifierExpression, factory, myExpression)) return;
if (!checkSideEffects(project, containingClass, qualifierExpression, factory, myExpression,editor)) return;
PsiElement newQualifier = qualifierExpression.replace(factory.createReferenceExpression(containingClass));
PsiElement qualifiedWithClassName = myExpression.copy();
newQualifier.delete();
@@ -110,69 +108,71 @@ public class AccessStaticViaInstanceFix extends LocalQuickFixAndIntentionActionO
}
}
private boolean checkSideEffects(final Project project, PsiClass containingClass, final PsiExpression qualifierExpression,
PsiElementFactory factory, final PsiElement myExpression) {
private boolean checkSideEffects(final Project project,
PsiClass containingClass,
final PsiExpression qualifierExpression,
PsiElementFactory factory,
final PsiElement myExpression,
Editor editor) {
final List<PsiElement> sideEffects = new ArrayList<PsiElement>();
boolean hasSideEffects = RemoveUnusedVariableUtil.checkSideEffects(qualifierExpression, null, sideEffects);
if (hasSideEffects && !myOnTheFly) return false;
if (hasSideEffects && !ApplicationManager.getApplication().isUnitTestMode()) {
final TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
final Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
if (editor == null) {
return false;
}
HighlightManager.getInstance(project).addOccurrenceHighlights(editor, PsiUtilCore.toPsiElementArray(sideEffects), attributes, true,
null);
try {
hasSideEffects = PsiUtil.isStatement(factory.createStatementFromText(qualifierExpression.getText(), qualifierExpression));
}
catch (IncorrectOperationException e) {
hasSideEffects = false;
}
final PsiReferenceExpression qualifiedWithClassName = (PsiReferenceExpression)myExpression.copy();
qualifiedWithClassName.setQualifierExpression(factory.createReferenceExpression(containingClass));
final boolean canCopeWithSideEffects = hasSideEffects;
final SideEffectWarningDialog dialog =
new SideEffectWarningDialog(project, false, null, sideEffects.get(0).getText(), PsiExpressionTrimRenderer.render(qualifierExpression),
canCopeWithSideEffects){
@Override
protected String sideEffectsDescription() {
if (canCopeWithSideEffects) {
return "<html><body>" +
" There are possible side effects found in expression '" +
qualifierExpression.getText() +
"'<br>" +
" You can:<ul><li><b>Remove</b> class reference along with whole expressions involved, or</li>" +
" <li><b>Transform</b> qualified expression into the statement on its own.<br>" +
" That is,<br>" +
" <table border=1><tr><td><code>" +
myExpression.getText() +
"</code></td></tr></table><br> becomes: <br>" +
" <table border=1><tr><td><code>" +
qualifierExpression.getText() +
";<br>" +
qualifiedWithClassName.getText() +
" </code></td></tr></table></li>" +
" </body></html>";
} else {
return "<html><body> There are possible side effects found in expression '" + qualifierExpression.getText() + "'<br>" +
"You can:<ul><li><b>Remove</b> class reference along with whole expressions involved, or</li></body></html>";
}
if (!hasSideEffects || ApplicationManager.getApplication().isUnitTestMode()) {
return true;
}
if (editor == null) {
return false;
}
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
HighlightManager.getInstance(project).addOccurrenceHighlights(editor, PsiUtilCore.toPsiElementArray(sideEffects), attributes, true, null);
try {
hasSideEffects = PsiUtil.isStatement(factory.createStatementFromText(qualifierExpression.getText(), qualifierExpression));
}
catch (IncorrectOperationException e) {
hasSideEffects = false;
}
final PsiReferenceExpression qualifiedWithClassName = (PsiReferenceExpression)myExpression.copy();
qualifiedWithClassName.setQualifierExpression(factory.createReferenceExpression(containingClass));
final boolean canCopeWithSideEffects = hasSideEffects;
final SideEffectWarningDialog dialog =
new SideEffectWarningDialog(project, false, null, sideEffects.get(0).getText(), PsiExpressionTrimRenderer.render(qualifierExpression),
canCopeWithSideEffects){
@Override
protected String sideEffectsDescription() {
if (canCopeWithSideEffects) {
return "<html><body>" +
" There are possible side effects found in expression '" +
qualifierExpression.getText() +
"'<br>" +
" You can:<ul><li><b>Remove</b> class reference along with whole expressions involved, or</li>" +
" <li><b>Transform</b> qualified expression into the statement on its own.<br>" +
" That is,<br>" +
" <table border=1><tr><td><code>" +
myExpression.getText() +
"</code></td></tr></table><br> becomes: <br>" +
" <table border=1><tr><td><code>" +
qualifierExpression.getText() +
";<br>" +
qualifiedWithClassName.getText() +
" </code></td></tr></table></li>" +
" </body></html>";
}
};
dialog.show();
int res = dialog.getExitCode();
if (res == RemoveUnusedVariableUtil.CANCEL) return false;
try {
if (res == RemoveUnusedVariableUtil.MAKE_STATEMENT) {
final PsiStatement statementFromText = factory.createStatementFromText(qualifierExpression.getText() + ";", null);
final PsiStatement statement = PsiTreeUtil.getParentOfType(myExpression, PsiStatement.class);
statement.getParent().addBefore(statementFromText, statement);
return "<html><body> There are possible side effects found in expression '" + qualifierExpression.getText() + "'<br>" +
"You can:<ul><li><b>Remove</b> class reference along with whole expressions involved, or</li></body></html>";
}
};
dialog.show();
int res = dialog.getExitCode();
if (res == RemoveUnusedVariableUtil.CANCEL) return false;
try {
if (res == RemoveUnusedVariableUtil.MAKE_STATEMENT) {
final PsiStatement statementFromText = factory.createStatementFromText(qualifierExpression.getText() + ";", null);
final PsiStatement statement = PsiTreeUtil.getParentOfType(myExpression, PsiStatement.class);
statement.getParent().addBefore(statementFromText, statement);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
return true;
}
@@ -15,91 +15,19 @@
*/
package com.intellij.codeInspection.accessStaticViaInstance;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.AccessStaticViaInstanceFix;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import com.intellij.psi.JavaResolveResult;
import com.intellij.psi.PsiReferenceExpression;
/**
* User: anna
* Date: 15-Nov-2005
*/
public class AccessStaticViaInstance extends BaseJavaBatchLocalInspectionTool {
public static final String ACCESS_STATIC_VIA_INSTANCE = "AccessStaticViaInstance";
public class AccessStaticViaInstance extends AccessStaticViaInstanceBase {
@Override
@NotNull
public String getGroupDisplayName() {
return "";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionsBundle.message("access.static.via.instance");
}
@Override
@NotNull
@NonNls
public String getShortName() {
return ACCESS_STATIC_VIA_INSTANCE;
}
@Override
public String getAlternativeID() {
return "static-access";
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
checkAccessStaticMemberViaInstanceReference(expression, holder, isOnTheFly);
}
};
}
private static void checkAccessStaticMemberViaInstanceReference(PsiReferenceExpression expr, ProblemsHolder holder, boolean onTheFly) {
JavaResolveResult result = expr.advancedResolve(false);
PsiElement resolved = result.getElement();
if (!(resolved instanceof PsiMember)) return;
PsiExpression qualifierExpression = expr.getQualifierExpression();
if (qualifierExpression == null) return;
if (qualifierExpression instanceof PsiReferenceExpression) {
final PsiElement qualifierResolved = ((PsiReferenceExpression)qualifierExpression).resolve();
if (qualifierResolved instanceof PsiClass || qualifierResolved instanceof PsiPackage) {
return;
}
}
if (!((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC)) return;
String description = JavaErrorMessages.message("static.member.accessed.via.instance.reference",
JavaHighlightUtil.formatType(qualifierExpression.getType()),
HighlightMessageUtil.getSymbolName(resolved, result.getSubstitutor()));
if (!onTheFly) {
if (RemoveUnusedVariableUtil.checkSideEffects(qualifierExpression, null, new ArrayList<PsiElement>())) {
holder.registerProblem(expr, description);
return;
}
}
holder.registerProblem(expr, description, new AccessStaticViaInstanceFix(expr, result, onTheFly));
protected AccessStaticViaInstanceFix createAccessStaticViaInstanceFix(PsiReferenceExpression expr,
boolean onTheFly,
JavaResolveResult result) {
return new AccessStaticViaInstanceFix(expr, result, onTheFly);
}
}