Merge branch 'master' into recur

This commit is contained in:
peter
2011-03-24 14:16:25 +01:00
101 changed files with 1804 additions and 973 deletions
@@ -48,11 +48,19 @@ public class CreateClassFromNewFix extends CreateFromUsageBaseFix {
protected void invokeImpl(PsiClass targetClass) {
assert ApplicationManager.getApplication().isWriteAccessAllowed();
PsiNewExpression newExpression = getNewExpression();
final PsiNewExpression newExpression = getNewExpression();
PsiJavaCodeReferenceElement referenceElement = getReferenceElement(newExpression);
final PsiClass psiClass = CreateFromUsageUtils.createClass(referenceElement, CreateClassKind.CLASS, null);
setupClassFromNewExpression(psiClass, newExpression);
final PsiJavaCodeReferenceElement referenceElement = getReferenceElement(newExpression);
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
final PsiClass psiClass = CreateFromUsageUtils.createClass(referenceElement, CreateClassKind.CLASS, null);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
setupClassFromNewExpression(psiClass, newExpression);
}
});
}
});
}
protected static void setupClassFromNewExpression(final PsiClass psiClass, final PsiNewExpression newExpression) {
@@ -41,6 +41,7 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -264,6 +265,7 @@ public class CreateFromUsageUtils {
public static PsiClass createClass(final PsiJavaCodeReferenceElement referenceElement,
final CreateClassKind classKind,
final String superClassName) {
assert !ApplicationManager.getApplication().isWriteAccessAllowed();
final String name = referenceElement.getReferenceName();
final PsiElement qualifierElement;
@@ -274,23 +276,7 @@ public class CreateFromUsageUtils {
return ApplicationManager.getApplication().runWriteAction(
new Computable<PsiClass>() {
public PsiClass compute() {
try {
PsiClass psiClass = (PsiClass) qualifierElement;
if (!CodeInsightUtilBase.preparePsiElementForWrite(psiClass)) return null;
PsiManager manager = psiClass.getManager();
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
PsiClass result = classKind == INTERFACE ? elementFactory.createInterface(name) :
classKind == CLASS ? elementFactory.createClass(name) :
elementFactory.createEnum(name);
CreateFromUsageBaseFix.setupGenericParameters(result, referenceElement);
result = (PsiClass)manager.getCodeStyleManager().reformat(result);
return (PsiClass) psiClass.add(result);
}
catch (IncorrectOperationException e) {
LOG.error(e);
return null;
}
return createClassInQualifier((PsiClass)qualifierElement, classKind, name, referenceElement);
}
});
}
@@ -302,20 +288,7 @@ public class CreateFromUsageUtils {
final PsiManager manager = referenceElement.getManager();
final PsiFile sourceFile = referenceElement.getContainingFile();
final Module module = ModuleUtil.findModuleForPsiElement(sourceFile);
PsiPackage aPackage = null;
if (qualifierElement instanceof PsiPackage) {
aPackage = (PsiPackage)qualifierElement;
}
else {
final PsiDirectory directory = sourceFile.getContainingDirectory();
if (directory != null) {
aPackage = JavaDirectoryService.getInstance().getPackage(directory);
}
if (aPackage == null) {
aPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage("");
}
}
PsiPackage aPackage = findTargetPackage(qualifierElement, manager, sourceFile);
if (aPackage == null) return null;
final PsiDirectory targetDirectory;
if (!ApplicationManager.getApplication().isUnitTestMode()) {
@@ -335,6 +308,48 @@ public class CreateFromUsageUtils {
return createClass(classKind, targetDirectory, name, manager, referenceElement, sourceFile, superClassName);
}
@Nullable
public static PsiPackage findTargetPackage(PsiElement qualifierElement, PsiManager manager, PsiFile sourceFile) {
PsiPackage aPackage = null;
if (qualifierElement instanceof PsiPackage) {
aPackage = (PsiPackage)qualifierElement;
}
else {
final PsiDirectory directory = sourceFile.getContainingDirectory();
if (directory != null) {
aPackage = JavaDirectoryService.getInstance().getPackage(directory);
}
if (aPackage == null) {
aPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage("");
}
}
if (aPackage == null) return null;
return aPackage;
}
public static PsiClass createClassInQualifier(PsiClass psiClass,
CreateClassKind classKind,
String name,
PsiJavaCodeReferenceElement referenceElement) {
try {
if (!CodeInsightUtilBase.preparePsiElementForWrite(psiClass)) return null;
PsiManager manager = psiClass.getManager();
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
PsiClass result = classKind == INTERFACE ? elementFactory.createInterface(name) :
classKind == CLASS ? elementFactory.createClass(name) :
elementFactory.createEnum(name);
CreateFromUsageBaseFix.setupGenericParameters(result, referenceElement);
result = (PsiClass)manager.getCodeStyleManager().reformat(result);
return (PsiClass) psiClass.add(result);
}
catch (IncorrectOperationException e) {
LOG.error(e);
return null;
}
}
public static PsiClass createClass(final CreateClassKind classKind,
final PsiDirectory directory,
final String name,
@@ -23,7 +23,6 @@ import com.intellij.pom.PomModelAspect;
import com.intellij.pom.event.PomModelEvent;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.pom.java.PomJavaAspect;
import com.intellij.pom.java.events.JavaTreeChanged;
import com.intellij.pom.java.events.PomJavaAspectChangeSet;
import com.intellij.pom.tree.TreeAspect;
import com.intellij.pom.tree.events.TreeChangeEvent;
@@ -69,7 +68,6 @@ public class PomJavaAspectImpl extends PomJavaAspect implements ProjectComponent
final PsiFile containingFile = changeSet.getRootElement().getPsi().getContainingFile();
if(!(containingFile.getLanguage() instanceof JavaLanguage)) return;
final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel);
set.addChange(new JavaTreeChanged(containingFile));
event.registerChangeSet(this, set);
}
}
@@ -78,8 +78,8 @@ public class PsiSuperMethodImplUtil {
@NotNull
private static List<MethodSignatureBackedByPsiMethod> findSuperMethodSignatures(PsiMethod method,
PsiClass parentClass,
boolean allowStaticMethod) {
PsiClass parentClass,
boolean allowStaticMethod) {
return new ArrayList<MethodSignatureBackedByPsiMethod>(SuperMethodsSearch.search(method, parentClass, true, allowStaticMethod).findAll());
}
@@ -306,4 +306,58 @@ public class PsiSuperMethodImplUtil {
private static Map<MethodSignature, HierarchicalMethodSignature> getSignaturesMap(final PsiClass aClass) {
return SIGNATURES_KEY.getValue(aClass);
}
// uses hierarchy signature tree if available, traverses class structure by itself otherwise
public static boolean isSuperMethodSmart(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
//boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod);
if (method == superMethod) return false;
PsiClass aClass = method.getContainingClass();
PsiClass superClass = superMethod.getContainingClass();
if (aClass == null || superClass == null || superClass == aClass) return false;
if (!canHaveSuperMethod(method, true, false)) return false;
PsiMethod[] superMethods = null;
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_KEY.getCachedValueOrNull(aClass);
if (cachedMap != null) {
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
if (signature != null) {
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures());
}
}
if (superMethods == null) {
PsiClassType[] directSupers = aClass.getSuperTypes();
List<PsiMethod> found = null;
boolean canceled = false;
for (PsiClassType directSuper : directSupers) {
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
// generics
canceled = true;
break;
}
PsiClass directSuperClass = resolveResult.getElement();
if (directSuperClass == null) continue;
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
if (candidates.length != 0) {
if (found == null) found = new ArrayList<PsiMethod>();
for (PsiMethod candidate : candidates) {
if (PsiUtil.canBeOverriden(candidate)) found.add(candidate);
}
}
}
superMethods = canceled ? null : found == null ? PsiMethod.EMPTY_ARRAY : found.toArray(new PsiMethod[found.size()]);
}
if (superMethods == null) {
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(method.getHierarchicalMethodSignature().getSuperSignatures());
}
for (PsiMethod superCandidate : superMethods) {
if (superMethod.equals(superCandidate) || isSuperMethodSmart(superCandidate, superMethod)) return true;
}
return false;
}
}
@@ -39,11 +39,11 @@ public class MethodSuperSearcher implements QueryExecutor<MethodSignatureBackedB
}
private static boolean addSuperMethods(final HierarchicalMethodSignature signature,
final PsiMethod method,
final PsiClass parentClass,
final boolean allowStaticMethod,
final boolean checkBases,
final Processor<MethodSignatureBackedByPsiMethod> consumer) {
final PsiMethod method,
final PsiClass parentClass,
final boolean allowStaticMethod,
final boolean checkBases,
final Processor<MethodSignatureBackedByPsiMethod> consumer) {
PsiMethod signatureMethod = signature.getMethod();
PsiClass hisClass = signatureMethod.getContainingClass();
if (parentClass == null || InheritanceUtil.isInheritorOrSelf(parentClass, hisClass, true)) {
@@ -49,7 +49,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
}
@NotNull
public SmartTypePointer createSmartTypePointer(PsiType type) {
public SmartTypePointer createSmartTypePointer(@NotNull PsiType type) {
return type.accept(new SmartTypeCreatingVisitor());
}
@@ -332,6 +332,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
public boolean isReferenceTo(PsiElement element) {
IElementType i = getLastChildNode().getElementType();
boolean resolvingToMethod = element instanceof PsiMethod;
if (i == JavaTokenType.IDENTIFIER) {
if (!(element instanceof PsiPackage)) {
if (!(element instanceof PsiNamedElement)) return false;
@@ -341,10 +342,15 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
}
}
else if (i == JavaTokenType.SUPER_KEYWORD || i == JavaTokenType.THIS_KEYWORD) {
if (!(element instanceof PsiMethod)) return false;
if (!resolvingToMethod) return false;
if (!((PsiMethod)element).isConstructor()) return false;
}
PsiElement parent = getParent();
boolean parentIsMethodCall = parent instanceof PsiMethodCallExpression;
// optimization: methodCallExpression should resolve to a method
if (parentIsMethodCall != resolvingToMethod) return false;
return element.getManager().areElementsEquivalent(element, resolve());
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.PsiConflictResolver;
@@ -150,7 +151,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
for (int k=i-1; k>=0; k--) {
PsiMethod existingMethod = (PsiMethod)conflicts.get(k).getElement();
if (PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
if (PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
conflicts.remove(i);
i--;
continue nextConflict;
@@ -189,12 +190,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
// filter out methods with incorrect inferred bounds (for unrelated methods only)
boolean existingTypeParamAgree = areTypeParametersAgree(existing);
boolean infoTypeParamAgree = areTypeParametersAgree(info);
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(method, existingMethod)) {
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) {
conflicts.remove(i);
i--;
continue;
}
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
signatures.put(signature, info);
int index = conflicts.indexOf(existing);
conflicts.remove(index);
@@ -35,7 +35,6 @@ import com.intellij.ide.util.PackageUtil;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -230,7 +229,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
JavaCodeStyleManager.getInstance(field.getProject()).shortenClassReferences(field);
}
private static PsiElement getPhysicalElement(final PsiExpression selectedExpr) {
public static PsiElement getPhysicalElement(final PsiExpression selectedExpr) {
PsiElement element = selectedExpr.getUserData(ElementToWorkOn.PARENT);
if (element == null) element = selectedExpr;
return element;
@@ -677,32 +676,8 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
createField(myFieldName, myType, initializer, initializerPlace == InitializationPlace.IN_FIELD_DECLARATION && initializer != null,
myParentClass);
PsiElement finalAnchorElement = null;
if (destClass == myParentClass) {
for (finalAnchorElement = myAnchorElement;
finalAnchorElement != null && finalAnchorElement.getParent() != destClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
setModifiers(myField, mySettings, mySettings.isDeclareStatic());
if ((anchorMember instanceof PsiField) &&
anchorMember.hasModifierProperty(PsiModifier.STATIC) == myField.hasModifierProperty(PsiModifier.STATIC)) {
myField = (PsiField)destClass.addBefore(myField, anchorMember);
}
else if (anchorMember instanceof PsiClassInitializer) {
myField = (PsiField)destClass.addBefore(myField, anchorMember);
destClass.addBefore(CodeEditUtil.createLineFeed(myField.getManager()), anchorMember);
}
else {
final PsiField forwardReference = checkForwardRefs(initializer);
if (forwardReference != null) {
myField = (PsiField)destClass.addAfter(myField, forwardReference);
} else {
myField = (PsiField)destClass.add(myField);
}
}
myField = appendField(initializer, destClass, myParentClass, myAnchorElement, myField);
if (!mySettings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(myOccurrences, myField, mySettings.getFieldVisibility());
}
@@ -800,7 +775,42 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
}
private PsiField checkForwardRefs(PsiExpression initializer) {
static PsiField appendField(final PsiExpression initializer,
final PsiClass destClass,
final PsiClass parentClass,
final PsiElement anchorElement,
final PsiField psiField) {
PsiElement finalAnchorElement = null;
if (destClass == parentClass) {
for (finalAnchorElement = anchorElement;
finalAnchorElement != null && finalAnchorElement.getParent() != destClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
if ((anchorMember instanceof PsiField) &&
anchorMember.hasModifierProperty(PsiModifier.STATIC) == psiField.hasModifierProperty(PsiModifier.STATIC)) {
return (PsiField)destClass.addBefore(psiField, anchorMember);
}
else if (anchorMember instanceof PsiClassInitializer) {
PsiField field = (PsiField)destClass.addBefore(psiField, anchorMember);
destClass.addBefore(CodeEditUtil.createLineFeed(field.getManager()), anchorMember);
return field;
}
else {
final PsiField forwardReference = checkForwardRefs(initializer, parentClass);
if (forwardReference != null) {
return (PsiField)destClass.addAfter(psiField, forwardReference);
} else {
return (PsiField)destClass.add(psiField);
}
}
}
private static PsiField checkForwardRefs(PsiExpression initializer, final PsiClass parentClass) {
final PsiField[] refConstantFields = new PsiField[1];
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
@@ -809,7 +819,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiField &&
((PsiField)resolve).hasModifierProperty(PsiModifier.FINAL) &&
PsiTreeUtil.isAncestor(myParentClass, resolve, false) && ((PsiField)resolve).hasInitializer()) {
PsiTreeUtil.isAncestor(parentClass, resolve, false) && ((PsiField)resolve).hasInitializer()) {
if (refConstantFields[0] == null || refConstantFields[0].getTextOffset() < resolve.getTextOffset()) {
refConstantFields[0] = (PsiField)resolve;
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.Computable;
@@ -62,9 +63,9 @@ public class InplaceIntroduceConstantPopup {
private final PsiLocalVariable myLocalVariable;
private final PsiExpression[] myOccurrences;
private final TypeSelectorManagerImpl myTypeSelectorManager;
private final PsiElement myAnchorElement;
private PsiElement myAnchorElement;
private int myAnchorIdx = -1;
private final PsiElement myAnchorElementIfAll;
private PsiElement myAnchorElementIfAll;
private int myAnchorIdxIfAll = -1;
private final OccurenceManager myOccurenceManager;
@@ -116,7 +117,7 @@ public class InplaceIntroduceConstantPopup {
}
myOccurenceManager = occurenceManager;
myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
myExprMarker = expr != null && expr.isPhysical() ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
myExprText = expr != null ? expr.getText() : null;
myLocalName = localVariable != null ? localVariable.getName() : null;
@@ -200,6 +201,7 @@ public class InplaceIntroduceConstantPopup {
final PsiField field = createFieldToStartTemplateOn(names, defaultType);
if (field != null) {
myEditor.getCaretModel().moveToOffset(field.getTextOffset());
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
nameSuggestions.add(field.getName());
nameSuggestions.addAll(Arrays.asList(names));
@@ -215,10 +217,10 @@ public class InplaceIntroduceConstantPopup {
return ApplicationManager.getApplication().runWriteAction(new Computable<PsiField>() {
@Override
public PsiField compute() {
PsiField field = elementFactory.createField(myConstantName != null ? myConstantName : names[0], psiType);
field = (PsiField)myParentClass.add(field);
PsiField field = elementFactory.createFieldFromText(psiType.getCanonicalText() + " " + (myConstantName != null ? myConstantName : names[0]) + " = " + myExprText + ";", myParentClass);
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true);
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true);
field = BaseExpressionToFieldHandler.ConvertToFieldRunnable.appendField(myExpr, myParentClass, myParentClass, myAnchorElementIfAll, field);
return field;
}
});
@@ -255,7 +257,7 @@ public class InplaceIntroduceConstantPopup {
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
myEditor, field, false,
myTypeSelectorManager.getTypesForAll().length > 1,
myExpr != null ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null, InplaceIntroduceConstantPopup.this.getOccurrenceMarkers());
myExpr != null && myExpr.isPhysical() ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null, InplaceIntroduceConstantPopup.this.getOccurrenceMarkers());
myDefaultParameterTypePointer =
SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType());
@@ -269,7 +271,7 @@ public class InplaceIntroduceConstantPopup {
@Override
protected PsiExpression getExpr() {
return myExpr;
return myExpr != null && myExpr.isValid() && myExpr.isPhysical() ? myExpr : null;
}
@Override
@@ -319,20 +321,23 @@ public class InplaceIntroduceConstantPopup {
myFieldTypePointer.getType(),
isDeleteVariable(),
myParentClass, isAnnotateNonNls(), false);
if (myLocalVariable != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, true, myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(),
myOccurrences, myOccurenceManager,
myAnchorIdxIfAll != -1? myOccurrences[myAnchorIdxIfAll].getParent() : myAnchorElementIfAll,
myAnchorIdx != -1 ? myOccurrences[myAnchorIdx].getParent() : myAnchorElement, myEditor,
myParentClass);
convertToFieldRunnable.run();
}
final Runnable runnable = new Runnable() {
public void run() {
if (myLocalVariable != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, true, myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(),
myOccurrences, myOccurenceManager,
myAnchorElementIfAll, myAnchorElement, myEditor, myParentClass);
convertToFieldRunnable.run();
}
}
};
ApplicationManager.getApplication().runWriteAction(runnable);
}
super.moveOffsetAfter(success);
if (myMoveToAnotherClassCb.isSelected()) {
@@ -389,9 +394,12 @@ public class InplaceIntroduceConstantPopup {
public void run() {
final PsiFile containingFile = myParentClass.getContainingFile();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
myExpr = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
if (myExpr != null) {
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
final RangeMarker exprMarker = getExprMarker();
if (exprMarker != null) {
myExpr = restoreExpression(containingFile, psiField, elementFactory, exprMarker, myExprText);
if (myExpr != null && myExpr.isPhysical()) {
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
}
}
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
@@ -405,6 +413,14 @@ public class InplaceIntroduceConstantPopup {
myOccurrences[i] = psiExpression;
}
}
if (myAnchorIdxIfAll != -1) {
myAnchorElementIfAll = myOccurrences[myAnchorIdxIfAll].getParent();
}
if (myAnchorIdx != -1) {
myAnchorElement = myOccurrences[myAnchorIdx].getParent();
}
myOccurrenceMarkers = null;
if (psiField.isValid()) {
psiField.delete();
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
@@ -95,7 +96,7 @@ public class InplaceIntroduceFieldPopup {
myInitializerExpression = initializerExpression;
myExprText = myInitializerExpression != null ? myInitializerExpression.getText() : null;
myLocalName = localVariable != null ? localVariable.getName() : null;
myExprMarker = myInitializerExpression != null ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null;
myExprMarker = myInitializerExpression != null && myInitializerExpression.isPhysical() ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null;
myTypeSelectorManager = typeSelectorManager;
myAnchorElement = anchorElement;
myAnchorElementIfAll = anchorElementIfAll;
@@ -176,6 +177,7 @@ public class InplaceIntroduceFieldPopup {
final PsiField field = createFieldToStartTemplateOn(suggestedNameInfo.names, defaultType);
if (field != null) {
myEditor.getCaretModel().moveToOffset(field.getTextOffset());
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
nameSuggestions.add(field.getName());
nameSuggestions.addAll(Arrays.asList(suggestedNameInfo.names));
@@ -233,7 +235,7 @@ public class InplaceIntroduceFieldPopup {
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
myEditor, psiVariable, false,
myTypeSelectorManager.getTypesForAll().length > 1,
myInitializerExpression != null ? myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null, InplaceIntroduceFieldPopup.this.getOccurrenceMarkers());
myInitializerExpression != null && myInitializerExpression.isPhysical() ? myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null, InplaceIntroduceFieldPopup.this.getOccurrenceMarkers());
myDefaultParameterTypePointer =
SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType());
myFieldRangeStart = myEditor.getDocument().createRangeMarker(psiVariable.getTextRange());
@@ -246,7 +248,7 @@ public class InplaceIntroduceFieldPopup {
@Override
protected PsiExpression getExpr() {
return myInitializerExpression;
return myInitializerExpression != null && myInitializerExpression.isValid() && myInitializerExpression.isPhysical() ? myInitializerExpression : null;
}
@Override
@@ -318,20 +320,25 @@ public class InplaceIntroduceFieldPopup {
myFieldTypePointer.getType(),
myIntroduceFieldPanel.isDeleteVariable(),
myParentClass, false, false);
if (myLocalVariable != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, myStatic, myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myInitializerExpression, settings, settings.getForcedType(),
myOccurrences, myOccurenceManager,
myAnchorIdxIfAll != -1? myOccurrences[myAnchorIdxIfAll].getParent() : myAnchorElementIfAll,
myAnchorIdx != -1 ? myOccurrences[myAnchorIdx].getParent() : myAnchorElement, myEditor,
myParentClass);
convertToFieldRunnable.run();
}
final Runnable runnable = new Runnable() {
public void run() {
if (myLocalVariable != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, myStatic, myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myInitializerExpression, settings, settings.getForcedType(),
myOccurrences, myOccurenceManager,
myAnchorIdxIfAll != -1? myOccurrences[myAnchorIdxIfAll].getParent() : myAnchorElementIfAll,
myAnchorIdx != -1 ? myOccurrences[myAnchorIdx].getParent() : myAnchorElement, myEditor,
myParentClass);
convertToFieldRunnable.run();
}
}
};
ApplicationManager.getApplication().runWriteAction(runnable);
}
super.moveOffsetAfter(success);
}
@@ -349,9 +356,11 @@ public class InplaceIntroduceFieldPopup {
public void run() {
final PsiFile containingFile = myParentClass.getContainingFile();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
myInitializerExpression = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
if (myInitializerExpression != null) {
myExprMarker = myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange());
if (getExprMarker() != null) {
myInitializerExpression = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
if (myInitializerExpression != null) {
myExprMarker = myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange());
}
}
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.*;
@@ -135,6 +136,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
if (parameter != null) {
myParameterIndex = myMethod.getParameterList().getParameterIndex(parameter);
myEditor.getCaretModel().moveToOffset(parameter.getTextOffset());
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
nameSuggestions.add(parameter.getName());
nameSuggestions.addAll(Arrays.asList(names));
@@ -247,20 +249,25 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
getReplaceFieldsWithGetters(), myMustBeFinal || myFinal, isGenerateDelegate(),
myParameterTypePointer.getType(),
parametersToRemove);
ApplicationManager.getApplication().invokeLater(new Runnable() {
final Runnable runnable = new Runnable() {
public void run() {
final boolean [] conflictsFound = new boolean[] {true};
processor.setPrepareSuccessfulSwingThreadCallback(new Runnable() {
@Override
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
conflictsFound[0] = processor.hasConflicts();
final boolean [] conflictsFound = new boolean[] {true};
processor.setPrepareSuccessfulSwingThreadCallback(new Runnable() {
@Override
public void run() {
conflictsFound[0] = processor.hasConflicts();
}
});
processor.run();
normalizeParameterIdxAccordingToRemovedParams(parametersToRemove);
ParameterInplaceIntroducer.super.moveOffsetAfter(!conflictsFound[0]);
}
});
processor.run();
normalizeParameterIdxAccordingToRemovedParams(parametersToRemove);
ParameterInplaceIntroducer.super.moveOffsetAfter(!conflictsFound[0]);
}
});
};
CommandProcessor.getInstance().executeCommand(myProject, runnable, IntroduceParameterHandler.REFACTORING_NAME, null);
} else {
super.moveOffsetAfter(success);
}
@@ -90,7 +90,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
final PsiElement[] statementsInRange = findStatementsAtOffset(editor, file, offset);
//try line selection
if (statementsInRange.length == 1 && (PsiUtil.hasErrorElementChild(statementsInRange[0]) || !PsiUtil.isStatement(statementsInRange[0]) || isPreferStatements())) {
if (statementsInRange.length == 1 && (PsiUtil.hasErrorElementChild(statementsInRange[0]) ||
!PsiUtil.isStatement(statementsInRange[0]) ||
statementsInRange[0].getTextRange().getStartOffset() >= offset ||
statementsInRange[0].getTextRange().getEndOffset() <= offset ||
isPreferStatements())) {
selectionModel.selectLineAtCaret();
if (findExpressionInRange(project, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) == null) {
selectionModel.removeSelection();
@@ -28,10 +28,7 @@ import com.intellij.ide.IdeTooltipManager;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.*;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
@@ -55,6 +52,7 @@ import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.TitlePanel;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.PositionTracker;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -161,8 +159,9 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
@Override
public boolean performInplaceRename(boolean processTextOccurrences, LinkedHashSet<String> nameSuggestions) {
final boolean result = super.performInplaceRename(processTextOccurrences, nameSuggestions);
showBalloon();
return super.performInplaceRename(processTextOccurrences, nameSuggestions);
return result;
}
public RangeMarker getExprMarker() {
@@ -180,10 +179,10 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
}
saveSettings(psiVariable);
adjustLine(psiVariable, document);
int startOffset = myExprMarker != null ? myExprMarker.getStartOffset() : psiVariable.getTextOffset();
int startOffset = myExprMarker != null && myExprMarker.isValid() ? myExprMarker.getStartOffset() : psiVariable.getTextOffset();
final PsiFile file = psiVariable.getContainingFile();
final PsiReference referenceAt = file.findReferenceAt(startOffset);
if (referenceAt != null && referenceAt.resolve() instanceof PsiLocalVariable) {
if (referenceAt != null && referenceAt.resolve() instanceof PsiVariable) {
startOffset = referenceAt.getElement().getTextRange().getEndOffset();
}
else {
@@ -193,6 +192,7 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
}
}
myEditor.getCaretModel().moveToOffset(startOffset);
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
if (psiVariable.getInitializer() != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
@@ -353,7 +353,7 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(component);
balloonBuilder.setFadeoutTime(0)
.setFillColor(IdeTooltipManager.GRAPHITE_COLOR)
.setFillColor(IdeTooltipManager.GRAPHITE_COLOR.brighter().brighter())
.setAnimationCycle(0)
.setHideOnClickOutside(false)
.setHideOnKeyOutside(false)
@@ -363,8 +363,11 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
final RelativePoint target = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor);
final Point screenPoint = target.getScreenPoint();
myBalloon = balloonBuilder.createBalloon();
myBalloon
.show(new RelativePoint(new Point(screenPoint.x, screenPoint.y - myEditor.getLineHeight())), Balloon.Position.above);
int y = screenPoint.y;
if (target.getPoint().getY() > myEditor.getLineHeight() + myBalloon.getPreferredSize().getHeight()) {
y -= myEditor.getLineHeight();
}
myBalloon.show(new RelativePoint(new Point(screenPoint.x, y)), Balloon.Position.above);
}
public class FinalListener implements ActionListener {
@@ -33,7 +33,10 @@ import com.intellij.psi.util.PsiUtilBase;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.refactoring.move.FileReferenceContextUtil;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil;
import com.intellij.refactoring.rename.RenameUtil;
import com.intellij.refactoring.util.NonCodeUsageInfo;
import com.intellij.refactoring.util.RefactoringUIUtil;
@@ -182,6 +185,7 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
Messages.showErrorDialog(myProject, e.getMessage(), CommonBundle.getErrorTitle());
return;
}
final List<PsiFile> movedFiles = new ArrayList<PsiFile>();
final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<PsiElement, PsiElement>();
for (PsiFile psiFile : myFilesToMove.keySet()) {
ChangeContextUtil.encodeContextInfo(psiFile, true);
@@ -195,7 +199,14 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
}
} else {
if (!moveDestination.equals(psiFile.getContainingDirectory())) {
psiFile.getManager().moveFile(psiFile, moveDestination);
MoveFileHandler.forElement(psiFile).prepareMovedFile(psiFile, moveDestination, oldToNewElementsMapping);
PsiFile moving = moveDestination.findFile(psiFile.getName());
if (moving == null) {
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, moveDestination);
}
moving = moveDestination.findFile(psiFile.getName());
movedFiles.add(moving);
listener.elementMoved(psiFile);
}
}
@@ -212,6 +223,12 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
}
}
}
// fix references in moved files to outer files
for (PsiFile movedFile : movedFiles) {
MoveFileHandler.forElement(movedFile).updateMovedFile(movedFile);
FileReferenceContextUtil.decodeFileReferences(movedFile);
}
for (PsiDirectory directory : myDirectories) {
directory.delete();
}
@@ -40,6 +40,7 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.*;
@@ -765,28 +766,30 @@ public class TypeMigrationLabeler {
return refs;
}
@TestOnly
public String getMigrationReport() {
final StringBuffer buffer = new StringBuffer();
final StringBuilder buffer = new StringBuilder();
buffer.append("Types:\n").append(getTypeEvaluator().getReport()).append("\n");
buffer.append("Types:\n" + getTypeEvaluator().getReport() + "\n");
buffer.append("Conversions:\n");
final String[] conversions = new String[myConversions.size()];
int k = 0;
for (final PsiElement expr : myConversions.keySet()) {
final Object conv = myConversions.get(expr);
final Object conversion = myConversions.get(expr);
if (conv instanceof Pair && ((Pair)conv).first == null) {
conversions[k++] = (expr.getText() + " -> " + ((Pair)conv).second + "\n");
if (conversion instanceof Pair && ((Pair)conversion).first == null) {
conversions[k++] = (expr.getText() + " -> " + ((Pair)conversion).second + "\n");
} else {
conversions[k++] = (expr.getText() + " -> " + conv + "\n");
conversions[k++] = (expr.getText() + " -> " + conversion + "\n");
}
}
Arrays.sort(conversions, new Comparator() {
public int compare(Object x, Object y) {
return ((String)x).compareTo((String)y);
Arrays.sort(conversions, new Comparator<String>() {
public int compare(String x, String y) {
return x.compareTo(y);
}
});
@@ -796,23 +799,22 @@ public class TypeMigrationLabeler {
buffer.append("\nNew expression type changes:\n");
final String[] newchanges = new String[myNewExpressionTypeChange.size()];
final String[] newChanges = new String[myNewExpressionTypeChange.size()];
k = 0;
for (final Map.Entry<TypeMigrationUsageInfo, PsiType> entry : myNewExpressionTypeChange.entrySet()) {
newchanges[k++] = entry.getKey().getElement().getText() + " -> " + entry.getValue().getCanonicalText() + "\n";
final PsiElement element = entry.getKey().getElement();
newChanges[k++] = (element != null ? element.getText() : entry.getKey()) + " -> " + entry.getValue().getCanonicalText() + "\n";
}
Arrays.sort(newchanges, new Comparator() {
public int compare(Object x, Object y) {
return ((String)x).compareTo((String)y);
Arrays.sort(newChanges, new Comparator<String>() {
public int compare(String x, String y) {
return x.compareTo(y);
}
});
for (String newchange : newchanges) {
buffer.append(newchange);
for (String change : newChanges) {
buffer.append(change);
}
buffer.append("Fails:\n");
@@ -830,13 +832,12 @@ public class TypeMigrationLabeler {
for (final Pair<PsiAnchor, PsiType> p : failsList) {
final PsiElement element = p.getFirst().retrieve();
if (element != null) {
buffer.append(element.getText() + "->" + p.getSecond().getCanonicalText() + "\n");
buffer.append(element.getText()).append("->").append(p.getSecond().getCanonicalText()).append("\n");
}
}
return buffer.toString();
}
public static class MigrateException extends RuntimeException {
}
public static class MigrateException extends RuntimeException { }
}
@@ -63,8 +63,8 @@ public class TypeMigrationRules {
@NonNls
@Nullable
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, PsiMember member, final PsiExpression context, final boolean isCovariantPosition,
final TypeMigrationLabeler labeler) {
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context,
final boolean isCovariantPosition, final TypeMigrationLabeler labeler) {
final TypeConversionDescriptorBase conversion = findConversion(from, to, member, context, labeler);
if (conversion != null) return conversion;
@@ -74,12 +74,13 @@ public class TypeMigrationRules {
}
if (TypeConversionUtil.isAssignable(to, from)) return new TypeConversionDescriptorBase();
}
if (!isCovariantPosition && TypeConversionUtil.isAssignable(from, to)) return new TypeConversionDescriptorBase();
return null;
return !isCovariantPosition && TypeConversionUtil.isAssignable(from, to) ? new TypeConversionDescriptorBase() : null;
}
@Nullable
public TypeConversionDescriptorBase findConversion(PsiType from, PsiType to, PsiMember member, PsiExpression context, TypeMigrationLabeler labeler) {
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member,
final PsiExpression context, final TypeMigrationLabeler labeler) {
for (TypeConversionRule descriptor : myConversionRules) {
final TypeConversionDescriptorBase conversion = descriptor.findConversion(from, to, member, context, labeler);
if (conversion != null) return conversion;
@@ -96,7 +97,8 @@ public class TypeMigrationRules {
}
@Nullable
public Pair<PsiType, PsiType> bindTypeParameters(final PsiType from, final PsiType to, final PsiMethod method, final PsiExpression context, final TypeMigrationLabeler labeler) {
public Pair<PsiType, PsiType> bindTypeParameters(final PsiType from, final PsiType to, final PsiMethod method,
final PsiExpression context, final TypeMigrationLabeler labeler) {
for (TypeConversionRule conversionRule : myConversionRules) {
final Pair<PsiType, PsiType> typePair = conversionRule.bindTypeParameters(from, to, method, context, labeler);
if (typePair != null) return typePair;