leaks in inplace refactorings: make MyExpression class static in order to release references on outer class (cherry picked from commit 4fc0c37)

This commit is contained in:
anna
2012-03-21 18:02:01 +01:00
parent 7e5c716642
commit a631e5322c
5 changed files with 182 additions and 107 deletions
@@ -99,6 +99,7 @@ public abstract class AbstractJavaInplaceIntroducer extends AbstractInplaceIntro
@Override
protected void saveSettings(@NotNull PsiVariable psiVariable) {
TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), getType());//myDefaultType.getType());
myTypeSelectorManager = null;
}
public PsiType getType() {
@@ -17,6 +17,7 @@ package com.intellij.refactoring.introduce.inplace;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.codeInsight.template.TextResult;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
@@ -33,10 +34,13 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.refactoring.rename.inplace.MyLookupExpression;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.PositionTracker;
import org.jetbrains.annotations.Nullable;
@@ -79,11 +83,6 @@ public abstract class InplaceVariableIntroducer<E extends PsiElement> extends In
initOccurrencesMarkers();
}
@Deprecated
public boolean performInplaceRename() {
return performInplaceRefactoring(null);
}
@Override
protected boolean shouldSelectAll() {
return true;
@@ -235,31 +234,61 @@ public abstract class InplaceVariableIntroducer<E extends PsiElement> extends In
}
@Override
protected LookupElement[] createLookupItems(LookupElement[] lookupItems, String name) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
final PsiNamedElement psiVariable = getVariable();
if (psiVariable != null) {
final TextResult insertedValue =
templateState != null ? templateState.getVariableValue(PRIMARY_VARIABLE_NAME) : null;
if (insertedValue != null) {
final String text = insertedValue.getText();
if (!text.isEmpty() && !Comparing.strEqual(text, name)) {
final LinkedHashSet<String> names = new LinkedHashSet<String>();
names.add(text);
for (NameSuggestionProvider provider : Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
final SuggestedNameInfo suggestedNameInfo = provider.getSuggestedNames(psiVariable, psiVariable, names);
if (suggestedNameInfo != null && provider instanceof PreferrableNameSuggestionProvider && !((PreferrableNameSuggestionProvider)provider).shouldCheckOthers()) break;
}
final LookupElement[] items = new LookupElement[names.size()];
final Iterator<String> iterator = names.iterator();
for (int i = 0; i < items.length; i++) {
items[i] = LookupElementBuilder.create(iterator.next());
}
return items;
}
}
}
return lookupItems;
protected MyLookupExpression createLookupExpression() {
return new MyIntroduceLookupExpression(getInitialName(), myNameSuggestions, myElementToRename, shouldSelectAll(), myAdvertisementText);
}
private static class MyIntroduceLookupExpression extends MyLookupExpression {
private final SmartPsiElementPointer<PsiNamedElement> myPointer;
public MyIntroduceLookupExpression(final String initialName,
final LinkedHashSet<String> names,
final PsiNamedElement elementToRename,
final boolean shouldSelectAll,
final String advertisementText) {
super(initialName, names, elementToRename, shouldSelectAll, advertisementText);
myPointer = SmartPointerManager.getInstance(elementToRename.getProject()).createSmartPsiElementPointer(elementToRename);
}
@Override
public LookupElement[] calculateLookupItems(ExpressionContext context) {
return createLookupItems(myName, context.getEditor(), getElement());
}
@Nullable
public PsiNamedElement getElement() {
return myPointer.getElement();
}
@Nullable
private LookupElement[] createLookupItems(String name, Editor editor, PsiNamedElement psiVariable) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
if (psiVariable != null) {
final TextResult insertedValue =
templateState != null ? templateState.getVariableValue(PRIMARY_VARIABLE_NAME) : null;
if (insertedValue != null) {
final String text = insertedValue.getText();
if (!text.isEmpty() && !Comparing.strEqual(text, name)) {
final LinkedHashSet<String> names = new LinkedHashSet<String>();
names.add(text);
for (NameSuggestionProvider provider : Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
final SuggestedNameInfo suggestedNameInfo = provider.getSuggestedNames(psiVariable, psiVariable, names);
if (suggestedNameInfo != null &&
provider instanceof PreferrableNameSuggestionProvider &&
!((PreferrableNameSuggestionProvider)provider).shouldCheckOthers()) {
break;
}
}
final LookupElement[] items = new LookupElement[names.size()];
final Iterator<String> iterator = names.iterator();
for (int i = 0; i < items.length; i++) {
items[i] = LookupElementBuilder.create(iterator.next());
}
return items;
}
}
}
return myLookupItems;
}
}
}
@@ -15,13 +15,9 @@
*/
package com.intellij.refactoring.rename.inplace;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.*;
@@ -43,7 +39,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -60,7 +55,6 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.ProjectScope;
@@ -68,8 +62,6 @@ import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
@@ -93,7 +85,7 @@ public abstract class InplaceRefactoring {
protected final Editor myEditor;
protected final Project myProject;
protected RangeMarker myRenameOffset;
private String myAdvertisementText;
protected String myAdvertisementText;
private ArrayList<RangeHighlighter> myHighlighters;
protected String myInitialName;
protected final String myOldName;
@@ -205,7 +197,9 @@ public abstract class InplaceRefactoring {
protected abstract boolean shouldSelectAll();
protected abstract LookupElement[] createLookupItems(LookupElement[] lookupItems, String name);
protected MyLookupExpression createLookupExpression() {
return new MyLookupExpression(getInitialName(), myNameSuggestions, myElementToRename, shouldSelectAll(), myAdvertisementText);
}
protected Collection<PsiReference> collectRefs(SearchScope referencesSearchScope) {
return ReferencesSearch.search(myElementToRename, referencesSearchScope, false).findAll();
@@ -536,8 +530,7 @@ public abstract class InplaceRefactoring {
int offset) {
if (reference.getElement() == selectedElement &&
contains(reference.getRangeInElement().shiftRight(selectedElement.getTextRange().getStartOffset()), offset)) {
Expression expression = new MyExpression(getInitialName(), myNameSuggestions);
builder.replaceElement(reference, PRIMARY_VARIABLE_NAME, expression, true);
builder.replaceElement(reference, PRIMARY_VARIABLE_NAME, createLookupExpression(), true);
}
else {
builder.replaceElement(reference, OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
@@ -555,8 +548,7 @@ public abstract class InplaceRefactoring {
final PsiElement selectedElement,
final TemplateBuilderImpl builder) {
if (element == selectedElement) {
Expression expression = new MyExpression(getInitialName(), myNameSuggestions);
builder.replaceElement(element, PRIMARY_VARIABLE_NAME, expression, true);
builder.replaceElement(element, PRIMARY_VARIABLE_NAME, createLookupExpression(), true);
}
else if (textRange != null) {
builder.replaceElement(element, textRange, OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
@@ -614,63 +606,6 @@ public abstract class InplaceRefactoring {
return range.getStartOffset() <= offset && offset <= range.getEndOffset();
}
protected class MyExpression extends Expression {
private final String myName;
private final LookupElement[] myLookupItems;
protected MyExpression(String name, LinkedHashSet<String> names) {
myName = name;
if (names == null) {
names = new LinkedHashSet<String>();
for (NameSuggestionProvider provider : Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
final SuggestedNameInfo suggestedNameInfo = provider.getSuggestedNames(myElementToRename, myElementToRename, names);
if (suggestedNameInfo != null && provider instanceof PreferrableNameSuggestionProvider && !((PreferrableNameSuggestionProvider)provider).shouldCheckOthers()) break;
}
}
myLookupItems = new LookupElement[names.size()];
final Iterator<String> iterator = names.iterator();
for (int i = 0; i < myLookupItems.length; i++) {
final String suggestion = iterator.next();
myLookupItems[i] = LookupElementBuilder.create(suggestion).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
if (shouldSelectAll()) return;
final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
final TemplateState templateState = TemplateManagerImpl.getTemplateState(topLevelEditor);
if (templateState != null) {
final TextRange range = templateState.getCurrentVariableRange();
if (range != null) {
topLevelEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), suggestion);
}
}
}
});
}
}
public LookupElement[] calculateLookupItems(ExpressionContext context) {
return createLookupItems(myLookupItems, myName);
}
public Result calculateQuickResult(ExpressionContext context) {
return calculateResult(context);
}
public Result calculateResult(ExpressionContext context) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
final TextResult insertedValue = templateState != null ? templateState.getVariableValue(PRIMARY_VARIABLE_NAME) : null;
if (insertedValue != null) {
if (!insertedValue.getText().isEmpty()) return insertedValue;
}
return new TextResult(myName);
}
@Override
public String getAdvertisingText() {
return myAdvertisementText;
}
}
private abstract class MyTemplateListener extends TemplateEditingAdapter {
protected abstract void restoreDaemonUpdateState();
@@ -0,0 +1,116 @@
/*
* Copyright 2000-2012 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.refactoring.rename.inplace;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.codeInsight.template.Result;
import com.intellij.codeInsight.template.TextResult;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider;
import java.util.Iterator;
import java.util.LinkedHashSet;
/**
* User: anna
* Date: 3/16/12
*/
public class MyLookupExpression extends Expression {
protected final String myName;
protected final LookupElement[] myLookupItems;
private final String myAdvertisementText;
public MyLookupExpression(final String name,
final LinkedHashSet<String> names,
final PsiNamedElement elementToRename,
final boolean shouldSelectAll,
final String advertisement) {
myName = name;
myAdvertisementText = advertisement;
myLookupItems = initLookupItems(names, elementToRename, shouldSelectAll);
}
private static LookupElement[] initLookupItems(LinkedHashSet<String> names,
PsiNamedElement elementToRename,
final boolean shouldSelectAll) {
if (names == null) {
names = new LinkedHashSet<String>();
for (NameSuggestionProvider provider : Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
final SuggestedNameInfo suggestedNameInfo = provider.getSuggestedNames(elementToRename, elementToRename, names);
if (suggestedNameInfo != null &&
provider instanceof PreferrableNameSuggestionProvider &&
!((PreferrableNameSuggestionProvider)provider).shouldCheckOthers()) {
break;
}
}
}
final LookupElement[] lookupElements = new LookupElement[names.size()];
final Iterator<String> iterator = names.iterator();
for (int i = 0; i < lookupElements.length; i++) {
final String suggestion = iterator.next();
lookupElements[i] = LookupElementBuilder.create(suggestion).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
if (shouldSelectAll) return;
final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(context.getEditor());
final TemplateState templateState = TemplateManagerImpl.getTemplateState(topLevelEditor);
if (templateState != null) {
final TextRange range = templateState.getCurrentVariableRange();
if (range != null) {
topLevelEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), suggestion);
}
}
}
});
}
return lookupElements;
}
public LookupElement[] calculateLookupItems(ExpressionContext context) {
return myLookupItems;
}
public Result calculateQuickResult(ExpressionContext context) {
return calculateResult(context);
}
public Result calculateResult(ExpressionContext context) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(context.getEditor());
final TextResult insertedValue = templateState != null ? templateState.getVariableValue(InplaceRefactoring.PRIMARY_VARIABLE_NAME) : null;
if (insertedValue != null) {
if (!insertedValue.getText().isEmpty()) return insertedValue;
}
return new TextResult(myName);
}
@Override
public String getAdvertisingText() {
return myAdvertisementText;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.refactoring.rename.inplace;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageExtension;
import com.intellij.lang.LanguageNamesValidation;
@@ -293,9 +292,4 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
final NamesValidator namesValidator = LanguageNamesValidation.INSTANCE.forLanguage(myLanguage);
return namesValidator == null || namesValidator.isIdentifier(newName, myProject);
}
@Override
protected LookupElement[] createLookupItems(final LookupElement[] lookupItems, final String name) {
return lookupItems;
}
}