psi leaks

This commit is contained in:
Alexey Kudravtsev
2011-04-18 17:06:17 +04:00
parent 65ca67c7d7
commit 8270a8614b
13 changed files with 255 additions and 191 deletions
@@ -20,8 +20,7 @@ import com.intellij.codeInsight.daemon.QuickFixBundle;
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.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
@@ -38,32 +37,36 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class AccessStaticViaInstanceFix implements LocalQuickFix {
public class AccessStaticViaInstanceFix extends LocalQuickFixAndIntentionActionOnPsiElement {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AccessStaticViaInstanceFix");
private final PsiReferenceExpression myExpression;
private final boolean myOnTheFly;
private final PsiMember myMember;
private final JavaResolveResult myResult;
private final String myText;
public AccessStaticViaInstanceFix(PsiReferenceExpression expression, JavaResolveResult result, boolean onTheFly) {
myExpression = expression;
super(expression);
myOnTheFly = onTheFly;
myMember = (PsiMember)result.getElement();
myResult = result;
PsiMember member = (PsiMember)result.getElement();
myText = calcText(member, result.getSubstitutor());
}
@NotNull
public String getName() {
PsiClass aClass = myMember.getContainingClass();
@Override
public String getText() {
return myText;
}
private static String calcText(PsiMember member, PsiSubstitutor substitutor) {
PsiClass aClass = member.getContainingClass();
if (aClass == null) return "";
return QuickFixBundle.message("access.static.via.class.reference.text",
HighlightMessageUtil.getSymbolName(myMember, myResult.getSubstitutor()),
HighlightMessageUtil.getSymbolName(member, substitutor),
HighlightUtil.formatClass(aClass),
HighlightUtil.formatClass(aClass,false));
HighlightUtil.formatClass(aClass, false));
}
@NotNull
@@ -71,16 +74,28 @@ public class AccessStaticViaInstanceFix implements LocalQuickFix {
return QuickFixBundle.message("access.static.via.class.reference.family");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
if (!myExpression.isValid() || !myMember.isValid()) return;
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
@Nullable("is null when called from inspection") Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiReferenceExpression myExpression = (PsiReferenceExpression)startElement;
if (!myExpression.isValid()) return;
if (!CodeInsightUtilBase.prepareFileForWrite(myExpression.getContainingFile())) return;
PsiElement element = myExpression.resolve();
if (!(element instanceof PsiMember)) return;
PsiMember myMember = (PsiMember)element;
if (!myMember.isValid()) return;
PsiClass containingClass = myMember.getContainingClass();
if (containingClass == null) return;
try {
final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
if (qualifierExpression != null) {
if (!checkSideEffects(project, containingClass, qualifierExpression, factory)) return;
if (!checkSideEffects(project, containingClass, qualifierExpression, factory, myExpression)) return;
PsiElement newQualifier = qualifierExpression.replace(factory.createReferenceExpression(containingClass));
PsiElement qualifiedWithClassName = myExpression.copy();
newQualifier.delete();
@@ -95,7 +110,7 @@ public class AccessStaticViaInstanceFix implements LocalQuickFix {
}
private boolean checkSideEffects(final Project project, PsiClass containingClass, final PsiExpression qualifierExpression,
PsiElementFactory factory) {
PsiElementFactory factory, final PsiElement myExpression) {
final List<PsiElement> sideEffects = new ArrayList<PsiElement>();
boolean hasSideEffects = RemoveUnusedVariableFix.checkSideEffects(qualifierExpression, null, sideEffects);
if (hasSideEffects && !myOnTheFly) return false;
@@ -35,7 +35,6 @@ import org.jetbrains.annotations.NotNull;
*/
public class SurroundWithIfFix implements LocalQuickFix {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.SurroundWithIfFix");
private final PsiExpression myExpression;
private final String myText;
@NotNull
@@ -44,8 +43,7 @@ public class SurroundWithIfFix implements LocalQuickFix {
}
public SurroundWithIfFix(@NotNull PsiExpression expressionToAssert) {
myExpression = expressionToAssert;
myText = myExpression.getText();
myText = expressionToAssert.getText();
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
@@ -83,11 +81,11 @@ public class SurroundWithIfFix implements LocalQuickFix {
return InspectionsBundle.message("inspection.surround.if.family");
}
public boolean isAvailable() {
if (!myExpression.isValid() || myText == null) {
public boolean isAvailable(PsiExpression qualifier) {
if (!qualifier.isValid() || myText == null) {
return false;
}
PsiStatement statement = PsiTreeUtil.getParentOfType(myExpression, PsiStatement.class);
PsiStatement statement = PsiTreeUtil.getParentOfType(qualifier, PsiStatement.class);
if (statement == null) return false;
PsiElement parent = statement.getParent();
return !(parent instanceof PsiForStatement);
@@ -126,7 +126,7 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
fixes.add(new AddAssertStatementFix(binary));
}
SurroundWithIfFix ifFix = new SurroundWithIfFix(qualifier);
if (ifFix.isAvailable()) {
if (ifFix.isAvailable(qualifier)) {
fixes.add(ifFix);
}
return fixes.toArray(new LocalQuickFix[fixes.size()]);
@@ -29,8 +29,10 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,9 +56,9 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
private static final String RETURN_VALUE_UNDEFINED = "#";
private ArrayList<RefMethod> mySuperMethods;
private ArrayList<RefMethod> myDerivedMethods;
private ArrayList<PsiClass> myUnThrownExceptions;
private List<RefMethod> mySuperMethods;
private List<RefMethod> myDerivedMethods;
private List<String> myUnThrownExceptions;
private RefParameter[] myParameters;
private String myReturnValueTemplate;
@@ -288,7 +290,7 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
getRefManager().fireBuildReferences(this);
}
private void collectUncaughtExceptions(PsiMethod method) {
private void collectUncaughtExceptions(@NotNull PsiMethod method) {
if (isExternalOverride()) return;
@NonNls final String name = method.getName();
if (getOwnerClass().isTestCase() && name.startsWith("test")) return;
@@ -296,9 +298,13 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
if (getSuperMethods().isEmpty()) {
PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
if (throwsList.length > 0) {
myUnThrownExceptions = new ArrayList<PsiClass>(throwsList.length);
myUnThrownExceptions = throwsList.length == 1 ? new SmartList<String>() : new ArrayList<String>(throwsList.length);
for (final PsiClassType type : throwsList) {
myUnThrownExceptions.add(type.resolve());
PsiClass aClass = type.resolve();
String fqn = aClass == null ? null : aClass.getQualifiedName();
if (fqn != null) {
myUnThrownExceptions.add(fqn);
}
}
}
}
@@ -314,7 +320,7 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
public void removeUnThrownExceptions(PsiClass unThrownException) {
if (myUnThrownExceptions != null) {
myUnThrownExceptions.remove(unThrownException);
myUnThrownExceptions.remove(unThrownException.getQualifiedName());
}
}
@@ -413,8 +419,8 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
else {
result[0] = PsiFormatUtil.formatMethod(psiMethod,
PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
PsiFormatUtil.SHOW_TYPE
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
PsiFormatUtilBase.SHOW_TYPE
);
}
}
@@ -525,7 +531,9 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
psiField.hasModifierProperty(PsiModifier.FINAL) &&
refUtil.compareAccess(refUtil.getAccessModifier(psiField), getAccessModifier()) >= 0) {
newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_CONTAINING_CLASS | PsiFormatUtil.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtilBase.SHOW_NAME |
PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
PsiFormatUtilBase.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
}
}
} else if (refUtil.isCallToSuperMethod(expression, (PsiMethod) getElement())) return;
@@ -573,17 +581,19 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
for (RefMethod refSuper : getSuperMethods()) {
((RefMethodImpl)refSuper).updateThrowsList(exceptionType);
}
} else if (myUnThrownExceptions != null) {
}
else if (myUnThrownExceptions != null) {
if (exceptionType == null) {
myUnThrownExceptions = null;
return;
}
PsiClass[] arrayed = myUnThrownExceptions.toArray(new PsiClass[myUnThrownExceptions.size()]);
for (int i = arrayed.length - 1; i >= 0; i--) {
PsiClass classType = arrayed[i];
if (InheritanceUtil.isInheritorOrSelf(exceptionType.resolve(), classType, true) ||
InheritanceUtil.isInheritorOrSelf(classType, exceptionType.resolve(), true)) {
PsiClass exceptionClass = exceptionType.resolve();
JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
for (int i = myUnThrownExceptions.size() - 1; i >= 0; i--) {
String exceptionFqn = myUnThrownExceptions.get(i);
PsiClass classType = facade.findClass(exceptionFqn, GlobalSearchScope.allScope(getRefManager().getProject()));
if (InheritanceUtil.isInheritorOrSelf(exceptionClass, classType, true) ||
InheritanceUtil.isInheritorOrSelf(classType, exceptionClass, true)) {
myUnThrownExceptions.remove(i);
}
}
@@ -595,7 +605,13 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
@Nullable
public PsiClass[] getUnThrownExceptions() {
if (myUnThrownExceptions == null) return null;
return myUnThrownExceptions.toArray(new PsiClass[myUnThrownExceptions.size()]);
JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
List<PsiClass> result = new ArrayList<PsiClass>(myUnThrownExceptions.size());
for (String exception : myUnThrownExceptions) {
PsiClass element = facade.findClass(exception, GlobalSearchScope.allScope(myManager.getProject()));
if (element != null) result.add(element);
}
return result.toArray(new PsiClass[result.size()]);
}
@@ -105,10 +105,6 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new JavaElementVisitor() {
public void visitReferenceExpression(PsiReferenceExpression expression) {
}
@Override
public void visitJavaFile(PsiJavaFile file) {
for (PsiClass aClass : file.getClasses()) {
@@ -143,7 +139,7 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
for (PsiField field : candidates) {
if (usedFields.contains(field) && !hasImplicitReadOrWriteUsage(field, implicitUsageProviders)) {
final String message = InspectionsBundle.message("inspection.field.can.be.local.problem.descriptor");
holder.registerProblem(field.getNameIdentifier(), message, new MyQuickFix(field));
holder.registerProblem(field.getNameIdentifier(), message, new MyQuickFix());
}
}
}
@@ -210,13 +206,9 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
}
private static boolean isImmutableState(PsiType type) {
if (type instanceof PsiPrimitiveType) {
return true;
}
if (PsiPrimitiveType.getUnboxedType(type) != null) {
return true;
}
return Comparing.strEqual(CommonClassNames.JAVA_LANG_STRING, type.getCanonicalText());
return type instanceof PsiPrimitiveType ||
PsiPrimitiveType.getUnboxedType(type) != null ||
Comparing.strEqual(CommonClassNames.JAVA_LANG_STRING, type.getCanonicalText());
}
private static Collection<PsiVariable> getWrittenVariables(ControlFlow controlFlow, Ref<Collection<PsiVariable>> writtenVariables) {
@@ -263,19 +255,15 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
}
private static class MyQuickFix implements LocalQuickFix {
private final PsiField myField;
public MyQuickFix(final PsiField field) {
myField = field;
}
@NotNull
public String getName() {
return InspectionsBundle.message("inspection.field.can.be.local.quickfix");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
if (!myField.isValid()) return; //weird. should not get here when field becomes invalid
PsiElement element = descriptor.getPsiElement();
PsiField myField = PsiTreeUtil.getParentOfType(element, PsiField.class);
if (myField == null || !myField.isValid()) return; //weird. should not get here when field becomes invalid
final Collection<PsiReference> refs = ReferencesSearch.search(myField).findAll();
if (refs.isEmpty()) return;
@@ -302,18 +290,20 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
final PsiExpression initializer = expression.getRExpression();
final PsiDeclarationStatement decl = elementFactory.createVariableDeclarationStatement(localName, myField.getType(), initializer);
if (!mayBeFinal) {
PsiUtil.setModifierProperty(((PsiModifierListOwner)decl.getDeclaredElements()[0]), PsiModifier.FINAL, false);
PsiUtil.setModifierProperty((PsiModifierListOwner)decl.getDeclaredElements()[0], PsiModifier.FINAL, false);
}
newDeclaration = anchor.replace(decl);
refsSet.remove(expression.getLExpression());
retargetReferences(elementFactory, localName, refsSet);
}
else {
newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences(elementFactory, localName, anchorBlock, anchor, refsSet);
newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences(elementFactory, localName, anchorBlock, anchor, refsSet,
myField);
}
}
else {
newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences(elementFactory, localName, anchorBlock, anchor, refsSet);
newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences(elementFactory, localName, anchorBlock, anchor, refsSet,
myField);
}
}
catch (IncorrectOperationException e) {
@@ -361,10 +351,12 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool {
}
}
private PsiElement addDeclarationWithFieldInitializerAndRetargetReferences(final PsiElementFactory elementFactory, final String localName,
final PsiCodeBlock anchorBlock,
final PsiElement anchor,
final Set<PsiReference> refs)
private static PsiElement addDeclarationWithFieldInitializerAndRetargetReferences(final PsiElementFactory elementFactory,
final String localName,
final PsiCodeBlock anchorBlock,
final PsiElement anchor,
final Set<PsiReference> refs,
PsiField myField)
throws IncorrectOperationException {
final PsiDeclarationStatement decl = elementFactory.createVariableDeclarationStatement(localName, myField.getType(), myField.getInitializer());
final PsiElement newDeclaration = anchorBlock.addBefore(decl, anchor);
@@ -100,4 +100,9 @@ public abstract class LocalQuickFixAndIntentionActionOnPsiElement implements Loc
@Nullable("is null when called from inspection") Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement);
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -82,10 +82,10 @@ public class StaticMethodOnlyUsedInOneClassInspection
private static class StaticMethodOnlyUsedInOneClassFix
extends InspectionGadgetsFix {
private final PsiClass usageClass;
private final SmartPsiElementPointer<PsiClass> usageClass;
public StaticMethodOnlyUsedInOneClassFix(PsiClass usageClass) {
this.usageClass = usageClass;
this.usageClass = SmartPointerManager.getInstance(usageClass.getProject()).createSmartPsiElementPointer(usageClass);
}
@NotNull
@@ -113,7 +113,7 @@ public class StaticMethodOnlyUsedInOneClassInspection
public Object getData(@NonNls String name) {
if (LangDataKeys.TARGET_PSI_ELEMENT.is(name)) {
return usageClass;
return usageClass.getElement();
}
return dataManager.getDataContext().getData(name);
}
@@ -56,22 +56,16 @@ public class IfStatementWithIdenticalBranchesInspection
public InspectionGadgetsFix buildFix(Object... infos){
if (infos.length > 0) {
final PsiIfStatement elseIfStatement = (PsiIfStatement) infos[0];
return new CollapseIfFix(elseIfStatement);
return new CollapseIfFix();
}
return new CollapseIfFix();
}
private static class CollapseIfFix extends InspectionGadgetsFix{
private final PsiIfStatement elseIfStatement;
public CollapseIfFix() {
}
public CollapseIfFix(PsiIfStatement elseIfStatement) {
this.elseIfStatement = elseIfStatement;
}
private CollapseIfFix() {
elseIfStatement = null;
}
@NotNull
public String getName(){
@@ -97,6 +91,7 @@ public class IfStatementWithIdenticalBranchesInspection
statement.delete();
return;
}
PsiIfStatement elseIfStatement = elseBranch instanceof PsiIfStatement ? (PsiIfStatement)elseBranch : null;
if (elseIfStatement == null) {
final PsiElement parent = statement.getParent();
if (thenBranch instanceof PsiBlockStatement) {
@@ -53,27 +53,31 @@ public class ConstantValueVariableUseInspection extends BaseInspection {
private static class ReplaceReferenceWithExpressionFix
extends InspectionGadgetsFix {
private final SmartPsiElementPointer<PsiExpression> expression;
private final String myText;
private final PsiExpression expression;
ReplaceReferenceWithExpressionFix(
ReplaceReferenceWithExpressionFix(
PsiExpression expression) {
this.expression = expression;
}
this.expression = SmartPointerManager.getInstance(expression.getProject()).createSmartPsiElementPointer(expression);
myText = expression.getText();
}
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"replace.reference.with.expression.quickfix",
expression.getText());
myText);
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
element.replace(expression);
PsiExpression exp = expression.getElement();
if (exp == null) return;
element.replace(exp );
}
}
@@ -53,8 +53,8 @@ public class TooBroadCatchInspection extends BaseInspection {
@Override @NotNull
protected String buildErrorString(Object... infos) {
final List<PsiType> typesMasked = (List<PsiType>)infos[0];
String typesMaskedString = typesMasked.get(0).getPresentableText();
final List<PsiClass> typesMasked = (List<PsiClass>)infos[0];
String typesMaskedString = typesMasked.get(0).getName();
if (typesMasked.size() == 1) {
return InspectionGadgetsBundle.message(
"too.broad.catch.problem.descriptor",
@@ -64,10 +64,10 @@ public class TooBroadCatchInspection extends BaseInspection {
final int lastTypeIndex = typesMasked.size() - 1;
for (int i = 1; i < lastTypeIndex; i++) {
typesMaskedString += ", ";
typesMaskedString += typesMasked.get(i).getPresentableText();
typesMaskedString += typesMasked.get(i).getName();
}
final String lastTypeString =
typesMasked.get(lastTypeIndex).getPresentableText();
typesMasked.get(lastTypeIndex).getName();
return InspectionGadgetsBundle.message(
"too.broad.catch.problem.descriptor1",
typesMaskedString, lastTypeString);
@@ -77,12 +77,10 @@ public class TooBroadCatchInspection extends BaseInspection {
@NotNull
@Override
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final List<PsiType> maskedTypes = (List<PsiType>)infos[0];
final PsiTryStatement tryStatement = (PsiTryStatement)infos[1];
final PsiCatchSection catchSection = (PsiCatchSection)infos[2];
final List<PsiClass> maskedTypes = (List<PsiClass>)infos[0];
final List<InspectionGadgetsFix> fixes = new ArrayList();
for (PsiType thrown : maskedTypes) {
fixes.add(new AddCatchSectionFix(tryStatement, thrown, catchSection));
for (PsiClass thrown : maskedTypes) {
fixes.add(new AddCatchSectionFix(thrown));
}
return fixes.toArray(new InspectionGadgetsFix[fixes.size()]);
}
@@ -95,29 +93,35 @@ public class TooBroadCatchInspection extends BaseInspection {
}
private static class AddCatchSectionFix extends InspectionGadgetsFix {
private final SmartPsiElementPointer<PsiClass> myThrown;
private final String myText;
private final PsiTryStatement myTryStatement;
private final PsiType myThrown;
private final PsiCatchSection myBeforeCatchSection;
AddCatchSectionFix(PsiTryStatement tryStatement, PsiType thrown,
PsiCatchSection catchSection) {
myTryStatement = tryStatement;
myThrown = thrown;
myBeforeCatchSection = catchSection;
AddCatchSectionFix(PsiClass thrown) {
myThrown = SmartPointerManager.getInstance(thrown.getProject()).createSmartPsiElementPointer(thrown);
myText = thrown.getName();
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
PsiElement typeElement = descriptor.getPsiElement();
if (typeElement == null) return;
PsiElement catchParameter = typeElement.getParent();
if (!(catchParameter instanceof PsiParameter)) return;
PsiElement catchBlock = ((PsiParameter)catchParameter).getDeclarationScope();
if (!(catchBlock instanceof PsiCatchSection)) return;
final PsiCatchSection myBeforeCatchSection = (PsiCatchSection)catchBlock;
final PsiTryStatement myTryStatement = myBeforeCatchSection.getTryStatement();
final JavaCodeStyleManager codeStyleManager =
JavaCodeStyleManager.getInstance(project);
final String name = codeStyleManager.suggestUniqueVariableName("e",
myTryStatement.getTryBlock(), false);
final PsiElementFactory factory =
JavaPsiFacade.getInstance(project).getElementFactory();
final PsiCatchSection section =
factory.createCatchSection((PsiClassType)myThrown, name,
PsiClass aClass = myThrown.getElement();
if (aClass == null) return;
final PsiCatchSection section =
factory.createCatchSection(factory.createType(aClass), name,
myTryStatement);
final PsiCatchSection element = (PsiCatchSection)
myTryStatement.addBefore(section, myBeforeCatchSection);
@@ -146,7 +150,7 @@ public class TooBroadCatchInspection extends BaseInspection {
@NotNull
public String getName() {
return InspectionGadgetsBundle.message("too.broad.catch.quickfix",
myThrown.getPresentableText());
myText);
}
}
@@ -188,7 +192,7 @@ public class TooBroadCatchInspection extends BaseInspection {
if (tryBlock == null) {
return;
}
final Set<? extends PsiType> exceptionsThrown =
final Set<PsiClassType> exceptionsThrown =
ExceptionUtils.calculateExceptionsThrown(tryBlock);
final int numExceptionsThrown = exceptionsThrown.size();
final Set<PsiType> exceptionsCaught =
@@ -207,52 +211,49 @@ public class TooBroadCatchInspection extends BaseInspection {
final List<PsiType> types =
disjunctionType.getDisjunctions();
for (PsiType type : types) {
final List<PsiType> maskedExceptions =
findMaskedExceptions(exceptionsThrown,
exceptionsCaught, type);
if (!maskedExceptions.isEmpty()) {
final PsiTypeElement typeElement =
parameter.getTypeElement();
registerError(typeElement, maskedExceptions,
statement, catchSection);
}
register(exceptionsThrown, exceptionsCaught, parameter, type);
}
} else {
final List<PsiType> maskedExceptions =
findMaskedExceptions(exceptionsThrown,
exceptionsCaught, typeCaught);
if (!maskedExceptions.isEmpty()) {
final PsiTypeElement typeElement =
parameter.getTypeElement();
registerError(typeElement, maskedExceptions, statement,
catchSection);
}
register(exceptionsThrown, exceptionsCaught, parameter, typeCaught);
}
}
}
private List<PsiType> findMaskedExceptions(
Set<? extends PsiType> exceptionsThrown,
private void register(Set<PsiClassType> exceptionsThrown, Set<PsiType> exceptionsCaught, PsiParameter parameter, PsiType type) {
final List<PsiClass> maskedExceptions =
findMaskedExceptions(exceptionsThrown,
exceptionsCaught, type);
if (!maskedExceptions.isEmpty()) {
final PsiTypeElement typeElement =
parameter.getTypeElement();
registerError(typeElement, maskedExceptions);
}
}
private List<PsiClass> findMaskedExceptions(
Set<PsiClassType> exceptionsThrown,
Set<PsiType> exceptionsCaught, PsiType typeCaught) {
if (exceptionsThrown.contains(typeCaught)) {
exceptionsCaught.add(typeCaught);
exceptionsThrown.remove(typeCaught);
}
final List<PsiType> typesMasked = new ArrayList();
for (PsiType typeThrown : exceptionsThrown) {
final List<PsiClass> typesMasked = new ArrayList();
for (PsiClassType typeThrown : exceptionsThrown) {
if (!exceptionsCaught.contains(typeThrown) &&
typeCaught.isAssignableFrom(typeThrown)) {
exceptionsCaught.add(typeThrown);
typesMasked.add(typeThrown);
PsiClass aClass = typeThrown.resolve();
if (aClass != null)
typesMasked.add(aClass);
}
}
if (onlyWarnOnRootExceptions) {
if (!ExceptionUtils.isGenericExceptionClass(typeCaught)) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
}
return typesMasked;
}
}
}
}
@@ -49,8 +49,8 @@ public class TooBroadThrowsInspection extends BaseInspection {
@Override @NotNull
protected String buildErrorString(Object... infos) {
final List<PsiType> typesMasked = (List<PsiType>)infos[0];
String typesMaskedString = typesMasked.get(0).getPresentableText();
final List<PsiClass> typesMasked = (List<PsiClass>)infos[0];
String typesMaskedString = typesMasked.get(0).getName();
if (typesMasked.size() == 1) {
return InspectionGadgetsBundle.message(
"overly.broad.throws.clause.problem.descriptor1",
@@ -59,10 +59,10 @@ public class TooBroadThrowsInspection extends BaseInspection {
final int lastTypeIndex = typesMasked.size() - 1;
for (int i = 1; i < lastTypeIndex; i++) {
typesMaskedString += ", ";
typesMaskedString += typesMasked.get(i).getPresentableText();
typesMaskedString += typesMasked.get(i).getName();
}
final String lastTypeString =
typesMasked.get(lastTypeIndex).getPresentableText();
typesMasked.get(lastTypeIndex).getName();
return InspectionGadgetsBundle.message(
"overly.broad.throws.clause.problem.descriptor2",
typesMaskedString, lastTypeString);
@@ -79,21 +79,23 @@ public class TooBroadThrowsInspection extends BaseInspection {
@NotNull
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
final Collection<PsiClassType> maskedExceptions =
(Collection<PsiClassType>)infos[0];
final Collection<PsiClass> maskedExceptions =
(Collection<PsiClass>)infos[0];
final Boolean originalNeeded = (Boolean) infos[1];
return new AddThrowsClauseFix(maskedExceptions,
originalNeeded.booleanValue());
}
private static class AddThrowsClauseFix extends InspectionGadgetsFix {
private final Collection<PsiClassType> types;
private final Collection<SmartPsiElementPointer<PsiClass>> types;
private final boolean originalNeeded;
AddThrowsClauseFix(Collection<PsiClassType> types,
AddThrowsClauseFix(@NotNull Collection<PsiClass> classes,
boolean originalNeeded) {
this.types = types;
types = new ArrayList<SmartPsiElementPointer<PsiClass>>();
for (PsiClass type : classes) {
types.add(SmartPointerManager.getInstance(type.getProject()).createSmartPsiElementPointer(type));
}
this.originalNeeded = originalNeeded;
}
@@ -122,9 +124,11 @@ public class TooBroadThrowsInspection extends BaseInspection {
if (!originalNeeded) {
element.delete();
}
for (PsiClassType type : types) {
final PsiJavaCodeReferenceElement referenceElement =
factory.createReferenceElementByType(type);
for (SmartPsiElementPointer<PsiClass> type : types) {
PsiClass aClass = type.getElement();
if (aClass == null) continue;
final PsiJavaCodeReferenceElement referenceElement =
factory.createReferenceExpression(aClass);
referenceList.add(referenceElement);
}
}
@@ -168,11 +172,14 @@ public class TooBroadThrowsInspection extends BaseInspection {
continue;
}
}
final List<PsiClassType> exceptionsMasked = new ArrayList();
final List<PsiClass> exceptionsMasked = new ArrayList<PsiClass>();
for (PsiClassType exceptionThrown : exceptionsThrown) {
if (referencedException.isAssignableFrom(exceptionThrown) &&
!exceptionsDeclared.contains(exceptionThrown)) {
exceptionsMasked.add(exceptionThrown);
PsiClass aClass = exceptionThrown.resolve();
if (aClass != null) {
exceptionsMasked.add(aClass);
}
}
}
if (!exceptionsMasked.isEmpty()) {
@@ -186,4 +193,4 @@ public class TooBroadThrowsInspection extends BaseInspection {
}
}
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.codeInspection.i18n.JavaI18nUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
@@ -31,6 +32,7 @@ import com.intellij.psi.impl.search.LowLevelSearchUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
import com.intellij.refactoring.util.occurences.BaseOccurenceManager;
@@ -210,8 +212,9 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
Set<PsiField> constants = new THashSet<PsiField>();
for (Iterator<PsiExpression> iterator = foundExpr.iterator(); iterator.hasNext();) {
PsiExpression expression1 = iterator.next();
if (expression1.getParent() instanceof PsiField) {
final PsiField field = (PsiField)expression1.getParent();
PsiElement parent = expression1.getParent();
if (parent instanceof PsiField) {
final PsiField field = (PsiField)parent;
if (field.getInitializer() == expression1 && field.hasModifierProperty(PsiModifier.FINAL) && field.hasModifierProperty(PsiModifier.STATIC)) {
constants.add(field);
iterator.remove();
@@ -221,37 +224,12 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
for (final PsiField constant : constants) {
final PsiClass containingClass = constant.getContainingClass();
if (containingClass == null) continue;
boolean isAccessible = JavaPsiFacade.getInstance(constant.getProject()).getResolveHelper() .isAccessible(constant, originalExpression,
containingClass);
boolean isAccessible = JavaPsiFacade.getInstance(constant.getProject()).getResolveHelper().isAccessible(constant, originalExpression,
containingClass);
if (!isAccessible && containingClass.getQualifiedName() == null) {
continue;
}
final LocalQuickFix replaceQuickFix = new LocalQuickFix() {
@NotNull
public String getName() {
return InspectionsBundle.message("inspection.duplicates.replace.quickfix", PsiFormatUtil
.formatVariable(constant, PsiFormatUtil.SHOW_CONTAINING_CLASS | PsiFormatUtil.SHOW_FQ_NAME | PsiFormatUtil.SHOW_NAME,
PsiSubstitutor.EMPTY));
}
public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
if (!CodeInsightUtilBase.prepareFileForWrite(originalExpression.getContainingFile())) return;
try {
final PsiReferenceExpression reference = createReferenceTo(constant, originalExpression);
if (reference != null) {
originalExpression.replace(reference);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@NotNull
public String getFamilyName() {
return InspectionsBundle.message("inspection.duplicates.replace.family.quickfix");
}
};
final LocalQuickFix replaceQuickFix = new ReplaceFix(constant, originalExpression);
fixes.add(replaceQuickFix);
}
}
@@ -265,11 +243,10 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
@Nullable
private static PsiReferenceExpression createReferenceTo(final PsiField constant, final PsiLiteralExpression context) throws IncorrectOperationException {
PsiReferenceExpression reference = (PsiReferenceExpression)JavaPsiFacade.getInstance(constant.getProject()).getElementFactory()
.createExpressionFromText(constant.getName(), context);
PsiElementFactory factory = JavaPsiFacade.getInstance(constant.getProject()).getElementFactory();
PsiReferenceExpression reference = (PsiReferenceExpression)factory.createExpressionFromText(constant.getName(), context);
if (reference.isReferenceTo(constant)) return reference;
reference = (PsiReferenceExpression)JavaPsiFacade.getInstance(constant.getProject()).getElementFactory()
.createExpressionFromText("XXX."+constant.getName(), null);
reference = (PsiReferenceExpression)factory.createExpressionFromText("XXX." + constant.getName(), null);
final PsiReferenceExpression classQualifier = (PsiReferenceExpression)reference.getQualifierExpression();
PsiClass containingClass = constant.getContainingClass();
if (containingClass.getQualifiedName() == null) return null;
@@ -296,7 +273,7 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
try {
MIN_STRING_LENGTH = Integer.parseInt(myMinStringLengthField.getText());
}
catch (NumberFormatException e1) {
catch (NumberFormatException ignored) {
}
}
});
@@ -312,7 +289,8 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
public IntroduceLiteralConstantFix(final PsiExpression[] expressions) {
myExpressions = new SmartPsiElementPointer[expressions.length];
for(int i=0; i<expressions.length; i++) {
myExpressions [i] = SmartPointerManager.getInstance(expressions [i].getProject()).createLazyPointer(expressions [i]);
PsiExpression expression = expressions[i];
myExpressions[i] = SmartPointerManager.getInstance(expression.getProject()).createSmartPsiElementPointer(expression);
}
}
@@ -324,6 +302,7 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (project.isDisposed()) return;
final List<PsiExpression> expressions = new ArrayList<PsiExpression>();
for(SmartPsiElementPointer ptr: myExpressions) {
final PsiElement element = ptr.getElement();
@@ -360,4 +339,56 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool {
return getName();
}
}
private static class ReplaceFix extends LocalQuickFixAndIntentionActionOnPsiElement {
private final String myText;
private final SmartPsiElementPointer<PsiField> myConst;
public ReplaceFix(PsiField constant, PsiLiteralExpression originalExpression) {
super(originalExpression);
myText = InspectionsBundle.message("inspection.duplicates.replace.quickfix", PsiFormatUtil
.formatVariable(constant, PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
PsiFormatUtilBase.SHOW_FQ_NAME |
PsiFormatUtilBase.SHOW_NAME,
PsiSubstitutor.EMPTY));
myConst = SmartPointerManager.getInstance(constant.getProject()).createSmartPsiElementPointer(constant);
}
@NotNull
@Override
public String getText() {
return myText;
}
@Override
public boolean startInWriteAction() {
return true;
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
@Nullable("is null when called from inspection") Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiLiteralExpression myOriginalExpression = (PsiLiteralExpression)startElement;
final PsiField myConstant = myConst.getElement();
if (myConstant == null) return;
if (!CodeInsightUtilBase.prepareFileForWrite(myOriginalExpression.getContainingFile())) return;
try {
final PsiReferenceExpression reference = createReferenceTo(myConstant, myOriginalExpression);
if (reference != null) {
myOriginalExpression.replace(reference);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@NotNull
public String getFamilyName() {
return InspectionsBundle.message("inspection.duplicates.replace.family.quickfix");
}
}
}
@@ -94,7 +94,7 @@ public class CheckDtdReferencesInspection extends XmlSuppressableInspectionTool
public static class AddDtdDeclarationFix implements LocalQuickFix {
private final String myMessageKey;
private final String myElementDeclarationName;
private final PsiReference myReference;
private final String myReference;
public AddDtdDeclarationFix(
@PropertyKey(resourceBundle=XmlBundle.PATH_TO_BUNDLE) String messageKey,
@@ -103,12 +103,12 @@ public class CheckDtdReferencesInspection extends XmlSuppressableInspectionTool
{
myMessageKey = messageKey;
myElementDeclarationName = elementDeclarationName;
myReference = reference;
myReference = reference.getCanonicalText();
}
@NotNull
public String getName() {
return XmlBundle.message(myMessageKey, myReference.getCanonicalText());
return XmlBundle.message(myMessageKey, myReference);
}
@NotNull
@@ -169,7 +169,7 @@ public class CheckDtdReferencesInspection extends XmlSuppressableInspectionTool
final Template t = templateManager.createTemplate("","");
if (prefixToInsert.length() > 0) t.addTextSegment(prefixToInsert);
t.addTextSegment("<!" + myElementDeclarationName + " " + myReference.getCanonicalText()+ " ");
t.addTextSegment("<!" + myElementDeclarationName + " " + myReference+ " ");
t.addEndVariable();
t.addTextSegment(">\n");
if (suffixToInsert.length() > 0) t.addTextSegment(suffixToInsert);