Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Kirill Kalishev
2010-02-09 11:00:19 +03:00
36 changed files with 640 additions and 238 deletions
@@ -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);
}
};
}
@@ -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<JavaModuleBuilder> {
final ProjectWizardStepFactory wizardFactory = ProjectWizardStepFactory.getInstance();
ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
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<Boolean>() {
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<JavaModuleBuilder> {
return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT,
module.getModuleWithLibrariesScope()) != null;
}
}
}
@@ -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<PsiVariable,VariableInfo> myVariableToInfoMap = new HashMap<PsiVariable, VariableInfo>();
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<PsiType, String>() {
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;
@@ -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();
@@ -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 =
@@ -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;
@@ -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);
@@ -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<PsiClass, String>() {
public String fun(PsiClass psiClass) {
return psiClass.getName();
}
}, ", "),
myTargetClass.getQualifiedName());
}
@@ -80,7 +80,7 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider {
}
final String[] strings = info != null ? info.names : ArrayUtil.EMPTY_STRING_ARRAY;
ArrayList<String> list = new ArrayList<String>(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
@@ -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<PsiElement, String> allRenames) {
final HashSet<PsiClass> superClasses = new HashSet<PsiClass>();
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<PsiElement, String> allRenames) {
allRenames.put(methodPrototype, newName);
for (PsiMethod method : methodPrototype.findDeepestSuperMethods()) {
OverridingMethodsSearch.search(method).forEach(new Processor<PsiMethod>() {
public boolean process(PsiMethod psiMethod) {
allRenames.put(psiMethod, newName);
return true;
}
});
allRenames.put(method, newName);
}
}
@@ -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<UsageInfo> 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 {
@@ -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);
@@ -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());
}
}
@@ -0,0 +1,17 @@
public class R {
private static int ourInt;
public static int getOurInt() {
return ourInt;
}
public static void doSmth() {
System.out.println(<selection>ourInt</selection>);
}
}
class Usage {
void foo() {
R.doSmth();
}
}
@@ -1,6 +1,6 @@
package pack2;
public interface A {
static class Class1 {
class Class1 {
}
}
@@ -0,0 +1,20 @@
interface Intf {
}
interface Factory<E extends Intf> {
E create();
void save(E obj);
static class helper {
static Factory<Intf> get2() {
return (Factory)new Factory<Intf>() {
public Intf create() { return null; }
public void save(Intf obj) { }
};
}
}
}
public class Clazz implements Intf {
}
@@ -0,0 +1,20 @@
interface Intf {
}
interface Factory<E extends Intf> {
E create();
void save(E obj);
static class helper {
static Factory<Intf> get2() {
return (Factory)new Factory<Clazz>() {
public Clazz create() { return null; }
public void save(Clazz obj) { }
};
}
}
}
public class Clazz implements Intf {
}
@@ -0,0 +1,22 @@
interface Intf {
}
interface Factory<E extends Intf> {
E create();
void save(E obj);
static class helper {
static Factory<Intf> get() {
return null;
}
}
}
public class Clazz implements Intf {
void bar() {
Intf y = Factory.helper.get().create();
Factory.helper.get().save(y);
}
}
@@ -0,0 +1,22 @@
interface Intf {
}
interface Factory<E extends Intf> {
E create();
void save(E obj);
static class helper {
static Factory<Intf> get() {
return null;
}
}
}
public class Clazz implements Intf {
void bar() {
Clazz y = Factory.helper.get().create();
Factory.helper.get().save(y);
}
}
@@ -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());
}
}
}
@@ -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/";
@@ -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() {
@@ -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 {
@@ -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);
}
@@ -220,7 +220,10 @@ public class BookmarkManager implements PersistentStateComponent<Element> {
}
private void writeExternal(Element element) {
for (Bookmark bookmark : myBookmarks) {
List<Bookmark> reversed = new ArrayList<Bookmark>(myBookmarks);
Collections.reverse(reversed);
for (Bookmark bookmark : reversed) {
Element bookmarkElement = new Element("bookmark");
bookmarkElement.setAttribute("url", bookmark.getFile().getUrl());
@@ -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:
@@ -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}
@@ -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);
@@ -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') {
@@ -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);
@@ -5,6 +5,14 @@
<version>1.0.0</version>
<vendor url="http://www.jetbrains.com" logo="/general/ijLogo.png">JetBrains</vendor>
<actions>
<action id="TestData.Navigate"
class="com.intellij.testAssistant.NavigateToTestDataAction"
text="Navigate to testdata">
<keyboard-shortcut first-keystroke="control shift D" keymap="$default"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.intellij.testAssistant.TestDataLineMarkerProvider"/>
<fileEditorProvider implementation="com.intellij.testAssistant.TestDataGroupEditorProvider"/>
@@ -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<String> 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;
}
}
@@ -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<PsiMethod> {
private List<String> myFileNames;
public TestDataNavigationHandler(List<String> 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<String> shortNames = new ArrayList<String>();
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<VirtualFile>() {
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;
}
}
});
}
}
}
@@ -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<PsiMethod> {
private List<String> myFileNames;
public TestDataNavigationHandler(List<String> 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<String> shortNames = new ArrayList<String>();
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<VirtualFile>() {
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;
}
}
});
}
}
@@ -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<String> myLogMessages = new ArrayList<String>();
private boolean myFoundTestDataParameters = false;
public TestDataReferenceCollector(String testDataPath, String testName) {
myTestDataPath = testDataPath;
@@ -34,10 +38,14 @@ public class TestDataReferenceCollector {
}
List<String> collectTestDataReferences(final PsiMethod method) {
return collectTestDataReferences(method, new HashMap<String, String>());
final List<String> result = collectTestDataReferences(method, new HashMap<String, Computable<String>>());
if (!myFoundTestDataParameters) {
myLogMessages.add("Found no parameters annotated with @TestDataFile");
}
return result;
}
private List<String> collectTestDataReferences(final PsiMethod method, final Map<String, String> argumentMap) {
private List<String> collectTestDataReferences(final PsiMethod method, final Map<String, Computable<String>> argumentMap) {
final List<String> result = new ArrayList<String>();
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<String, String> argumentMap, List<String> result, final int index) {
private void processCallArgument(PsiMethodCallExpression expression, Map<String, Computable<String>> argumentMap, List<String> 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<String, String> buildArgumentMap(PsiMethodCallExpression expression, PsiMethod method) {
Map<String, String> result = new HashMap<String, String>();
private Map<String, Computable<String>> buildArgumentMap(PsiMethodCallExpression expression, PsiMethod method) {
Map<String, Computable<String>> result = new HashMap<String, Computable<String>>();
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.<String, String>emptyMap());
if (value != null) {
result.put(parameters [i].getName(), value);
}
final int finalI = i;
result.put(parameters [i].getName(), new Computable<String>() {
public String compute() {
return evaluate(arguments [finalI], Collections.<String, Computable<String>>emptyMap());
}
});
}
return result;
}
@Nullable
private String evaluate(PsiExpression expression, Map<String, String> arguments) {
private String evaluate(PsiExpression expression, Map<String, Computable<String>> 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");
}
}
@@ -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));
}
}