diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java index 969fb93946c0..39a8f5e53578 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java @@ -30,6 +30,5 @@ public interface JavaHighlightInfoTypes extends HighlightInfoType { HighlightDisplayKey.findOrRegister(UnusedImportLocalInspection.SHORT_NAME, UnusedImportLocalInspection.DISPLAY_NAME), CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); - HighlightInfoType JAVA_KEYWORD = new HighlightInfoType.HighlightInfoTypeImpl( - HighlightSeverity.INFORMATION, SyntaxHighlighterColors.KEYWORD); + HighlightInfoType JAVA_KEYWORD = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, SyntaxHighlighterColors.KEYWORD); } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java index b179a7afd201..e2c51dc074b9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java @@ -111,7 +111,7 @@ public class CreateClassDialog extends DialogWrapper { } myTfClassName.setText(myClassName); - myDestinationCB.setData(myProject, getBaseDir(normalizedPackageName), ProjectRootManager.getInstance(myProject).getContentSourceRoots(), new Pass() { + myDestinationCB.setData(myProject, getBaseDir(normalizedPackageName), new Pass() { @Override public void pass(String s) { setErrorText(s); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 5557de518d1b..9e441705a70c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -743,21 +743,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme public void processVariants(final PsiScopeProcessor processor) { final OrFilter filter = new OrFilter(); - PsiElement superParent = getParent(); - boolean smartCompletion = true; - if (isQualified()) { - smartCompletion = false; - } - else { - while (superParent != null) { - if (superParent instanceof PsiCodeBlock || superParent instanceof PsiLocalVariable) { - smartCompletion = false; - break; - } - superParent = superParent.getParent(); - } - } - if (!smartCompletion && !isCodeFragmentType(getTreeParent().getElementType()) && !(getParent() instanceof PsiAnnotation)) { + if (isInCode()) { filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter()))); filter.addFilter(ElementClassFilter.VARIABLE); } @@ -805,6 +791,28 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme PsiScopesUtil.resolveAndWalk(proc, this, null, true); } + private boolean isInCode() { + if (isCodeFragmentType(getTreeParent().getElementType()) || getParent() instanceof PsiAnnotation) { + return false; + } + + if (isQualified()) { + return true; + } + + PsiElement superParent = getParent(); + while (superParent != null) { + if (superParent instanceof PsiCodeBlock || superParent instanceof PsiLocalVariable) { + return true; + } + if (superParent instanceof PsiClass) { + return false; + } + superParent = superParent.getParent(); + } + return false; + } + private void addClassFilter(final OrFilter filter) { if (getParent() instanceof PsiAnnotation) { filter.addFilter(new AnnotationTypeFilter()); diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java index 71f60f483c49..77929a3d0056 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java @@ -72,7 +72,7 @@ class CopyClassDialog extends DialogWrapper{ RefactoringBundle.message("copy.class.copy.0.1", UsageViewUtil.getType(aClass), UsageViewUtil.getLongName(aClass)); myInformationLabel.setText(text); init(); - myDestinationCB.setData(myProject, defaultTargetDirectory, ProjectRootManager.getInstance(myProject).getContentSourceRoots(), + myDestinationCB.setData(myProject, defaultTargetDirectory, new Pass() { @Override public void pass(String s) { diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java index e333ae4387bc..fe0f43364770 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java @@ -15,7 +15,6 @@ */ package com.intellij.refactoring.extractSuperclass; -import com.intellij.ide.util.PackageUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; @@ -76,7 +75,7 @@ public abstract class JavaExtractSuperBaseDialog extends ExtractSuperBaseDialog< panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); panel.add(new JBLabel(RefactoringBundle.message("target.destination.folder")), BorderLayout.NORTH); - myDestinationFolderComboBox.setData(myProject, myTargetDirectory, sourceRoots, new Pass() { + myDestinationFolderComboBox.setData(myProject, myTargetDirectory, new Pass() { @Override public void pass(String s) { } diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassDialog.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassDialog.java index 5a58b6c98976..69c1b8f6c9ed 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassDialog.java @@ -18,20 +18,26 @@ package com.intellij.refactoring.extractclass; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Pass; import com.intellij.psi.*; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.RefactorJBundle; +import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.classMembers.DelegatingMemberInfoModel; import com.intellij.refactoring.classMembers.MemberInfoBase; import com.intellij.refactoring.classMembers.MemberInfoChange; import com.intellij.refactoring.classMembers.MemberInfoChangeListener; +import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; import com.intellij.refactoring.ui.*; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.ReferenceEditorComboWithBrowseButton; +import com.intellij.ui.components.JBLabel; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,6 +58,7 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi private final List memberInfo; private final JTextField classNameField; private final ReferenceEditorComboWithBrowseButton packageTextField; + private final DestinationFolderComboBox myDestinationFolderComboBox; private final JTextField sourceClassTextField; private JCheckBox myGenerateAccessorsCb; private final JavaVisibilityPanel myVisibilityPanel; @@ -80,6 +87,13 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi validateButtons(); } }); + myDestinationFolderComboBox = new DestinationFolderComboBox() { + @Override + public String getTargetPackage() { + return getPackageName(); + } + }; + myDestinationFolderComboBox.setData(myProject, sourceClass.getContainingFile().getContainingDirectory(), packageTextField.getChildComponent()); classNameField.getDocument().addDocumentListener(docListener); sourceClassTextField = new JTextField(); final MemberInfo.Filter filter = new MemberInfo.Filter() { @@ -129,7 +143,8 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi return o1.getMember().getTextOffset() - o2.getMember().getTextOffset(); } }); - final ExtractClassProcessor processor = new ExtractClassProcessor(sourceClass, fields, methods, classes, packageName, newClassName, myVisibilityPanel.getVisibility(), isGenerateAccessors(), + final ExtractClassProcessor processor = new ExtractClassProcessor(sourceClass, fields, methods, classes, packageName, myDestinationFolderComboBox.selectDirectory(new PackageWrapper(PsiManager.getInstance(myProject), packageName), false), + newClassName, myVisibilityPanel.getVisibility(), isGenerateAccessors(), isExtractAsEnum() ? enumConstants : Collections.emptyList()); if (processor.getCreatedClass() == null) { Messages.showErrorDialog(myVisibilityPanel, "Unable to create class with the given name"); @@ -246,6 +261,14 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi packageNamePanel.add(packageTextField, BorderLayout.CENTER); box.add(packageNamePanel); + if (ProjectRootManager.getInstance(myProject).getContentSourceRoots().length > 1) { + final JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + panel.add(new JBLabel(RefactoringBundle.message("target.destination.folder")), BorderLayout.NORTH); + panel.add(myDestinationFolderComboBox, BorderLayout.CENTER); + box.add(panel); + } + box.add(Box.createVerticalStrut(10)); final JPanel panel = new JPanel(new BorderLayout()); panel.add(box, BorderLayout.CENTER); diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java index 9c7f742ba292..3abc727bf69e 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java @@ -17,11 +17,12 @@ package com.intellij.refactoring.extractclass; import com.intellij.ide.util.PackageUtil; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; @@ -38,13 +39,16 @@ import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.RefactorJBundle; import com.intellij.refactoring.extractclass.usageInfo.*; import com.intellij.refactoring.move.MoveInstanceMembersUtil; +import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; import com.intellij.refactoring.psi.MethodInheritanceUtils; import com.intellij.refactoring.psi.TypeParametersVisitor; import com.intellij.refactoring.util.FixableUsageInfo; import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor; +import com.intellij.refactoring.util.RefactoringUIUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.usageView.UsageInfo; @@ -68,6 +72,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { private final Set innerClassesToMakePublic = new HashSet(); private final List typeParams = new ArrayList(); private final String newPackageName; + private final MoveDestination myMoveDestination; private final String myNewVisibility; private final boolean myGenerateAccessors; private final List enumConstants; @@ -84,7 +89,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { List innerClasses, String newPackageName, String newClassName) { - this(sourceClass, fields, methods, innerClasses, newPackageName, newClassName, null, false, Collections.emptyList()); + this(sourceClass, fields, methods, innerClasses, newPackageName, null, newClassName, null, false, Collections.emptyList()); } public ExtractClassProcessor(PsiClass sourceClass, @@ -92,12 +97,14 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { List methods, List classes, String packageName, + MoveDestination moveDestination, String newClassName, String newVisibility, boolean generateAccessors, List enumConstants) { super(sourceClass.getProject()); this.sourceClass = sourceClass; this.newPackageName = packageName; + myMoveDestination = moveDestination; myNewVisibility = newVisibility; myGenerateAccessors = generateAccessors; this.enumConstants = new ArrayList(); @@ -126,13 +133,12 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { } typeParams.addAll(typeParamSet); } - myClass = ApplicationManager.getApplication().runWriteAction( - new Computable() { - public PsiClass compute() { - return buildClass(); - } + myClass = new WriteCommandAction(myProject, getCommandName()){ + @Override + protected void run(Result result) throws Throwable { + result.setResult(buildClass()); } - ); + }.execute().getResultObject(); myExtractEnumProcessor = new ExtractEnumProcessor(myProject, this.enumConstants, fields, myClass); } @@ -144,6 +150,10 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { protected boolean preprocessUsages(final Ref refUsages) { final MultiMap conflicts = new MultiMap(); myExtractEnumProcessor.findEnumConstantConflicts(refUsages, conflicts); + if (!DestinationFolderComboBox.isAccessible(myProject, sourceClass.getContainingFile().getVirtualFile(), + myClass.getContainingFile().getContainingDirectory().getVirtualFile())) { + conflicts.putValue(sourceClass, "Extracted class won't be accessible in " + RefactoringUIUtil.getDescription(sourceClass, true)); + } ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { myClass.delete(); @@ -683,11 +693,15 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { try { final PsiFile containingFile = sourceClass.getContainingFile(); - + final PsiDirectory directory; final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); - final Module module = ModuleUtil.findModuleForPsiElement(containingFile); - assert module != null; - final PsiDirectory directory = PackageUtil.findOrCreateDirectoryForPackage(module, newPackageName, containingDirectory, false, true); + if (myMoveDestination != null) { + directory = myMoveDestination.getTargetDirectory(containingDirectory); + } else { + final Module module = ModuleUtil.findModuleForPsiElement(containingFile); + assert module != null; + directory = PackageUtil.findOrCreateDirectoryForPackage(module, newPackageName, containingDirectory, false, true); + } if (directory != null) { final PsiFile newFile = PsiFileFactory.getInstance(project).createFileFromText(newClassName + ".java", classString); final PsiElement addedFile = directory.add(newFile); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectDialog.java index d492c5e11bff..d12601822139 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectDialog.java @@ -27,12 +27,12 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiFormatUtil; -import com.intellij.refactoring.HelpID; -import com.intellij.refactoring.RefactorJBundle; -import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.*; +import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.ParameterTablePanel; +import com.intellij.ui.ComboboxWithBrowseButton; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.RecentsManager; import com.intellij.ui.ReferenceEditorComboWithBrowseButton; @@ -75,6 +75,7 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog { private ReferenceEditorComboWithBrowseButton existingClassField; private JCheckBox myGenerateAccessorsCheckBox; private JCheckBox myEscalateVisibilityCheckBox; + private ComboboxWithBrowseButton myDestinationCb; private static final String RECENTS_KEY = "IntroduceParameterObject.RECENTS_KEY"; private static final String EXISTING_KEY = "IntroduceParameterObject.EXISTING_KEY"; @@ -168,7 +169,9 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog { } final String newVisibility = myEscalateVisibilityCheckBox.isEnabled() && myEscalateVisibilityCheckBox.isSelected() ? VisibilityUtil.ESCALATE_VISIBILITY : null; - invokeRefactoring(new IntroduceParameterObjectProcessor(className, packageName, sourceMethod, + final MoveDestination moveDestination = ((DestinationFolderComboBox)myDestinationCb) + .selectDirectory(new PackageWrapper(PsiManager.getInstance(myProject), packageName), false); + invokeRefactoring(new IntroduceParameterObjectProcessor(className, packageName, moveDestination, sourceMethod, parameters.toArray(new ParameterTablePanel.VariableData[parameters.size()]), keepMethod, useExistingClass, createInnerClass, newVisibility, myGenerateAccessorsCheckBox.isSelected())); @@ -312,6 +315,13 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog { enableGenerateAccessors(); } }); + myDestinationCb = new DestinationFolderComboBox() { + @Override + public String getTargetPackage() { + return getPackageName(); + } + }; + ((DestinationFolderComboBox)myDestinationCb).setData(myProject, sourceMethod.getContainingFile().getContainingDirectory(), packageTextField.getChildComponent()); } private void enableGenerateAccessors() { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectForm.form b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectForm.form index 1e08a25aab1d..0ea2aa74025f 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectForm.form +++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectForm.form @@ -3,7 +3,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -70,6 +70,20 @@ + + + + + + + + + + + + + + diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java index 9700054b619c..d36c58f2ff55 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java @@ -33,6 +33,7 @@ import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.RefactorJBundle; import com.intellij.refactoring.introduceparameterobject.usageInfo.*; import com.intellij.refactoring.psi.PropertyUtils; @@ -49,14 +50,12 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringProcessor { private static final Logger logger = Logger.getInstance("com.siyeh.rpp.introduceparameterobject.IntroduceParameterObjectProcessor"); + private MoveDestination myMoveDestination; private final PsiMethod method; private final String className; private final String packageName; @@ -75,12 +74,14 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP public IntroduceParameterObjectProcessor(String className, String packageName, + MoveDestination moveDestination, PsiMethod method, ParameterTablePanel.VariableData[] parameters, boolean keepMethodAsDelegate, final boolean useExistingClass, final boolean createInnerClass, String newVisibility, boolean generateAccessors) { super(method.getProject()); + myMoveDestination = moveDestination; this.method = method; this.className = className; this.packageName = packageName; @@ -144,10 +145,17 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP conflicts.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + "Selected class has no compatible constructors"); } } - else if (existingClass != null) { - conflicts.putValue(existingClass, - RefactorJBundle.message("cannot.perform.the.refactoring") + - RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name")); + else { + if (existingClass != null) { + conflicts.putValue(existingClass, + RefactorJBundle.message("cannot.perform.the.refactoring") + + RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name")); + } + if (myMoveDestination != null) { + if (!myMoveDestination.isTargetAccessible(myProject, method.getContainingFile().getVirtualFile())) { + conflicts.putValue(method, "Created class won't be accessible"); + } + } } for (UsageInfo usageInfo : refUsages.get()) { if (usageInfo instanceof FixableUsageInfo) { @@ -274,8 +282,13 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP } else { final PsiFile containingFile = method.getContainingFile(); final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); - final Module module = ModuleUtil.findModuleForPsiElement(containingFile); - final PsiDirectory directory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, containingDirectory, true, true); + final PsiDirectory directory; + if (myMoveDestination != null) { + directory = myMoveDestination.getTargetDirectory(containingDirectory); + } else { + final Module module = ModuleUtil.findModuleForPsiElement(containingFile); + directory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, containingDirectory, true, true); + } if (directory != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/AutocreatingSingleSourceRootMoveDestination.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/AutocreatingSingleSourceRootMoveDestination.java index a0786bf04a2e..c1bc3bf60038 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/AutocreatingSingleSourceRootMoveDestination.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/AutocreatingSingleSourceRootMoveDestination.java @@ -15,11 +15,16 @@ */ package com.intellij.refactoring.move.moveClassesOrPackages; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.util.RefactoringConflictsUtil; import com.intellij.refactoring.util.RefactoringUtil; @@ -80,6 +85,18 @@ public class AutocreatingSingleSourceRootMoveDestination extends AutocreatingMov RefactoringConflictsUtil.analyzeModuleConflicts(getTargetPackage().getManager().getProject(), elements, usages, mySourceRoot, conflicts); } + @Override + public boolean isTargetAccessible(Project project, VirtualFile place) { + final boolean inTestSourceContent = ProjectRootManager.getInstance(project).getFileIndex().isInTestSourceContent(place); + final Module module = ModuleUtil.findModuleForFile(place, project); + if (mySourceRoot != null && + module != null && + !GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, inTestSourceContent).contains(mySourceRoot)) { + return false; + } + return true; + } + PsiDirectory myTargetDirectory = null; private PsiDirectory getDirectory() throws IncorrectOperationException { if (myTargetDirectory == null) { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java index 556f69a244bb..657dfd0a2a04 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.Pass; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.PackageWrapper; import com.intellij.ui.*; @@ -64,12 +65,21 @@ public abstract class DestinationFolderComboBox extends ComboboxWithBrowseButton return false; } + public void setData(final Project project, + final PsiDirectory initialTargetDirectory, + final EditorComboBox editorComboBox) { + setData(project, initialTargetDirectory, new Pass() { + @Override + public void pass(String s) { + } + }, editorComboBox); + } + public void setData(final Project project, final PsiDirectory initialTargetDirectory, - final VirtualFile[] sourceRoots, final Pass errorMessageUpdater, final EditorComboBox editorComboBox) { myInitialTargetDirectory = initialTargetDirectory; - mySourceRoots = sourceRoots; + mySourceRoots = ProjectRootManager.getInstance(project).getContentSourceRoots(); new ComboboxSpeedSearch(getComboBox()) { @Override protected String getElementText(Object element) { @@ -111,7 +121,7 @@ public abstract class DestinationFolderComboBox extends ComboboxWithBrowseButton @Override public void actionPerformed(ActionEvent e) { VirtualFile root = MoveClassesOrPackagesUtil - .chooseSourceRoot(new PackageWrapper(PsiManager.getInstance(project), getTargetPackage()), sourceRoots, initialTargetDirectory); + .chooseSourceRoot(new PackageWrapper(PsiManager.getInstance(project), getTargetPackage()), mySourceRoots, initialTargetDirectory); if (root == null) return; final ComboBoxModel model = getComboBox().getModel(); for (int i = 0; i < model.getSize(); i++) { @@ -121,17 +131,17 @@ public abstract class DestinationFolderComboBox extends ComboboxWithBrowseButton return; } } - setComboboxModel(getComboBox(), root, fileIndex, sourceRoots, project, true, errorMessageUpdater); + setComboboxModel(getComboBox(), root, fileIndex, mySourceRoots, project, true, errorMessageUpdater); } }); editorComboBox.addDocumentListener(new DocumentAdapter() { @Override public void documentChanged(DocumentEvent e) { - setComboboxModel(getComboBox(), initialSourceRoot, fileIndex, sourceRoots, project, false, errorMessageUpdater); + setComboboxModel(getComboBox(), initialSourceRoot, fileIndex, mySourceRoots, project, false, errorMessageUpdater); } }); - setComboboxModel(getComboBox(), initialSourceRoot, fileIndex, sourceRoots, project, false, errorMessageUpdater); + setComboboxModel(getComboBox(), initialSourceRoot, fileIndex, mySourceRoots, project, false, errorMessageUpdater); getComboBox().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -234,4 +244,17 @@ public abstract class DestinationFolderComboBox extends ComboboxWithBrowseButton } return true; } + + public static boolean isAccessible(final Project project, + final VirtualFile virtualFile, + final VirtualFile targetVirtualFile) { + final boolean inTestSourceContent = ProjectRootManager.getInstance(project).getFileIndex().isInTestSourceContent(virtualFile); + final Module module = ModuleUtil.findModuleForFile(virtualFile, project); + if (targetVirtualFile != null && + module != null && + !GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, inTestSourceContent).contains(targetVirtualFile)) { + return false; + } + return true; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java index 56c2818ec489..f0605a3241d3 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java @@ -264,7 +264,7 @@ public class MoveClassesOrPackagesDialog extends RefactoringDialog { myCbSearchInComments.setSelected(searchInComments); myCbSearchTextOccurences.setSelected(searchForTextOccurences); - ((DestinationFolderComboBox)myDestinationFolderCB).setData(myProject, myInitialTargetDirectory, getSourceRoots(), + ((DestinationFolderComboBox)myDestinationFolderCB).setData(myProject, myInitialTargetDirectory, new Pass() { @Override public void pass(String s) { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MultipleRootsMoveDestination.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MultipleRootsMoveDestination.java index ce162220a646..b24013958510 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MultipleRootsMoveDestination.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MultipleRootsMoveDestination.java @@ -16,6 +16,7 @@ package com.intellij.refactoring.move.moveClassesOrPackages; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.refactoring.PackageWrapper; @@ -95,6 +96,11 @@ public class MultipleRootsMoveDestination extends AutocreatingMoveDestination { MultiMap conflicts, final UsageInfo[] usages) { } + @Override + public boolean isTargetAccessible(Project project, VirtualFile place) { + return true; + } + public PsiDirectory getTargetIfExists(PsiDirectory source) { return findTargetDirectoryForSource(source.getVirtualFile()); } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/SingleSourceRootMoveDestination.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/SingleSourceRootMoveDestination.java index 2aad74cba529..6d628cffdcf5 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/SingleSourceRootMoveDestination.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/SingleSourceRootMoveDestination.java @@ -16,7 +16,13 @@ package com.intellij.refactoring.move.moveClassesOrPackages; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.util.RefactoringConflictsUtil; @@ -73,6 +79,18 @@ public class SingleSourceRootMoveDestination implements MoveDestination { RefactoringConflictsUtil.analyzeModuleConflicts(myPackage.getManager().getProject(), elements, usages, myTargetDirectory, conflicts); } + @Override + public boolean isTargetAccessible(Project project, VirtualFile place) { + final boolean inTestSourceContent = ProjectRootManager.getInstance(project).getFileIndex().isInTestSourceContent(place); + final Module module = ModuleUtil.findModuleForFile(place, project); + final VirtualFile targetVirtualFile = myTargetDirectory.getVirtualFile(); + if (module != null && + !GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, inTestSourceContent).contains(targetVirtualFile)) { + return false; + } + return true; + } + public PsiDirectory getTargetDirectory(PsiFile source) { return myTargetDirectory; } diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java index bf64d60c39ef..2770a49fc694 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java @@ -29,12 +29,15 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.*; import com.intellij.util.ui.Table; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -59,6 +62,8 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { private JTextField myNewClassName; private ReferenceEditorComboWithBrowseButton myPackageTextField; private ReferenceEditorComboWithBrowseButton myExistentClassTF; + private ComboboxWithBrowseButton myDestinationCb; + private JPanel myCreateNewPanel; private static final Logger LOG = Logger.getInstance("#" + ReplaceConstructorWithBuilderDialog.class.getName()); private final LinkedHashMap myParametersMap; @@ -99,6 +104,7 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { if (builderClass != null && !CommonRefactoringUtil.checkReadOnlyStatus(myProject, builderClass)) return; } invokeRefactoring(new ReplaceConstructorWithBuilderProcessor(getProject(), myConstructors, myParametersMap, className, packageName, + ((DestinationFolderComboBox)myDestinationCb).selectDirectory(new PackageWrapper(myConstructors[0].getManager(), packageName), false), myCreateBuilderClassRadioButton.isSelected())); } @@ -139,8 +145,7 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { } private void setEnabled(final boolean createNew) { - myNewClassName.setEnabled(createNew); - myPackageTextField.setEnabled(createNew); + UIUtil.setEnabled(myCreateNewPanel, createNew, true); myExistentClassTF.setEnabled(!createNew); } @@ -222,6 +227,13 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { new PackageNameReferenceEditorCombo(((PsiJavaFile)myConstructors[0].getContainingFile()).getPackageName(), myProject, RECENT_KEYS, RefactoringBundle.message("choose.destination.package")); myPackageTextField.getChildComponent().getDocument().addDocumentListener(adapter); + myDestinationCb = new DestinationFolderComboBox() { + @Override + public String getTargetPackage() { + return myPackageTextField.getText().trim(); + } + }; + ((DestinationFolderComboBox)myDestinationCb).setData(myProject, myConstructors[0].getContainingFile().getContainingDirectory(), myPackageTextField.getChildComponent()); myExistentClassTF = new ReferenceEditorComboWithBrowseButton(new ActionListener() { public void actionPerformed(ActionEvent e) { diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderPanel.form b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderPanel.form index 82ecbac38788..63601539eb95 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderPanel.form +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderPanel.form @@ -2,7 +2,7 @@
- + @@ -15,7 +15,7 @@ - + @@ -30,14 +30,14 @@ - + - + @@ -80,11 +80,27 @@ + + + + + + + + + + + + + + + + - + diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java index 34d730af16f0..f17f9c0041a1 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java @@ -37,6 +37,7 @@ import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo.ReplaceConstructorWithSettersChainInfo; import com.intellij.refactoring.util.FixableUsageInfo; import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor; @@ -48,6 +49,7 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -59,6 +61,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto private final String myPackageName; private final boolean myCreateNewBuilderClass; private final PsiElementFactory myElementFactory; + private MoveDestination myMoveDestination; public ReplaceConstructorWithBuilderProcessor(Project project, @@ -66,8 +69,9 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto Map parametersMap, String className, String packageName, - boolean createNewBuilderClass) { + MoveDestination moveDestination, boolean createNewBuilderClass) { super(project); + myMoveDestination = moveDestination; myElementFactory = JavaPsiFacade.getInstance(myProject).getElementFactory(); myConstructors = constructors; myParametersMap = parametersMap; @@ -108,9 +112,14 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto final PsiFile containingFile = myConstructors[0].getContainingFile(); final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); - final Module module = ModuleUtil.findModuleForPsiElement(containingFile); - assert module != null; - final PsiDirectory directory = PackageUtil.findOrCreateDirectoryForPackage(module, myPackageName, containingDirectory, true, true); + final PsiDirectory directory; + if (myMoveDestination != null) { + directory = myMoveDestination.getTargetDirectory(containingDirectory); + } else { + final Module module = ModuleUtil.findModuleForPsiElement(containingFile); + assert module != null; + directory = PackageUtil.findOrCreateDirectoryForPackage(module, myPackageName, containingDirectory, true, true); + } if (directory != null) { @@ -280,6 +289,10 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto } else if (myCreateNewBuilderClass){ conflicts.putValue(builderClass, "Class with chosen name already exist."); } + + if (myMoveDestination != null && myCreateNewBuilderClass) { + myMoveDestination.analyzeModuleConflicts(Collections.emptyList(), conflicts, refUsages.get()); + } final PsiMethod commonConstructor = getMostCommonConstructor(); if (commonConstructor == null) { diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index 53b4e9aea17c..e31bbc68192d 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -253,47 +253,50 @@ public class RefactoringConflictsUtil { boolean isInTestSources = ModuleRootManager.getInstance(targetModule).getFileIndex().isInTestSourceContent(vFile); NextUsage: for (UsageInfo usage : usages) { - if (usage instanceof MoveRenameUsageInfo) { - final MoveRenameUsageInfo moveRenameUsageInfo = (MoveRenameUsageInfo)usage; - final PsiElement element = usage.getElement(); - if (element != null && PsiTreeUtil.getParentOfType(element, PsiImportStatement.class, false) == null) { + final PsiElement element = usage.getElement(); + if (element != null && PsiTreeUtil.getParentOfType(element, PsiImportStatement.class, false) == null) { - for (PsiElement scope : scopes) { - if (PsiTreeUtil.isAncestor(scope, element, false)) continue NextUsage; + for (PsiElement scope : scopes) { + if (PsiTreeUtil.isAncestor(scope, element, false)) continue NextUsage; + } + + final GlobalSearchScope resolveScope1 = element.getResolveScope(); + if (!resolveScope1.isSearchInModuleContent(targetModule, isInTestSources)) { + final PsiFile usageFile = element.getContainingFile(); + PsiElement container; + if (usageFile instanceof PsiJavaFile) { + container = ConflictsUtil.getContainer(element); } - - final GlobalSearchScope resolveScope1 = element.getResolveScope(); - if (!resolveScope1.isSearchInModuleContent(targetModule, isInTestSources)) { - final PsiFile usageFile = element.getContainingFile(); - PsiElement container; - if (usageFile instanceof PsiJavaFile) { - container = ConflictsUtil.getContainer(element); - } - else { - container = usageFile; - } - final String scopeDescription = RefactoringUIUtil.getDescription(container, true); - final VirtualFile usageVFile = usageFile.getVirtualFile(); - if (usageVFile != null) { - Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(usageVFile); - if (module != null) { - final String message; - final PsiElement referencedElement = moveRenameUsageInfo.getReferencedElement(); - assert referencedElement != null : moveRenameUsageInfo; - if (module == targetModule && isInTestSources) { - message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.from.production.of.module.2", - RefactoringUIUtil.getDescription(referencedElement, true), - scopeDescription, - CommonRefactoringUtil.htmlEmphasize(module.getName())); - } - else { - message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.from.module.2", - RefactoringUIUtil.getDescription(referencedElement, true), - scopeDescription, - CommonRefactoringUtil.htmlEmphasize(module.getName())); - } - conflicts.putValue(referencedElement, CommonRefactoringUtil.capitalize(message)); + else { + container = usageFile; + } + final String scopeDescription = RefactoringUIUtil.getDescription(container, true); + final VirtualFile usageVFile = usageFile.getVirtualFile(); + if (usageVFile != null) { + Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(usageVFile); + if (module != null) { + final String message; + final PsiElement referencedElement; + if (usage instanceof MoveRenameUsageInfo) { + referencedElement = ((MoveRenameUsageInfo)usage).getReferencedElement(); } + else { + referencedElement = usage.getElement(); + } + assert referencedElement != null : usage; + if (module == targetModule && isInTestSources) { + message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.from.production.of.module.2", + RefactoringUIUtil.getDescription(referencedElement, true), + scopeDescription, + CommonRefactoringUtil.htmlEmphasize(module.getName())); + } + else { + message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.from.module.2", + RefactoringUIUtil.getDescription(referencedElement, true), + scopeDescription, + CommonRefactoringUtil.htmlEmphasize(module.getName())); + } + conflicts.putValue(referencedElement, CommonRefactoringUtil.capitalize(message)); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueDialog.java b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueDialog.java index 281acc42c674..ba2eeb564db0 100644 --- a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueDialog.java @@ -28,10 +28,13 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.RefactorJBundle; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox; import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo; import com.intellij.refactoring.ui.RefactoringDialog; +import com.intellij.ui.ComboboxWithBrowseButton; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.ReferenceEditorComboWithBrowseButton; import com.intellij.util.ui.UIUtil; @@ -64,6 +67,7 @@ class WrapReturnValueDialog extends RefactoringDialog { private JRadioButton myCreateInnerClassButton; private JTextField myInnerClassNameTextField; private JPanel myCreateInnerPanel; + private ComboboxWithBrowseButton myDestinationCb; private static final String RECENT_KEYS = "WrapReturnValue.RECENT_KEYS"; WrapReturnValueDialog(PsiMethod sourceMethod) { @@ -96,7 +100,8 @@ class WrapReturnValueDialog extends RefactoringDialog { packageName = getPackageName(); } invokeRefactoring( - new WrapReturnValueProcessor(className, packageName, sourceMethod, useExistingClass, createInnerClass, (PsiField)myFieldsCombo.getSelectedItem())); + new WrapReturnValueProcessor(className, packageName, ((DestinationFolderComboBox)myDestinationCb).selectDirectory(new PackageWrapper(sourceMethod.getManager(), packageName), false), + sourceMethod, useExistingClass, createInnerClass, (PsiField)myFieldsCombo.getSelectedItem())); } @Override @@ -278,5 +283,13 @@ class WrapReturnValueDialog extends RefactoringDialog { } }, "", PsiManager.getInstance(myProject), true, RECENT_KEYS); existingClassField.getChildComponent().getDocument().addDocumentListener(adapter); + + myDestinationCb = new DestinationFolderComboBox() { + @Override + public String getTargetPackage() { + return getPackageName(); + } + }; + ((DestinationFolderComboBox)myDestinationCb).setData(myProject, sourceMethod.getContainingFile().getContainingDirectory(), packageTextField.getChildComponent()); } } diff --git a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueForm.form b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueForm.form index 66d6a9aa9630..4114a0d8d3e9 100644 --- a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueForm.form +++ b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueForm.form @@ -3,7 +3,7 @@ - + @@ -24,7 +24,7 @@ - + @@ -63,6 +63,20 @@ + + + + + + + + + + + + + + diff --git a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java index 8df928b61013..5c991c6b2ac9 100644 --- a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java @@ -31,6 +31,7 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.RefactorJBundle; import com.intellij.refactoring.psi.PropertyUtils; import com.intellij.refactoring.psi.TypeParametersVisitor; @@ -58,6 +59,7 @@ public class WrapReturnValueProcessor extends FixableUsagesRefactoringProcessor private static final Logger LOG = Logger.getInstance("com.siyeh.rpp.wrapreturnvalue.WrapReturnValueProcessor"); + private MoveDestination myMoveDestination; private final PsiMethod method; private final String className; private final String packageName; @@ -71,10 +73,11 @@ public class WrapReturnValueProcessor extends FixableUsagesRefactoringProcessor public WrapReturnValueProcessor(String className, String packageName, - PsiMethod method, + MoveDestination moveDestination, PsiMethod method, boolean useExistingClass, final boolean createInnerClass, PsiField delegateField) { super(method.getProject()); + myMoveDestination = moveDestination; this.method = method; this.className = className; this.packageName = packageName; @@ -227,6 +230,9 @@ public class WrapReturnValueProcessor extends FixableUsagesRefactoringProcessor if (existingClass != null) { conflicts.putValue(existingClass, RefactorJBundle.message("there.already.exists.a.class.with.the.selected.name")); } + if (myMoveDestination != null && !myMoveDestination.isTargetAccessible(myProject, method.getContainingFile().getVirtualFile())) { + conflicts.putValue(method, "Created class won't be accessible in the call place"); + } } return showConflicts(conflicts, refUsages.get()); } @@ -268,8 +274,13 @@ public class WrapReturnValueProcessor extends FixableUsagesRefactoringProcessor final PsiFile containingFile = method.getContainingFile(); final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); - final Module module = ModuleUtil.findModuleForPsiElement(containingFile); - final PsiDirectory directory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, containingDirectory, true, true); + final PsiDirectory directory; + if (myMoveDestination != null) { + directory = myMoveDestination.getTargetDirectory(containingDirectory); + } else { + final Module module = ModuleUtil.findModuleForPsiElement(containingFile); + directory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, containingDirectory, true, true); + } if (directory != null) { final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiFile); diff --git a/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous.java b/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous.java new file mode 100644 index 000000000000..8b5f2006ad3e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous.java @@ -0,0 +1,10 @@ +class A { + A() { + new Runnable() { + pri + }; + + } + + public void prepareImage() {} +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous_after.java b/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous_after.java new file mode 100644 index 000000000000..b9c77cc06935 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/PrivateInAnonymous_after.java @@ -0,0 +1,10 @@ +class A { + A() { + new Runnable() { + private + }; + + } + + public void prepareImage() {} +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MultiFieldDeclNames.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MultiFieldDeclNames.java new file mode 100644 index 000000000000..fea0a70743cc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MultiFieldDeclNames.java @@ -0,0 +1,4 @@ +class Test{ + int field1 = 0, field2 = 0; + int field3, field4; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java index 1cab6140cb63..9de8be955b1c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java @@ -1,59 +1,59 @@ -import java.io.*; // highlight on demand import as class name +import java.io.*; // highlight on demand import as class name -class a { - void method() { - method(); +class a { + void method() { + method(); - new Exception(); - new java.lang.Exception(); + new Exception(); + new java.lang.Exception(); } - a() { - new a(); + a() { + new a(); } /** - * @see itf#method(double) + * @see itf#method(double) */ - static void f() { - Integer.parseInt(""); - java.lang.Integer.parseInt(""); - f(); + static void f() { + Integer.parseInt(""); + java.lang.Integer.parseInt(""); + f(); } - interface itf{ - int CONST = 0; + interface itf{ + int CONST = 0; /** . - * @param d Important param + * @param d Important param */ - void method(double d); + void method(double d); } - void ff(Runnable r) { - ff( - new java.lang.Runnable() + void ff(Runnable r) { + ff( + new java.lang.Runnable() { - public void run() {} - int instance = 0; + public void run() {} + int instance = 0; } ); - int i = java.lang.Integer.MIN_VALUE; - int j = itf.CONST; + int i = java.lang.Integer.MIN_VALUE; + int j = itf.CONST; } } -class NoCtrClass { +class NoCtrClass { { // default constructor call looks like class - new NoCtrClass(); + new NoCtrClass(); } - void ff(int param) { - int i = 1; - i ++; + void ff(int param) { + int i = 1; + i ++; - param = 0; + param = 0; } } -class Generic<TT extends Runnable> { - TT field; +class Generic<TT extends Runnable> { + TT field; } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/Shared.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/Shared.java index 913a45aff6df..0fc75e7503a3 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/Shared.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/Shared.java @@ -1,10 +1,10 @@ package x; -class Shared { - Shared x = new Shared(); - java.util.List - list( - java.util.Map map +class Shared { + Shared x = new Shared(); + java.util.List + list( + java.util.Map map ) { return null; } -} \ No newline at end of file +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/X.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/X.java index 36bfc3e1718e..c16a8cdd1939 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/X.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/scopeBased/x/X.java @@ -1,10 +1,10 @@ package x; -class X { - X x = new X(); - java.util.List - list( - java.util.Map map +class X { + X x = new X(); + java.util.List + list( + java.util.Map map ) { return null; } -} \ No newline at end of file +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/variables/MultiFieldDecl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/variables/MultiFieldDecl.java deleted file mode 100644 index 4fb0047c16b5..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/variables/MultiFieldDecl.java +++ /dev/null @@ -1,4 +0,0 @@ -class Test{ - int field1 = 0, field2 = 0; - int field3, field4; -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 5ac71e462daf..f684c51723a6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -427,6 +427,7 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { configure() assertStringItems 'final', 'finalize' } + public void testPrivateInAnonymous() throws Throwable { doTest() } public void testMethodParenthesesSpaces() throws Throwable { final settings = CodeStyleSettingsManager.getSettings(getProject()) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index de3baf9edbdb..205bc25da987 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java @@ -101,7 +101,7 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { scheme.setAttributes(utilKey, utilAttributes); try { - doTest(BASE_PATH+"/scopeBased/x/X.java", BASE_PATH+"/scopeBased", false, true); + testFile(BASE_PATH + "/scopeBased/x/X.java").projectRoot(BASE_PATH + "/scopeBased").checkSymbolNames().test(); } finally { scopeManager.removeAllSets(); @@ -132,7 +132,7 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { scheme.setAttributes(projectKey, projectAttributes); try { - doTest(BASE_PATH+"/scopeBased/x/Shared.java", BASE_PATH+"/scopeBased", false, true); + testFile(BASE_PATH+"/scopeBased/x/Shared.java").projectRoot(BASE_PATH+"/scopeBased").checkSymbolNames().test(); } finally { scopeManager.removeAllSets(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java index 8fac2b46da3c..5988544c5533 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java @@ -265,7 +265,10 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase { public void testNamesHighlighting() throws Exception { LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(LanguageLevel.JDK_1_5); - doTest(false, true); + testFile(BASE_PATH + "/" + getTestName(false) + ".java").checkSymbolNames().test(); + } + public void testMultiFieldDeclNames() throws Exception { + testFile(BASE_PATH + "/" + getTestName(false) + ".java").checkSymbolNames().test(); } public static class MyAnnotator implements Annotator { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/VariableHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/VariableHighlightingTest.java deleted file mode 100644 index b276ae185f58..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/VariableHighlightingTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.intellij.codeInsight.daemon; - -public class VariableHighlightingTest extends DaemonAnalyzerTestCase{ - private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/variables"; - - public void testMultiFieldDecl() throws Exception { - doTest("MultiFieldDecl.java"); - } - - protected void doTest(String filePath) throws Exception { - super.doTest(BASE_PATH + "/" + filePath, false, true); - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java index 0ff1c851d1a1..6efeb175695d 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java @@ -145,7 +145,7 @@ public class ExtractClassTest extends MultiFileTestCase{ private static void doTest(final PsiClass aClass, final ArrayList methods, final ArrayList fields, final String conflicts, boolean generateGettersSetters) { try { - ExtractClassProcessor processor = new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", "Extracted", null, generateGettersSetters, Collections.emptyList()); + ExtractClassProcessor processor = new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", null, "Extracted", null, generateGettersSetters, Collections.emptyList()); processor.run(); LocalFileSystem.getInstance().refresh(false); FileDocumentManager.getInstance().saveAllDocuments(); @@ -266,7 +266,7 @@ public class ExtractClassTest extends MultiFileTestCase{ fields.add(aClass.findFieldByName("myT", false)); final ExtractClassProcessor processor = - new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", "Extracted", PsiModifier.PUBLIC, false, Collections.emptyList()); + new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", null, "Extracted", PsiModifier.PUBLIC, false, Collections.emptyList()); processor.run(); LocalFileSystem.getInstance().refresh(false); FileDocumentManager.getInstance().saveAllDocuments(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java index d78364fe1e16..c73d01fa6340 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java @@ -158,7 +158,7 @@ public class ExtractEnumTest extends MultiFileTestCase { } try { final ExtractClassProcessor processor = - new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", "EEnum", + new ExtractClassProcessor(aClass, fields, methods, new ArrayList(), "", null, "EEnum", null, generateAccessors, enumConstants); processor.run(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java index 95ba680e5892..66942460a50a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java @@ -51,7 +51,7 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{ final PsiMethod method = aClass.findMethodsByName("foo", false)[0]; final ParameterTablePanel.VariableData[] datas = function.fun(method); - IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor("Param", "", method, datas, delegate, false, + IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor("Param", "", null, method, datas, delegate, false, createInner, null, false); processor.run(); } @@ -172,7 +172,7 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{ assertNotNull("Class Test not found", aClass); final PsiMethod method = aClass.findMethodsByName("foo", false)[0]; - IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor(existingClassName, existingClassPackage, method, + IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor(existingClassName, existingClassPackage, null, method, generateParams(method), false, true, false, newVisibility, generateAccessors); processor.run(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java index 5af77957eec3..7d18135056f3 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java @@ -104,7 +104,7 @@ public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase { } } try { - new ReplaceConstructorWithBuilderProcessor(getProject(), constructors, map, "Builder", packageName, createNewBuilderClass).run(); + new ReplaceConstructorWithBuilderProcessor(getProject(), constructors, map, "Builder", packageName, null, createNewBuilderClass).run(); if (conflicts != null) { fail("Conflicts were not detected:" + conflicts); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java b/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java index 37e312545086..4d69c1ea4633 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java @@ -4,8 +4,6 @@ */ package com.intellij.refactoring; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiField; @@ -53,7 +51,8 @@ public class WrapReturnValueTest extends MultiFileTestCase{ assertTrue(!existing || wrapperClass != null); final PsiField delegateField = existing ? wrapperClass.findFieldByName("myField", false) : null; - WrapReturnValueProcessor processor = new WrapReturnValueProcessor(wrapperClassName, "", method, existing, createInnerClass, + WrapReturnValueProcessor processor = new WrapReturnValueProcessor(wrapperClassName, "", + null, method, existing, createInnerClass, delegateField); processor.run(); /*LocalFileSystem.getInstance().refresh(false); diff --git a/java/openapi/src/com/intellij/refactoring/MoveDestination.java b/java/openapi/src/com/intellij/refactoring/MoveDestination.java index 7415ee358106..229a5dc7fcbe 100644 --- a/java/openapi/src/com/intellij/refactoring/MoveDestination.java +++ b/java/openapi/src/com/intellij/refactoring/MoveDestination.java @@ -15,10 +15,16 @@ */ package com.intellij.refactoring; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.MultiMap; @@ -63,4 +69,6 @@ public interface MoveDestination { String verify(PsiPackage source); void analyzeModuleConflicts(final Collection elements, MultiMap conflicts, final UsageInfo[] usages); + + boolean isTargetAccessible(Project project, VirtualFile place); } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index dd74f73a0d9b..58c5ea04d482 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -75,6 +75,7 @@ import com.intellij.psi.search.UsageSearchContext; import com.intellij.psi.xml.XmlFileNSInfoProvider; import com.intellij.testFramework.ExpectedHighlightingData; import com.intellij.testFramework.FileTreeAccessFilter; +import com.intellij.testFramework.HighlightTestInfo; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; import com.intellij.util.IncorrectOperationException; @@ -98,7 +99,6 @@ import java.util.Map; public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { private final Map myAvailableTools = new THashMap(); private final Map myAvailableLocalTools = new THashMap(); - private boolean toInitializeDaemon; private final FileTreeAccessFilter myFileTreeAccessFilter = new FileTreeAccessFilter(); @Override @@ -246,29 +246,45 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { return result.toArray(new LocalInspectionTool[result.size()]); } - protected void doTest(String filePath, boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) throws Exception { + protected void doTest(@NonNls @NotNull String filePath, boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) throws Exception { configureByFile(filePath); doDoTest(checkWarnings, checkInfos, checkWeakWarnings); } - protected void doTest(String filePath, boolean checkWarnings, boolean checkInfos) throws Exception { + protected void doTest(@NonNls @NotNull String filePath, boolean checkWarnings, boolean checkInfos) throws Exception { doTest(filePath, checkWarnings, checkInfos, false); } - protected void doTest(@NonNls String filePath, @NonNls String projectRoot, boolean checkWarnings, boolean checkInfos) throws Exception { + protected void doTest(@NonNls @NotNull String filePath, @NonNls String projectRoot, boolean checkWarnings, boolean checkInfos) throws Exception { configureByFile(filePath, projectRoot); doDoTest(checkWarnings, checkInfos); } - protected void doTest(VirtualFile vFile, boolean checkWarnings, boolean checkInfos) throws Exception { + @NotNull + @SuppressWarnings("TestMethodWithIncorrectSignature") + protected HighlightTestInfo testFile(@NonNls @NotNull String... filePath) { + return new HighlightTestInfo(getTestRootDisposable(), filePath){ + @Override + public HighlightTestInfo doTest() throws Exception { + configureByFiles(projectRoot, filePaths); + ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); + if (checkSymbolNames) data.checkSymbolNames(); + checkHighlighting(data); + return this; + } + }; + } + + protected void doTest(@NotNull VirtualFile vFile, boolean checkWarnings, boolean checkInfos) throws Exception { doTest(new VirtualFile[] { vFile }, checkWarnings, checkInfos ); } - protected void doTest(VirtualFile[] vFile, boolean checkWarnings, boolean checkInfos) throws Exception { + protected void doTest(@NotNull VirtualFile[] vFile, boolean checkWarnings, boolean checkInfos) throws Exception { configureByFiles(null, vFile); doDoTest(checkWarnings, checkInfos); } + @NotNull protected Collection doDoTest(boolean checkWarnings, boolean checkInfos) { return doDoTest(checkWarnings, checkInfos, false); } @@ -277,7 +293,9 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { return checkHighlighting(new ExpectedHighlightingData(myEditor.getDocument(),checkWarnings, checkWeakWarnings, checkInfos, myFile)); } - protected Collection checkHighlighting(final ExpectedHighlightingData data) { + @NotNull + protected Collection checkHighlighting(@NotNull final ExpectedHighlightingData data) { + data.init(); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); //to load text @@ -309,14 +327,16 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { return infos; } - public void allowTreeAccessForFile(final VirtualFile file) { + public void allowTreeAccessForFile(@NotNull VirtualFile file) { myFileTreeAccessFilter.allowTreeAccessForFile(file); } + @NotNull protected Collection highlightErrors() { return filter(doHighlighting(), HighlightSeverity.ERROR); } + @NotNull protected List doHighlighting() { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); @@ -359,7 +379,8 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { return annotatedWith(CanChangeDocumentDuringHighlighting.class); } - public static List filter(final List infos, HighlightSeverity minSeverity) { + @NotNull + public static List filter(@NotNull List infos, @NotNull HighlightSeverity minSeverity) { ArrayList result = new ArrayList(); for (final HighlightInfo info : infos) { if (info.getSeverity().compareTo(minSeverity) >= 0) result.add(info); @@ -379,16 +400,16 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { return false; } - protected static void findAndInvokeIntentionAction(final Collection infos, String intentionActionName, final Editor editor, - final PsiFile file) throws IncorrectOperationException { + protected static void findAndInvokeIntentionAction(@NotNull Collection infos, @NotNull String intentionActionName, @NotNull Editor editor, + @NotNull PsiFile file) throws IncorrectOperationException { IntentionAction intentionAction = findIntentionAction(infos, intentionActionName, editor, file); assertNotNull(intentionActionName, intentionAction); assertTrue(ShowIntentionActionsHandler.chooseActionAndInvoke(file, editor, intentionAction, intentionActionName)); } - protected static IntentionAction findIntentionAction(final Collection infos, final String intentionActionName, final Editor editor, - final PsiFile file) { + protected static IntentionAction findIntentionAction(@NotNull Collection infos, @NotNull String intentionActionName, @NotNull Editor editor, + @NotNull PsiFile file) { List actions = LightQuickFixTestCase.getAvailableActions(editor, file); IntentionAction intentionAction = LightQuickFixTestCase.findActionWithText(actions, intentionActionName); diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index 478e28156ba2..a0a7ea41e946 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -28,6 +28,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.testFramework.ExpectedHighlightingData; import com.intellij.testFramework.FileTreeAccessFilter; +import com.intellij.testFramework.HighlightTestInfo; import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; import com.intellij.util.ArrayUtil; @@ -80,7 +81,12 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos) { getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); - ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(),checkWarnings, checkInfos); + ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(),checkWarnings, checkInfos); + checkHighlighting(data); + } + + private void checkHighlighting(ExpectedHighlightingData data) { + data.init(); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); getFile().getText(); //to load text @@ -91,7 +97,22 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); - expectedData.checkResult(infos, getEditor().getDocument().getText()); + data.checkResult(infos, getEditor().getDocument().getText()); + } + + protected HighlightTestInfo testFile(@NonNls @NotNull String filePath) { + return new HighlightTestInfo(getTestRootDisposable(), filePath){ + @Override + public HighlightTestInfo doTest() throws Exception { + String path = assertOneElement(filePaths); + configureByFile(path); + ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); + if (checkSymbolNames) data.checkSymbolNames(); + + checkHighlighting(data); + return this; + } + }; } @NotNull diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index f874f78c26c2..7336a226228c 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java @@ -35,6 +35,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.RegExp; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.FilenameFilter; @@ -303,7 +304,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase return getAvailableActions(getEditor(), getFile()); } - public static List getAvailableActions(final Editor editor, final PsiFile file) { + public static List getAvailableActions(@NotNull Editor editor, @NotNull PsiFile file) { return CodeInsightTestFixtureImpl.getAvailableIntentions(editor, file); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index f4a1bae6c79d..d4973948b383 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -41,7 +41,6 @@ import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.MarkupModel; -import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; @@ -61,7 +60,10 @@ import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.search.scope.packageSet.NamedScope; import com.intellij.psi.search.scope.packageSet.NamedScopeManager; import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; -import com.intellij.util.*; +import com.intellij.util.Alarm; +import com.intellij.util.CommonProcessors; +import com.intellij.util.Processor; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import gnu.trove.THashMap; @@ -596,46 +598,6 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx return true; } - static void addHighlight(MarkupModel markup, - Project project, - HighlightInfo toAdd) { - ApplicationManager.getApplication().assertIsDispatchThread(); - - stripWarningsCoveredByErrors(project, toAdd, markup.getDocument()); - } - - private static void stripWarningsCoveredByErrors(Project project, final HighlightInfo toAdd, Document document) { - final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project); - final Set covered = new THashSet(); - - // either toAdd is warning and covered by one of errors in highlightsToSet or toAdd is an error and covers warnings in highlightsToSet or it is OK - final boolean addingError = severityRegistrar.compare(HighlightSeverity.ERROR, toAdd.getSeverity()) <= 0; - boolean toAddIsVisible = processHighlights(document, project, null, toAdd.getActualStartOffset(), - toAdd.getActualEndOffset(), new Processor() { - public boolean process(HighlightInfo interval) { - boolean isError = severityRegistrar.compare(HighlightSeverity.ERROR, interval.getSeverity()) <= 0; - if (addingError && !isError && isCoveredBy(interval, toAdd)) { - covered.add(interval); - } - return addingError || !isError || !isCoveredBy(toAdd, interval); - } - }); - if (!toAddIsVisible) { - // toAdd is covered by - toAdd.highlighter.dispose(); - } - for (HighlightInfo warning : covered) { - RangeHighlighter highlighter = warning.highlighter; - if (highlighter != null) { - highlighter.dispose(); - } - } - } - - static boolean isCoveredBy(HighlightInfo info, HighlightInfo coveredBy) { - return coveredBy.startOffset <= info.startOffset && info.endOffset <= coveredBy.endOffset && info.getGutterIconRenderer() == null; - } - @Nullable public static List getLineMarkers(Document document, Project project) { ApplicationManager.getApplication().assertIsDispatchThread(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java index 295a460f0ab1..1ff1b1a8a5ec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java @@ -52,8 +52,7 @@ public interface HighlightInfoType { HighlightInfoType WRONG_REF = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES); - HighlightInfoType GENERIC_WARNINGS_OR_ERRORS_FROM_SERVER = new HighlightInfoTypeImpl( - HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING, CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING); + HighlightInfoType GENERIC_WARNINGS_OR_ERRORS_FROM_SERVER = new HighlightInfoTypeImpl(HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING, CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING); HighlightInfoType DUPLICATE_FROM_SERVER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.DUPLICATE_FROM_SERVER); @@ -65,25 +64,28 @@ public interface HighlightInfoType { HighlightDisplayKey.findOrRegister(DEPRECATION_SHORT_NAME, DEPRECATION_DISPLAY_NAME, DEPRECATION_ID), CodeInsightColors.DEPRECATED_ATTRIBUTES); - HighlightInfoType LOCAL_VARIABLE = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); - HighlightInfoType INSTANCE_FIELD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); - HighlightInfoType STATIC_FIELD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.STATIC_FIELD_ATTRIBUTES); - HighlightInfoType PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.PARAMETER_ATTRIBUTES); + HighlightSeverity SYMBOL_TYPE_SEVERITY = new HighlightSeverity("SYMBOL_TYPE_SEVERITY", HighlightSeverity.INFORMATION.myVal-2); + + HighlightInfoType LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); + HighlightInfoType INSTANCE_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); + HighlightInfoType STATIC_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_FIELD_ATTRIBUTES); + HighlightInfoType PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.PARAMETER_ATTRIBUTES); + HighlightInfoType METHOD_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_CALL_ATTRIBUTES); + HighlightInfoType METHOD_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); + HighlightInfoType CONSTRUCTOR_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); + HighlightInfoType CONSTRUCTOR_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_DECLARATION_ATTRIBUTES); + HighlightInfoType STATIC_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_METHOD_ATTRIBUTES); + HighlightInfoType CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CLASS_NAME_ATTRIBUTES); + HighlightInfoType INTERFACE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); + HighlightInfoType TYPE_PARAMETER_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES); + HighlightInfoType ABSTRACT_CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ABSTRACT_CLASS_NAME_ATTRIBUTES); + HighlightInfoType ANNOTATION_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES); + HighlightInfoType ANNOTATION_ATTRIBUTE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES); + HighlightInfoType REASSIGNED_LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); + HighlightInfoType REASSIGNED_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); + HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); + HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, null); // t.o.d.o attributes depend on the t.o.d.o text - HighlightInfoType METHOD_CALL = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.METHOD_CALL_ATTRIBUTES); - HighlightInfoType METHOD_DECLARATION = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); - HighlightInfoType CONSTRUCTOR_CALL = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); - HighlightInfoType CONSTRUCTOR_DECLARATION = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.CONSTRUCTOR_DECLARATION_ATTRIBUTES); - HighlightInfoType STATIC_METHOD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.STATIC_METHOD_ATTRIBUTES); - HighlightInfoType CLASS_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.CLASS_NAME_ATTRIBUTES); - HighlightInfoType INTERFACE_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); - HighlightInfoType TYPE_PARAMETER_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES); - HighlightInfoType ABSTRACT_CLASS_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.ABSTRACT_CLASS_NAME_ATTRIBUTES); - HighlightInfoType ANNOTATION_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES); - HighlightInfoType ANNOTATION_ATTRIBUTE_NAME = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES); - HighlightInfoType REASSIGNED_LOCAL_VARIABLE = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); - HighlightInfoType REASSIGNED_PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); - HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); HighlightInfoType UNHANDLED_EXCEPTION = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); HighlightSeverity INJECTED_FRAGMENT_SEVERITY = new HighlightSeverity("INJECTED_FRAGMENT_SEVERITY", HighlightSeverity.INFORMATION.myVal-1); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java index 3c58d6b80ad3..b0703b68dcd8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java @@ -97,27 +97,25 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable private void updateChangesForDocument(@NotNull final Document document) { if (DaemonListeners.isUnderIgnoredAction(null)) return; List> toUpdate = changedElements.get(document); - if (toUpdate != null) { - Application application = ApplicationManager.getApplication(); - final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); - if (editor != null && !application.isUnitTestMode()) { - application.invokeLater(new Runnable() { - public void run() { - if (myProject.isDisposed()) return; - EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel(); - PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document); - TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, document, file); - } - }, ModalityState.stateForComponent(editor.getComponent())); - } - - for (Pair changedElement : toUpdate) { - PsiElement element = changedElement.getFirst(); - Boolean whiteSpaceOptimizationAllowed = changedElement.getSecond(); - updateByChange(element, document, whiteSpaceOptimizationAllowed); - } - changedElements.remove(document); + if (toUpdate == null) return; + Application application = ApplicationManager.getApplication(); + final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); + if (editor != null && !application.isUnitTestMode()) { + application.invokeLater(new Runnable() { + public void run() { + EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel(); + PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document); + TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, document, file); + } + }, ModalityState.stateForComponent(editor.getComponent()), myProject.getDisposed()); } + + for (Pair changedElement : toUpdate) { + PsiElement element = changedElement.getFirst(); + Boolean whiteSpaceOptimizationAllowed = changedElement.getSecond(); + updateByChange(element, document, whiteSpaceOptimizationAllowed); + } + changedElements.remove(document); } public void childAdded(PsiTreeChangeEvent event) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 5e45f82673d0..50389367850b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -55,7 +55,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator STANDARD_SEVERITIES = new HashMap(); + private static final Map STANDARD_SEVERITIES = new THashMap(); static { STANDARD_SEVERITIES.put(HighlightSeverity.ERROR.toString(), HighlightInfoType.ERROR); @@ -102,7 +102,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator incinerator = new MultiMap(){ @Override @@ -167,10 +171,17 @@ public class UpdateHighlightersUtil { @NotNull Map ranges2markersCache) { ApplicationManager.getApplication().assertIsDispatchThread(); if (info.isFileLevelAnnotation || info.getGutterIconRenderer() != null) return; + if (info.getStartOffset() < startOffset || info.getEndOffset() > endOffset) return; MarkupModel markup = DocumentMarkupModel.forDocument(document, project, true); + final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project); + final boolean myInfoIsError = isSevereError(info, severityRegistrar); Processor otherHighlightInTheWayProcessor = new Processor() { public boolean process(HighlightInfo oldInfo) { + if (!myInfoIsError && isSevereError(oldInfo, severityRegistrar) && isCoveredBy(info, oldInfo)) { + return false; + } + return oldInfo.group != group || !oldInfo.equalsByActualOffset(info); } }; @@ -180,10 +191,7 @@ public class UpdateHighlightersUtil { return; } - if (info.getStartOffset() < startOffset || info.getEndOffset() > endOffset) return; - - createOrReuseHighlighterFor(info, colorsScheme, document, group, file, (MarkupModelEx)markup, null, ranges2markersCache, - SeverityRegistrar.getInstance(project)); + createOrReuseHighlighterFor(info, colorsScheme, document, group, file, (MarkupModelEx)markup, null, ranges2markersCache, severityRegistrar); clearWhiteSpaceOptimizationFlag(document); assertMarkupConsistent(markup, project); @@ -373,10 +381,10 @@ public class UpdateHighlightersUtil { private static boolean isWarningCoveredByError(HighlightInfo info, Collection overlappingIntervals, SeverityRegistrar severityRegistrar) { - if (!isError(info, severityRegistrar)) { + if (!isSevereError(info, severityRegistrar)) { for (HighlightInfo overlapping : overlappingIntervals) { - boolean overlapIsError = isError(overlapping, severityRegistrar); - if (overlapIsError && DaemonCodeAnalyzerImpl.isCoveredBy(info, overlapping)) { + boolean overlapIsError = isSevereError(overlapping, severityRegistrar); + if (overlapIsError && isCoveredBy(info, overlapping)) { return true; } } @@ -384,20 +392,21 @@ public class UpdateHighlightersUtil { return false; } - private static boolean isError(HighlightInfo info, SeverityRegistrar severityRegistrar) { - return severityRegistrar.compare(HighlightSeverity.ERROR, info.getSeverity()) <= 0; + private static boolean isSevereError(HighlightInfo info, SeverityRegistrar severityRegistrar) { + HighlightSeverity severity = info.getSeverity(); + return severityRegistrar.compare(HighlightSeverity.ERROR, severity) <= 0 || severity == HighlightInfoType.SYMBOL_TYPE_SEVERITY; } // return true if changed private static RangeHighlighter createOrReuseHighlighterFor(@NotNull final HighlightInfo info, - @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - @NotNull final Document document, - final int group, - @NotNull final PsiFile psiFile, - @NotNull MarkupModelEx markup, - @Nullable HighlightersRecycler infosToRemove, - @NotNull final Map ranges2markersCache, - SeverityRegistrar severityRegistrar) { + @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used + @NotNull final Document document, + final int group, + @NotNull final PsiFile psiFile, + @NotNull MarkupModelEx markup, + @Nullable HighlightersRecycler infosToRemove, + @NotNull final Map ranges2markersCache, + SeverityRegistrar severityRegistrar) { final int infoStartOffset = info.startOffset; int infoEndOffset = info.endOffset; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index 1e57f45a5ebe..f69471b8df33 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -40,6 +40,8 @@ import javax.swing.border.EmptyBorder; import java.awt.*; public class LookupCellRenderer implements ListCellRenderer { + private static final int AFTER_TAIL = 10; + private static final int AFTER_TYPE = 6; private Icon myEmptyIcon = EmptyIcon.create(5); private final Font myNormalFont; private final Font myBoldFont; @@ -90,10 +92,10 @@ public class LookupCellRenderer implements ListCellRenderer { myPanel = new LookupPanel(); myPanel.add(myNameComponent, BorderLayout.WEST); myPanel.add(myTailComponent, BorderLayout.CENTER); - myTailComponent.setBorder(new EmptyBorder(0, 0, 0, 10)); + myTailComponent.setBorder(new EmptyBorder(0, 0, 0, AFTER_TAIL)); myPanel.add(myTypeLabel, BorderLayout.EAST); - myTypeLabel.setBorder(new EmptyBorder(0, 0, 0, 6)); + myTypeLabel.setBorder(new EmptyBorder(0, 0, 0, AFTER_TYPE)); myNormalMetrics = myLookup.getEditor().getComponent().getFontMetrics(myNormalFont); myBoldMetrics = myLookup.getEditor().getComponent().getFontMetrics(myBoldFont); @@ -117,12 +119,12 @@ public class LookupCellRenderer implements ListCellRenderer { final Color foreground = isSelected ? SELECTED_FOREGROUND_COLOR : FOREGROUND_COLOR; final Color background = getItemBackground(list, index, isSelected); - int allowedWidth = list.getWidth() - getCommonGapsWidth() - getIconIndent(); + int allowedWidth = list.getWidth() - AFTER_TAIL - AFTER_TYPE - getIconIndent(); final LookupElementPresentation presentation = new RealLookupElementPresentation(allowedWidth, myNormalMetrics, myBoldMetrics); item.renderElement(presentation); myNameComponent.clear(); - myNameComponent.setIcon(getIcon(presentation.getIcon())); + myNameComponent.setIcon(augmentIcon(presentation.getIcon(), myEmptyIcon)); myNameComponent.setBackground(background); allowedWidth -= setItemTextLabel(item, foreground, isSelected, presentation, allowedWidth); @@ -293,10 +295,6 @@ public class LookupCellRenderer implements ListCellRenderer { return used; } - private Icon getIcon(Icon icon){ - return augmentIcon(icon, myEmptyIcon); - } - public static Icon augmentIcon(@Nullable Icon icon, @NotNull Icon standard) { if (icon == null) { return standard; @@ -318,11 +316,7 @@ public class LookupCellRenderer implements ListCellRenderer { myEmptyIcon = new EmptyIcon(Math.max(icon.getIconWidth(), myEmptyIcon.getIconWidth()), Math.max(icon.getIconHeight(), myEmptyIcon.getIconHeight())); } - return RealLookupElementPresentation.calculateWidth(p, myNormalMetrics, myBoldMetrics) + getCommonGapsWidth(); - } - - private int getCommonGapsWidth() { - return 2 * myNormalMetrics.stringWidth("W"); //tail-type separation and a space after type + return RealLookupElementPresentation.calculateWidth(p, myNormalMetrics, myBoldMetrics) + AFTER_TAIL + AFTER_TYPE; } public int getIconIndent() { @@ -333,7 +327,6 @@ public class LookupCellRenderer implements ListCellRenderer { private static class MySimpleColoredComponent extends SimpleColoredComponent { private MySimpleColoredComponent() { setFocusBorderAroundIcon(true); - setBorderInsets(new Insets(0, 0, 0, 0)); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 4bf0d3775e28..4fc7bf65f25c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -134,6 +134,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable private final LookupLayeredPane myLayeredPane = new LookupLayeredPane(); private JButton myScrollBarIncreaseButton; private boolean myStartCompletionWhenNothingMatches; + private boolean myResizePending; public LookupImpl(Project project, Editor editor, @NotNull LookupArranger arranger){ super(new JPanel(new BorderLayout())); @@ -285,7 +286,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable myLookupTextWidth = Math.max(maxWidth, myLookupTextWidth); myModel.setItemPresentation(item, presentation); - + myResizePending = true; } public Collection getActionsFor(LookupElement element) { @@ -335,6 +336,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable myAdditionalPrefix += c; myInitialPrefix = null; myFrozenItems.clear(); + myResizePending = true; refreshUi(false); ensureSelectionVisible(); } @@ -365,6 +367,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable myAdditionalPrefix = myAdditionalPrefix.substring(0, len - 1); myInitialPrefix = null; myFrozenItems.clear(); + myResizePending = true; if (!myReused) { refreshUi(false); ensureSelectionVisible(); @@ -440,9 +443,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable updateListHeight(listModel); if (!model.isEmpty()) { - int listWidth = Math.min(myLookupTextWidth + myCellRenderer.getIconIndent(), UISettings.getInstance().MAX_LOOKUP_LIST_WIDTH); - myList.setFixedCellWidth(Math.max(listWidth, myAdComponent.getAdComponent().getPreferredSize().width)); - LookupElement first = model.iterator().next(); if (isFocused() && (!(isExactPrefixItem(first, true) || isExactPrefixItem(first, false)) || mySelectionTouched)) { restoreSelection(oldSelected, hasPreselected, oldInvariant, snapshot.second); @@ -533,10 +533,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable private void addEmptyItem(DefaultListModel model) { LookupItem item = new EmptyLookupItem(myCalculating ? " " : LangBundle.message("completion.no.suggestions")); myMatchers.put(item, new CamelHumpMatcher("")); - if (!myCalculating) { - myList.setFixedCellWidth(Math.max(myCellRenderer.updateMaximumWidth(renderItemApproximately(item)), myLookupTextWidth)); - } - model.addElement(item); } @@ -801,7 +797,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable LOG.assertTrue(marker.isValid(), "invalid marker"); marker.dispose(); if (isVisible()) { - updateLookupBounds(); + updateLookupLocation(); } checkValid(); } @@ -1272,7 +1268,13 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable } updateScrollbarVisibility(); - updateLookupBounds(); + + if (myResizePending) { + myResizePending = false; + pack(); + } + + updateLookupLocation(); if (reused || selectionVisible) { ensureSelectionVisible(); @@ -1280,8 +1282,8 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable } } - private void updateLookupBounds() { - HintManagerImpl.adjustEditorHintPosition(this, myEditor, calculatePosition()); + private void updateLookupLocation() { + HintManagerImpl.updateLocation(this, myEditor, calculatePosition()); } private void updateScrollbarVisibility() { @@ -1350,8 +1352,12 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable setLayout(new AbstractLayoutManager() { @Override - public Dimension preferredLayoutSize(Container parent) { - return mainPanel.getPreferredSize(); + public Dimension preferredLayoutSize(@Nullable Container parent) { + int maxCellWidth = myLookupTextWidth + myCellRenderer.getIconIndent(); + int width = Math.max(myScrollPane.getPreferredSize().width - myScrollPane.getViewport().getPreferredSize().width + maxCellWidth, + myAdComponent.getAdComponent().getPreferredSize().width); + return new Dimension(Math.min(width, UISettings.getInstance().MAX_LOOKUP_LIST_WIDTH), + mainPanel.getPreferredSize().height); } @Override @@ -1360,12 +1366,19 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable mainPanel.setSize(size); mainPanel.validate(); - UISettings.getInstance().MAX_LOOKUP_LIST_WIDTH = Math.max(300, myScrollPane.getViewport().getWidth()); - int visibleRowCount = myList.getLastVisibleIndex() - myList.getFirstVisibleIndex() + 1; - if (visibleRowCount != myList.getModel().getSize()) { - UISettings.getInstance().MAX_LOOKUP_ITEM_COUNT = Math.max(5, visibleRowCount); + if (!myResizePending) { + Dimension preferredSize = preferredLayoutSize(null); + if (preferredSize.width != size.width) { + UISettings.getInstance().MAX_LOOKUP_LIST_WIDTH = Math.max(300, size.width); + } + + int listHeight = myList.getLastVisibleIndex() - myList.getFirstVisibleIndex() + 1; + if (listHeight != myList.getModel().getSize() && listHeight != myList.getVisibleRowCount() && preferredSize.height != size.height) { + UISettings.getInstance().MAX_LOOKUP_ITEM_COUNT = Math.max(5, listHeight); + } } + myList.setFixedCellWidth(myScrollPane.getViewport().getWidth()); layoutStatusIcons(); layoutHint(); diff --git a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java b/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java index d0096b3c8249..e3c3026e9e8a 100644 --- a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java +++ b/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java @@ -96,10 +96,6 @@ public class HighlightSeverity implements Comparable, JDOMExt return myVal - highlightSeverity.myVal; } - public void setVal(final int val) { - myVal = val; - } - public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); } diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index a0be3b414140..39cdb4d3c53e 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -290,7 +290,7 @@ public class HintManagerImpl extends HintManager implements Disposable { Component component = hint.getComponent(); - doShowInGivenLocation(hint, editor, p, hintInfo); + doShowInGivenLocation(hint, editor, p, hintInfo, true); ListenerUtil.addMouseListener(component, new MouseAdapter() { public void mousePressed(MouseEvent e) { @@ -364,10 +364,10 @@ public class HintManagerImpl extends HintManager implements Disposable { } } - private static void doShowInGivenLocation(final LightweightHint hint, final Editor editor, Point p, HintHint hintInfo) { + private static void doShowInGivenLocation(final LightweightHint hint, final Editor editor, Point p, HintHint hintInfo, boolean updateSize) { if (ApplicationManager.getApplication().isUnitTestMode()) return; JLayeredPane layeredPane = editor.getComponent().getRootPane().getLayeredPane(); - Dimension size = hint.getComponent().getPreferredSize(); + Dimension size = updateSize ? hint.getComponent().getPreferredSize() : hint.getComponent().getSize(); if (hint.isRealPopup()) { final Point editorCorner = editor.getComponent().getLocation(); @@ -382,24 +382,28 @@ public class HintManagerImpl extends HintManager implements Disposable { p = rectangle.getLocation(); SwingUtilities.convertPointFromScreen(p, layeredPane); } - else if ((layeredPane.getWidth() < p.x + size.width) && !hintInfo.isAwtTooltip() && !hint.isRealPopup()) { + else if ((layeredPane.getWidth() < p.x + size.width) && !hintInfo.isAwtTooltip()) { p.x = Math.max(0, layeredPane.getWidth() - size.width); } if (hint.isVisible()) { - hint.updateBounds(p.x, p.y); + if (updateSize) { + hint.updateBounds(p.x, p.y); + } else { + hint.updateLocation(p.x, p.y); + } } else { hint.show(layeredPane, p.x, p.y, editor.getContentComponent(), hintInfo); } } - - public static void adjustEditorHintPosition(final LightweightHint hint, final Editor editor, final Point p) { - adjustEditorHintPosition(hint, editor, p, UNDER); + + public static void updateLocation(final LightweightHint hint, final Editor editor, Point p) { + doShowInGivenLocation(hint, editor, p, createHintHint(editor, p, hint, UNDER), false); } public static void adjustEditorHintPosition(final LightweightHint hint, final Editor editor, final Point p, short constraint) { - doShowInGivenLocation(hint, editor, p, createHintHint(editor, p, hint, constraint)); + doShowInGivenLocation(hint, editor, p, createHintHint(editor, p, hint, constraint), true); } public void hideAllHints() { @@ -767,6 +771,10 @@ public class HintManagerImpl extends HintManager implements Disposable { hintInfo.setPreferredPosition(Balloon.Position.atLeft); } + if (hint.isAwtTooltip()) { + hintInfo.setAwtTooltip(true); + } + hintInfo.setPositionChangeShift(0, editor.getLineHeight()); return hintInfo; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index bd19fb67559a..6aa1a89f84ca 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -523,6 +523,9 @@ public final class IdeKeyEventDispatcher implements Disposable { public void performAction(final InputEvent e, final AnAction action, final AnActionEvent actionEvent) { e.consume(); + if (Registry.is("actionSystem.fixLostTyping")) { + IdeEventQueue.getInstance().getKeyEventDispatcher().resetState(); + } action.actionPerformed(actionEvent); } }; @@ -773,6 +776,9 @@ public final class IdeKeyEventDispatcher implements Disposable { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { + if (Registry.is("actionSystem.fixLostTyping")) { + IdeEventQueue.getInstance().getKeyEventDispatcher().resetState(); + } final AnActionEvent event = new AnActionEvent(null, ctx, ActionPlaces.UNKNOWN, (Presentation)action.getTemplatePresentation().clone(), ActionManager.getInstance(), 0); diff --git a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java index dc9e3d10ed66..633278dec56c 100644 --- a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java +++ b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java @@ -22,6 +22,7 @@ import com.intellij.openapi.application.Application; 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.ui.popup.JBPopup; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ExpirableRunnable; @@ -66,6 +67,7 @@ public class FocusTrackback { private boolean mySheduledForRestore; private boolean myWillBeSheduledForRestore; private boolean myForcedRestore; + private boolean myTrack = false; public FocusTrackback(@NotNull Object requestor, Component parent, boolean mustBeShown) { this(requestor, parent == null || parent instanceof Window ? (Window)parent : SwingUtilities.getWindowAncestor(parent), mustBeShown); @@ -187,6 +189,10 @@ public class FocusTrackback { } public void restoreFocus() { + myTrack = + getRequestor() instanceof DialogWrapper && "Use Interface Where Possible".equals(((DialogWrapper)getRequestor()).getTitle()); + + final Application app = ApplicationManager.getApplication(); if (app == null || wrongOS() || myConsumed || isSheduledForRestore()) return; @@ -207,6 +213,12 @@ public class FocusTrackback { } } + if (!myForcedRestore) { + if (index == 0 && stack.size() == 1 && !UIUtil.isMeaninglessFocusOwner(getFocusOwner())) { + myForcedRestore = true; + } + } + if (project != null && !project.isDisposed()) { final IdeFocusManager focusManager = IdeFocusManager.getInstance(project); cleanParentWindow(); diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index a9af17597695..f2d658a3c651 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -184,7 +184,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { Point actualPoint = new Point(x, y); JComponent actualComponent = new OpaquePanel(new BorderLayout()); actualComponent.add(myComponent, BorderLayout.CENTER); - if (myHintHint.isAwtTooltip()) { + if (isAwtTooltip()) { fixActualPoint(actualPoint); @@ -223,7 +223,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { protected void onPopupCancel() {} private void fixActualPoint(Point actualPoint) { - if (!myHintHint.isAwtTooltip()) return; + if (!isAwtTooltip()) return; if (!myIsRealPopup) return; Dimension size = myComponent.getPreferredSize(); @@ -357,21 +357,19 @@ public class LightweightHint extends UserDataHolderBase implements Hint { @Override public void pack() { - updateBounds(-1, -1, false); + setSize(myComponent.getPreferredSize()); } @Override public void updateBounds(int x, int y) { - updateBounds(x, y, true); + setSize(myComponent.getPreferredSize()); + updateLocation(x, y); } - private void updateBounds(int x, int y, boolean updateLocation) { - setSize(myComponent.getPreferredSize()); - if (updateLocation) { - Point point = new Point(x, y); - fixActualPoint(point); - setLocation(new RelativePoint(myParentComponent, point)); - } + public void updateLocation(int x, int y) { + Point point = new Point(x, y); + fixActualPoint(point); + setLocation(new RelativePoint(myParentComponent, point)); } public final JComponent getComponent() { @@ -436,7 +434,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myPopup.setSize(size); } else { //todo kirillk - if (myHintHint.isAwtTooltip()) { + if (isAwtTooltip()) { return; } else { myComponent.setSize(size); @@ -447,6 +445,10 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } } + public boolean isAwtTooltip() { + return myHintHint != null && myHintHint.isAwtTooltip(); + } + public Dimension getSize() { return myComponent.getSize(); } diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java index bb629d05541c..3de5ac653c0c 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java +++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java @@ -25,6 +25,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.SeveritiesProvider; import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -64,22 +65,21 @@ public class ExpectedHighlightingData { @NonNls private static final String END_LINE_WARNING_MARKER = "EOLWarning"; @NonNls private static final String LINE_MARKER = "lineMarker"; + @NotNull private final Document myDocument; private final PsiFile myFile; @NonNls private static final String ANY_TEXT = "*"; - String myText; + private final String myText; - public static class ExpectedHighlightingSet { + private static class ExpectedHighlightingSet { private final boolean endOfLine; final boolean enabled; final Set infos; - final HighlightInfoType defaultErrorType; final HighlightSeverity severity; - public ExpectedHighlightingSet(HighlightInfoType defaultErrorType, HighlightSeverity severity, boolean endOfLine, boolean enabled) { + public ExpectedHighlightingSet(@NotNull HighlightSeverity severity, boolean endOfLine, boolean enabled) { this.endOfLine = endOfLine; this.enabled = enabled; infos = new THashSet(); - this.defaultErrorType = defaultErrorType; this.severity = severity; } } @@ -87,6 +87,16 @@ public class ExpectedHighlightingData { protected final Map highlightingTypes; private final Map lineMarkerInfos = new THashMap(); + public void init() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + extractExpectedLineMarkerSet(myDocument); + extractExpectedHighlightsSet(myDocument); + refreshLineMarkers(); + } + }); + } + public ExpectedHighlightingData(@NotNull Document document,boolean checkWarnings, boolean checkInfos) { this(document, checkWarnings, false, checkInfos); } @@ -98,35 +108,64 @@ public class ExpectedHighlightingData { this(document, checkWarnings, checkWeakWarnings, checkInfos, null); } - public ExpectedHighlightingData(@NotNull final Document document, - final boolean checkWarnings, - final boolean checkWeakWarnings, - final boolean checkInfos, - PsiFile file) { + public ExpectedHighlightingData(@NotNull final Document document, PsiFile file) { + myDocument = document; myFile = file; myText = document.getText(); highlightingTypes = new LinkedHashMap(); new WriteCommandAction.Simple(file == null ? null : file.getProject()) { public void run() { - highlightingTypes.put(ERROR_MARKER, new ExpectedHighlightingSet(HighlightInfoType.ERROR, HighlightSeverity.ERROR, false, true)); - highlightingTypes.put(WARNING_MARKER, new ExpectedHighlightingSet(HighlightInfoType.WARNING, HighlightSeverity.WARNING, false, checkWarnings)); - highlightingTypes.put(INFORMATION_MARKER, new ExpectedHighlightingSet(HighlightInfoType.WEAK_WARNING, HighlightSeverity.WEAK_WARNING, false, checkWeakWarnings)); - highlightingTypes.put("inject", new ExpectedHighlightingSet(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT, HighlightInfoType.INJECTED_FRAGMENT_SEVERITY, false, checkInfos)); - highlightingTypes.put(INFO_MARKER, new ExpectedHighlightingSet(HighlightInfoType.TODO, HighlightSeverity.INFORMATION, false, checkInfos)); + boolean checkWarnings= false; + boolean checkWeakWarnings = false; + boolean checkInfos = false; + + + + highlightingTypes.put(ERROR_MARKER, new ExpectedHighlightingSet(HighlightSeverity.ERROR, false, true)); + highlightingTypes.put(WARNING_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WARNING, false, checkWarnings)); + highlightingTypes.put(INFORMATION_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WEAK_WARNING, false, checkWeakWarnings)); + highlightingTypes.put("inject", new ExpectedHighlightingSet(HighlightInfoType.INJECTED_FRAGMENT_SEVERITY, false, checkInfos)); + highlightingTypes.put(INFO_MARKER, new ExpectedHighlightingSet(HighlightSeverity.INFORMATION, false, checkInfos)); + highlightingTypes.put("symbolName", new ExpectedHighlightingSet(HighlightInfoType.SYMBOL_TYPE_SEVERITY, false, false)); for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) { for (HighlightInfoType type : provider.getSeveritiesHighlightInfoTypes()) { final HighlightSeverity severity = type.getSeverity(null); - highlightingTypes.put(severity.toString(), new ExpectedHighlightingSet(type, severity, false, true)); + highlightingTypes.put(severity.toString(), new ExpectedHighlightingSet(severity, false, true)); } } - highlightingTypes.put(END_LINE_HIGHLIGHT_MARKER,new ExpectedHighlightingSet(HighlightInfoType.ERROR, HighlightSeverity.ERROR, true, true)); - highlightingTypes.put(END_LINE_WARNING_MARKER, new ExpectedHighlightingSet(HighlightInfoType.WARNING, HighlightSeverity.WARNING, true, checkWarnings)); + highlightingTypes.put(END_LINE_HIGHLIGHT_MARKER, new ExpectedHighlightingSet(HighlightSeverity.ERROR, true, true)); + highlightingTypes.put(END_LINE_WARNING_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WARNING, true, checkWarnings)); initAdditionalHighlightingTypes(); - extractExpectedLineMarkerSet(document); - extractExpectedHighlightsSet(document); - refreshLineMarkers(); } }.execute().throwException(); + + } + public ExpectedHighlightingData(@NotNull final Document document, + final boolean checkWarnings, + final boolean checkWeakWarnings, + final boolean checkInfos, + PsiFile file) { + this(document, file); + if (checkWarnings) checkWarnings(); + if (checkWeakWarnings) checkWeakWarnings(); + if (checkInfos) checkInfos(); + } + + public void checkWarnings() { + highlightingTypes.put(WARNING_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WARNING, false, true)); + highlightingTypes.put(END_LINE_WARNING_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WARNING, true, true)); + + } + public void checkWeakWarnings() { + highlightingTypes.put(INFORMATION_MARKER, new ExpectedHighlightingSet(HighlightSeverity.WEAK_WARNING, false, true)); + } + public void checkInfos() { + highlightingTypes.put(INFO_MARKER, new ExpectedHighlightingSet(HighlightSeverity.INFORMATION, false, true)); + highlightingTypes.put("inject", new ExpectedHighlightingSet(HighlightInfoType.INJECTED_FRAGMENT_SEVERITY, false, true)); + + } + public void checkSymbolNames() { + highlightingTypes.put("symbolName", new ExpectedHighlightingSet(HighlightInfoType.SYMBOL_TYPE_SEVERITY, false, true)); } private void refreshLineMarkers() { @@ -242,7 +281,8 @@ public class ExpectedHighlightingData { Field field = HighlightInfoType.class.getField(typeString); type = (HighlightInfoType)field.get(null); } - catch (Exception ignore) { + catch (Exception e) { + LOG.error(e); } LOG.assertTrue(type != null, "Wrong highlight type: " + typeString); } diff --git a/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java b/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java new file mode 100644 index 000000000000..9d12ebc4f484 --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2011 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.testFramework; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public abstract class HighlightTestInfo implements Disposable { + @NotNull protected final String[] filePaths; + protected boolean checkWarnings; + protected boolean checkInfos; + protected boolean checkSymbolNames; + protected boolean checkWeakWarnings; + protected String projectRoot; + private boolean tested; + private final String myPlace; + + public HighlightTestInfo(@NotNull Disposable parentDisposable, @NonNls @NotNull String... filePaths) { + this.filePaths = filePaths; + // disposer here for catching the case of not calling test() + Disposer.register(parentDisposable, this); + myPlace = parentDisposable.toString(); + } + public HighlightTestInfo checkWarnings() { checkWarnings = true; return this; } + public HighlightTestInfo checkWeakWarnings() { checkWeakWarnings = true; return this; } + public HighlightTestInfo checkInfos() { checkInfos = true; return this; } + public HighlightTestInfo checkSymbolNames() { checkSymbolNames = true; return this; } + public HighlightTestInfo projectRoot(@NonNls @NotNull String root) { projectRoot = root; return this; } + + public HighlightTestInfo test() throws Exception { + doTest(); + tested = true; + Disposer.dispose(this); + return this; + } + + @Override + public void dispose() { + assert tested : "You must call HighlightTestInfo.test() in " + myPlace; + } + + protected abstract HighlightTestInfo doTest() throws Exception; +} diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 9bcd6abfc1f2..f1765700d398 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -463,10 +463,13 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da checkForSettingsDamage(); doTearDown(getProject(), ourApplication, true); - super.tearDown(); - - myThreadTracker.checkLeak(); - ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).checkInjectorsAreDisposed(); + try { + super.tearDown(); + } + finally { + myThreadTracker.checkLeak(); + ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).checkInjectorsAreDisposed(); + } } public static void doTearDown(final Project project, IdeaTestApplication application, boolean checkForEditors) throws Exception { diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java index ab537c5ffb63..6aaa3b81647e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java @@ -48,7 +48,7 @@ public abstract class PlatformLiteFixture extends UsefulTestCase { } public void initApplication() { - if (ApplicationManager.getApplication() instanceof MockApplicationEx) return; + // if (ApplicationManager.getApplication() instanceof MockApplicationEx) return; ApplicationManagerEx.setApplication(disposeOnTearDown(new MockApplicationEx()), getTestRootDisposable()); getApplication().registerService(EncodingManager.class, EncodingManagerImpl.class); } diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 84fcab5f96c0..5e4f1257c5b6 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -68,7 +68,17 @@ public abstract class UsefulTestCase extends TestCase { private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory(); public static final String IDEA_MARKER_CLASS = "com.intellij.openapi.components.impl.stores.IdeaProjectStoreImpl"; - protected final Disposable myTestRootDisposable = Disposer.newDisposable(); + protected final Disposable myTestRootDisposable = new Disposable() { + @Override + public void dispose() { + } + + @Override + public String toString() { + String testName = getTestName(false); + return UsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName); + } + }; private CodeStyleSettings myOldCodeStyleSettings; private String myTempDir; diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java index 264898616be4..6be249c5717e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java @@ -37,6 +37,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiReference; +import com.intellij.testFramework.HighlightTestInfo; import com.intellij.testFramework.TestDataFile; import com.intellij.usageView.UsageInfo; import com.intellij.util.Consumer; @@ -147,6 +148,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture { long testHighlighting(@NonNls String... filePaths); long testHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, VirtualFile file); + HighlightTestInfo testFile(@NonNls @NotNull String... filePath); void testInspection(String testDir, InspectionTool tool); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 974b3383400d..bcce6b781ecf 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -360,8 +360,9 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig assertNotNull(psiFile); final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile); assertNotNull(document); - return Trinity.create(psiFile, createEditor(file), - new ExpectedHighlightingData(document, checkWarnings, checkWeakWarnings, checkInfos, psiFile)); + ExpectedHighlightingData data = new ExpectedHighlightingData(document, checkWarnings, checkWeakWarnings, checkInfos, psiFile); + data.init(); + return Trinity.create(psiFile, createEditor(file), data); } }); for (Trinity trinity : datas) { @@ -409,6 +410,21 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig return duration.get().longValue(); } + @Override + public HighlightTestInfo testFile(@NonNls @NotNull String... filePath) { + return new HighlightTestInfo(getTestRootDisposable(), filePath){ + @Override + public HighlightTestInfo doTest() throws Exception { + configureByFiles(filePaths); + ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); + if (checkSymbolNames) data.checkSymbolNames(); + data.init(); + collectAndCheckHighlightings(data, Ref.create(0L)); + return this; + } + }; + } + public void openFileInEditor(@NotNull final VirtualFile file) { myFile = myPsiManager.findFile(file); myEditor = createEditor(file); @@ -1305,7 +1321,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig throws Exception { ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); - + data.init(); collectAndCheckHighlightings(data, duration); } @@ -1364,13 +1380,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @NotNull public List doHighlighting() { final Project project = getProject(); - new WriteCommandAction.Simple(project) { - @Override - protected void run() throws Throwable { - PsiDocumentManager.getInstance(project).commitAllDocuments(); - } - }.execute().throwException(); - + PsiDocumentManager.getInstance(project).commitAllDocuments(); return ApplicationManager.getApplication().runReadAction(new Computable>() { @@ -1430,7 +1440,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig return myFile; } - public static List getAvailableIntentions(final Editor editor, final PsiFile file) { + public static List getAvailableIntentions(@NotNull final Editor editor, @NotNull final PsiFile file) { return ApplicationManager.getApplication().runReadAction(new Computable>() { @Override public List compute() { @@ -1439,7 +1449,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig }); } - private static List doGetAvailableIntentions(Editor editor, PsiFile file) { + private static List doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) { ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo(); ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1); List descriptors = new ArrayList(); diff --git a/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java b/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java index f4f2b7c54002..a347509231cb 100644 --- a/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java +++ b/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java @@ -32,6 +32,7 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.TestDataFile; import com.intellij.util.ThrowableRunnable; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; @@ -124,6 +125,7 @@ public class AntHighlightingTest extends DaemonAnalyzerTestCase { } + @NotNull @Override protected List doHighlighting() { final List infos = super.doHighlighting(); diff --git a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java index 57c54065d6f4..5312d3912c4f 100644 --- a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java +++ b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java @@ -188,6 +188,7 @@ public abstract class HighlightingTestBase extends UsefulTestCase implements Ide final PsiFile file = myTestFixture.getFile(); final Document doc = myTestFixture.getEditor().getDocument(); ExpectedHighlightingData data = new ExpectedHighlightingData(doc, true, checkWeakWarnings, false, file); + data.init(); PsiDocumentManager.getInstance(myTestFixture.getProject()).commitAllDocuments(); Collection highlights1 = doHighlighting(includeExternalToolPass);