mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
psi leaks
This commit is contained in:
+32
-17
@@ -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()]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-26
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user