diff --git a/java/execution/impl/src/com/intellij/execution/junit2/configuration/ClassBrowser.java b/java/execution/impl/src/com/intellij/execution/junit2/configuration/ClassBrowser.java index 587087e0d6e7..36eb1e37e3dd 100644 --- a/java/execution/impl/src/com/intellij/execution/junit2/configuration/ClassBrowser.java +++ b/java/execution/impl/src/com/intellij/execution/junit2/configuration/ClassBrowser.java @@ -20,7 +20,6 @@ import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.configuration.BrowseModuleValueActionListener; import com.intellij.execution.configurations.ConfigurationUtil; import com.intellij.ide.util.TreeClassChooser; -import com.intellij.ide.util.TreeClassChooserDialog; import com.intellij.ide.util.TreeClassChooserFactory; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -51,7 +50,7 @@ public abstract class ClassBrowser extends BrowseModuleValueActionListener { info.showNow(); return null; } - final TreeClassChooser dialog = TreeClassChooserFactory.getInstance(getProject()).createWithInnerClassesScopeChooser(myTitle, classFilter.getScope(), classFilter, null); + final TreeClassChooser dialog = createClassChooser(classFilter); configureDialog(dialog); dialog.showDialog(); final PsiClass psiClass = dialog.getSelectedClass(); @@ -60,6 +59,10 @@ public abstract class ClassBrowser extends BrowseModuleValueActionListener { return JavaExecutionUtil.getRuntimeQualifiedName(psiClass); } + protected TreeClassChooser createClassChooser(TreeClassChooser.ClassFilterWithScope classFilter) { + return TreeClassChooserFactory.getInstance(getProject()).createWithInnerClassesScopeChooser(myTitle, classFilter.getScope(), classFilter, null); + } + protected abstract TreeClassChooser.ClassFilterWithScope getFilter() throws NoFilterException; protected void onClassChoosen(final PsiClass psiClass) { } @@ -91,12 +94,16 @@ public abstract class ClassBrowser extends BrowseModuleValueActionListener { public static ClassBrowser createAppletClassBrowser(final Project project, final ConfigurationModuleSelector moduleSelector) { - return new MainClassBrowser(project, moduleSelector, ExecutionBundle.message("choose.applet.class.dialog.title")) { - protected TreeClassChooser.ClassFilter createFilter(final Module module) { + final String title = ExecutionBundle.message("choose.applet.class.dialog.title"); + return new MainClassBrowser(project, moduleSelector, title) { + + @Override + protected TreeClassChooser createClassChooser(TreeClassChooser.ClassFilterWithScope classFilter) { + final Module module = moduleSelector.getModule(); final GlobalSearchScope scope = module == null ? GlobalSearchScope.allScope(myProject) : GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); - final PsiClass appletClass = JavaPsiFacade.getInstance(project).findClass("java.applet.Applet", scope); - return new TreeClassChooserDialog.InheritanceClassFilterImpl(appletClass, false, false, ConfigurationUtil.PUBLIC_INSTANTIATABLE_CLASS); + final PsiClass appletClass = JavaPsiFacade.getInstance(project).findClass("java.applet.Applet", scope); + return TreeClassChooserFactory.getInstance(getProject()).createInheritanceClassChooser(title, classFilter.getScope(), appletClass, false, false, ConfigurationUtil.PUBLIC_INSTANTIATABLE_CLASS); } }; } diff --git a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java index 41095075aadf..fb56252366ad 100644 --- a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java +++ b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java @@ -20,9 +20,11 @@ import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.IconLoader; import com.intellij.psi.CommonClassNames; import com.intellij.psi.JavaPsiFacade; @@ -67,7 +69,12 @@ public class JavaModuleType extends ModuleType { final ProjectWizardStepFactory wizardFactory = ProjectWizardStepFactory.getInstance(); ArrayList steps = new ArrayList(); steps.add(wizardFactory.createSourcePathsStep(wizardContext, moduleBuilder, getWizardIcon(), "reference.dialogs.new.project.fromScratch.source")); - steps.add(wizardFactory.createProjectJdkStep(wizardContext)); + steps.add(wizardFactory.createProjectJdkStep(wizardContext, JavaSdk.getInstance(), moduleBuilder, new Computable() { + public Boolean compute() { + final Sdk projectJdk = wizardContext.getProjectJdk(); + return projectJdk == null || projectJdk.getSdkType() != JavaSdk.getInstance() ? Boolean.TRUE : Boolean.FALSE; + } + }, getWizardIcon(), "reference.dialogs.new.project.fromScratch.sdk")); final ModuleWizardStep supportForFrameworksStep = wizardFactory.createSupportForFrameworksStep(wizardContext, moduleBuilder); if (supportForFrameworksStep != null) { steps.add(supportForFrameworksStep); @@ -121,4 +128,4 @@ public class JavaModuleType extends ModuleType { return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, module.getModuleWithLibrariesScope()) != null; } -} \ No newline at end of file +} diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java index f08ffb59aeed..03abe9c2a0d3 100644 --- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java @@ -20,19 +20,20 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.ParameterTablePanel; import com.intellij.refactoring.util.RefactoringMessageUtil; -import com.intellij.ui.EditorTextField; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.NonFocusableCheckBox; +import com.intellij.util.Function; import com.intellij.util.containers.HashMap; -import org.jetbrains.annotations.NonNls; import javax.swing.*; import java.awt.*; @@ -45,7 +46,7 @@ class AnonymousToInnerDialog extends DialogWrapper{ private final PsiAnonymousClass myAnonClass; private final boolean myNeedsThis; - private EditorTextField myNameField; + private NameSuggestionsField myNameField; private final ParameterTablePanel.VariableData[] myVariableData; private final Map myVariableToInfoMap = new HashMap(); private JCheckBox myCbMakeStatic; @@ -79,11 +80,20 @@ class AnonymousToInnerDialog extends DialogWrapper{ init(); + final String[] names; String name = myAnonClass.getBaseClassReference().getReferenceName(); - @NonNls final String prefix = "My"; - name = prefix + name; //? - myNameField.setText(name); - myNameField.selectAll(); + PsiType[] typeParameters = myAnonClass.getBaseClassReference().getTypeParameters(); + if (typeParameters.length > 0) { + names = new String[]{StringUtil.join(typeParameters, new Function() { + public String fun(PsiType psiType) { + return psiType.getPresentableText(); + } + }, "") + name, "My" + name}; + } else { + names = new String[]{"My" + name}; + } + myNameField.setSuggestions(names); + myNameField.selectNameWithoutExtension(); } protected Action[] createActions(){ @@ -104,7 +114,7 @@ class AnonymousToInnerDialog extends DialogWrapper{ } public String getClassName() { - return myNameField.getText().trim(); + return myNameField.getEnteredName(); } public VariableInfo[] getVariableInfos() { @@ -183,7 +193,7 @@ class AnonymousToInnerDialog extends DialogWrapper{ JLabel namePrompt = new JLabel(RefactoringBundle.message("anonymousToInner.class.name.label.text")); panel.add(namePrompt, gbConstraints); - myNameField = new EditorTextField(""); + myNameField = new NameSuggestionsField(myProject); gbConstraints.gridwidth = 1; gbConstraints.weightx = 1; gbConstraints.gridx = 1; diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index 54c492afe4e8..f1fb9c9bd157 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -52,10 +52,10 @@ public class CopyClassesHandler implements CopyHandlerDelegate { FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.copyClass"); PsiClass aClass = convertToTopLevelClass(elements); assert aClass != null; - Project project = aClass.getProject(); if (defaultTargetDirectory == null) { defaultTargetDirectory = aClass.getContainingFile().getContainingDirectory(); } + Project project = defaultTargetDirectory.getProject(); CopyClassDialog dialog = new CopyClassDialog(aClass, defaultTargetDirectory, project, false); dialog.setTitle(RefactoringBundle.message("copy.handler.copy.class")); dialog.show(); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java index 16b23ae7e1fd..94b79585d4de 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java @@ -33,8 +33,10 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.IntroduceParameterRefactoring; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; import com.intellij.refactoring.introduceVariable.IntroduceVariableBase; @@ -253,7 +255,15 @@ public class IntroduceParameterProcessor extends BaseRefactoringProcessor implem for (final UsageInfo usageInfo : usageArray) { if (usageInfo instanceof ExternalUsageInfo && isMethodUsage(usageInfo)) { final PsiElement place = usageInfo.getElement(); - for (final PsiElement element : result) { + for (PsiElement element : result) { + if (element instanceof PsiField && myReplaceFieldsWithGetters != IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE) { //check getter access instead + final PsiClass psiClass = ((PsiField)element).getContainingClass(); + LOG.assertTrue(psiClass != null); + final PsiMethod method = psiClass.findMethodBySignature(PropertyUtil.generateGetterPrototype((PsiField)element), true); + if (method != null){ + element = method; + } + } if (element instanceof PsiMember && !JavaPsiFacade.getInstance(myProject).getResolveHelper().isAccessible((PsiMember)element, place, null)) { String message = diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java index a6adff0d5dc1..efd4672e9f5e 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java @@ -227,10 +227,9 @@ public class OldReferenceResolver { if (JavaPsiFacade.getInstance(psiField.getProject()).getResolveHelper().isAccessible(getter, newExpr, null)) { PsiElementFactory factory = JavaPsiFacade.getInstance(newExpr.getProject()).getElementFactory(); String id = getter.getName(); - final PsiElement parent = newExpr.getParent(); String qualifier = null; - if (parent instanceof PsiReferenceExpression) { - final PsiExpression qualifierExpression = ((PsiReferenceExpression)parent).getQualifierExpression(); + if (newExpr instanceof PsiReferenceExpression) { + final PsiExpression qualifierExpression = ((PsiReferenceExpression)newExpr).getQualifierExpression(); if (qualifierExpression != null) { qualifier = qualifierExpression.getText(); } @@ -238,8 +237,8 @@ public class OldReferenceResolver { PsiMethodCallExpression getterCall = (PsiMethodCallExpression)factory.createExpressionFromText((qualifier != null ? qualifier + "." : "") + id + "()", null); getterCall = (PsiMethodCallExpression)CodeStyleManager.getInstance(myProject).reformat(getterCall); - if (parent != null) { - newExpr = parent.replace(getterCall); + if (newExpr.getParent() != null) { + newExpr = newExpr.replace(getterCall); } else { newExpr = getterCall; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 251716f4652a..d2788c7d9ea6 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -577,6 +577,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme } declaration = (PsiDeclarationStatement) putStatementInLoopBody(declaration, container, finalAnchorStatement); + declaration = (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(declaration); PsiVariable var = (PsiVariable) declaration.getDeclaredElements()[0]; PsiUtil.setModifierProperty(var, PsiModifier.FINAL, declareFinal); diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java index 112436e3f89a..d6728cb2224c 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java @@ -39,6 +39,7 @@ import com.intellij.refactoring.rename.RenameUtil; import com.intellij.refactoring.util.*; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.VisibilityUtil; @@ -142,7 +143,12 @@ public class MoveClassToInnerProcessor extends BaseRefactoringProcessor { for (PsiClass classToMove : myClassesToMove) { ChangeContextUtil.encodeContextInfo(classToMove, true); PsiClass newClass = (PsiClass)myTargetClass.addBefore(classToMove, myTargetClass.getRBrace()); - PsiUtil.setModifierProperty(newClass, PsiModifier.STATIC, true); + if (myTargetClass.isInterface()) { + PsiUtil.setModifierProperty(newClass, PsiModifier.PACKAGE_LOCAL, true); + } + else { + PsiUtil.setModifierProperty(newClass, PsiModifier.STATIC, true); + } newClass = (PsiClass)ChangeContextUtil.decodeContextInfo(newClass, null, null); oldToNewElementsMapping.put(classToMove, newClass); } @@ -290,7 +296,11 @@ public class MoveClassToInnerProcessor extends BaseRefactoringProcessor { protected String getCommandName() { return RefactoringBundle.message("move.class.to.inner.command.name", - myClassesToMove[0].getQualifiedName(), + (myClassesToMove.length > 1 ? "classes " : "class ") + StringUtil.join(myClassesToMove, new Function() { + public String fun(PsiClass psiClass) { + return psiClass.getName(); + } + }, ", "), myTargetClass.getQualifiedName()); } diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java index 45c32fbfe8a7..a670185f3d00 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java @@ -80,7 +80,7 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider { } final String[] strings = info != null ? info.names : ArrayUtil.EMPTY_STRING_ARRAY; ArrayList list = new ArrayList(Arrays.asList(strings)); - final String properlyCased = suggestProperlyCasedName(element); + final String[] properlyCased = suggestProperlyCasedName(element); if (!list.contains(initialName)) { list.add(0, initialName); } @@ -89,8 +89,10 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider { list.remove(i); list.add(0, initialName); } - if (properlyCased != null && !properlyCased.equals(initialName)) { - list.add(1, properlyCased); + if (properlyCased != null) { + for (String properlyCasedSuggestion : properlyCased) { + list.add(1, properlyCasedSuggestion); + } } if (parameterName != null && !list.contains(parameterName)) { list.add(parameterName); @@ -137,7 +139,7 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider { } @Nullable - private static String suggestProperlyCasedName(PsiElement psiElement) { + private static String[] suggestProperlyCasedName(PsiElement psiElement) { if (!(psiElement instanceof PsiNamedElement)) return null; String name = ((PsiNamedElement)psiElement).getName(); if (name == null) return null; @@ -156,25 +158,29 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider { if (i > 0) buffer.append('_'); buffer.append(word.toUpperCase()); } - return buffer.toString(); + return new String[] {buffer.toString()}; } else { - StringBuilder buffer = new StringBuilder(prefix); - for (int i = 0; i < words.length; i++) { - String word = words[i]; - final boolean prefixRequiresCapitalization = prefix.length() > 0 && !StringUtil.endsWithChar(prefix, '_'); - if (i > 0 || prefixRequiresCapitalization) { - buffer.append(StringUtil.capitalize(word)); - } - else { - buffer.append(StringUtil.decapitalize(word)); - } - } - return buffer.toString(); + return new String[]{suggestProperlyCasedName(prefix, words), suggestProperlyCasedName(prefix, NameUtil.splitNameIntoWords(name.toLowerCase()))}; } } - return name; + return new String[]{name}; + } + + private static String suggestProperlyCasedName(String prefix, String[] words) { + StringBuilder buffer = new StringBuilder(prefix); + for (int i = 0; i < words.length; i++) { + String word = words[i]; + final boolean prefixRequiresCapitalization = prefix.length() > 0 && !StringUtil.endsWithChar(prefix, '_'); + if (i > 0 || prefixRequiresCapitalization) { + buffer.append(StringUtil.capitalize(word)); + } + else { + buffer.append(StringUtil.decapitalize(word)); + } + } + return buffer.toString(); } @Nullable diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java index 9183a46d3f21..967825a50ae1 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java @@ -23,7 +23,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.search.searches.ClassInheritorsSearch; -import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.HelpID; @@ -36,7 +36,7 @@ import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.HashSet; +import com.intellij.util.Processor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -192,11 +192,11 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor { } if (getter != null) { - addOverriddenAndImplemented(aClass, getter, newGetterName, allRenames); + addOverriddenAndImplemented(getter, newGetterName, allRenames); } if (setter != null) { - addOverriddenAndImplemented(aClass, setter, newSetterName, allRenames); + addOverriddenAndImplemented(setter, newSetterName, allRenames); } if (shouldRenameSetterParameter) { @@ -211,18 +211,16 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor { return Messages.showYesNoDialog(project, text, RefactoringBundle.message("rename.title"), Messages.getQuestionIcon()) != 0; } - private static void addOverriddenAndImplemented(PsiClass aClass, PsiMethod methodPrototype, String newName, - final Map allRenames) { - final HashSet superClasses = new HashSet(); - InheritanceUtil.getSuperClasses(aClass, superClasses, true); - superClasses.add(aClass); - - for (PsiClass superClass : superClasses) { - PsiMethod method = superClass.findMethodBySignature(methodPrototype, false); - - if (method != null) { - allRenames.put(method, newName); - } + private static void addOverriddenAndImplemented(PsiMethod methodPrototype, final String newName, final Map allRenames) { + allRenames.put(methodPrototype, newName); + for (PsiMethod method : methodPrototype.findDeepestSuperMethods()) { + OverridingMethodsSearch.search(method).forEach(new Processor() { + public boolean process(PsiMethod psiMethod) { + allRenames.put(psiMethod, newName); + return true; + } + }); + allRenames.put(method, newName); } } diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java index af6e8a816231..2b004c272dfa 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java @@ -15,9 +15,12 @@ */ package com.intellij.refactoring.safeDelete; +import com.intellij.openapi.Disposable; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.refactoring.HelpID; @@ -25,20 +28,23 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo; import com.intellij.ui.BooleanTableCellRenderer; import com.intellij.ui.ScrollPaneFactory; -import com.intellij.util.ui.Table; import com.intellij.usageView.UsageInfo; +import com.intellij.usages.impl.UsagePreviewPanel; +import com.intellij.util.ui.Table; +import org.jetbrains.annotations.NonNls; import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumnModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import org.jetbrains.annotations.NonNls; - /** * @author dsl */ @@ -49,6 +55,7 @@ class OverridingMethodsDialog extends DialogWrapper { private static final int CHECK_COLUMN = 0; private Table myTable; + private final UsagePreviewPanel myUsagePreviewPanel; public OverridingMethodsDialog(Project project, List overridingMethods) { super(project, true); @@ -67,7 +74,7 @@ class OverridingMethodsDialog extends DialogWrapper { PsiFormatUtil.SHOW_TYPE ); } - + myUsagePreviewPanel = new UsagePreviewPanel(project); setTitle(RefactoringBundle.message("unused.overriding.methods.title")); init(); } @@ -106,6 +113,12 @@ class OverridingMethodsDialog extends DialogWrapper { return myTable; } + @Override + protected void dispose() { + Disposer.dispose(myUsagePreviewPanel); + super.dispose(); + } + protected JComponent createCenterPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(8, 0, 4, 0)); @@ -157,7 +170,35 @@ class OverridingMethodsDialog extends DialogWrapper { JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); panel.add(scrollPane, BorderLayout.CENTER); - return panel; + ListSelectionListener selectionListener = new ListSelectionListener() { + public void valueChanged(final ListSelectionEvent e) { + int index = myTable.getSelectionModel().getLeadSelectionIndex(); + if (index != -1) { + UsageInfo usageInfo = myOverridingMethods.get(index); + myUsagePreviewPanel.updateLayout(Collections.singletonList(usageInfo)); + } + else { + myUsagePreviewPanel.updateLayout(null); + } + } + }; + myTable.getSelectionModel().addListSelectionListener(selectionListener); + + final Splitter splitter = new Splitter(true, 0.3f); + splitter.setFirstComponent(panel); + splitter.setSecondComponent(myUsagePreviewPanel); + myUsagePreviewPanel.updateLayout(null); + + Disposer.register(myDisposable, new Disposable(){ + public void dispose() { + splitter.dispose(); + } + }); + + if (tableModel.getRowCount() != 0) { + myTable.getSelectionModel().addSelectionInterval(0,0); + } + return splitter; } class MyTableModel extends AbstractTableModel { diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java index b82d9f927e83..83b6f1f7a7ab 100644 --- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java +++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java @@ -294,6 +294,9 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces processUsage(variable); return; } + } else if (classReference.getParent() instanceof PsiAnonymousClass) { + processUsage(classReference); + return; } } markNode(ref); //??? @@ -635,10 +638,17 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces final PsiType type = ((PsiParameter)element).getType(); final PsiClass aClass = PsiUtil.resolveClassInType(type); if (aClass != null) { - if (!myManager.isInProject(element) || !myManager.areElementsEquivalent(aClass, myClass)) { - if (!isSuperInheritor(aClass)) { - markNode(element); + if (aClass instanceof PsiTypeParameter) { + for (Node node : myElementToNode.get(element).mySuccessors) { + final PsiResolveHelper psiResolveHelper = JavaPsiFacade.getInstance(myProject).getResolveHelper(); + final PsiType psiType = psiResolveHelper + .inferTypeForMethodTypeParameter((PsiTypeParameter)aClass, new PsiParameter[]{(PsiParameter)element}, + new PsiExpression[]{(PsiExpression)node.myMark.myElement}, PsiSubstitutor.EMPTY, null, + false); + if (checkNode(element, PsiUtil.resolveClassInType(psiType))) break; } + } else { + checkNode(element, aClass); } } else { // unresolvable class @@ -648,6 +658,16 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces } } + private boolean checkNode(PsiElement element, PsiClass psiClass) { + if (!myManager.isInProject(element) || !myManager.areElementsEquivalent(psiClass, myClass)) { + if (!isSuperInheritor(psiClass)) { + markNode(element); + return true; + } + } + return false; + } + protected abstract boolean isSuperInheritor(PsiClass aClass); protected abstract boolean isInSuper(PsiElement member); diff --git a/java/java-tests/testData/refactoring/introduceParameter/afterStaticFieldWithGetterReplacement.java b/java/java-tests/testData/refactoring/introduceParameter/afterStaticFieldWithGetterReplacement.java new file mode 100644 index 000000000000..a0288ebd69f2 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceParameter/afterStaticFieldWithGetterReplacement.java @@ -0,0 +1,17 @@ +public class R { + private static int ourInt; + + public static int getOurInt() { + return ourInt; + } + + public static void doSmth(final int anObject) { + System.out.println(anObject); + } +} + +class Usage { + void foo() { + R.doSmth(R.getOurInt()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceParameter/beforeStaticFieldWithGetterReplacement.java b/java/java-tests/testData/refactoring/introduceParameter/beforeStaticFieldWithGetterReplacement.java new file mode 100644 index 000000000000..89135cc9d1d2 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceParameter/beforeStaticFieldWithGetterReplacement.java @@ -0,0 +1,17 @@ +public class R { + private static int ourInt; + + public static int getOurInt() { + return ourInt; + } + + public static void doSmth() { + System.out.println(ourInt); + } +} + +class Usage { + void foo() { + R.doSmth(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/moveClassToInner/locallyUsedPackageLocalToPublicInterface/after/pack2/A.java b/java/java-tests/testData/refactoring/moveClassToInner/locallyUsedPackageLocalToPublicInterface/after/pack2/A.java index 2c9548698627..afe56184679b 100644 --- a/java/java-tests/testData/refactoring/moveClassToInner/locallyUsedPackageLocalToPublicInterface/after/pack2/A.java +++ b/java/java-tests/testData/refactoring/moveClassToInner/locallyUsedPackageLocalToPublicInterface/after/pack2/A.java @@ -1,6 +1,6 @@ package pack2; public interface A { - static class Class1 { + class Class1 { } } diff --git a/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/after/Clazz.java b/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/after/Clazz.java new file mode 100644 index 000000000000..94ce2ffe56c6 --- /dev/null +++ b/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/after/Clazz.java @@ -0,0 +1,20 @@ +interface Intf { +} + +interface Factory { + E create(); + void save(E obj); + + static class helper { + static Factory get2() { + return (Factory)new Factory() { + public Intf create() { return null; } + public void save(Intf obj) { } + }; + } + } +} + + +public class Clazz implements Intf { +} diff --git a/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/before/Clazz.java b/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/before/Clazz.java new file mode 100644 index 000000000000..e2cd2a9721f5 --- /dev/null +++ b/java/java-tests/testData/refactoring/turnRefsToSuper/anonymousWithTypeArguments/before/Clazz.java @@ -0,0 +1,20 @@ +interface Intf { +} + +interface Factory { + E create(); + void save(E obj); + + static class helper { + static Factory get2() { + return (Factory)new Factory() { + public Clazz create() { return null; } + public void save(Clazz obj) { } + }; + } + } +} + + +public class Clazz implements Intf { +} diff --git a/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/after/Clazz.java b/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/after/Clazz.java new file mode 100644 index 000000000000..ef0d6df502c4 --- /dev/null +++ b/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/after/Clazz.java @@ -0,0 +1,22 @@ +interface Intf { +} + +interface Factory { + E create(); + + void save(E obj); + + static class helper { + static Factory get() { + return null; + } + } +} + + +public class Clazz implements Intf { + void bar() { + Intf y = Factory.helper.get().create(); + Factory.helper.get().save(y); + } +} diff --git a/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/before/Clazz.java b/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/before/Clazz.java new file mode 100644 index 000000000000..fde99a08dac0 --- /dev/null +++ b/java/java-tests/testData/refactoring/turnRefsToSuper/typeArgumentsParam/before/Clazz.java @@ -0,0 +1,22 @@ +interface Intf { +} + +interface Factory { + E create(); + + void save(E obj); + + static class helper { + static Factory get() { + return null; + } + } +} + + +public class Clazz implements Intf { + void bar() { + Clazz y = Factory.helper.get().create(); + Factory.helper.get().save(y); + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java index 175bed687acf..6ac077915e71 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java @@ -40,11 +40,11 @@ public class ChangeSignatureTargetTest extends LightCodeInsightTestCase { } private void doTest(String expectedMemberName) throws Exception { - String basePath = "/refactoring/changeSignatureTarget/" + getTestName(false); + String basePath = "/refactoring/changeSignatureTarget/" + getTestName(true); @NonNls final String filePath = basePath + ".java"; configureByFile(filePath); final PsiMember member = ChangeSignatureTargetUtil.findTargetMember(getFile(), getEditor()); assertNotNull(member); assertEquals(expectedMemberName, member.getName()); } -} \ No newline at end of file +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java index ff168460789c..bb175be25c86 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java @@ -8,12 +8,14 @@ import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiLocalVariable; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.testFramework.TestDataPath; import junit.framework.Assert; import org.jetbrains.annotations.NonNls; /** * @author ven */ +@TestDataPath("$CONTENT_ROOT/testData") public class IntroduceConstantTest extends LightCodeInsightTestCase { @NonNls private static final String BASE_PATH = "/refactoring/introduceConstant/"; diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java index 9cee9fa41f98..ed788b2c29a4 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java @@ -22,10 +22,12 @@ import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler; import com.intellij.refactoring.introduceParameter.IntroduceParameterProcessor; import com.intellij.refactoring.introduceParameter.Util; import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.testFramework.TestDataPath; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +@TestDataPath("$CONTENT_ROOT/testData") public class IntroduceParameterTest extends LightCodeInsightTestCase { @Override protected String getTestDataPath() { @@ -234,6 +236,10 @@ public class IntroduceParameterTest extends LightCodeInsightTestCase { "Incomplete call(Root()): expected to delete the 1 parameter but only 0 parameters found"); } + public void testStaticFieldWithGetterReplacement() throws Exception { + doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); + } + private void doTestThroughHandler() throws Exception { configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); new IntroduceParameterHandler().invoke(getProject(), myEditor, myFile, new DataContext() { diff --git a/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java b/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java index a9a0e9302462..dd1167897034 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java @@ -126,6 +126,14 @@ public class TurnRefsToSuperTest extends MultiFileTestCase { doTest("IImpl", "I", false); } + public void testAnonymousWithTypeArguments() throws Exception { + doTest("Clazz", "Intf", false); + } + + public void testTypeArgumentsParam() throws Exception { + doTest("Clazz", "Intf", false); + } + private void doTest(@NonNls final String className, @NonNls final String superClassName, final boolean replaceInstanceOf) throws Exception { doTest(new PerformAction() { public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java index 687681df885b..548c0c0e9702 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java @@ -27,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.ReadonlyStatusHandler; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; @@ -231,6 +232,9 @@ public class Browser extends JPanel { String fileURL = url.toExternalForm(); fileURL = fileURL.substring(0, fileURL.indexOf('#')); VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL); + if (vFile == null) { + vFile = VfsUtil.findFileByURL(url); + } if (vFile != null) { fireClickEvent(vFile, offset, offset); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java index bdd93f96f2d8..b0497f856bba 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java @@ -220,7 +220,10 @@ public class BookmarkManager implements PersistentStateComponent { } private void writeExternal(Element element) { - for (Bookmark bookmark : myBookmarks) { + List reversed = new ArrayList(myBookmarks); + Collections.reverse(reversed); + + for (Bookmark bookmark : reversed) { Element bookmarkElement = new Element("bookmark"); bookmarkElement.setAttribute("url", bookmark.getFile().getUrl()); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java index 16188769c18d..9508dd5a4910 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java @@ -16,11 +16,14 @@ package com.intellij.refactoring.rename; +import com.intellij.navigation.ItemPresentation; +import com.intellij.navigation.NavigationItem; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiNamedElement; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.rename.naming.AutomaticRenamer; @@ -211,7 +214,7 @@ public class AutomaticRenamingDialog extends DialogWrapper { } protected void dispose() { - myUsagePreviewPanel.dispose(); + Disposer.dispose(myUsagePreviewPanel); super.dispose(); } @@ -241,7 +244,15 @@ public class AutomaticRenamingDialog extends DialogWrapper { case CHECK_COLUMN: return Boolean.valueOf(myShouldRename[rowIndex]); case OLD_NAME_COLUMN: - return myRenames[rowIndex].getName(); + final PsiNamedElement namedElement = myRenames[rowIndex]; + String location = null; + if (namedElement instanceof NavigationItem) { + final ItemPresentation presentation = ((NavigationItem)namedElement).getPresentation(); + if (presentation != null) { + location = presentation.getLocationString(); + } + } + return namedElement.getName() + (location != null ? " " + location : ""); case NEW_NAME_COLUMN: return myNewNames[rowIndex]; default: diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index f20f16af35cc..2ce788085ef2 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -691,7 +691,7 @@ inline.to.anonymous.no.abstract=Abstract classes cannot be inlined inline.to.anonymous.no.inheritors=Classes which have subclasses cannot be inlined inline.to.anonymous.no.multiple.interfaces=Classes which implement multiple interfaces cannot be inlined inline.to.anonymous.no.superclass.and.interface=Classes which have a superclass and implement an interface cannot be inlined -move.class.to.inner.command.name=Move class {0} to {1} +move.class.to.inner.command.name=Move {0} to {1} move.classes.destination.to.package=To packa&ge move.classes.destination.make.inner=&Make inner class of move.to.inner.duplicate.inner.class=Class {0} already contains an inner class named {1} diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index 1f091888542d..c21415584e7b 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -95,7 +95,7 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest * @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/ * @throws Exception */ - protected void configureByFile(@NonNls String filePath) throws Exception { + protected void configureByFile(@TestDataFile @NonNls String filePath) throws Exception { String fullPath = getTestDataPath() + filePath; final File ioFile = new File(fullPath); diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index b327b4958bc7..0fe7ac86fa17 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1236,7 +1236,7 @@ public class StringUtil { @NonNls StringBuilder result = new StringBuilder(); for (int i = 0; i < text.length(); i++) { final char c = text.charAt(i); - if (c == ' ' || Character.isLetter(c) || Character.isDigit(c)) { + if (c == ' ' || Character.isLetter(c) || Character.isDigit(c) || c == '_') { result.append(c); } else if (c == '\n') { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListViewerDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListViewerDialog.java index 7e273ad2bef6..259de7485e40 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListViewerDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListViewerDialog.java @@ -97,7 +97,7 @@ public class ChangeListViewerDialog extends DialogWrapper implements DataProvide private void initCommitMessageArea(final Project project, final CommittedChangeList changeList) { myCommitMessageArea = new JEditorPane(UIUtil.HTML_MIME, ""); myCommitMessageArea.setEditable(false); - @NonNls final String text = IssueLinkHtmlRenderer.formatTextIntoHtml(project, changeList.getComment()); + @NonNls final String text = IssueLinkHtmlRenderer.formatTextIntoHtml(project, changeList.getComment().trim()); myCommitMessageArea.setBackground(UIUtil.getComboBoxDisabledBackground()); myCommitMessageArea.addHyperlinkListener(new BrowserHyperlinkListener()); commitMessageScroll = new JScrollPane(myCommitMessageArea); diff --git a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml index 21c2a880ff68..29db15133145 100644 --- a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml +++ b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml @@ -5,6 +5,14 @@ 1.0.0 JetBrains + + + + + + diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java new file mode 100644 index 000000000000..9ebcc328cfa4 --- /dev/null +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2010 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.testAssistant; + +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author yole + */ +public class NavigateToTestDataAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + final PsiMethod method = findTargetMethod(e); + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + if (method == null || editor == null) { + return; + } + final String name = method.getName(); + if (name.startsWith("test")) { + final String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass()); + if (testDataPath == null) { + final Notification notification = + new Notification("testdata", "No testdata path", "Cannot find testdata path for class", NotificationType.INFORMATION); + Notifications.Bus.notify(notification, method.getProject()); + } + else { + final TestDataReferenceCollector collector = new TestDataReferenceCollector(testDataPath, name.substring(4)); + List fileNames = collector.collectTestDataReferences(method); + if (fileNames.size() == 0) { + String message = collector.getLog(); + if (message == null) { + message = "Cannot find testdata files for class"; + } + final Notification notification = new Notification("testdata", "Found no testdata files", message, NotificationType.INFORMATION); + Notifications.Bus.notify(notification, method.getProject()); + } + else { + new TestDataNavigationHandler(fileNames).navigate(method, JBPopupFactory.getInstance().guessBestPopupLocation(editor)); + } + } + } + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(findTargetMethod(e) != null); + } + + @Nullable + private static PsiMethod findTargetMethod(AnActionEvent e) { + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + final PsiFile file = e.getData(LangDataKeys.PSI_FILE); + if (file != null && editor != null) { + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + return PsiTreeUtil.getParentOfType(element, PsiMethod.class); + } + return null; + } +} diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java index da4c464101ca..52ed57753ab1 100644 --- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java @@ -2,35 +2,15 @@ package com.intellij.testAssistant; import com.intellij.codeHighlighting.Pass; import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.fileEditor.OpenFileDescriptor; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.popup.PopupChooserBuilder; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.awt.RelativePoint; -import com.intellij.util.ArrayUtil; import com.intellij.util.Icons; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.event.MouseEvent; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -63,7 +43,7 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider { } @Nullable - private static String getTestDataBasePath(PsiClass psiClass) { + public static String getTestDataBasePath(PsiClass psiClass) { final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(psiClass, Collections.singleton("com.intellij.testFramework.TestDataPath")); if (annotation != null) { final PsiAnnotationMemberValue value = annotation.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); @@ -85,127 +65,4 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider { return null; } - private static class TestDataNavigationHandler implements GutterIconNavigationHandler { - private List myFileNames; - - public TestDataNavigationHandler(List fileNames) { - myFileNames = fileNames; - } - - public void navigate(MouseEvent e, final PsiMethod elt) { - if (myFileNames.size() == 1) { - openFileByIndex(elt.getProject(), 0); - } - else { - TestDataGroupVirtualFile groupFile = getTestDataGroup(); - if (groupFile != null) { - new OpenFileDescriptor(elt.getProject(), groupFile).navigate(true); - } - else { - showNavigationPopup(elt.getProject(), e); - } - } - } - - @Nullable - private TestDataGroupVirtualFile getTestDataGroup() { - if (myFileNames.size() != 2) { - return null; - } - VirtualFile file1 = LocalFileSystem.getInstance().refreshAndFindFileByPath(myFileNames.get(0)); - VirtualFile file2 = LocalFileSystem.getInstance().refreshAndFindFileByPath(myFileNames.get(1)); - if (file1 == null || file2 == null) { - return null; - } - final int commonPrefixLength = StringUtil.commonPrefixLength(file1.getName(), file2.getName()); - if (file1.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { - return new TestDataGroupVirtualFile(file2, file1); - } - if (file2.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { - return new TestDataGroupVirtualFile(file1, file2); - } - return null; - } - - private void showNavigationPopup(final Project project, MouseEvent e) { - List shortNames = new ArrayList(); - for (String fileName : myFileNames) { - shortNames.add(new File(fileName).getName()); - } - final String CREATE_MISSING_OPTION = "Create Missing Files"; - if (myFileNames.size() == 2) { - shortNames.add(CREATE_MISSING_OPTION); - } - final JList list = new JList(shortNames.toArray(new String[shortNames.size()])); - list.setCellRenderer(new ColoredListCellRenderer() { - @Override - protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { - String fileName = (String)value; - if (!fileName.equals(CREATE_MISSING_OPTION)) { - final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); - setIcon(fileType.getIcon()); - } - append(fileName); - } - }); - PopupChooserBuilder builder = new PopupChooserBuilder(list); - builder.setItemChoosenCallback(new Runnable() { - public void run() { - final int[] indices = list.getSelectedIndices(); - if (ArrayUtil.indexOf(indices, myFileNames.size()) >= 0) { - createMissingFiles(project); - } - else { - for (int index : indices) { - openFileByIndex(project, index); - } - } - } - }).createPopup().show(new RelativePoint(e)); - } - - private void createMissingFiles(Project project) { - for (String name : myFileNames) { - if (LocalFileSystem.getInstance().refreshAndFindFileByPath(name) == null) { - createFileByName(project, name); - } - } - final TestDataGroupVirtualFile testDataGroup = getTestDataGroup(); - if (testDataGroup != null) { - new OpenFileDescriptor(project, testDataGroup).navigate(true); - } - } - - private void openFileByIndex(final Project project, final int index) { - final String path = myFileNames.get(index); - final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); - if (file != null) { - new OpenFileDescriptor(project, file).navigate(true); - } - else { - int rc = Messages.showYesNoDialog(project, "The referenced testdata file " + path + " does not exist. Would you like to create it?", - "Create Testdata File", Messages.getQuestionIcon()); - if (rc == 0) { - VirtualFile vFile = createFileByName(project, path); - new OpenFileDescriptor(project, vFile).navigate(true); - } - } - } - - private VirtualFile createFileByName(final Project project, final String path) { - return ApplicationManager.getApplication().runWriteAction(new Computable() { - public VirtualFile compute() { - try { - final File file = new File(path); - final VirtualFile parent = VfsUtil.createDirectories(file.getParent()); - return parent.createChildData(this, file.getName()); - } - catch (IOException e) { - Messages.showErrorDialog(project, e.getMessage(), "Create Testdata File"); - return null; - } - } - }); - } - } } diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java new file mode 100644 index 000000000000..0856f6cd98f3 --- /dev/null +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java @@ -0,0 +1,173 @@ +/* + * Copyright 2000-2010 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.testAssistant; + +import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiMethod; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** +* @author yole +*/ +public class TestDataNavigationHandler implements GutterIconNavigationHandler { + private List myFileNames; + + public TestDataNavigationHandler(List fileNames) { + myFileNames = fileNames; + } + + public void navigate(MouseEvent e, final PsiMethod elt) { + navigate(elt, new RelativePoint(e)); + } + + public void navigate(PsiMethod elt, final RelativePoint point) { + if (myFileNames.size() == 1) { + openFileByIndex(elt.getProject(), 0); + } + else { + TestDataGroupVirtualFile groupFile = getTestDataGroup(); + if (groupFile != null) { + new OpenFileDescriptor(elt.getProject(), groupFile).navigate(true); + } + else { + showNavigationPopup(elt.getProject(), point); + } + } + } + + @Nullable + private TestDataGroupVirtualFile getTestDataGroup() { + if (myFileNames.size() != 2) { + return null; + } + VirtualFile file1 = LocalFileSystem.getInstance().refreshAndFindFileByPath(myFileNames.get(0)); + VirtualFile file2 = LocalFileSystem.getInstance().refreshAndFindFileByPath(myFileNames.get(1)); + if (file1 == null || file2 == null) { + return null; + } + final int commonPrefixLength = StringUtil.commonPrefixLength(file1.getName(), file2.getName()); + if (file1.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { + return new TestDataGroupVirtualFile(file2, file1); + } + if (file2.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { + return new TestDataGroupVirtualFile(file1, file2); + } + return null; + } + + private void showNavigationPopup(final Project project, final RelativePoint point) { + List shortNames = new ArrayList(); + for (String fileName : myFileNames) { + shortNames.add(new File(fileName).getName()); + } + final String CREATE_MISSING_OPTION = "Create Missing Files"; + if (myFileNames.size() == 2) { + shortNames.add(CREATE_MISSING_OPTION); + } + final JList list = new JList(shortNames.toArray(new String[shortNames.size()])); + list.setCellRenderer(new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + String fileName = (String)value; + if (!fileName.equals(CREATE_MISSING_OPTION)) { + final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); + setIcon(fileType.getIcon()); + } + append(fileName); + } + }); + PopupChooserBuilder builder = new PopupChooserBuilder(list); + builder.setItemChoosenCallback(new Runnable() { + public void run() { + final int[] indices = list.getSelectedIndices(); + if (ArrayUtil.indexOf(indices, myFileNames.size()) >= 0) { + createMissingFiles(project); + } + else { + for (int index : indices) { + openFileByIndex(project, index); + } + } + } + }).createPopup().show(point); + } + + private void createMissingFiles(Project project) { + for (String name : myFileNames) { + if (LocalFileSystem.getInstance().refreshAndFindFileByPath(name) == null) { + createFileByName(project, name); + } + } + final TestDataGroupVirtualFile testDataGroup = getTestDataGroup(); + if (testDataGroup != null) { + new OpenFileDescriptor(project, testDataGroup).navigate(true); + } + } + + private void openFileByIndex(final Project project, final int index) { + final String path = myFileNames.get(index); + final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); + if (file != null) { + new OpenFileDescriptor(project, file).navigate(true); + } + else { + int rc = Messages.showYesNoDialog(project, "The referenced testdata file " + path + " does not exist. Would you like to create it?", + "Create Testdata File", Messages.getQuestionIcon()); + if (rc == 0) { + VirtualFile vFile = createFileByName(project, path); + new OpenFileDescriptor(project, vFile).navigate(true); + } + } + } + + private VirtualFile createFileByName(final Project project, final String path) { + return ApplicationManager.getApplication().runWriteAction(new Computable() { + public VirtualFile compute() { + try { + final File file = new File(path); + final VirtualFile parent = VfsUtil.createDirectories(file.getParent()); + return parent.createChildData(this, file.getName()); + } + catch (IOException e) { + Messages.showErrorDialog(project, e.getMessage(), "Create Testdata File"); + return null; + } + } + }); + } +} diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceCollector.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceCollector.java index 90c3c8dbcec4..bb6e69ccf27e 100644 --- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceCollector.java +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceCollector.java @@ -15,6 +15,8 @@ */ package com.intellij.testAssistant; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.testFramework.UsefulTestCase; import org.jetbrains.annotations.Nullable; @@ -27,6 +29,8 @@ import java.util.*; public class TestDataReferenceCollector { private final String myTestDataPath; private final String myTestName; + private final List myLogMessages = new ArrayList(); + private boolean myFoundTestDataParameters = false; public TestDataReferenceCollector(String testDataPath, String testName) { myTestDataPath = testDataPath; @@ -34,10 +38,14 @@ public class TestDataReferenceCollector { } List collectTestDataReferences(final PsiMethod method) { - return collectTestDataReferences(method, new HashMap()); + final List result = collectTestDataReferences(method, new HashMap>()); + if (!myFoundTestDataParameters) { + myLogMessages.add("Found no parameters annotated with @TestDataFile"); + } + return result; } - private List collectTestDataReferences(final PsiMethod method, final Map argumentMap) { + private List collectTestDataReferences(final PsiMethod method, final Map> argumentMap) { final List result = new ArrayList(); method.accept(new JavaRecursiveElementVisitor() { @Override @@ -52,6 +60,7 @@ public class TestDataReferenceCollector { PsiParameter psiParameter = psiParameters[i]; final PsiModifierList modifierList = psiParameter.getModifierList(); if (modifierList != null && modifierList.findAnnotation("com.intellij.testFramework.TestDataFile") != null) { + myFoundTestDataParameters = true; processCallArgument(expression, argumentMap, result, i); haveAnnotatedParameters = true; } @@ -65,7 +74,7 @@ public class TestDataReferenceCollector { return result; } - private void processCallArgument(PsiMethodCallExpression expression, Map argumentMap, List result, final int index) { + private void processCallArgument(PsiMethodCallExpression expression, Map> argumentMap, List result, final int index) { final PsiExpression[] arguments = expression.getArgumentList().getExpressions(); if (arguments.length > index) { String testDataFile = evaluate(arguments [index], argumentMap); @@ -75,21 +84,23 @@ public class TestDataReferenceCollector { } } - private Map buildArgumentMap(PsiMethodCallExpression expression, PsiMethod method) { - Map result = new HashMap(); + private Map> buildArgumentMap(PsiMethodCallExpression expression, PsiMethod method) { + Map> result = new HashMap>(); final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiExpression[] arguments = expression.getArgumentList().getExpressions(); for (int i = 0; i < arguments.length && i < parameters.length; i++) { - String value = evaluate(arguments [i], Collections.emptyMap()); - if (value != null) { - result.put(parameters [i].getName(), value); - } + final int finalI = i; + result.put(parameters [i].getName(), new Computable() { + public String compute() { + return evaluate(arguments [finalI], Collections.>emptyMap()); + } + }); } return result; } @Nullable - private String evaluate(PsiExpression expression, Map arguments) { + private String evaluate(PsiExpression expression, Map> arguments) { if (expression instanceof PsiBinaryExpression) { PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression; if (binaryExpression.getOperationTokenType() == JavaTokenType.PLUS) { @@ -110,7 +121,7 @@ public class TestDataReferenceCollector { final PsiElement result = ((PsiReferenceExpression)expression).resolve(); if (result instanceof PsiParameter) { final String name = ((PsiParameter)result).getName(); - return arguments.get(name); + return arguments.get(name).compute(); } if (result instanceof PsiVariable) { final PsiExpression initializer = ((PsiVariable)result).getInitializer(); @@ -133,6 +144,11 @@ public class TestDataReferenceCollector { } } } + myLogMessages.add("Failed to evaluate " + expression.getText()); return null; } + + public String getLog() { + return StringUtil.join(myLogMessages, "\n"); + } } diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nInspection.java index 370da4b9a527..32a31717cad4 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nInspection.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nInspection.java @@ -425,11 +425,11 @@ public class I18nInspection extends BaseLocalInspectionTool { fixes.add(createIntroduceConstantFix(expression)); } - final PsiManager manager = expression.getManager(); - if (PsiUtil.getLanguageLevel(expression).hasEnumKeywordAndAutoboxing() && - JavaPsiFacade.getInstance(manager.getProject()).findClass(AnnotationUtil.NON_NLS, expression.getResolveScope()) != null) { - for(PsiModifierListOwner element: nonNlsTargets) { - if (!AnnotationUtil.isAnnotated(element, AnnotationUtil.NLS, true)) { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(expression.getManager().getProject()); + if (PsiUtil.getLanguageLevel(expression).hasEnumKeywordAndAutoboxing()) { + for (PsiModifierListOwner element : nonNlsTargets) { + if (!AnnotationUtil.isAnnotated(element, AnnotationUtil.NLS, true) && + facade.findClass(AnnotationUtil.NON_NLS, element.getResolveScope()) != null) { fixes.add(new AddAnnotationFix(AnnotationUtil.NON_NLS, element)); } }