diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index cd8ff3afdb36..78549253c339 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -314,7 +314,6 @@ - diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerErrorTreeView.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerErrorTreeView.java index 3e2bc2b342de..d3414f3d4528 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerErrorTreeView.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerErrorTreeView.java @@ -197,7 +197,6 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel { final String[] text = messageElement.getText(); if (text.length > 0) { if (text[0].startsWith("[") && text[0].indexOf("]") != -1) { - presentation.setVisible(true); final Navigatable navigatable = messageElement.getNavigatable(); if (navigatable instanceof OpenFileDescriptor) { final OpenFileDescriptor fileDescriptor = (OpenFileDescriptor)navigatable; @@ -217,6 +216,7 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel { final SuppressFix suppressInspectionFix = getSuppressAction(id); final boolean available = suppressInspectionFix.isAvailable(project, null, context); presentation.setEnabled(available); + presentation.setVisible(available); if (available) { presentation.setText(suppressInspectionFix.getText()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 76f0fa24b0b9..06b9574b6450 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -459,7 +459,7 @@ public class JavaCompletionUtil { } } - if (javaReference instanceof PsiReferenceExpression && !((PsiReferenceExpression)javaReference).isQualified()) { + if (javaReference instanceof PsiJavaCodeReferenceElement && !((PsiJavaCodeReferenceElement)javaReference).isQualified()) { final StaticMemberProcessor memberProcessor = JavaGlobalMemberNameCompletionContributor.completeStaticMembers(parameters); memberProcessor.processMembersOfRegisteredClasses(matcher, new PairConsumer() { @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index bef51af9bdbb..d4d178428a33 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -29,6 +29,7 @@ import com.intellij.ide.fileTemplates.JavaTemplateUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -182,7 +183,7 @@ public class CreateFromUsageUtils { } } - public static void setupEditor(PsiMethod method, Editor newEditor) { + public static void setupEditor(PsiMethod method, final Editor newEditor) { PsiCodeBlock body = method.getBody(); if (body != null) { PsiElement l = PsiTreeUtil.skipSiblingsForward(body.getLBrace(), PsiWhiteSpace.class); @@ -191,7 +192,14 @@ public class CreateFromUsageUtils { int start = l.getTextRange().getStartOffset(); int end = r.getTextRange().getEndOffset(); newEditor.getCaretModel().moveToOffset(Math.max(start, end)); - newEditor.getSelectionModel().setSelection(Math.min(start, end), Math.max(start, end)); + if (end < start) { + newEditor.getCaretModel().moveToOffset(end + 1); + CodeStyleManager styleManager = CodeStyleManager.getInstance(method.getProject()); + final String lineIndent = styleManager.getLineIndent(method.getContainingFile(), Math.min(start, end)); + EditorModificationUtil.insertStringAtCaret(newEditor, lineIndent); + } else { + newEditor.getSelectionModel().setSelection(Math.min(start, end), Math.max(start, end)); + } newEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression.java b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression.java new file mode 100644 index 000000000000..d27cd96b9e4d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression.java @@ -0,0 +1,11 @@ +import static Foo.assertNotNull; + +class Foo { + static void assertNotNull() {} +} + +class Bar { + { + asnn lists.get(0).size() > 0); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression_after.java b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression_after.java new file mode 100644 index 000000000000..bcc1d55c1423 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedMethodsBeforeExpression_after.java @@ -0,0 +1,11 @@ +import static Foo.assertNotNull; + +class Foo { + static void assertNotNull() {} +} + +class Bar { + { + assertNotNull(); lists.get(0).size() > 0); + } +} \ 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 89576fded6b9..293d6206aaab 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1328,5 +1328,6 @@ public class ListUtils { public void testListArrayListCast() { doTest('\n') } public void testInterfaceImplementationNoCast() { doTest() } + public void testStaticallyImportedMethodsBeforeExpression() { doTest() } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index e2364c04bab4..4eb3dfa3f5ac 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -208,6 +208,8 @@ public class IncProjectBuilder { private void runBuild(CompileContext context) throws ProjectBuildException { context.setDone(0.0f); + LOG.info("Building project '" + context.getProject().getProjectName() + "'; isRebuild:" +context.isProjectRebuild() + "; isMake:" + context.isMake()); + if (context.isProjectRebuild()) { cleanOutputRoots(context); } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java b/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java index 7243b484fca3..9463e1f6fdc0 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java @@ -136,6 +136,11 @@ public class ClassRepr extends Proto { public boolean hadValue() { return false; } + + @Override + public boolean weakedAccess() { + return diff.weakedAccess(); + } }; } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Difference.java b/jps/model/src/org/jetbrains/ether/dependencyView/Difference.java index a761581b7a39..38f875f33d92 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Difference.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Difference.java @@ -1,6 +1,7 @@ package org.jetbrains.ether.dependencyView; import com.intellij.openapi.util.Pair; +import org.jetbrains.asm4.Opcodes; import java.util.*; @@ -12,6 +13,16 @@ import java.util.*; * To change this template use File | Settings | File Templates. */ abstract class Difference { + public static boolean isPackageLocal(final int access) { + return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0; + } + + public static boolean weakerAccess(final int me, final int then) { + return ((me & Opcodes.ACC_PRIVATE) > 0 && (then & Opcodes.ACC_PRIVATE) == 0) || + ((me & Opcodes.ACC_PROTECTED) > 0 && (then & Opcodes.ACC_PUBLIC) > 0) || + (isPackageLocal(me) && (then & Opcodes.ACC_PROTECTED) > 0); + } + public static final int NONE = 0; public static final int ACCESS = 1; public static final int TYPE = 2; @@ -21,8 +32,11 @@ abstract class Difference { public interface Specifier { Collection added(); + Collection removed(); + Collection> changed(); + boolean unchanged(); } @@ -105,11 +119,13 @@ abstract class Difference { public abstract boolean no(); + public abstract boolean weakedAccess(); + public abstract int addedModifiers(); public abstract int removedModifiers(); public abstract boolean packageLocalOn(); - public abstract boolean hadValue (); + public abstract boolean hadValue(); } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index f7dbe66bc798..2b0ad81be653 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -733,19 +733,9 @@ public class Mappings { } } - private static boolean isPackageLocal(final int access) { - return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0; - } - - private static boolean weakerAccess(final int me, final int then) { - return ((me & Opcodes.ACC_PRIVATE) > 0 && (then & Opcodes.ACC_PRIVATE) == 0) || - ((me & Opcodes.ACC_PROTECTED) > 0 && (then & Opcodes.ACC_PUBLIC) > 0) || - (isPackageLocal(me) && (then & Opcodes.ACC_PROTECTED) > 0); - } - private static boolean isVisibleIn(final ClassRepr c, final ProtoMember m, final ClassRepr scope) { final boolean privacy = ((m.access & Opcodes.ACC_PRIVATE) > 0) && c.name != scope.name; - final boolean packageLocality = isPackageLocal(m.access) && !c.getPackageName().equals(scope.getPackageName()); + final boolean packageLocality = Difference.isPackageLocal(m.access) && !c.getPackageName().equals(scope.getPackageName()); return !privacy && !packageLocality; } @@ -1080,7 +1070,7 @@ public class Mappings { final Option subtypeOf = u.isSubtypeOf(mm.type, m.type); - if (weakerAccess(mm.access, m.access) || + if (Difference.weakerAccess(mm.access, m.access) || ((m.access & Opcodes.ACC_STATIC) > 0 && (mm.access & Opcodes.ACC_STATIC) == 0) || ((m.access & Opcodes.ACC_STATIC) == 0 && (mm.access & Opcodes.ACC_STATIC) > 0) || ((m.access & Opcodes.ACC_FINAL) > 0) || @@ -1382,7 +1372,7 @@ public class Mappings { final boolean ffPrivate = (ff.access & Opcodes.ACC_PRIVATE) > 0; final boolean ffProtected = (ff.access & Opcodes.ACC_PROTECTED) > 0; final boolean ffPublic = (ff.access & Opcodes.ACC_PUBLIC) > 0; - final boolean ffPLocal = isPackageLocal(ff.access); + final boolean ffPLocal = Difference.isPackageLocal(ff.access); if (!ffPrivate) { final TIntHashSet propagated = o.propagateFieldAccess(ff.name, cc.name); @@ -1441,10 +1431,15 @@ public class Mappings { final Difference d = f.second; final FieldRepr field = f.first; - debug("Field: ", it.name); + debug("Field: ", field.name); if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) { - if ((d.base() & Difference.ACCESS) > 0 || ((d.base() & Difference.VALUE) > 0 && d.hadValue())) { + final int changedModifiers = d.addedModifiers() | d.removedModifiers(); + final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0; + final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0; + final boolean valueChanged = (d.base() & Difference.VALUE) > 0 && d.hadValue(); + + if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) { debug("Inline field changed it's access or value => a switch to non-incremental mode requested"); if (!incrementalDecision(it.name, field, affectedFiles, filter)) { debug("End of Differentiate, returning false"); @@ -1643,7 +1638,10 @@ public class Mappings { } } - private void cleanupRemovedClass(@NotNull ClassRepr cr, Collection clusters, IntIntMultiMaplet subclassesTrashBin, IntIntMultiMaplet dependenciesTrashBin) { + private void cleanupRemovedClass(@NotNull ClassRepr cr, + Collection clusters, + IntIntMultiMaplet subclassesTrashBin, + IntIntMultiMaplet dependenciesTrashBin) { final int className = cr.name; for (final int superSomething : cr.getSupers()) { @@ -1811,7 +1809,6 @@ public class Mappings { return true; } }); - } finally { delta.close(); @@ -2026,7 +2023,7 @@ public class Mappings { @NotNull private Set getDeletedClasses() { - return myDeletedClasses != null? Collections.emptySet() : Collections.unmodifiableSet(myDeletedClasses); + return myDeletedClasses != null ? Collections.emptySet() : Collections.unmodifiableSet(myDeletedClasses); } private TIntHashSet getChangedClasses() { @@ -2052,5 +2049,4 @@ public class Mappings { private void debug(final String comment, final boolean s) { myDebugS.debug(comment, s); } - } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/MethodRepr.java b/jps/model/src/org/jetbrains/ether/dependencyView/MethodRepr.java index 357807351b75..64641c47b5f6 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/MethodRepr.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/MethodRepr.java @@ -85,6 +85,11 @@ class MethodRepr extends ProtoMember { public boolean hadValue() { return ((MethodRepr)past).hasValue(); } + + @Override + public boolean weakedAccess() { + return diff.weakedAccess(); + } }; } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Proto.java b/jps/model/src/org/jetbrains/ether/dependencyView/Proto.java index 0c4dbf18e50a..39aaf0b36ed2 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Proto.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Proto.java @@ -1,6 +1,6 @@ package org.jetbrains.ether.dependencyView; -import groovyjarjarasm.asm.Opcodes; +import org.jetbrains.asm4.Opcodes; import org.jetbrains.ether.RW; import java.io.DataInput; @@ -86,17 +86,19 @@ class Proto implements RW.Savable { public boolean packageLocalOn() { return ((past.access & Opcodes.ACC_PRIVATE) != 0 || (past.access & Opcodes.ACC_PUBLIC) != 0 || - (past.access & Opcodes.ACC_PROTECTED) != 0) - - && - - ((access & Opcodes.ACC_PRIVATE) == 0 && (access & Opcodes.ACC_PROTECTED) == 0 && (access & Opcodes.ACC_PUBLIC) == 0); + (past.access & Opcodes.ACC_PROTECTED) != 0) && + Difference.isPackageLocal(access); } @Override public boolean hadValue() { return false; } + + @Override + public boolean weakedAccess() { + return Difference.weakerAccess(past.access, access); + } }; } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/ProtoMember.java b/jps/model/src/org/jetbrains/ether/dependencyView/ProtoMember.java index bdfee422d6bd..ed1e350a2ec4 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/ProtoMember.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/ProtoMember.java @@ -172,6 +172,11 @@ abstract class ProtoMember extends Proto { public boolean hadValue() { return ((ProtoMember)past).hasValue(); } + + @Override + public boolean weakedAccess() { + return diff.weakedAccess(); + } }; } } diff --git a/platform/core-api/src/com/intellij/util/IconUtil.java b/platform/core-api/src/com/intellij/util/IconUtil.java index 95cccedcc9e8..1bca832cf114 100644 --- a/platform/core-api/src/com/intellij/util/IconUtil.java +++ b/platform/core-api/src/com/intellij/util/IconUtil.java @@ -211,6 +211,14 @@ public class IconUtil { return getToolbarDecoratorIcon("addClass.png"); } + public static Icon getImportIcon() { + return IconLoader.getIcon("/toolbarDecorator/import.png"); + } + + public static Icon getExportIcon() { + return IconLoader.getIcon("/toolbarDecorator/export.png"); + } + public static Icon getToolbarDecoratorIcon(String name) { return IconLoader.getIcon(getToolbarDecoratorIconsFolder() + name); } diff --git a/platform/icons/src/toolbarDecorator/export.png b/platform/icons/src/toolbarDecorator/export.png new file mode 100644 index 000000000000..b3ece155aca8 Binary files /dev/null and b/platform/icons/src/toolbarDecorator/export.png differ diff --git a/platform/icons/src/toolbarDecorator/import.png b/platform/icons/src/toolbarDecorator/import.png new file mode 100644 index 000000000000..be19d32757ca Binary files /dev/null and b/platform/icons/src/toolbarDecorator/import.png differ diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateGroup.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateGroup.java index 51faa4ab489b..e86ac895ea47 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateGroup.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateGroup.java @@ -17,12 +17,22 @@ package com.intellij.codeInsight.template.impl; import com.intellij.openapi.options.CompoundScheme; +import org.jetbrains.annotations.Nullable; public class TemplateGroup extends CompoundScheme { + private final String myReplace; public TemplateGroup(final String name) { - super(name); + this(name, null); } + public TemplateGroup(String name, @Nullable String replace) { + super(name); + myReplace = replace; + } + + public String getReplace() { + return myReplace; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java index 41c49b33a83e..a3f82a0e2f0c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java @@ -487,7 +487,14 @@ public class TemplateSettings implements PersistentStateComponent, Expo String templateName = getDefaultTemplateName(defTemplate); InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, defTemplate); if (inputStream != null) { - readDefTemplateFile(inputStream, templateName, provider.getClass().getClassLoader(), registerTemplate); + TemplateGroup group = + readTemplateFile(JDOMUtil.loadDocument(inputStream), templateName, true, registerTemplate, provider.getClass().getClassLoader()); + if (group != null && group.getReplace() != null) { + Collection templates = myTemplates.get(group.getReplace()); + for (TemplateImpl template : templates) { + removeTemplate(template); + } + } } } @@ -495,10 +502,6 @@ public class TemplateSettings implements PersistentStateComponent, Expo return defTemplate.substring(defTemplate.lastIndexOf("/") + 1); } - private void readDefTemplateFile(InputStream inputStream, String defGroupName, ClassLoader classLoader, boolean registerTemplate) throws JDOMException, InvalidDataException, IOException { - readTemplateFile(JDOMUtil.loadDocument(inputStream), defGroupName, true, registerTemplate, classLoader); - } - @Nullable private TemplateGroup readTemplateFile(Document document, @NonNls String defGroupName, boolean isDefault, boolean registerTemplate, ClassLoader classLoader) throws InvalidDataException { if (document == null) { @@ -512,7 +515,7 @@ public class TemplateSettings implements PersistentStateComponent, Expo String groupName = root.getAttributeValue(GROUP); if (groupName == null || groupName.length() == 0) groupName = defGroupName; - TemplateGroup result = new TemplateGroup(groupName); + TemplateGroup result = new TemplateGroup(groupName, root.getAttributeValue("REPLACE")); Map created = new LinkedHashMap(); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java index d2c272630bf2..3858734b488c 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java @@ -22,6 +22,7 @@ import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.ui.InspectionNode; import com.intellij.codeInspection.ui.InspectionTreeNode; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -109,5 +110,8 @@ public class CommonInspectionToolWrapper extends InspectionToolWrapper void unregisterListener(@NotNull FacetTypeId typeId, @NotNull ProjectWideFacetListener listener) { - myDispatchers.get(typeId).removeListener(listener); + final EventDispatcher dispatcher = myDispatchers.get(typeId); + if (dispatcher != null) { + dispatcher.removeListener(listener); + } } public void registerListener(@NotNull final FacetTypeId typeId, @NotNull final ProjectWideFacetListener listener, diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java index 5d5d0b33f93b..182decab5fa2 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java @@ -22,6 +22,7 @@ import com.intellij.application.options.SchemesToImportPopup; import com.intellij.ide.highlighter.custom.SyntaxTable; import com.intellij.ide.highlighter.custom.impl.ReadFileType; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; @@ -35,7 +36,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.templateLanguages.TemplateDataLanguagePatterns; import com.intellij.ui.*; import com.intellij.ui.components.JBList; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.IconUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,8 +44,6 @@ import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.*; @@ -134,13 +133,13 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable public void reset() { myTempPatternsTable = myManager.getExtensionMap().copy(); myTempTemplateDataLanguages = TemplateDataLanguagePatterns.getInstance().getAssocTable(); - + myTempFileTypes = new HashSet(Arrays.asList(getModifiableFileTypes())); myOriginalToEditedMap.clear(); updateFileTypeList(); updateExtensionList(); - + myFileTypePanel.myIgnoreFilesField.setText(myManager.getIgnoredFilesList()); } @@ -148,7 +147,8 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable if (!myManager.isIgnoredFilesListEqualToCurrent(myFileTypePanel.myIgnoreFilesField.getText())) return true; HashSet types = new HashSet(Arrays.asList(getModifiableFileTypes())); return !myTempPatternsTable.equals(myManager.getExtensionMap()) || !myTempFileTypes.equals(types) || - !myOriginalToEditedMap.isEmpty() || !myTempTemplateDataLanguages.equals(TemplateDataLanguagePatterns.getInstance().getAssocTable()); + !myOriginalToEditedMap.isEmpty() || + !myTempTemplateDataLanguages.equals(TemplateDataLanguagePatterns.getInstance().getAssocTable()); } public void disposeUIResources() { @@ -194,7 +194,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable UserFileType ftToEdit = myOriginalToEditedMap.get(fileType); if (ftToEdit == null) ftToEdit = ((UserFileType)fileType).clone(); TypeEditor editor = - new TypeEditor(myRecognizedFileType.myEditButton, ftToEdit, FileTypesBundle.message("filetype.edit.existing.title")); + new TypeEditor(myRecognizedFileType.myFileTypesList, ftToEdit, FileTypesBundle.message("filetype.edit.existing.title")); editor.show(); if (editor.isOK()) { myOriginalToEditedMap.put((UserFileType)fileType, ftToEdit); @@ -220,7 +220,8 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable private void addFileType() { //TODO: support adding binary file types... AbstractFileType type = new AbstractFileType(new SyntaxTable()); - TypeEditor editor = new TypeEditor(myRecognizedFileType.myAddButton, type, FileTypesBundle.message("filetype.edit.new.title")); + TypeEditor editor = + new TypeEditor(myRecognizedFileType.myFileTypesList, type, FileTypesBundle.message("filetype.edit.new.title")); editor.show(); if (editor.isOK()) { myTempFileTypes.add(type); @@ -242,7 +243,9 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable if (type == null) return; final String title = - item == null ? FileTypesBundle.message("filetype.edit.add.pattern.title") : FileTypesBundle.message("filetype.edit.edit.pattern.title"); + item == null + ? FileTypesBundle.message("filetype.edit.add.pattern.title") + : FileTypesBundle.message("filetype.edit.edit.pattern.title"); final Language oldLanguage = item == null ? null : myTempTemplateDataLanguages.findAssociatedFileType(item); final FileTypePatternDialog dialog = new FileTypePatternDialog(item, type, oldLanguage); @@ -259,20 +262,21 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable FileType registeredFileType = findExistingFileType(matcher); if (registeredFileType != null && registeredFileType != type) { if (registeredFileType.isReadOnly()) { - Messages.showMessageDialog(myPatterns.myAddButton, + Messages.showMessageDialog(myPatterns.myPatternsList, FileTypesBundle.message("filetype.edit.add.pattern.exists.error", registeredFileType.getDescription()), title, Messages.getErrorIcon()); return; } else { - if (0 == Messages.showOkCancelDialog(myPatterns.myAddButton, FileTypesBundle.message("filetype.edit.add.pattern.exists.message", - registeredFileType.getDescription()), - FileTypesBundle.message("filetype.edit.add.pattern.exists.title"), - FileTypesBundle.message("filetype.edit.add.pattern.reassign.button"), - CommonBundle.getCancelButtonText(), Messages.getQuestionIcon())) { + if (0 == Messages.showOkCancelDialog(myPatterns.myPatternsList, FileTypesBundle.message("filetype.edit.add.pattern.exists.message", + registeredFileType.getDescription()), + FileTypesBundle.message("filetype.edit.add.pattern.exists.title"), + FileTypesBundle.message("filetype.edit.add.pattern.reassign.button"), + CommonBundle.getCancelButtonText(), Messages.getQuestionIcon())) { myTempPatternsTable.removeAssociation(matcher, registeredFileType); myTempTemplateDataLanguages.removeAssociation(matcher, oldLanguage); - } else { + } + else { return; } } @@ -345,16 +349,13 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable public static class RecognizedFileTypes extends JPanel { private JList myFileTypesList; - private JButton myAddButton; - private JButton myEditButton; - private JButton myRemoveButton; - private JPanel myWholePanel; - private JButton myExportButton; - private JButton myImportButton; + private FileTypeConfigurable myController; public RecognizedFileTypes() { super(new BorderLayout()); - add(myWholePanel, BorderLayout.CENTER); + + myFileTypesList = new JBList(new DefaultListModel()); + myFileTypesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); myFileTypesList.setCellRenderer(new FileTypeRenderer(myFileTypesList.getCellRenderer(), new FileTypeRenderer.FileTypeListProvider() { public Iterable getCurrentFileTypeList() { ArrayList result = new ArrayList(); @@ -364,16 +365,80 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable return result; } })); - myFileTypesList.setModel(new DefaultListModel()); + myFileTypesList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) myController.editFileType(); + } + }); - if (getSchemesManager().isImportAvailable()) { - myImportButton.setVisible(true); - } - if (getSchemesManager().isExportAvailable()) { - myExportButton.setVisible(true); - } + ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myFileTypesList) + .setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.addFileType(); + } + }).setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.removeFileType(); + } + }).setEditAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.editFileType(); + } + }).setEditActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + final FileType fileType = getSelectedFileType(); + return canBeModified(fileType); + } + }).setRemoveActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + final FileType fileType = getSelectedFileType(); + final boolean modified = canBeModified(fileType); + final boolean shared = getSchemesManager().isShared(fileType); + return shared || modified; + } + }).disableUpDownActions(); + //if (getSchemesManager().isImportAvailable()) { + toolbarDecorator.addExtraAction(new AnActionButton("Import Shared...", IconUtil.getImportIcon()) { + @Override + public void actionPerformed(AnActionEvent e) { + new SchemesToImportPopup(myFileTypesList) { + protected void onSchemeSelected(final AbstractFileType scheme) { + myController.importFileType(scheme); + } + }.show(getSchemesManager(), collectRegisteredFileTypes()); + } + }); + //} + + //if (getSchemesManager().isExportAvailable()) { + toolbarDecorator.addExtraAction(new AnActionButton("Share...", IconUtil.getExportIcon()) { + @Override + public void actionPerformed(AnActionEvent e) { + FileType selected = (FileType)myFileTypesList.getSelectedValue(); + if (selected instanceof AbstractFileType) { + ExportSchemeAction.doExport((AbstractFileType)selected, getSchemesManager()); + } + } + + @Override + public void updateButton(AnActionEvent e) { + FileType fileType = getSelectedFileType(); + boolean b = canBeModified(fileType); + boolean shared = getSchemesManager().isShared(fileType); + setEnabled(b && !shared); + } + }); + //} + + add(toolbarDecorator.createPanel(), BorderLayout.CENTER); + setBorder(IdeBorderFactory.createTitledBorder(FileTypesBundle.message("filetypes.recognized.group"), false)); } private SchemesManager getSchemesManager() { @@ -381,58 +446,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable } public void attachActions(final FileTypeConfigurable controller) { - myAddButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - controller.addFileType(); - } - }); - myEditButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - controller.editFileType(); - } - }); - myFileTypesList.addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - FileType fileType = getSelectedFileType(); - boolean b = canBeModified(fileType); - myEditButton.setEnabled(b); - myRemoveButton.setEnabled(b); - boolean shared = getSchemesManager().isShared(fileType); - myExportButton.setEnabled(b && !shared); - if (shared) { - myRemoveButton.setEnabled(true); - } - } - }); - myRemoveButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - controller.removeFileType(); - } - }); - myFileTypesList.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) controller.editFileType(); - } - }); - - myImportButton.addActionListener(new ActionListener(){ - public void actionPerformed(final ActionEvent e) { - new SchemesToImportPopup(myWholePanel){ - protected void onSchemeSelected(final AbstractFileType scheme) { - controller.importFileType(scheme); - } - }.show(getSchemesManager(), collectRegisteredFileTypes()); - } - }); - - myExportButton.addActionListener(new ActionListener(){ - public void actionPerformed(final ActionEvent e) { - FileType selected = (FileType)myFileTypesList.getSelectedValue(); - if (selected instanceof AbstractFileType) { - ExportSchemeAction.doExport((AbstractFileType)selected, getSchemesManager()); - } - } - }); + myController = controller; } private Collection collectRegisteredFileTypes() { @@ -448,7 +462,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable } public JComponent getComponent() { - return myWholePanel; + return this; } public void setFileTypes(FileType[] types) { @@ -489,13 +503,10 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable updateFileTypeList(); updateExtensionList(); myRecognizedFileType.selectFileType(type); - } public static class PatternsPanel extends JPanel { private JBList myPatternsList; - private JComponent myAddButton; - private JPanel myWholePanel; private FileTypeConfigurable myController; public PatternsPanel() { @@ -505,27 +516,25 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable myPatternsList.setCellRenderer(new ExtensionRenderer()); myPatternsList.getEmptyText().setText(FileTypesBundle.message("filetype.settings.no.patterns")); - myWholePanel = ToolbarDecorator.createDecorator(myPatternsList) - .setAddAction(new AnActionButtonRunnable() { - @Override - public void run(AnActionButton button) { - myController.addPattern(); - } - }).setEditAction(new AnActionButtonRunnable() { - @Override - public void run(AnActionButton button) { - myController.editPattern(); - } - }).setRemoveAction(new AnActionButtonRunnable() { - @Override - public void run(AnActionButton button) { - myController.removePattern(); - } - }).disableUpDownActions().createPanel(); - UIUtil.addBorder(myWholePanel, IdeBorderFactory.createTitledBorder(FileTypesBundle.message("filetype.registered.patterns.group"), false)); - myAddButton = ToolbarDecorator.findAddButton(myWholePanel).getContextComponent(); + add(ToolbarDecorator.createDecorator(myPatternsList) + .setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.addPattern(); + } + }).setEditAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.editPattern(); + } + }).setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + myController.removePattern(); + } + }).disableUpDownActions().createPanel(), BorderLayout.CENTER); - add(myWholePanel, BorderLayout.CENTER); + setBorder(IdeBorderFactory.createTitledBorder(FileTypesBundle.message("filetype.registered.patterns.group"), false)); } public void attachActions(final FileTypeConfigurable controller) { @@ -533,7 +542,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable } public JComponent getComponent() { - return myWholePanel; + return this; } public void clearList() { diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/RecognizedFileTypes.form b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/RecognizedFileTypes.form deleted file mode 100644 index c633e980ad11..000000000000 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/RecognizedFileTypes.form +++ /dev/null @@ -1,82 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/platform/platform-api/src/com/intellij/openapi/startup/StartupManager.java b/platform/platform-api/src/com/intellij/openapi/startup/StartupManager.java index 25f8624a5339..2c6cef0f7e65 100644 --- a/platform/platform-api/src/com/intellij/openapi/startup/StartupManager.java +++ b/platform/platform-api/src/com/intellij/openapi/startup/StartupManager.java @@ -58,6 +58,7 @@ public abstract class StartupManager { * progress bar is displayed. You may access the PSI structures from the activity. * * @param runnable the activity to execute. + * @see StartupActivity#POST_STARTUP_ACTIVITY */ public abstract void registerPostStartupActivity(@NotNull Runnable runnable); diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java index f50793c7edd5..54d27084edef 100644 --- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.table.TableView; import com.intellij.util.ui.ElementProducer; @@ -78,6 +79,7 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan private Dimension myPreferredSize; private CommonActionsPanel myPanel; private Comparator myButtonComparator; + private boolean myAsTopToolbar = false; protected abstract JComponent getComponent(); @@ -87,33 +89,31 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan return myPanel; } - public ToolbarDecorator initPositionAndBorder() { - myToolbarPosition = UIUtil.isUnderAquaLookAndFeel() ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT; - myBorder = new CustomLineBorder(0, - myToolbarPosition == ActionToolbarPosition.RIGHT ? 1 : 0, - myToolbarPosition == ActionToolbarPosition.TOP ? 1 : 0, - myToolbarPosition == ActionToolbarPosition.LEFT ? 1 : 0); - final JComponent c = getComponent(); - if (c != null) { - c.setBorder(IdeBorderFactory.createEmptyBorder(0)); - } + public ToolbarDecorator initPosition() { + setToolbarPosition(SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT); + return this; + } + + public ToolbarDecorator setAsTopToolbar() { + myAsTopToolbar = true; + setToolbarPosition(ActionToolbarPosition.TOP); return this; } public static ToolbarDecorator createDecorator(@NotNull JTable table) { - return new TableToolbarDecorator(table, null).initPositionAndBorder(); + return new TableToolbarDecorator(table, null).initPosition(); } public static ToolbarDecorator createDecorator(@NotNull JTree tree) { - return new TreeToolbarDecorator(tree).initPositionAndBorder(); + return new TreeToolbarDecorator(tree).initPosition(); } public static ToolbarDecorator createDecorator(@NotNull JList list) { - return new ListToolbarDecorator(list).initPositionAndBorder(); + return new ListToolbarDecorator(list).initPosition(); } public static ToolbarDecorator createDecorator(@NotNull TableView table, @Nullable ElementProducer producer) { - return new TableToolbarDecorator(table, producer).initPositionAndBorder(); + return new TableToolbarDecorator(table, producer).initPosition(); } public ToolbarDecorator disableAddAction() { @@ -301,9 +301,15 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan installUpdaters(); updateButtons(); installDnD(); - panel.setBorder(new LineBorder(UIUtil.getBorderColor())); panel.putClientProperty(ActionToolbar.ACTION_TOOLBAR_PROPERTY_KEY, myPanel.getComponent(0)); DataManager.registerDataProvider(panel, this); + if (!myAsTopToolbar) { + panel.setBorder(new LineBorder(UIUtil.getBorderColor())); + final JComponent c = getComponent(); + if (contextComponent != null) { + contextComponent.setBorder(IdeBorderFactory.createEmptyBorder(0)); + } + } return panel; } diff --git a/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java index 99d71127a323..667d89a274d6 100644 --- a/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/TreeToolbarDecorator.java @@ -31,9 +31,8 @@ class TreeToolbarDecorator extends ToolbarDecorator { } @Override - public ToolbarDecorator initPositionAndBorder() { - return super.initPositionAndBorder() - .setToolbarPosition(SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.TOP); + public ToolbarDecorator initPosition() { + return setToolbarPosition(SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.TOP); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeEditor.java b/platform/platform-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeEditor.java index f82cdebc9c6c..5cc6a593a1bb 100644 --- a/platform/platform-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeEditor.java +++ b/platform/platform-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeEditor.java @@ -24,6 +24,7 @@ import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.components.JBList; +import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -136,25 +137,10 @@ public class CustomFileTypeEditor extends SettingsEditor { JPanel panel = new JPanel(new BorderLayout()); JPanel fileTypePanel = new JPanel(new BorderLayout()); - JPanel info = new JPanel(new GridBagLayout()); - GridBagConstraints gc = new GridBagConstraints(); - gc.gridx = 0; - gc.gridy = 0; - gc.anchor = GridBagConstraints.WEST; - gc.fill = GridBagConstraints.BOTH; - info.add(new JLabel(IdeBundle.message("editbox.customfiletype.name")), gc); - gc.gridx = 1; - gc.gridy = 0; - gc.weightx = 1; - info.add(myFileTypeName, gc); - - gc.weightx = 0; - gc.gridx = 0; - gc.gridy = 1; - info.add(new JLabel(IdeBundle.message("editbox.customfiletype.description")), gc); - gc.gridx = 1; - info.add(myFileTypeDescr, gc); - info.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 5)); + JPanel info = FormBuilder.createFormBuilder() + .addLabeledComponent(IdeBundle.message("editbox.customfiletype.name"), myFileTypeName) + .addLabeledComponent(IdeBundle.message("editbox.customfiletype.description"), myFileTypeDescr).getPanel(); + info.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); fileTypePanel.add(info, BorderLayout.NORTH); JPanel highlighterPanel = new JPanel(); @@ -164,10 +150,11 @@ public class CustomFileTypeEditor extends SettingsEditor { commentsAndNumbersPanel.setLayout(new GridBagLayout()); JPanel _panel1 = new JPanel(new BorderLayout()); - GridBag gb = new GridBag().setDefaultFill(GridBagConstraints.HORIZONTAL).setDefaultAnchor(GridBagConstraints.WEST).setDefaultInsets(1, - 5, - 1, - 5); + GridBag gb = new GridBag() + .setDefaultFill(GridBagConstraints.HORIZONTAL) + .setDefaultAnchor(GridBagConstraints.WEST) + .setDefaultInsets(1, 5, 1, 5); + commentsAndNumbersPanel.add(new JLabel(IdeBundle.message("editbox.customfiletype.line.comment")), gb.nextLine().next()); commentsAndNumbersPanel.add(myLineComment, gb.next()); commentsAndNumbersPanel.add(myCommentAtLineStart, gb.next().coverLine(2)); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java index 71a45bffc87c..056870f32628 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java @@ -33,7 +33,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.util.*; +import java.util.ArrayList; import java.util.List; /** @@ -135,7 +135,9 @@ public class Utils{ if (actionGroup.hideIfNoVisibleChildren() && !visibleChildren) { continue; } - presentation.setEnabled(actionGroup.canBePerformed(context) || visibleChildren); + if (!actionGroup.canBePerformed(context) && !visibleChildren) { + presentation.setEnabled(false); + } list.add(child); } else { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java index 3a983be0cc52..2e528457a167 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java @@ -21,7 +21,6 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; @@ -34,9 +33,6 @@ import com.intellij.openapi.vfs.newvfs.RefreshQueue; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; import com.intellij.util.TimeoutUtil; -import com.intellij.util.concurrency.JBLock; -import com.intellij.util.concurrency.JBReentrantReadWriteLock; -import com.intellij.util.concurrency.LockFactory; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -47,51 +43,30 @@ import java.io.IOException; import java.util.*; public final class LocalFileSystemImpl extends LocalFileSystemBase implements ApplicationComponent { - private final JBReentrantReadWriteLock LOCK = LockFactory.createReadWriteLock(); - private final JBLock WRITE_LOCK = LOCK.writeLock(); - + private final Object myLock = new Object(); private final List myRootsToWatch = new ArrayList(); - private WatchRequest[] myCachedNormalizedRequests = null; - + private WatchRequestImpl[] myCachedNormalizedRequests = null; private final FileWatcher myWatcher; private static class WatchRequestImpl implements WatchRequest { - public final String myRootPath; - - public String myFSRootPath; - public final boolean myToWatchRecursively; - boolean myDominated; + private final String myRootPath; + private final boolean myToWatchRecursively; + private String myFSRootPath; + private boolean myDominated; public WatchRequestImpl(String rootPath, final boolean toWatchRecursively) { - myToWatchRecursively = toWatchRecursively; final int index = rootPath.indexOf(JarFileSystem.JAR_SEPARATOR); if (index >= 0) rootPath = rootPath.substring(0, index); - final File file = new File(rootPath.replace('/', File.separatorChar)); - if (!file.isDirectory()) { - final File parentFile = file.getParentFile(); - if (parentFile != null) { - if (SystemInfo.isFileSystemCaseSensitive) { - myFSRootPath = parentFile.getAbsolutePath(); // fixes problem with symlinks under Unix (however does not under Windows!) - } - else { - try { - myFSRootPath = parentFile.getCanonicalPath(); - } - catch (IOException e) { - myFSRootPath = rootPath; //need something - } - } - } - else { - myFSRootPath = rootPath.replace('/', File.separatorChar); - } - myRootPath = myFSRootPath.replace(File.separatorChar, '/'); - } - else { - myRootPath = rootPath.replace(File.separatorChar, '/'); - myFSRootPath = rootPath.replace('/', File.separatorChar); + File rootFile = new File(FileUtil.toSystemDependentName(rootPath)); + if (index > 0 || !rootFile.isDirectory()) { + rootFile = rootFile.getParentFile(); + assert rootFile != null : rootPath; } + + myFSRootPath = rootFile.getAbsolutePath(); + myRootPath = FileUtil.toSystemIndependentName(myFSRootPath); + myToWatchRecursively = toWatchRecursively; } @Override @@ -100,6 +75,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap return myRootPath; } + /** @deprecated implementation details (to remove in IDEA 13) */ @Override @NotNull public String getFileSystemRootPath() { @@ -111,13 +87,10 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap return myToWatchRecursively; } + /** @deprecated implementation details (to remove in IDEA 13) */ @Override public boolean dominates(@NotNull WatchRequest other) { - if (myToWatchRecursively) { - return other.getRootPath().startsWith(myRootPath); - } - - return !other.isToWatchRecursively() && myRootPath.equals(other.getRootPath()); + return LocalFileSystemImpl.dominates(this, (WatchRequestImpl)other); } @Override @@ -160,13 +133,12 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap myRootsToWatch.clear(); } - private WatchRequest[] normalizeRootsForRefresh() { + private WatchRequestImpl[] normalizeRootsForRefresh() { if (myCachedNormalizedRequests != null) return myCachedNormalizedRequests; List result = new ArrayList(); // No need to call for a read action here since we're only called with it on hands already. - WRITE_LOCK.lock(); - try { + synchronized (myLock) { NextRoot: for (WatchRequestImpl request : myRootsToWatch) { String rootPath = request.getRootPath(); @@ -189,20 +161,17 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap request.myDominated = false; } } - finally { - WRITE_LOCK.unlock(); - } - myCachedNormalizedRequests = result.toArray(new WatchRequest[result.size()]); + myCachedNormalizedRequests = result.toArray(new WatchRequestImpl[result.size()]); return myCachedNormalizedRequests; } private void storeRefreshStatusToFiles() { - if (FileWatcher.getInstance().isOperational()) { + if (myWatcher.isOperational()) { // TODO: different ways to mark dirty for all these cases - markPathsDirty(FileWatcher.getInstance().getDirtyPaths()); - markFlatDirsDirty(FileWatcher.getInstance().getDirtyDirs()); - markRecursiveDirsDirty(FileWatcher.getInstance().getDirtyRecursivePaths()); + markPathsDirty(myWatcher.getDirtyPaths()); + markFlatDirsDirty(myWatcher.getDirtyDirs()); + markRecursiveDirsDirty(myWatcher.getDirtyRecursivePaths()); } } @@ -269,26 +238,22 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap application.runReadAction(new Runnable() { @Override public void run() { - WRITE_LOCK.lock(); - try { - final WatchRequest[] watchRequests = normalizeRootsForRefresh(); + synchronized (myLock) { + final WatchRequestImpl[] watchRequests = normalizeRootsForRefresh(); List myRecursiveRoots = new ArrayList(); List myFlatRoots = new ArrayList(); - for (WatchRequest root : watchRequests) { + for (WatchRequestImpl root : watchRequests) { if (root.isToWatchRecursively()) { - myRecursiveRoots.add(root.getFileSystemRootPath()); + myRecursiveRoots.add(root.myFSRootPath); } else { - myFlatRoots.add(root.getFileSystemRootPath()); + myFlatRoots.add(root.myFSRootPath); } } myWatcher.setWatchRoots(myRecursiveRoots, myFlatRoots); } - finally { - WRITE_LOCK.unlock(); - } } }); } @@ -298,8 +263,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap private static final long PERIOD = 1000; public StoreRefreshStatusThread() { - //noinspection HardCodedStringLiteral - super("StoreRefreshStatusThread"); + super(StoreRefreshStatusThread.class.getSimpleName()); setPriority(MIN_PRIORITY); setDaemon(true); } @@ -324,14 +288,13 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap @Override public WatchRequest addRootToWatch(@NotNull final String rootPath, final boolean toWatchRecursively) { - if (rootPath.length() == 0 || !FileWatcher.getInstance().isOperational()) return null; + if (rootPath.length() == 0 || !myWatcher.isOperational()) return null; Application app = ApplicationManager.getApplication(); return app.runReadAction(new Computable() { @Override public WatchRequest compute() { - WRITE_LOCK.lock(); - try { + synchronized (myLock) { final WatchRequestImpl result = new WatchRequestImpl(rootPath, toWatchRecursively); boolean alreadyWatched = isAlreadyWatched(result); if (!alreadyWatched) { @@ -355,24 +318,29 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap setUpFileWatcher(); return result; } - finally { - WRITE_LOCK.unlock(); - } } }); } - private boolean isAlreadyWatched(final WatchRequest request) { - for (final WatchRequest current : normalizeRootsForRefresh()) { - if (current.dominates(request)) return true; + private boolean isAlreadyWatched(final WatchRequestImpl request) { + for (final WatchRequestImpl current : normalizeRootsForRefresh()) { + if (dominates(current, request)) return true; } return false; } + private static boolean dominates(final WatchRequestImpl request, final WatchRequestImpl other) { + if (request.myToWatchRecursively) { + return other.myRootPath.startsWith(request.myRootPath); + } + + return !other.myToWatchRecursively && request.myRootPath.equals(other.myRootPath); + } + @Override @NotNull public Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean toWatchRecursively) { - if (!FileWatcher.getInstance().isOperational()) return Collections.emptySet(); + if (!myWatcher.isOperational()) return Collections.emptySet(); final Set result = new HashSet(); final Set filesToSynchronize = new HashSet(); @@ -380,8 +348,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap Application application = ApplicationManager.getApplication(); application.runReadAction(new Runnable() { public void run() { - WRITE_LOCK.lock(); - try { + synchronized (myLock) { for (String rootPath : rootPaths) { LOG.assertTrue(rootPath != null); if (rootPath.length() > 0) { @@ -399,9 +366,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap myCachedNormalizedRequests = null; setUpFileWatcher(); } - finally { - WRITE_LOCK.unlock(); - } } }); @@ -421,16 +385,12 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap public void removeWatchedRoot(@NotNull final WatchRequest watchRequest) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { - WRITE_LOCK.lock(); - try { + synchronized (myLock) { if (myRootsToWatch.remove((WatchRequestImpl)watchRequest) && !((WatchRequestImpl)watchRequest).myDominated) { myCachedNormalizedRequests = null; setUpFileWatcher(); } } - finally { - WRITE_LOCK.unlock(); - } } }); } @@ -439,16 +399,12 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap public void removeWatchedRoots(@NotNull final Collection rootsToWatch) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { - WRITE_LOCK.lock(); - try { + synchronized (myLock) { if (myRootsToWatch.removeAll(rootsToWatch)) { myCachedNormalizedRequests = null; setUpFileWatcher(); } } - finally { - WRITE_LOCK.unlock(); - } } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index c7b2b88a308c..6f8f8bf192fb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -195,26 +195,32 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private static final boolean IS_UNDER_TEAMCITY = System.getProperty("bootstrap.testcases") != null; - private static final boolean SHOULD_PERFORM_ACCESS_CHECK = System.getenv("NO_FS_ROOTS_ACCESS_CHECK") == null; - private static final boolean IS_UNIT_TESTS = ApplicationManager.getApplication().isUnitTestMode(); - - - private static final Collection additionalRoots = new THashSet(); + private static final Collection ourAdditionalRoots = new THashSet(); @TestOnly - public static void allowToAccess(@NotNull String root) { - additionalRoots.add(FileUtil.toSystemIndependentName(root)); + public static void allowRootAccess(@NotNull String... roots) { + for (String root : roots) { + ourAdditionalRoots.add(FileUtil.toSystemIndependentName(root)); + } + } + + @TestOnly + public static void disallowRootAccess(@NotNull String... roots) { + for (String root : roots) { + ourAdditionalRoots.remove(FileUtil.toSystemIndependentName(root)); + } } @TestOnly private static void assertAccessInTests(VirtualFileSystemEntry child) { - if (IS_UNIT_TESTS && - IS_UNDER_TEAMCITY && - ApplicationManager.getApplication() instanceof ApplicationImpl && - ((ApplicationImpl)ApplicationManager.getApplication()).isComponentsCreated() && - SHOULD_PERFORM_ACCESS_CHECK) { + final Application application = ApplicationManager.getApplication(); + if (IS_UNDER_TEAMCITY && + SHOULD_PERFORM_ACCESS_CHECK && + application.isUnitTestMode() && + application instanceof ApplicationImpl && + ((ApplicationImpl)application).isComponentsCreated()) { NewVirtualFileSystem fileSystem = child.getFileSystem(); if (fileSystem != LocalFileSystem.getInstance() && fileSystem != JarFileSystem.getInstance()) { return; @@ -256,25 +262,25 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { @Nullable private static Set allowedRoots() { if (insideGettingRoots) return null; + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length == 0) return null; + final Set allowed = new THashSet(); - String homePath = PathManager.getHomePath(); - allowed.add(FileUtil.toSystemIndependentName(homePath)); + allowed.add(FileUtil.toSystemIndependentName(PathManager.getHomePath())); + try { URL outUrl = Application.class.getResource("/"); String output = new File(outUrl.toURI()).getParentFile().getParentFile().getPath(); allowed.add(FileUtil.toSystemIndependentName(output)); } catch (URISyntaxException ignored) { } - String javaHome = SystemProperties.getJavaHome(); - allowed.add(FileUtil.toSystemIndependentName(javaHome)); - String tempDirectorySpecific = new File(FileUtil.getTempDirectory()).getParent(); - allowed.add(FileUtil.toSystemIndependentName(tempDirectorySpecific)); - String tempDirectory = System.getProperty("java.io.tmpdir"); - allowed.add(FileUtil.toSystemIndependentName(tempDirectory)); - String userHome = SystemProperties.getUserHome(); - allowed.add(FileUtil.toSystemIndependentName(userHome)); + + allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getJavaHome())); + allowed.add(FileUtil.toSystemIndependentName(new File(FileUtil.getTempDirectory()).getParent())); + allowed.add(FileUtil.toSystemIndependentName(System.getProperty("java.io.tmpdir"))); + allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getUserHome())); + for (Project project : openProjects) { if (!project.isInitialized()) { return null; // all is allowed @@ -290,12 +296,8 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { allowed.add(FileUtil.toSystemIndependentName(location)); } - //for (Sdk sdk : ProjectJdkTable.getInstance().getAllJdks()) { - // allowed.add(FileUtil.toSystemIndependentName(sdk.getHomePath())); - //} - for (String root : additionalRoots) { - allowed.add(root); - } + allowed.addAll(ourAdditionalRoots); + return allowed; } @@ -303,20 +305,19 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private static VirtualFile[] getAllRoots(Project project) { insideGettingRoots = true; - Set roots = new THashSet(); + final Set roots = new THashSet(); + final Module[] modules = ModuleManager.getInstance(project).getModules(); for (Module module : modules) { final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries(); for (OrderEntry entry : orderEntries) { - VirtualFile[] files = entry.getFiles(OrderRootType.CLASSES); - ContainerUtil.addAll(roots, files); - files = entry.getFiles(OrderRootType.SOURCES); - ContainerUtil.addAll(roots, files); - files = entry.getFiles(OrderRootType.CLASSES_AND_OUTPUT); - ContainerUtil.addAll(roots, files); + ContainerUtil.addAll(roots, entry.getFiles(OrderRootType.CLASSES)); + ContainerUtil.addAll(roots, entry.getFiles(OrderRootType.SOURCES)); + ContainerUtil.addAll(roots, entry.getFiles(OrderRootType.CLASSES_AND_OUTPUT)); } } + insideGettingRoots = false; return VfsUtil.toVirtualFileArray(roots); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java index 074522040598..533f55ef7733 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vfs.local; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.idea.Bombed; +import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; @@ -27,6 +28,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.testFramework.PlatformLangTestCase; import com.intellij.util.Function; import com.intellij.util.TimeoutUtil; @@ -35,6 +37,7 @@ import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; import java.io.File; +import java.io.IOException; import java.util.*; public class FileWatcherTest extends PlatformLangTestCase { @@ -104,7 +107,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(file); + delete(file); } } @@ -131,7 +134,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(file); + delete(file); } } @@ -159,7 +162,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(topDir); + delete(topDir); } } @@ -180,7 +183,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(topDir); + delete(topDir); } } @@ -201,7 +204,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(topDir); + delete(topDir); } } @@ -246,7 +249,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoots(Arrays.asList(request1, request2)); - FileUtil.delete(topDir); + delete(topDir); } } @@ -273,8 +276,8 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(topLink); - FileUtil.delete(topDir); + delete(topLink); + delete(topDir); } } @@ -302,8 +305,8 @@ public class FileWatcherTest extends PlatformLangTestCase { } finally { myFileSystem.removeWatchedRoot(request); - FileUtil.delete(linkDir); - FileUtil.delete(targetDir); + delete(linkDir); + delete(targetDir); } } @@ -334,32 +337,40 @@ public class FileWatcherTest extends PlatformLangTestCase { final int rv = new GeneralCommandLine("subst", subst + ":", targetDir.getAbsolutePath()).createProcess().waitFor(); assertEquals(0, rv); - final File substDir = new File((subst + ":\\").toUpperCase(Locale.US), subDir.getName()); - final File substFile = new File(substDir, file.getName()); - refresh(targetDir); - refresh(substDir); + final String substRoot = (subst + ":\\").toUpperCase(Locale.US); + VirtualDirectoryImpl.allowRootAccess(substRoot); - final LocalFileSystem.WatchRequest request = watch(substDir); try { - FileUtil.writeToFile(file, "new content"); - assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath()); + final File substDir = new File(substRoot, subDir.getName()); + final File substFile = new File(substDir, file.getName()); + refresh(targetDir); + refresh(substDir); - final LocalFileSystem.WatchRequest request2 = watch(targetDir); + final LocalFileSystem.WatchRequest request = watch(substDir); try { - FileUtil.delete(file); - assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath()); + FileUtil.writeToFile(file, "new content"); + assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath()); + + final LocalFileSystem.WatchRequest request2 = watch(targetDir); + try { + FileUtil.delete(file); + assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath()); + } + finally { + unwatch(request2); + } + + FileUtil.writeToFile(file, "re-creation"); + assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath()); } finally { - unwatch(request2); + myFileSystem.removeWatchedRoot(request); } - - FileUtil.writeToFile(file, "re-creation"); - assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath()); } finally { - myFileSystem.removeWatchedRoot(request); + VirtualDirectoryImpl.disallowRootAccess(substRoot); + delete(targetDir); new GeneralCommandLine("subst", subst + ":", "/d").createProcess().waitFor(); - FileUtil.delete(targetDir); } } @@ -415,6 +426,22 @@ public class FileWatcherTest extends PlatformLangTestCase { return vFile; } + private void delete(@NotNull final File file) throws IOException { + final VirtualFile vFile = myFileSystem.findFileByIoFile(file); + if (vFile != null) { + final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); + try { + vFile.delete(this); + } + finally { + token.finish(); + } + } + if (file.exists()) { + FileUtil.delete(file); + } + } + private void assertEvent(final Class type, final String... paths) throws InterruptedException { final List events = getEvents(); assertEquals(events.toString(), paths.length, events.size()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ConstantZipperUpdater.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ConstantZipperUpdater.java new file mode 100644 index 000000000000..45ff0abf4ec8 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ConstantZipperUpdater.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.vcs; + +import com.intellij.openapi.Disposable; +import com.intellij.util.Alarm; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 4/11/12 + * Time: 3:10 PM + */ +public class ConstantZipperUpdater { + private final ZipperUpdater myZipperUpdater; + private final Runnable myRunnable; + + public ConstantZipperUpdater(final int delay, final Alarm.ThreadToUse threadToUse, final Disposable parentDisposable, + final Runnable runnable) { + myRunnable = runnable; + myZipperUpdater = new ZipperUpdater(delay, threadToUse, parentDisposable); + } + + public void request() { + myZipperUpdater.queue(myRunnable); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeVfsListener.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeVfsListener.java index 91969e3058fe..352ad57981b2 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeVfsListener.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeVfsListener.java @@ -20,12 +20,15 @@ import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectLocator; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vcs.ConstantZipperUpdater; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.ZipperUpdater; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.*; +import com.intellij.util.Alarm; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.messages.MessageBusConnection; @@ -34,6 +37,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -49,10 +53,45 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL private final MessageBusConnection myMessageBusConnection; // for tests only private boolean myForbid; + private final ConstantZipperUpdater myZipperUpdater; + private final List myQueue; + private final Object myLock; public VcsDirtyScopeVfsListener() { myProjectLocator = ProjectLocator.getInstance(); myMessageBusConnection = ApplicationManager.getApplication().getMessageBus().connect(); + myLock = new Object(); + myQueue = new ArrayList(); + myZipperUpdater = new ConstantZipperUpdater(300, Alarm.ThreadToUse.SHARED_THREAD, ApplicationManager.getApplication(), + new Runnable() { + @Override + public void run() { + ArrayList list; + synchronized (myLock) { + list = new ArrayList(myQueue); + myQueue.clear(); + } + Map, HashSet>> map = + new HashMap, HashSet>>(); + for (FileAndDirsCollector collector : list) { + Map, HashSet>> pairMap = + collector.map; + for (Map.Entry, HashSet>> entry : pairMap + .entrySet()) { + final VcsDirtyScopeManager key = entry.getKey(); + Pair, HashSet> existing = map.get(key); + Pair, HashSet> value = entry.getValue(); + if (existing != null) { + existing.getFirst().addAll(value.getFirst()); + existing.getSecond().addAll(value.getSecond()); + } else { + map.put(key, value); + } + } + } + new FileAndDirsCollector().markDirty(map); + } + }); } public void setForbid(boolean forbid) { @@ -130,14 +169,10 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL } private void markDirtyOnPooled(final FileAndDirsCollector dirtyFilesAndDirs) { - if (! dirtyFilesAndDirs.isEmpty()) { - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - dirtyFilesAndDirs.markDirty(); - } - }); + synchronized (myLock) { + myQueue.add(dirtyFilesAndDirs); } + myZipperUpdater.request(); } @Nullable @@ -201,7 +236,11 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL } void markDirty() { - for (Map.Entry, HashSet>> entry : map.entrySet()) { + markDirty(map); + } + + void markDirty(final Map, HashSet>> outerMap) { + for (Map.Entry, HashSet>> entry : outerMap.entrySet()) { VcsDirtyScopeManager manager = entry.getKey(); HashSet files = entry.getValue().first; HashSet dirs = entry.getValue().second; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java index c8b4d9e78e9a..b30e1467d767 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java @@ -360,36 +360,25 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements removeMapping(); updateRootCheckers(); } + }).setAddActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + return !myIsDisabled; + } + }).setEditActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + final boolean hasSelection = myDirectoryMappingTable.getSelectedObject() != null; + return (!myIsDisabled) && hasSelection; + } + }).setRemoveActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + final boolean hasSelection = myDirectoryMappingTable.getSelectedObject() != null; + return (!myIsDisabled) && hasSelection; + } }).disableUpDownActions().createPanel(); - - AnActionButton addButton = ToolbarDecorator.findAddButton(panelForTable); - assert addButton != null; - addButton.addCustomUpdater(new AnActionButtonUpdater() { - @Override - public boolean isEnabled(AnActionEvent e) { - return !myIsDisabled; - } - }); - - AnActionButton editButton = ToolbarDecorator.findEditButton(panelForTable); - assert editButton != null; - editButton.addCustomUpdater(new AnActionButtonUpdater() { - @Override - public boolean isEnabled(AnActionEvent e) { - final boolean hasSelection = myDirectoryMappingTable.getSelectedObject() != null; - return (!myIsDisabled) && hasSelection; - } - }); - - AnActionButton removeButton = ToolbarDecorator.findRemoveButton(panelForTable); - assert removeButton != null; - removeButton.addCustomUpdater(new AnActionButtonUpdater() { - @Override - public boolean isEnabled(AnActionEvent e) { - final boolean hasSelection = myDirectoryMappingTable.getSelectedObject() != null; - return (!myIsDisabled) && hasSelection; - } - }); + panelForTable.setPreferredSize(new Dimension(-1, 200)); return panelForTable; } @@ -523,8 +512,9 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements VcsRootErrorLabel(String title) { super(new BorderLayout(DEFAULT_HGAP, DEFAULT_VGAP)); - CompoundBorder outsideBorder = BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(5, 0, 5, 0, UIUtil.getPanelBackground()), - BorderFactory.createLineBorder(UIUtil.getPanelBackground().darker())); + CompoundBorder outsideBorder = + BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(5, 0, 5, 0, UIUtil.getPanelBackground()), + BorderFactory.createLineBorder(UIUtil.getPanelBackground().darker())); setBorder(BorderFactory.createCompoundBorder(outsideBorder, BorderFactory.createEmptyBorder(DEFAULT_VGAP, DEFAULT_HGAP, DEFAULT_VGAP, DEFAULT_HGAP))); setOpaque(true); @@ -553,5 +543,4 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements }, null); } } - } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java index 71613ab35ee3..86dc3940cd42 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java @@ -36,7 +36,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstract implements Configurable.NoScroll { +public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstract { public static final Icon ICON = IconLoader.getIcon("/general/configurableVcs.png"); private final Project myProject; private VcsDirectoryConfigurationPanel myMappings; diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java index 0f2f668a5caf..a000949f1ce6 100644 --- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java @@ -218,9 +218,11 @@ public class GitSSHXmlRpcClient implements GitSSHHandler { return (String)myClient.execute(methodName("getLastSuccessful"), parameters); } catch (XmlRpcException e) { + log("getLastSuccessful failed. handlerNo: " + handlerNo + ", userName: " + userName + ", client: " + myClient.getURL()); throw new RuntimeException("Invocation failed " + e.getMessage(), e); } catch (IOException e) { + log("getLastSuccessful failed. handlerNo: " + handlerNo + ", userName: " + userName + ", client: " + myClient.getURL()); throw new RuntimeException("Invocation failed " + e.getMessage(), e); } } @@ -248,4 +250,8 @@ public class GitSSHXmlRpcClient implements GitSSHHandler { private static Vector adjustNull(final Vector s) { return s.size() == 0 ? null : s; } + + private static void log(String s) { + System.err.println(s); + } } diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java index 5799db2270f4..82dace3f7910 100644 --- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java @@ -573,5 +573,12 @@ public class SSHConfig { private static T mergeValue(T first, T second) { return first == null ? second : first; } + + @Override + public String toString() { + return String.format("Host{myUser='%s', myHostName='%s', myPort=%d, myIdentityFile='%s'}", + myUser, myHostName, myPort, myIdentityFile); + } + } } diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java index 858a2d3e0317..46c3fdf131bd 100644 --- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java @@ -191,8 +191,9 @@ public class SSHMain { */ private void authenticate(final Connection c) throws IOException { LinkedList methods = new LinkedList(myHost.getPreferredMethods()); + //log("authenticating... " + this); String lastSuccessfulMethod = myXmlRpcClient.getLastSuccessful(myHandlerNo, getUserHostString()); - System.err.println("SSH: authentication methods: " + methods + " last successful method: " + lastSuccessfulMethod); + //log("SSH: authentication methods: " + methods + " last successful method: " + lastSuccessfulMethod); if (lastSuccessfulMethod != null && lastSuccessfulMethod.length() > 0 && methods.remove(lastSuccessfulMethod)) { methods.addFirst(lastSuccessfulMethod); } @@ -588,4 +589,15 @@ public class SSHMain { } } } + + @Override + public String toString() { + return String + .format("SSHMain{myHost=%s, myHandlerNo=%d, myCommand='%s', myExitCode=%d, myLastError='%s'}", myHost, myHandlerNo, myCommand, + myExitCode, myLastError); + } + + private static void log(String s) { + System.err.println(s); + } } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index fbd6d581fa36..f08a21597a60 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -399,7 +399,9 @@ public abstract class GitHandler { myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject)); myEnvironmentCleanedUp = false; myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(myHandlerNo)); - myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(ssh.getXmlRcpPort())); + int port = ssh.getXmlRcpPort(); + myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port)); + LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port)); } myCommandLine.setEnvParams(myEnv); // start process diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java index c46daa9e26b6..5b8a55bc7efb 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java @@ -36,6 +36,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; +import com.intellij.util.containers.CollectionFactory; import com.intellij.util.xml.*; import com.intellij.util.xml.reflect.DomCollectionChildDescription; import org.jetbrains.annotations.NotNull; @@ -50,10 +51,18 @@ import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem; import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MavenDomUtil { + + // see http://maven.apache.org/settings.html + private static final Set SUBTAGS_IN_SETTINGS_FILE = CollectionFactory.newSet("localRepository", "interactiveMode", + "usePluginRegistry", "offline", "pluginGroups", + "servers", "mirrors", "proxies", "profiles", + "activeProfiles"); + public static boolean isMavenFile(PsiFile file) { return isProjectFile(file) || isProfilesFile(file) || isSettingsFile(file); } @@ -71,14 +80,36 @@ public class MavenDomUtil { if (!(file instanceof XmlFile)) return false; String name = file.getName(); - return name.equals(MavenConstants.PROFILES_XML); + if (!name.equals(MavenConstants.PROFILES_XML)) return false; + + XmlTag rootTag = ((XmlFile)file).getRootTag(); + return rootTag != null && "profilesXml".equals(rootTag.getName()); } public static boolean isSettingsFile(PsiFile file) { if (!(file instanceof XmlFile)) return false; String name = file.getName(); - return name.equals(MavenConstants.SETTINGS_XML); + if (!name.equals(MavenConstants.SETTINGS_XML)) return false; + + XmlTag rootTag = ((XmlFile)file).getRootTag(); + if (rootTag == null || !"settings".equals(rootTag.getName())) return false; + + String xmlns = rootTag.getAttributeValue("xmlns"); + if (xmlns != null) { + return xmlns.contains("maven"); + } + + boolean hasTag = false; + + for (PsiElement e = rootTag.getFirstChild(); e != null; e = e.getNextSibling()) { + if (e instanceof XmlTag) { + if (SUBTAGS_IN_SETTINGS_FILE.contains(((XmlTag)e).getName())) return true; + hasTag = true; + } + } + + return !hasTag; } public static boolean isMavenFile(PsiElement element) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java index cc9fdd942cb0..70bd3d6942f6 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java @@ -145,7 +145,7 @@ public class MavenProjectReader { return new RawModelReadResult(result, problems, alwaysOnProfiles); } - private void readModelBody(MavenModelBase mavenModelBase, MavenBuildBase mavenBuildBase, Element xmlModel) { + private static void readModelBody(MavenModelBase mavenModelBase, MavenBuildBase mavenBuildBase, Element xmlModel) { mavenModelBase.setModules(MavenJDOMUtil.findChildrenValuesByPath(xmlModel, "modules", "module")); collectProperties(MavenJDOMUtil.findChildByPath(xmlModel, "properties"), mavenModelBase); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java index 2dbefe8798d4..3e9bf7f92ddd 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java @@ -23,7 +23,9 @@ import org.jetbrains.idea.maven.utils.actions.MavenAction; import org.jetbrains.idea.maven.utils.actions.MavenActionUtil; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class ToggleProfileAction extends MavenAction { public void update(AnActionEvent e) { @@ -55,7 +57,7 @@ public class ToggleProfileAction extends MavenAction { return activeCount == 0 || activeCount == selectedProfiles.size(); } - private boolean isActive(MavenProjectsManager projectsManager, List profiles) { + private static boolean isActive(MavenProjectsManager projectsManager, List profiles) { return projectsManager.getExplicitProfiles().contains(profiles.get(0)); } @@ -64,7 +66,7 @@ public class ToggleProfileAction extends MavenAction { MavenProjectsManager manager = MavenActionUtil.getProjectsManager(e.getDataContext()); List selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES); - Collection activeProfiles = manager.getExplicitProfiles(); + Set activeProfiles = new HashSet(manager.getExplicitProfiles()); if (isActive(manager, selectedProfiles)) { activeProfiles.removeAll(selectedProfiles); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java index 707fae5105a6..1b4721e121a0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java @@ -33,8 +33,6 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import static com.intellij.openapi.util.text.StringUtil.isEmptyOrSpaces; - public class MavenJDOMUtil { @Nullable public static Element read(final VirtualFile file, @Nullable final ErrorHandler handler) { @@ -95,7 +93,7 @@ public class MavenJDOMUtil { public void endTag(CharSequence localName, String namespace, int startoffset, int endoffset) { String name = localName.toString(); - if (isEmptyOrSpaces(name)) return; + if (StringUtil.isEmptyOrSpaces(name)) return; int index = -1; for (int i = stack.size() - 1; i >= 0; i--) { @@ -129,22 +127,27 @@ public class MavenJDOMUtil { return result[0]; } + @Nullable public static Element findChildByPath(@Nullable Element element, String path) { - if (element == null) return null; + int i = 0; + while (element != null) { + int dot = path.indexOf('.', i); + if (dot == -1) { + return element.getChild(path.substring(i)); + } - List parts = StringUtil.split(path, "."); - Element current = element; - for (String each : parts) { - current = current.getChild(each); - if (current == null) break; + element = element.getChild(path.substring(i, dot)); + i = dot + 1; } - return current; + + return null; } public static String findChildValueByPath(@Nullable Element element, String path, String defaultValue) { Element child = findChildByPath(element, path); - String childValue = child == null ? null : child.getTextTrim(); - return StringUtil.isEmptyOrSpaces(childValue) ? defaultValue : childValue; + if (child == null) return defaultValue; + String childValue = child.getTextTrim(); + return childValue.isEmpty() ? defaultValue : childValue; } public static String findChildValueByPath(@Nullable Element element, String path) { @@ -163,7 +166,7 @@ public class MavenJDOMUtil { List result = new ArrayList(); for (Element each : findChildrenByPath(element, path, childrenName)) { String value = each.getTextTrim(); - if (!StringUtil.isEmptyOrSpaces(value)) { + if (!value.isEmpty()) { result.add(value); } } @@ -173,13 +176,20 @@ public class MavenJDOMUtil { private static List collectChildren(@Nullable Element container, String subPath) { if (container == null) return Collections.emptyList(); - List subParts = StringUtil.split(subPath, "."); - String childName = subParts.get(0); - String pathInChild = subParts.size() > 1 ? StringUtil.join(subParts.subList(1, subParts.size()), ".") : null; + int firstDot = subPath.indexOf('.'); + + if (firstDot == -1) { + //noinspection unchecked + return (List)container.getChildren(subPath); + } + + String childName = subPath.substring(0, firstDot); + String pathInChild = subPath.substring(firstDot + 1); List result = new ArrayList(); + //noinspection unchecked for (Element each : (Iterable)container.getChildren(childName)) { - Element child = pathInChild == null ? each : findChildByPath(each, pathInChild); + Element child = findChildByPath(each, pathInChild); if (child != null) result.add(child); } return result; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index 30e6488daec5..39c77be94815 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -101,7 +101,7 @@ public class SvnHistoryProvider @Override protected void updateButtons() { } - }.initPositionAndBorder() + }.initPosition() .addExtraAction(AnActionButton.fromAction(sourceAction)) .createPanel(); fieldPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.TOP));