From 8b34abad20929fec4f9f475d99cea10ec8f363aa Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 13 Nov 2012 11:19:02 +0100 Subject: [PATCH 01/24] IDEA-94442 (String concatenation inspection shall have an option to be ignored in toString() methods) --- .../siyeh/InspectionGadgetsBundle.properties | 13 +- .../StringConcatenationInspection.java | 120 ++++++------------ .../StringConcatenation.html | 2 + 3 files changed, 50 insertions(+), 85 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index f011343268f6..a5b63fad45e5 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -268,8 +268,8 @@ printstacktrace.call.display.name=Call to 'printStackTrace()' printstacktrace.call.problem.descriptor=Call to #ref() should probably be replaced with more robust logging #loc todo.comment.display.name=TODO comment todo.comment.problem.descriptor=TODO comment #ref #loc -abstract.method.call.in.constructor.display.name=Abstract method call in constructor -abstract.method.call.in.constructor.problem.descriptor=Call to abstract method #ref() during object construction #loc +abstract.method.call.in.constructor.display.name=Abstract method called during object construction +abstract.method.call.in.constructor.problem.descriptor=Call to 'abstract' method #ref() during object construction #loc instance.variable.may.not.be.initialized.display.name=Instance field may not be initialized instance.variable.may.not.be.initialized.problem.descriptor=Instance field #ref may not be initialized during object construction #loc instance.Variable.may.not.be.initialized.problem.descriptor.junit=Instance field #ref may not be initialized during object construction or 'setUp()' call #loc @@ -278,9 +278,9 @@ instance.variable.used.before.initialized.display.name=Instance field used befor instance.variable.used.before.initialized.problem.descriptor=Instance field #ref used before initialized #loc non.final.static.variable.initialization.display.name=Non-final static field is used during class initialization non.final.static.variable.initialization.problem.descriptor=Non-final static field #ref used during class initialization #loc -overridable.method.call.in.constructor.display.name=Overridable method call during object construction -overridable.method.call.in.constructor.problem.descriptor=Call to overridable method during object construction #loc -overridden.method.call.in.constructor.display.name=Overridden method call during object construction +overridable.method.call.in.constructor.display.name=Overridable method called during object construction +overridable.method.call.in.constructor.problem.descriptor=Call to overridable method #ref() during object construction #loc +overridden.method.call.in.constructor.display.name=Overridden method called during object construction overridden.method.call.in.constructor.problem.descriptor=Call to overridden method #ref() during object construction #loc static.variable.may.not.be.initialized.display.name=Static field may not be initialized static.variable.may.not.be.initialized.problem.descriptor=Static field #ref may not be initialized during class initialization #loc @@ -358,6 +358,7 @@ string.concatenation.ignore.exceptions.option=Ignore for throwable arguments string.concatenation.ignore.constant.initializers.option=Ignore for initializers of constants ignore.in.test.code=Ignore in &test code ignore.in.annotations=Ignore in annotations +ignore.in.tostring=Ignore inside toString() methods string.equalsignorecase.call.display.name=Call to 'String.equalsIgnoreCase()' string.equalsignorecase.call.problem.descriptor=String.#ref() using internationalized strings #loc string.equals.call.display.name=Call to 'String.equals()' @@ -1623,7 +1624,7 @@ unpredictable.big.decimal.constructor.call.quickfix=Replace with ''new BigDecima unnecessary.unary.minus.display.name=Unnecessary unary minus unnecessary.unary.minus.problem.descriptor=Unnecessary unary minus #loc unnecessary.unary.minus.quickfix=Remove unary minus and invert parent operation sign -make.field.final.quickfix=Make ''{0}'' final +make.field.final.quickfix=Make ''{0}'' ''final'' increment.decrement.used.as.expression.quickfix=Extract ''{0}'' to separate statement ignore.classes.in.hierarchy.column.name=Ignore subclasses of overly.strong.type.cast.ignore.in.matching.instanceof.option=Ignore casts with a matching instanceof expression diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java index 05d324243be2..74db7775a1be 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java @@ -28,6 +28,7 @@ import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.DelegatingFix; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.MethodUtils; import com.siyeh.ig.psiutils.TestUtils; import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; @@ -58,72 +59,58 @@ public class StringConcatenationInspection extends BaseInspection { @SuppressWarnings({"PublicField"}) public boolean ignoreInTestCode = false; + @SuppressWarnings("PublicField") + public boolean ignoreInToString = false; + @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "string.concatenation.display.name"); + return InspectionGadgetsBundle.message("string.concatenation.display.name"); } @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "string.concatenation.problem.descriptor"); + return InspectionGadgetsBundle.message("string.concatenation.problem.descriptor"); } @Override @NotNull protected InspectionGadgetsFix[] buildFixes(Object... infos) { - final PsiPolyadicExpression polyadicExpression = - (PsiPolyadicExpression)infos[0]; + final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)infos[0]; final Collection result = new ArrayList(); final PsiElement parent = polyadicExpression.getParent(); if (parent instanceof PsiVariable) { final PsiVariable variable = (PsiVariable)parent; - final InspectionGadgetsFix fix = new DelegatingFix( - new AddAnnotationFix(AnnotationUtil.NON_NLS, variable)); + final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, variable)); result.add(fix); } else if (parent instanceof PsiAssignmentExpression) { - final PsiAssignmentExpression assignmentExpression = - (PsiAssignmentExpression)parent; + final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent; final PsiExpression lhs = assignmentExpression.getLExpression(); if (lhs instanceof PsiReferenceExpression) { - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)lhs; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs; final PsiElement target = referenceExpression.resolve(); if (target instanceof PsiModifierListOwner) { - final PsiModifierListOwner modifierListOwner = - (PsiModifierListOwner)target; - final InspectionGadgetsFix fix = new DelegatingFix( - new AddAnnotationFix(AnnotationUtil.NON_NLS, - modifierListOwner)); + final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target; + final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, modifierListOwner)); result.add(fix); } } } final PsiExpression[] operands = polyadicExpression.getOperands(); for (PsiExpression operand : operands) { - final PsiModifierListOwner element1 = - getAnnotatableElement(operand); + final PsiModifierListOwner element1 = getAnnotatableElement(operand); if (element1 != null) { - final InspectionGadgetsFix fix = new DelegatingFix( - new AddAnnotationFix(AnnotationUtil.NON_NLS, element1)); + final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, element1)); result.add(fix); } } - final PsiElement expressionParent = PsiTreeUtil.getParentOfType( - polyadicExpression, PsiReturnStatement.class, - PsiExpressionList.class); - if (!(expressionParent instanceof PsiExpressionList) && - expressionParent != null) { - final PsiMethod method = - PsiTreeUtil.getParentOfType(expressionParent, - PsiMethod.class); + final PsiElement expressionParent = PsiTreeUtil.getParentOfType(polyadicExpression, PsiReturnStatement.class, PsiExpressionList.class); + if (!(expressionParent instanceof PsiExpressionList) && expressionParent != null) { + final PsiMethod method = PsiTreeUtil.getParentOfType(expressionParent, PsiMethod.class); if (method != null) { - final InspectionGadgetsFix fix = new DelegatingFix( - new AddAnnotationFix(AnnotationUtil.NON_NLS, method)); + final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, method)); result.add(fix); } } @@ -131,13 +118,11 @@ public class StringConcatenationInspection extends BaseInspection { } @Nullable - public static PsiModifierListOwner getAnnotatableElement( - PsiExpression expression) { + public static PsiModifierListOwner getAnnotatableElement(PsiExpression expression) { if (!(expression instanceof PsiReferenceExpression)) { return null; } - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)expression; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression; final PsiElement element = referenceExpression.resolve(); if (!(element instanceof PsiModifierListOwner)) { return null; @@ -156,6 +141,7 @@ public class StringConcatenationInspection extends BaseInspection { optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.constant.initializers.option"), "ignoreConstantInitializers"); optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.test.code"), "ignoreInTestCode"); + optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.tostring"), "ignoreInToString"); return optionsPanel; } @@ -164,12 +150,10 @@ public class StringConcatenationInspection extends BaseInspection { return new StringConcatenationVisitor(); } - private class StringConcatenationVisitor - extends BaseInspectionVisitor { + private class StringConcatenationVisitor extends BaseInspectionVisitor { @Override - public void visitPolyadicExpression( - @NotNull PsiPolyadicExpression expression) { + public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) { super.visitPolyadicExpression(expression); final IElementType tokenType = expression.getOperationTokenType(); if (!JavaTokenType.PLUS.equals(tokenType)) { @@ -185,7 +169,7 @@ public class StringConcatenationInspection extends BaseInspection { return; } } - if (isInsideAnnotation(expression)) { + if (AnnotationUtil.isInsideAnnotation(expression)) { return; } if (ignoreInTestCode && TestUtils.isInTestCode(expression)) { @@ -193,46 +177,32 @@ public class StringConcatenationInspection extends BaseInspection { } if (ignoreAsserts) { final PsiAssertStatement assertStatement = - PsiTreeUtil.getParentOfType(expression, - PsiAssertStatement.class, true, - PsiCodeBlock.class); + PsiTreeUtil.getParentOfType(expression, PsiAssertStatement.class, true, PsiCodeBlock.class); if (assertStatement != null) { return; } } if (ignoreSystemErrs || ignoreSystemOuts) { final PsiMethodCallExpression methodCallExpression = - PsiTreeUtil.getParentOfType(expression, - PsiMethodCallExpression.class, true, - PsiCodeBlock.class); + PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class); if (methodCallExpression != null) { - final PsiReferenceExpression methodExpression = - methodCallExpression.getMethodExpression(); + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); @NonNls - final String canonicalText = - methodExpression.getCanonicalText(); - if (ignoreSystemOuts && - "System.out.println".equals(canonicalText) || - "System.out.print".equals(canonicalText)) { + final String canonicalText = methodExpression.getCanonicalText(); + if (ignoreSystemOuts && "System.out.println".equals(canonicalText) || "System.out.print".equals(canonicalText)) { return; } - if (ignoreSystemErrs && - "System.err.println".equals(canonicalText) || - "System.err.print".equals(canonicalText)) { + if (ignoreSystemErrs && "System.err.println".equals(canonicalText) || "System.err.print".equals(canonicalText)) { return; } } } if (ignoreThrowableArguments) { final PsiNewExpression newExpression = - PsiTreeUtil.getParentOfType(expression, - PsiNewExpression.class, true, - PsiCodeBlock.class); + PsiTreeUtil.getParentOfType(expression, PsiNewExpression.class, true, PsiCodeBlock.class); if (newExpression != null) { final PsiType newExpressionType = newExpression.getType(); - if (newExpressionType != null && - InheritanceUtil.isInheritor(newExpressionType, - "java.lang.Throwable")) { + if (newExpressionType != null && InheritanceUtil.isInheritor(newExpressionType, "java.lang.Throwable")) { return; } } @@ -244,17 +214,21 @@ public class StringConcatenationInspection extends BaseInspection { } if (parent instanceof PsiField) { final PsiField field = (PsiField)parent; - if (field.hasModifierProperty(PsiModifier.STATIC) && - field.hasModifierProperty(PsiModifier.FINAL)) { + if (field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL)) { return; } final PsiClass containingClass = field.getContainingClass(); - if (containingClass != null && - containingClass.isInterface()) { + if (containingClass != null && containingClass.isInterface()) { return; } } } + if (ignoreInToString) { + final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class); + if (MethodUtils.isToString(method)) { + return; + } + } if (NonNlsUtils.isNonNlsAnnotatedUse(expression)) { return; } @@ -263,24 +237,12 @@ public class StringConcatenationInspection extends BaseInspection { if (!ExpressionUtils.isStringConcatenationOperand(operand)) { continue; } - final PsiJavaToken token = - expression.getTokenBeforeOperand(operand); + final PsiJavaToken token = expression.getTokenBeforeOperand(operand); if (token == null) { continue; } registerError(token, expression); } } - - private boolean isInsideAnnotation(PsiExpression expression) { - while (true) { - final PsiElement parent = expression.getParent(); - if (!(parent instanceof PsiPolyadicExpression)) { - return parent instanceof PsiArrayInitializerMemberValue || - parent instanceof PsiNameValuePair; - } - expression = (PsiExpression)parent; - } - } } } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html index 054e58735e67..3a4adf737f64 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html @@ -22,6 +22,8 @@ of constant fields.

Use the sixth checkbox to ignore string concatenations in test code.

+Use the seventh checkbox to ignore string concatentations inside toString() methods. +

Powered by InspectionGadgets \ No newline at end of file From cc9a5b886dff636b962117c7ba1e8b978447941c Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Tue, 13 Nov 2012 11:32:59 +0100 Subject: [PATCH 02/24] Implement pair methods in CoreJavaCodeStyleManager --- .../core/CoreJavaCodeStyleManager.java | 70 ++++++++++++++++++- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java index 4e9f5e68a6f8..e311029cd77d 100644 --- a/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java @@ -15,10 +15,14 @@ */ package com.intellij.core; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; @@ -26,6 +30,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.LinkedHashSet; public class CoreJavaCodeStyleManager extends JavaCodeStyleManager { @Override @@ -96,16 +101,75 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager { @Override public String suggestUniqueVariableName(@NonNls String baseName, PsiElement place, boolean lookForward) { - return null; + int index = 0; + PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class); + NextName: + while (true) { + String name = baseName; + if (index > 0) { + name += index; + } + index++; + if (PsiUtil.isVariableNameUnique(name, place)) { + if (lookForward) { + final String name1 = name; + PsiElement run = scope; + while (run != null) { + class CancelException extends RuntimeException { + } + try { + run.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitAnonymousClass(final PsiAnonymousClass aClass) { + } + + @Override public void visitVariable(PsiVariable variable) { + if (name1.equals(variable.getName())) { + throw new CancelException(); + } + } + }); + } + catch (CancelException e) { + continue NextName; + } + run = run.getNextSibling(); + if (scope instanceof PsiMethod) {//do not check next member for param name conflict + break; + } + } + + } + return name; + } + } } @NotNull @Override - public SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, + public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo, PsiElement place, boolean ignorePlaceName, boolean lookForward) { - return SuggestedNameInfo.NULL_INFO; + final String[] names = baseNameInfo.names; + final LinkedHashSet uniqueNames = new LinkedHashSet(names.length); + for (String name : names) { + if (ignorePlaceName && place instanceof PsiNamedElement) { + final String placeName = ((PsiNamedElement)place).getName(); + if (Comparing.strEqual(placeName, name)) { + uniqueNames.add(name); + continue; + } + } + uniqueNames.add(suggestUniqueVariableName(name, place, lookForward)); + } + + return new SuggestedNameInfo(ArrayUtil.toStringArray(uniqueNames)) { + @Override + public void nameChosen(String name) { + baseNameInfo.nameChosen(name); + } + }; } @Override From 65b3919059ed7c82104f0bf7d03eec78ed61543b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 13 Nov 2012 14:51:58 +0400 Subject: [PATCH 03/24] IDEA-94646 Save Project As Template: output folder should not be saved probably --- .../templates/ArchivedProjectTemplate.java | 11 +- .../templates/ArchivedTemplatesFactory.java | 7 +- .../SaveProjectAsTemplateAction.java | 168 +++++++++++++----- .../SaveProjectAsTemplateDialog.java | 9 +- .../com/intellij/openapi/project/Project.java | 3 + .../com/intellij/openapi/progress/Task.java | 6 + 6 files changed, 149 insertions(+), 55 deletions(-) diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java index 4564c89a204e..b5c007e81f21 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java @@ -15,9 +15,7 @@ */ package com.intellij.platform.templates; -import com.intellij.ide.util.newProjectWizard.ProjectNameStep; import com.intellij.ide.util.projectWizard.ModuleBuilder; -import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.ModuleTypeManager; @@ -26,7 +24,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.platform.ProjectTemplate; -import com.intellij.ui.IdeBorderFactory; import org.jdom.Document; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,19 +44,13 @@ public class ArchivedProjectTemplate implements ProjectTemplate { private final String myDisplayName; private final URL myArchivePath; private final ModuleType myModuleType; - private final WizardContext myContext; - private final ProjectNameStep mySettingsStep; public ArchivedProjectTemplate(String displayName, - URL archivePath, - WizardContext context) { + URL archivePath) { myDisplayName = displayName; myArchivePath = archivePath; - myContext = context; myModuleType = computeModuleType(this); - mySettingsStep = new ProjectNameStep(context, null); - mySettingsStep.getComponent().setBorder(IdeBorderFactory.createEmptyBorder(0)); } @NotNull diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java index 1e439581104e..ff441c330a52 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java @@ -101,6 +101,11 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory { return PathManager.getConfigPath() + "/resources/projectTemplates"; } + public static File getTemplateFile(String name) { + String configURL = getCustomTemplatesPath(); + return new File(configURL + "/" + name + ".zip"); + } + @NotNull @Override public String[] getGroups() { @@ -122,7 +127,7 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory { if (child.endsWith(ZIP)) { URL templateUrl = new URL(url.toExternalForm() + "/" + child); String name = child.substring(0, child.length() - ZIP.length()).replace('_', ' '); - templates.add(new ArchivedProjectTemplate(name, templateUrl, context)); + templates.add(new ArchivedProjectTemplate(name, templateUrl)); } } } diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java index 2c35a4cacf2e..e4a3cbdb539c 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java +++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java @@ -18,21 +18,32 @@ package com.intellij.platform.templates; import com.intellij.CommonBundle; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.StorageScheme; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.progress.PerformInBackgroundOption; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; +import com.intellij.openapi.roots.ContentIterator; +import com.intellij.openapi.roots.FileIndex; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.ZipUtil; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.io.FileFilter; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; @@ -44,9 +55,11 @@ import java.util.zip.ZipOutputStream; */ public class SaveProjectAsTemplateAction extends AnAction { + private static final Logger LOG = Logger.getInstance(SaveProjectAsTemplateAction.class); + @Override public void actionPerformed(AnActionEvent e) { - Project project = getEventProject(e); + final Project project = getEventProject(e); assert project != null; StorageScheme scheme = ((ProjectEx)project).getStateStore().getStorageScheme(); if (scheme != StorageScheme.DIRECTORY_BASED) { @@ -55,52 +68,127 @@ public class SaveProjectAsTemplateAction extends AnAction { return; } - VirtualFile descriptionFile = VfsUtil.findRelativeFile(project.getBaseDir(), ArchivedProjectTemplate.DESCRIPTION_PATH.split("/")); - SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile); - if (dialog.showAndGet()) { - File file = dialog.getTemplateFile(); - ZipOutputStream stream = null; - try { - file.getParentFile().mkdirs(); - stream = new ZipOutputStream(new FileOutputStream(file)); + final VirtualFile descriptionFile = getDescriptionFile(project); + final SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile); - VirtualFile dir = getDirectoryToSave(project, dialog.getModuleToSave()); - String description = dialog.getDescription(); - if (descriptionFile == null) { - stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH)); - stream.write(description.getBytes()); - stream.closeEntry(); + if (dialog.showAndGet()) { + + final Module moduleToSave = dialog.getModuleToSave(); + final File file = dialog.getTemplateFile(); + final String description = dialog.getDescription(); + + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Saving Project as Template", true, PerformInBackgroundOption.DEAF) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + saveProject(project, file, moduleToSave, description, indicator); } - else { - VfsUtil.saveText(descriptionFile, description); + + @Override + public void onSuccess() { + Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" + + "It's available now in Project Wizard", "Template Created"); } - ZipUtil.addDirToZipRecursively(stream, null, new File(dir.getPath()), dir.getName(), new FileFilter() { - @Override - public boolean accept(File pathname) { - if (!".idea".equals(pathname.getParent())) return true; - // todo filter out some garbage from .idea - return true; - } - }, null); - Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" + - "It's available now in Project Wizard", "Template Created"); - } - catch (IOException ex) { - Messages.showErrorDialog(project, ex.getMessage(), "Error"); - } - finally { - StreamUtil.closeStream(stream); - } + + @Override + public void onCancel() { + file.delete(); + } + }); } } - private static VirtualFile getDirectoryToSave(Project project, @Nullable String moduleName) { - if (moduleName == null) { + public static VirtualFile getDescriptionFile(Project project) { + return VfsUtil.findRelativeFile(ArchivedProjectTemplate.DESCRIPTION_PATH, project.getBaseDir()); + } + + public static void saveProject(final Project project, + final File zipFile, + Module moduleToSave, + final String description, + final ProgressIndicator indicator) { + + indicator.setText("Saving project..."); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + project.save(); + } + }); + } + }); + indicator.setText("Processing project files..."); + ZipOutputStream stream = null; + try { + FileUtil.ensureExists(zipFile.getParentFile()); + stream = new ZipOutputStream(new FileOutputStream(zipFile)); + + final VirtualFile dir = getDirectoryToSave(project, moduleToSave); + final VirtualFile descriptionFile = getDescriptionFile(project); + if (descriptionFile == null) { + stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH)); + stream.write(description.getBytes()); + stream.closeEntry(); + } + else { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + public void run() { + try { + VfsUtil.saveText(descriptionFile, description); + } + catch (IOException e) { + LOG.error(e); + } + } + }); + } + + FileIndex index = moduleToSave == null + ? ProjectRootManager.getInstance(project).getFileIndex() + : ModuleRootManager.getInstance(moduleToSave).getFileIndex(); + final ZipOutputStream finalStream = stream; + index.iterateContent(new ContentIterator() { + @Override + public boolean processFile(VirtualFile file) { + if (!file.isDirectory()) { + indicator.setText2(file.getName()); + try { + String relativePath = VfsUtilCore.getRelativePath(file, dir, '/'); + if (relativePath == null) { + throw new RuntimeException("Can't find relative path for " + file); + } + ZipUtil.addFileToZip(finalStream, new File(file.getPath()), dir.getName() + "/" + relativePath, null, null); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + indicator.checkCanceled(); + // if (!".idea".equals(fileName.getParent())) return true; + // todo filter out some garbage from .idea + return true; + } + }); + } + catch (Exception ex) { + LOG.error(ex); + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + Messages.showErrorDialog(project, "Can't save project as template", "Internal Error"); + } + }); + } + finally { + StreamUtil.closeStream(stream); + } + } + + private static VirtualFile getDirectoryToSave(Project project, @Nullable Module module) { + if (module == null) { return project.getBaseDir(); } else { - Module module = ModuleManager.getInstance(project).findModuleByName(moduleName); - assert module != null : "Can't find module " + moduleName; VirtualFile moduleFile = module.getModuleFile(); assert moduleFile != null; return moduleFile.getParent(); diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java index bd7278ef5a1d..860c54f325e1 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java +++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java @@ -45,6 +45,7 @@ import java.util.List; public class SaveProjectAsTemplateDialog extends DialogWrapper { private static final String WHOLE_PROJECT = ""; + @NotNull private final Project myProject; private JPanel myPanel; private JTextField myName; private EditorTextField myDescription; @@ -53,6 +54,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper { protected SaveProjectAsTemplateDialog(@NotNull Project project, @Nullable VirtualFile descriptionFile) { super(project); + myProject = project; setTitle("Save Project As Template"); Module[] modules = ModuleManager.getInstance(project).getModules(); @@ -113,8 +115,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper { File getTemplateFile() { String name = myName.getText(); - String configURL = ArchivedTemplatesFactory.getCustomTemplatesPath(); - return new File(configURL + "/" + name + ".zip"); + return ArchivedTemplatesFactory.getTemplateFile(name); } String getDescription() { @@ -122,10 +123,10 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper { } @Nullable - String getModuleToSave() { + Module getModuleToSave() { String item = (String)myModuleCombo.getSelectedItem(); if (item == null || item.equals(WHOLE_PROJECT)) return null; - return item; + return ModuleManager.getInstance(myProject).findModuleByName(item); } private final static Logger LOG = Logger.getInstance(SaveProjectAsTemplateDialog.class); diff --git a/platform/core-api/src/com/intellij/openapi/project/Project.java b/platform/core-api/src/com/intellij/openapi/project/Project.java index bcdefa175b91..84f4b9c84e3c 100644 --- a/platform/core-api/src/com/intellij/openapi/project/Project.java +++ b/platform/core-api/src/com/intellij/openapi/project/Project.java @@ -112,6 +112,9 @@ public interface Project extends ComponentManager, AreaInstance { @NonNls String getLocation(); + /** + * Should be invoked under WriteAction. + */ void save(); boolean isOpen(); diff --git a/platform/platform-api/src/com/intellij/openapi/progress/Task.java b/platform/platform-api/src/com/intellij/openapi/progress/Task.java index 858b53857a11..afae37cb6486 100644 --- a/platform/platform-api/src/com/intellij/openapi/progress/Task.java +++ b/platform/platform-api/src/com/intellij/openapi/progress/Task.java @@ -55,8 +55,14 @@ public abstract class Task implements TaskInfo, Progressive { myCanBeCancelled = canBeCancelled; } + /** + * This callback will be invoked on AWT dispatch thread. + */ public void onCancel() {} + /** + * This callback will be invoked on AWT dispatch thread. + */ public void onSuccess() {} public final Project getProject() { From 95ba49214e1a613beef776bb5af69ec6c3052bab Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Nov 2012 14:38:52 +0400 Subject: [PATCH 04/24] cleanup --- .../openapi/roots/impl/DirectoryInfo.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java index 37cb9a7170f5..2d41b3ac1896 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java @@ -35,7 +35,7 @@ import org.jetbrains.annotations.TestOnly; import java.util.*; -public class DirectoryInfo { +public final class DirectoryInfo { private Module module; // module to which content it belongs or null private VirtualFile libraryClassRoot; // class root in library private VirtualFile contentRoot; @@ -53,6 +53,9 @@ public class DirectoryInfo { */ private OrderEntry[] orderEntries; + public DirectoryInfo() { + } + @TestOnly @SuppressWarnings({"unchecked"}) public boolean equals(Object o) { @@ -272,7 +275,7 @@ public class DirectoryInfo { return BitUtil.isSet(sourceFlag, MODULE_SOURCE_FLAG); } - public void setInModuleSource(boolean inModuleSource) { + void setInModuleSource(boolean inModuleSource) { sourceFlag = (byte)BitUtil.set(sourceFlag, MODULE_SOURCE_FLAG, inModuleSource); } @@ -280,7 +283,7 @@ public class DirectoryInfo { return BitUtil.isSet(sourceFlag, TEST_SOURCE_FLAG); } - public void setTestSource(boolean testSource) { + void setTestSource(boolean testSource) { sourceFlag = (byte)BitUtil.set(sourceFlag, TEST_SOURCE_FLAG, testSource); } @@ -288,7 +291,7 @@ public class DirectoryInfo { return BitUtil.isSet(sourceFlag, LIBRARY_SOURCE_FLAG); } - public void setInLibrarySource(boolean inLibrarySource) { + void setInLibrarySource(boolean inLibrarySource) { sourceFlag = (byte)BitUtil.set(sourceFlag, LIBRARY_SOURCE_FLAG, inLibrarySource); } @@ -296,19 +299,19 @@ public class DirectoryInfo { return module; } - public void setModule(Module module) { + void setModule(Module module) { this.module = module; } - public void setLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) { + void setLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) { this.libraryClassRoot = libraryClassRoot; } - public void setContentRoot(VirtualFile contentRoot) { + void setContentRoot(VirtualFile contentRoot) { this.contentRoot = contentRoot; } - public void setSourceRoot(@NotNull VirtualFile sourceRoot) { + void setSourceRoot(@NotNull VirtualFile sourceRoot) { this.sourceRoot = sourceRoot; } From 860707addf7a052155fa3d2298b19534ea284ee3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Nov 2012 14:39:38 +0400 Subject: [PATCH 05/24] cleanup --- .../gotoByName/DefaultChooseByNameItemProvider.java | 3 ++- .../com/intellij/openapi/util/text/StringUtil.java | 12 ++---------- platform/util/src/com/intellij/util/io/IOUtil.java | 8 +++++--- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java index b774beeaf5cd..1a2b2806c1f7 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java @@ -187,7 +187,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider private static boolean matchesQualifier(final Object element, @NotNull final ChooseByNameBase base, - final List> patternsAndMatchers) { + @NotNull List> patternsAndMatchers) { final String name = base.getModel().getFullName(element); if (name == null) return false; @@ -220,6 +220,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider return true; } + @NotNull private static List> getPatternsAndMatchers(String qualifierPattern, final ChooseByNameBase base) { return ContainerUtil.map2List(split(qualifierPattern, base), new Function>() { @NotNull diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index a45c8aadc8fc..eb004fbfc82d 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -217,16 +217,8 @@ public class StringUtil extends StringUtilRt { fromIndex = 0; } - int max = sourceCount - 1; - - for (int i = fromIndex; i <= max; i++) { - /* Look for first character. */ - if (!charsEqualIgnoreCase(where.charAt(i), what)) { - while (++i <= max && !charsEqualIgnoreCase(where.charAt(i), what)) ; - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { + for (int i = fromIndex; i < sourceCount; i++) { + if (charsEqualIgnoreCase(where.charAt(i), what)) { return i; } } diff --git a/platform/util/src/com/intellij/util/io/IOUtil.java b/platform/util/src/com/intellij/util/io/IOUtil.java index cd0e075603c5..f25f391cd773 100644 --- a/platform/util/src/com/intellij/util/io/IOUtil.java +++ b/platform/util/src/com/intellij/util/io/IOUtil.java @@ -128,10 +128,12 @@ public class IOUtil { public static boolean isAscii(final String str) { for (int i = 0; i != str.length(); ++ i) { final char c = str.charAt(i); - if (c < 0 || c >= 128) { - return false; - } + if (!isAscii(c)) return false; } return true; } + + public static boolean isAscii(char c) { + return c >= 0 && c < 128; + } } From 844fc33279274bdd9d7302c5b8480749322b4b86 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Nov 2012 15:04:42 +0400 Subject: [PATCH 06/24] performance --- .../RemoveUnnecessaryEscapeCharactersIntention.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/RemoveUnnecessaryEscapeCharactersIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/RemoveUnnecessaryEscapeCharactersIntention.java index 4b5918e4524e..a1a78da3db84 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/RemoveUnnecessaryEscapeCharactersIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/RemoveUnnecessaryEscapeCharactersIntention.java @@ -42,7 +42,7 @@ public class RemoveUnnecessaryEscapeCharactersIntention extends Intention { final Document document = editor.getDocument(); final TextRange range = element.getTextRange(); - document.replaceString(range.getStartOffset(), range.getEndOffset(), removeUnnecessaryEscapeSymbols(((GrLiteral)element))); + document.replaceString(range.getStartOffset(), range.getEndOffset(), removeUnnecessaryEscapeSymbols((GrLiteral)element)); } @NotNull @@ -51,9 +51,10 @@ public class RemoveUnnecessaryEscapeCharactersIntention extends Intention { return new PsiElementPredicate() { @Override public boolean satisfiedBy(PsiElement element) { - final String text = element.getText(); + String text; + return element instanceof GrLiteral && - getStartQuote(text) != null && + getStartQuote(text = element.getText()) != null && !removeUnnecessaryEscapeSymbols((GrLiteral)element).equals(text); } }; From 93d058e78e7176ccc41316f37841af07952c4683 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Nov 2012 18:23:50 +0400 Subject: [PATCH 07/24] redraw on the search finish, on the ctrl-R, ctrl-W --- .../src/com/intellij/find/actions/ShowUsagesAction.java | 5 +++-- .../src/com/intellij/ide/util/gotoByName/ModelDiff.java | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java index 154690837b1e..ba62e70e16d0 100644 --- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java @@ -336,6 +336,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { Container parent = processIcon.getParent(); parent.remove(processIcon); parent.repaint(); + pingEDT.ping(); // repaint title synchronized (usages) { if (visibleNodes.isEmpty()) { if (usages.isEmpty()) { @@ -422,7 +423,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { @Override public void removeRangeFromModel(int start, int end) { - for (int i=end-1; i>=start; i--) { + for (int i=end; i>=start; i--) { removeRow(i); } } @@ -504,7 +505,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { if (shortcut != null) { shortcutText = "(" + KeymapUtil.getShortcutText(shortcut) + ")"; } - return new InplaceButton("Options..." + shortcutText, AllIcons.General.Settings, new ActionListener() { + return new InplaceButton("Settings..." + shortcutText, AllIcons.General.Settings, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ModelDiff.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ModelDiff.java index 1cef825ab9fc..546a09a99530 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ModelDiff.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ModelDiff.java @@ -83,7 +83,6 @@ public class ModelDiff { @Override public void apply() { - //System.out.println("removing: "+this); myListModel.removeRangeFromModel(start, end); } From 482f3c76fc72e218055fb4d0e6b373b13028cdcd Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Nov 2012 19:42:48 +0400 Subject: [PATCH 08/24] notnull --- .../impl/ExcludeCompilerOutputPolicy.java | 21 +++++++++++-------- .../impl/DirectoryIndexExcludePolicy.java | 7 +++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java index 7dfb138567b4..f880d36a6b19 100644 --- a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java +++ b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -39,25 +40,26 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy } @Override - public boolean isExcludeRoot(final VirtualFile f) { + public boolean isExcludeRoot(final VirtualFile file) { CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(myProject); - if (isEqualWithFileOrUrl(f, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true; + if (isEqualWithFileOrUrl(file, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true; for (Module m : ModuleManager.getInstance(myProject).getModules()) { CompilerModuleExtension rm = CompilerModuleExtension.getInstance(m); - if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true; - if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true; + if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true; + if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true; } return false; } @Override - public boolean isExcludeRootForModule(final Module module, final VirtualFile excludeRoot) { + public boolean isExcludeRootForModule(@NotNull final Module module, final VirtualFile excludeRoot) { final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module); return Comparing.equal(compilerModuleExtension.getCompilerOutputPath(), excludeRoot) || Comparing.equal(compilerModuleExtension.getCompilerOutputPathForTests(), excludeRoot); } + @NotNull @Override public VirtualFile[] getExcludeRootsForProject() { VirtualFile outputPath = CompilerProjectExtension.getInstance(myProject).getCompilerOutput(); @@ -67,8 +69,9 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy return VirtualFile.EMPTY_ARRAY; } + @NotNull @Override - public VirtualFilePointer[] getExcludeRootsForModule(final ModuleRootModel rootModel) { + public VirtualFilePointer[] getExcludeRootsForModule(@NotNull final ModuleRootModel rootModel) { ArrayList result = new ArrayList(); final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class); if (extension == null) { @@ -87,12 +90,12 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy return result.isEmpty() ? VirtualFilePointer.EMPTY_ARRAY : result.toArray(new VirtualFilePointer[result.size()]); } - private static boolean isEqualWithFileOrUrl(VirtualFile f, VirtualFile fileToCompareWith, String url) { + private static boolean isEqualWithFileOrUrl(VirtualFile file, VirtualFile fileToCompareWith, String url) { if (fileToCompareWith != null) { - if (Comparing.equal(fileToCompareWith, f)) return true; + if (Comparing.equal(fileToCompareWith, file)) return true; } else if (url != null) { - if (FileUtil.pathsEqual(url, f.getUrl())) return true; + if (FileUtil.pathsEqual(url, file.getUrl())) return true; } return false; } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java index 73a453487117..b31519ccb4a2 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java @@ -21,6 +21,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; +import org.jetbrains.annotations.NotNull; /** * @author yole @@ -29,7 +30,9 @@ public interface DirectoryIndexExcludePolicy { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.directoryIndexExcludePolicy"); boolean isExcludeRoot(VirtualFile file); - boolean isExcludeRootForModule(final Module module, final VirtualFile file); + boolean isExcludeRootForModule(@NotNull Module module, final VirtualFile file); + @NotNull VirtualFile[] getExcludeRootsForProject(); - VirtualFilePointer[] getExcludeRootsForModule(ModuleRootModel rootModel); + @NotNull + VirtualFilePointer[] getExcludeRootsForModule(@NotNull ModuleRootModel rootModel); } From 8160d4900c6480eb32ffb0b6c7aaebf152ba3cd6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 13 Nov 2012 14:33:57 +0400 Subject: [PATCH 09/24] IDEA-94813 "Preview Usages" is broken --- .../intellij/usages/impl/UsageViewImpl.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 2e01877f091b..845139ee3a8d 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -139,7 +139,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra private final GroupNode myRoot; private final UsageViewTreeModelBuilder myModel; private final Object lock = new Object(); - private Splitter myTreeSplitter; + private Splitter myPreviewSplitter; public UsageViewImpl(@NotNull final Project project, @NotNull UsageViewPresentation presentation, @@ -266,13 +266,13 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra disposeUsageContextPanels(); JScrollPane treePane = ScrollPaneFactory.createScrollPane(myTree); - myTreeSplitter = new Splitter(); - myTreeSplitter.setFirstComponent(treePane); + myPreviewSplitter = new Splitter(false, 0.5f, 0.1f, 0.9f); + myPreviewSplitter.setFirstComponent(treePane); - myCentralPanel.add(myTreeSplitter, BorderLayout.CENTER); + myCentralPanel.add(myPreviewSplitter, BorderLayout.CENTER); if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) { - myTreeSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS); + myPreviewSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS); treePane.putClientProperty(UIUtil.KEEP_BORDER_SIDES, SideBorder.RIGHT); final JBTabbedPane tabbedPane = new JBTabbedPane(SwingConstants.BOTTOM){ @NotNull @@ -316,10 +316,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra }); tabbedPane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT)); - myTreeSplitter.setSecondComponent(tabbedPane); + myPreviewSplitter.setSecondComponent(tabbedPane); } else { - myTreeSplitter.setProportion(1); + myPreviewSplitter.setProportion(1); } myCentralPanel.add(myButtonPanel, BorderLayout.SOUTH); @@ -330,13 +330,13 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra private void tabSelected(@NotNull final UsageContextPanel.Provider provider) { myCurrentUsageContextProvider = provider; - saveSplitterProportions(); setupCentralPanel(); updateOnSelectionChanged(); } private void disposeUsageContextPanels() { if (myCurrentUsageContextPanel != null) { + saveSplitterProportions(); Disposer.dispose(myCurrentUsageContextPanel); myCurrentUsageContextPanel = null; } @@ -607,7 +607,6 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra }); excludeUsages(excludedUsages.toArray(new Usage[excludedUsages.size()])); if (myCentralPanel != null) { - saveSplitterProportions(); setupCentralPanel(); } SwingUtilities.invokeLater(new Runnable() { @@ -937,15 +936,11 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra @Override public void close() { - saveSplitterProportions(); - UsageViewManager.getInstance(myProject).closeContent(myContent); } private void saveSplitterProportions() { - if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) { - UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS = myTreeSplitter.getProportion(); - } + UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS = myPreviewSplitter.getProportion(); } @Override From d05dbde74fbe5fbd136b41da996639fcf2915471 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 13 Nov 2012 15:07:07 +0400 Subject: [PATCH 10/24] Bug Fix: don't mark empty directory as source. --- .../maven/importing/MavenFoldersImporter.java | 4 +- .../maven/importing/FoldersImportingTest.java | 41 +++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java index 537d8609ab05..085239a00820 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java @@ -216,7 +216,7 @@ public class MavenFoldersImporter { private void configGeneratedSourceFolder(@NotNull File targetDir, boolean isTestSources) { switch (myImportingSettings.getGeneratedSourcesFolder()) { case GENERATED_SOURCE_FOLDER: - myModel.addSourceFolder(targetDir.getPath(), isTestSources); + myModel.addSourceFolder(targetDir.getPath(), isTestSources, true); break; case SUBFOLDER: @@ -242,7 +242,7 @@ public class MavenFoldersImporter { private void addAsSourceFolder(@NotNull File dir, boolean isTestSources) { if (!myModel.hasRegisteredSourceSubfolder(dir)) { - myModel.addSourceFolder(dir.getPath(), isTestSources); + myModel.addSourceFolder(dir.getPath(), isTestSources, true); } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java index 6afaa2f7cacf..248c3cd67b97 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java @@ -21,12 +21,12 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.project.MavenImportingSettings; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.Path; import java.io.File; +import java.io.IOException; public class FoldersImportingTest extends MavenImportingTestCase { public void testSimpleProjectStructure() throws Exception { @@ -646,8 +646,8 @@ public class FoldersImportingTest extends MavenImportingTestCase { public void testAddingExistingGeneratedSourcesWithCustomTargetDir() throws Exception { createStdProjectFolders(); - createProjectSubDirs("targetCustom/generated-sources/src", - "targetCustom/generated-test-sources/test"); + createProjectSubDirsWithFile("targetCustom/generated-sources/src", + "targetCustom/generated-test-sources/test"); importProject("test" + "project" + @@ -859,10 +859,10 @@ public class FoldersImportingTest extends MavenImportingTestCase { public void testDoesNotExcludeGeneratedSourcesUnderTargetDir() throws Exception { createStdProjectFolders(); - createProjectSubDirs("target/foo", - "target/bar", - "target/generated-sources/baz", - "target/generated-test-sources/bazz"); + createProjectSubDirsWithFile("target/foo", + "target/bar", + "target/generated-sources/baz", + "target/generated-test-sources/bazz"); importProject("test" + "project" + @@ -993,10 +993,10 @@ public class FoldersImportingTest extends MavenImportingTestCase { public void testAnnotationProcessorSources() throws Exception { createStdProjectFolders(); - createProjectSubDirs("target/generated-sources/foo", - "target/generated-sources/annotations", - "target/generated-test-sources/test-annotations", - "target/generated-test-sources/foo"); + createProjectSubDirsWithFile("target/generated-sources/foo", + "target/generated-sources/annotations", + "target/generated-test-sources/test-annotations", + "target/generated-test-sources/foo"); importProject("test" + "project" + @@ -1017,14 +1017,13 @@ public class FoldersImportingTest extends MavenImportingTestCase { public void testCustomAnnotationProcessorSources() throws Exception { createStdProjectFolders(); - createProjectSubDirs("anno", - "test-anno", - "target/generated-sources/foo", - "target/generated-sources/annotations", - "target/generated-sources/test-annotations", - "target/generated-test-sources/foo"); + createProjectSubDirsWithFile("anno", + "target/generated-sources/foo", + "target/generated-sources/annotations", + "target/generated-sources/test-annotations", + "target/generated-test-sources/foo"); - createProjectSubFile("anno/aaa.java"); + createProjectSubDir("test-anno"); importProject("test" + "project" + @@ -1061,4 +1060,10 @@ public class FoldersImportingTest extends MavenImportingTestCase { private CompilerModuleExtension getCompilerExtension(String moduleName) { return ModuleRootManager.getInstance(getModule(moduleName)).getModuleExtension(CompilerModuleExtension.class); } + + private void createProjectSubDirsWithFile(String ... dirs) throws IOException { + for (String dir : dirs) { + createProjectSubFile(dir + "/a.txt"); + } + } } From aebb63468c3b9ea836b9c909eb745a6eb967f71c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 13 Nov 2012 15:15:15 +0400 Subject: [PATCH 11/24] IDEA-94826 Process input reversed --- .../src/com/intellij/execution/impl/ConsoleUtil.java | 8 ++++---- .../src/com/intellij/execution/impl/ConsoleViewImpl.java | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleUtil.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleUtil.java index 1573ba23f5d1..a917ebfc0ab0 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleUtil.java @@ -15,9 +15,6 @@ */ package com.intellij.execution.impl; -import static com.intellij.execution.impl.ConsoleViewImpl.TokenInfo; -import static com.intellij.execution.impl.ConsoleViewImpl.HyperlinkTokenInfo; - import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.ui.ConsoleViewContentType; import org.jetbrains.annotations.NotNull; @@ -25,6 +22,9 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.execution.impl.ConsoleViewImpl.HyperlinkTokenInfo; +import static com.intellij.execution.impl.ConsoleViewImpl.TokenInfo; + /** * Holds utility methods for console processing. * @@ -36,7 +36,7 @@ public class ConsoleUtil { private ConsoleUtil() { } - public static void addToken(int length, @Nullable HyperlinkInfo info, ConsoleViewContentType contentType, List tokens) { + public static void addToken(int length, @Nullable HyperlinkInfo info, ConsoleViewContentType contentType, @NotNull List tokens) { int startOffset = 0; if (!tokens.isEmpty()) { final TokenInfo lastToken = tokens.get(tokens.size() - 1); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index e2894e84ba0e..ddfa271720ce 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -272,7 +272,10 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo }); } - protected ConsoleViewImpl(@NotNull final Project project, @NotNull GlobalSearchScope searchScope, boolean viewer, @Nullable FileType fileType, + protected ConsoleViewImpl(@NotNull final Project project, + @NotNull GlobalSearchScope searchScope, + boolean viewer, + @Nullable FileType fileType, @NotNull final ConsoleState initialState) { super(new BorderLayout()); isViewer = viewer; @@ -480,7 +483,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myEditor = null; myHyperlinks = null; } - } + } private void cancelAllFlushRequests() { synchronized (myCurrentRequests) { @@ -1516,7 +1519,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo startOffset = info.endOffset; } else { - startOffset = Math.max(deferredOffset, info.startOffset); + startOffset = Math.max(deferredOffset, Math.max(info.startOffset, offset)); } buffer.addUserText(startOffset - deferredOffset, textToUse); From ed3afcad9a718167657b9b274d742e15dcafdb3a Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Tue, 13 Nov 2012 12:21:11 +0100 Subject: [PATCH 12/24] DirectoryInfo: make some internal stuff public 'cos it is necessary for UpSource --- .../src/com/intellij/openapi/roots/impl/DirectoryInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java index 37cb9a7170f5..e83f129b64ad 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java @@ -237,7 +237,7 @@ public class DirectoryInfo { } }; - static final Comparator BY_OWNER_MODULE = new Comparator() { + public static final Comparator BY_OWNER_MODULE = new Comparator() { @Override public int compare(OrderEntry o1, OrderEntry o2) { String name1 = o1.getOwnerModule().getName(); @@ -246,7 +246,7 @@ public class DirectoryInfo { } }; - void setInternedOrderEntries(@NotNull OrderEntry[] internedOrderEntries) { + public void setInternedOrderEntries(@NotNull OrderEntry[] internedOrderEntries) { orderEntries = internedOrderEntries; } From d62affc5b7aced70e00f956ec4d7199c9e66bb30 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 13 Nov 2012 15:24:56 +0400 Subject: [PATCH 13/24] don't build JPS distribution for ultimate build configuration --- build/scripts/dist.gant | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 0cd9bdcfc85d..fed966d6fc00 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -79,7 +79,7 @@ target('default': 'The default target') { layoutAll([buildNumber: "IC-$snapshot", system_selector: "IdeaIC${p("component.version.major")}", tools_jar: true], - home, null, paths) + home, null, paths, true) } target('build-dist-jars' : 'Target to build jars from locally compiled classes') { @@ -90,10 +90,10 @@ target('build-dist-jars' : 'Target to build jars from locally compiled classes') layoutAll([buildNumber: "IC-$snapshot", system_selector: "IdeaIC${p("component.version.major")}", tools_jar: true], - home, null, paths) + home, null, paths) } -def layoutAll(Map args, String home, String out, Paths _paths = null) { +def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) { Paths paths = _paths != null ? _paths : new Paths(out) wireBuildDate(args.buildNumber, appInfoFile()) @@ -105,8 +105,10 @@ def layoutAll(Map args, String home, String out, Paths _paths = null) { notifyArtifactBuilt(paths.artifacts_core) layouts.layout_core_upsource(home, paths.artifacts_core_upsource) notifyArtifactBuilt(paths.artifacts_core_upsource) - layouts.layout_jps(home, paths.artifacts_jps) - notifyArtifactBuilt(paths.artifacts_jps) + if (buildJps) { + layouts.layout_jps(home, paths.artifacts_jps) + notifyArtifactBuilt(paths.artifacts_jps) + } layout(paths.distAll) { dir("bin") { From 7fce8c77ae70fa1dd4b4e0df80b2113f45800299 Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Tue, 13 Nov 2012 12:35:37 +0100 Subject: [PATCH 14/24] DirectoryInfo: more public stuff for UpSource --- .../intellij/openapi/roots/impl/DirectoryInfo.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java index 58b295b6c840..641b2b6df775 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java @@ -275,7 +275,7 @@ public final class DirectoryInfo { return BitUtil.isSet(sourceFlag, MODULE_SOURCE_FLAG); } - void setInModuleSource(boolean inModuleSource) { + public void setInModuleSource(boolean inModuleSource) { sourceFlag = (byte)BitUtil.set(sourceFlag, MODULE_SOURCE_FLAG, inModuleSource); } @@ -283,7 +283,7 @@ public final class DirectoryInfo { return BitUtil.isSet(sourceFlag, TEST_SOURCE_FLAG); } - void setTestSource(boolean testSource) { + public void setTestSource(boolean testSource) { sourceFlag = (byte)BitUtil.set(sourceFlag, TEST_SOURCE_FLAG, testSource); } @@ -291,7 +291,7 @@ public final class DirectoryInfo { return BitUtil.isSet(sourceFlag, LIBRARY_SOURCE_FLAG); } - void setInLibrarySource(boolean inLibrarySource) { + public void setInLibrarySource(boolean inLibrarySource) { sourceFlag = (byte)BitUtil.set(sourceFlag, LIBRARY_SOURCE_FLAG, inLibrarySource); } @@ -299,19 +299,19 @@ public final class DirectoryInfo { return module; } - void setModule(Module module) { + public void setModule(Module module) { this.module = module; } - void setLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) { + public void setLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) { this.libraryClassRoot = libraryClassRoot; } - void setContentRoot(VirtualFile contentRoot) { + public void setContentRoot(VirtualFile contentRoot) { this.contentRoot = contentRoot; } - void setSourceRoot(@NotNull VirtualFile sourceRoot) { + public void setSourceRoot(@NotNull VirtualFile sourceRoot) { this.sourceRoot = sourceRoot; } From bd72cc402d5d0a78ffdcb3399cf571f477ceeffa Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 13 Nov 2012 12:37:08 +0100 Subject: [PATCH 15/24] Fix bit condition checking --- platform/util/src/com/intellij/util/BitUtil.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/util/src/com/intellij/util/BitUtil.java b/platform/util/src/com/intellij/util/BitUtil.java index eb4a70d41f21..ddcb8e3d0c04 100644 --- a/platform/util/src/com/intellij/util/BitUtil.java +++ b/platform/util/src/com/intellij/util/BitUtil.java @@ -19,16 +19,16 @@ package com.intellij.util; * @since 27.03.2012 */ public class BitUtil { - public static boolean isSet(final byte value, final byte flag) { - return (value & flag) == flag; + public static boolean isSet(final byte value, final byte mask) { + return (value & mask) == mask; } - public static boolean isSet(final int value, final int flag) { - return (value & flag) == flag; + public static boolean isSet(final int value, final int mask) { + return (value & mask) == mask; } public static boolean notSet(final int value, final int mask) { - return (value & mask) == 0; + return (value & mask) != mask; } /** From 73ceb852932b7dce96ffb0d8ed611866242faff4 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 13 Nov 2012 12:51:54 +0100 Subject: [PATCH 16/24] IDEA-94506 (parser support for intersection types in casts) --- .../lang/java/parser/ExpressionParser.java | 2 +- .../lang/java/parser/ReferenceParser.java | 45 +++++++++++-------- .../expressions/LambdaExpression12.txt | 38 ++++++++++------ .../expressions/LambdaExpression13.txt | 35 +++++++++++---- .../parser/partial/ExpressionParserTest.java | 5 +-- 5 files changed, 80 insertions(+), 45 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index 0c37ad317ebc..72a4c6a04637 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -266,7 +266,7 @@ public class ExpressionParser { builder.advanceLexer(); final ReferenceParser.TypeInfo typeInfo = - myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD); + myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD | ReferenceParser.CONJUNCTIONS); if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) { typeCast.rollbackTo(); return parsePostfix(builder); diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 461e6efd75fe..989f895393b0 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable; import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.java.parser.JavaParserUtil.*; import static com.intellij.util.BitUtil.isSet; +import static com.intellij.util.BitUtil.notSet; +import static com.intellij.util.BitUtil.set; public class ReferenceParser { public static final int EAT_LAST_DOT = 0x01; @@ -35,6 +37,7 @@ public class ReferenceParser { public static final int WILDCARD = 0x04; public static final int DIAMONDS = 0x08; public static final int DISJUNCTIONS = 0x10; + public static final int CONJUNCTIONS = 0x20; public static class TypeInfo { public boolean isPrimitive = false; @@ -61,29 +64,32 @@ public class ReferenceParser { @Nullable public TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags) { - final TypeInfo typeInfo = parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS), - isSet(flags, ELLIPSIS)); + final TypeInfo typeInfo = parseTypeInfo(builder, flags, false); - if (typeInfo != null && isSet(flags, DISJUNCTIONS) && builder.getTokenType() == JavaTokenType.OR) { - typeInfo.marker = typeInfo.marker.precede(); + if (typeInfo != null) { + assert notSet(flags, DISJUNCTIONS|CONJUNCTIONS) : "don't not set both flags simultaneously"; + final IElementType operator = isSet(flags, DISJUNCTIONS) ? JavaTokenType.OR : isSet(flags, CONJUNCTIONS) ? JavaTokenType.AND : null; - while (builder.getTokenType() == JavaTokenType.OR) { - builder.advanceLexer(); - if (builder.getTokenType() != JavaTokenType.IDENTIFIER) { - error(builder, JavaErrorMessages.message("expected.identifier")); + if (operator != null && builder.getTokenType() == operator) { + typeInfo.marker = typeInfo.marker.precede(); + + while (builder.getTokenType() == operator) { + builder.advanceLexer(); + if (builder.getTokenType() != JavaTokenType.IDENTIFIER) { + error(builder, JavaErrorMessages.message("expected.identifier")); + } + parseTypeInfo(builder, flags, false); } - parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS), isSet(flags, ELLIPSIS)); - } - typeInfo.marker.done(JavaElementType.TYPE); + typeInfo.marker.done(JavaElementType.TYPE); + } } return typeInfo; } @Nullable - private TypeInfo parseTypeInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard, final boolean badWildcard, - final boolean diamonds, final boolean ellipsis) { + private TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags, final boolean badWildcard) { if (builder.getTokenType() == null) return null; final TypeInfo typeInfo = new TypeInfo(); @@ -96,14 +102,14 @@ public class ReferenceParser { typeInfo.isPrimitive = true; } else if (tokenType == JavaTokenType.IDENTIFIER) { - parseJavaCodeReference(builder, eatLastDot, true, false, false, false, diamonds, typeInfo); + parseJavaCodeReference(builder, isSet(flags, EAT_LAST_DOT), true, false, false, false, isSet(flags, DIAMONDS), typeInfo); } - else if ((wildcard || badWildcard) && tokenType == JavaTokenType.QUEST) { + else if ((isSet(flags, WILDCARD) || badWildcard) && tokenType == JavaTokenType.QUEST) { type.drop(); - typeInfo.marker = parseWildcardType(builder, wildcard); + typeInfo.marker = parseWildcardType(builder, isSet(flags, WILDCARD)); return typeInfo.marker != null ? typeInfo : null; } - else if (diamonds && tokenType == JavaTokenType.GT) { + else if (isSet(flags, DIAMONDS) && tokenType == JavaTokenType.GT) { emptyElement(builder, JavaElementType.DIAMOND_TYPE); type.done(JavaElementType.TYPE); typeInfo.marker = type; @@ -133,7 +139,7 @@ public class ReferenceParser { type = type.precede(); } - if (ellipsis && builder.getTokenType() == JavaTokenType.ELLIPSIS) { + if (isSet(flags, ELLIPSIS) && builder.getTokenType() == JavaTokenType.ELLIPSIS) { type = type.precede(); builder.advanceLexer(); type.done(JavaElementType.TYPE); @@ -263,9 +269,10 @@ public class ReferenceParser { return false; } + final int flags = set(set(EAT_LAST_DOT, WILDCARD, wildcard), DIAMONDS, diamonds); boolean isOk = true; while (true) { - if (parseTypeInfo(builder, true, wildcard, true, diamonds, false) == null) { + if (parseTypeInfo(builder, flags, true) == null) { error(builder, JavaErrorMessages.message("expected.identifier")); } else { diff --git a/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression12.txt b/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression12.txt index 576a40ebec84..8230bc75702b 100644 --- a/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression12.txt +++ b/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression12.txt @@ -1,18 +1,28 @@ PsiJavaFile:LambdaExpression12.java - PsiErrorElement:Unparsed tokens - PsiJavaToken:LT('<') - PsiIdentifier:T('T') - PsiJavaToken:GT('>') + PsiTypeCastExpression:(I1 & I2) () -> null PsiJavaToken:LPARENTH('(') + PsiTypeElement:I1 & I2 + PsiTypeElement:I1 + PsiJavaCodeReferenceElement:I1 + PsiIdentifier:I1('I1') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaToken:AND('&') + PsiWhiteSpace(' ') + PsiTypeElement:I2 + PsiJavaCodeReferenceElement:I2 + PsiIdentifier:I2('I2') + PsiReferenceParameterList + PsiJavaToken:RPARENTH(')') PsiWhiteSpace(' ') - PsiJavaToken:ARROW('->') - PsiWhiteSpace(' ') - PsiKeyword:new('new') - PsiWhiteSpace(' ') - PsiIdentifier:C('C') - PsiJavaToken:LT('<') - PsiIdentifier:T('T') - PsiJavaToken:GT('>') - PsiJavaToken:LPARENTH('(') - PsiJavaToken:RPARENTH(')') \ No newline at end of file + PsiLambdaExpression:() -> null + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression13.txt b/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression13.txt index 2b6c6786cfbb..6d3574958161 100644 --- a/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression13.txt +++ b/java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression13.txt @@ -1,10 +1,29 @@ PsiJavaFile:LambdaExpression13.java - PsiErrorElement:Unparsed tokens - PsiJavaToken:LT('<') - PsiIdentifier:T('T') - PsiJavaToken:GT('>') - PsiIdentifier:t('t') + PsiTypeCastExpression:(I1 & I2) () -> {} + PsiJavaToken:LPARENTH('(') + PsiTypeElement:I1 & I2 + PsiTypeElement:I1 + PsiJavaCodeReferenceElement:I1 + PsiIdentifier:I1('I1') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaToken:AND('&') + PsiWhiteSpace(' ') + PsiTypeElement:I2 + PsiJavaCodeReferenceElement:I2 + PsiIdentifier:I2('I2') + PsiReferenceParameterList + + PsiJavaToken:RPARENTH(')') PsiWhiteSpace(' ') - PsiJavaToken:ARROW('->') - PsiWhiteSpace(' ') - PsiIdentifier:t('t') \ No newline at end of file + PsiLambdaExpression:() -> {} + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java index 8f5726aba7f3..4a30c6dcbf67 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java @@ -134,15 +134,14 @@ public class ExpressionParserTest extends JavaParsingTestCase { public void testLambdaExpression9() { doParserTest("(I)p -> null"); } public void testLambdaExpression10() { doParserTest("(I)(p -> null)"); } public void testLambdaExpression11() { doParserTest("() -> { }"); } - public void testLambdaExpression12() { doParserTest("() -> new C()"); } // these two expressions - public void testLambdaExpression13() { doParserTest("t -> t"); } // should no longer be parsed + public void testLambdaExpression12() { doParserTest("(I1 & I2) () -> null"); } + public void testLambdaExpression13() { doParserTest("(I1 & I2) () -> {}"); } public void testLambdaExpression14() { doParserTest("(String t) -> t"); } public void testLambdaExpression15() { doParserTest("(int a, int b) -> a + b"); } public void testLambdaExpression16() { doParserTest("(final int x) -> x"); } public void testLambdaExpression17() { doParserTest("(String s -> s"); } public void testLambdaExpression18() { doParserTest("(java.lang.String s, -> s"); } public void testLambdaExpression19() { doParserTest("(@A T t) -> (null)"); } - public void testAmbiguousLambdaExpression() { doParserTest("f( (x) < y , z > (w) -> v )"); } private void doParserTest(@NonNls final String text) { From 370775e5bd726e8f3383b8ff397e09fe7c44012a Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 13 Nov 2012 15:47:32 +0400 Subject: [PATCH 17/24] fix npe on 10.6 (as suggested by bjansen) --- .../src/com/intellij/ui/mac/MacFileChooserDialogImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java index f871bab65bca..2bd7d7f2a055 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java @@ -56,6 +56,10 @@ public class MacFileChooserDialogImpl implements PathChooserDialog { private static final Callback SHOULD_ENABLE_URL = new Callback() { @SuppressWarnings("UnusedDeclaration") public boolean callback(ID self, String selector, ID panel, ID url) { + if (ourImplMap.get(self) == null) { + // Since it has already been removed from the map, the file is likely to be valid if the user was able to select it + return true; + } if (url == null || url.intValue() == 0) return false; final ID filename = Foundation.invoke(url, "path"); final String fileName = Foundation.toStringViaUTF8(filename); From 02f266bd1f2d96ad8b1077ca04ed0c1e6602efb0 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 13 Nov 2012 14:58:05 +0400 Subject: [PATCH 18/24] IDEA-19061 Integrate the Rearranger-plugin into core-IDE 'add new matching rule' action --- .../arrangement/ArrangementConstants.java | 2 - .../ArrangementNodeDisplayManager.java | 5 ++- .../action/AddArrangementRuleAction.java | 23 ++++++++-- .../action/RemoveArrangementRuleAction.java | 6 --- .../EmptyArrangementRuleComponent.java | 43 +++++++++++++++++++ .../match/ArrangementMatchingRuleEditor.java | 37 +++++++++++----- .../match/ArrangementMatchingRulesPanel.java | 13 +++--- .../util/ArrangementConfigUtil.java | 16 ++++--- .../arrangement/util/TitleWithToolbar.java | 7 ++- 9 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java index 8e6f8bbf65a9..31bada03209e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java @@ -48,8 +48,6 @@ public class ArrangementConstants { public static final boolean LOG_RULE_MODIFICATION = Boolean.parseBoolean(System.getProperty("log.arrangement.rule.modification")); - public static final DataKey NEW_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.New"); - public static final DataKey> UPDATE_MOVE_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.Update.Move"); public static final DataKey> MOVE_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.Move"); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java index 6bf8dd50692e..2a30831c5ede 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; /** * Encapsulates various functionality related to showing arrangement nodes to end-users. @@ -62,8 +63,8 @@ public class ArrangementNodeDisplayManager { } private void refreshMaxWidths() { - Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, null); - for (Map.Entry> entry : map.entrySet()) { + Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, null); + for (Map.Entry> entry : map.entrySet()) { myMaxWidths.put(entry.getKey(), maxWidth(entry.getKey(), entry.getValue())); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java index 6b62e3e2f372..fec896ddb9b5 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java @@ -16,10 +16,14 @@ package com.intellij.application.options.codeStyle.arrangement.action; import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants; +import com.intellij.application.options.codeStyle.arrangement.component.EmptyArrangementRuleComponent; +import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl; +import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesModel; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.project.DumbAware; +import gnu.trove.TIntArrayList; /** * @author Denis Zhdanov @@ -34,9 +38,22 @@ public class AddArrangementRuleAction extends AnAction implements DumbAware { @Override public void actionPerformed(AnActionEvent e) { - Runnable function = ArrangementConstants.NEW_RULE_FUNCTION_KEY.getData(e.getDataContext()); - if (function != null) { - function.run(); + ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext()); + if (control == null) { + return; } + + TIntArrayList rows = control.getSelectedModelRows(); + ArrangementMatchingRulesModel model = control.getModel(); + int rowToEdit; + if (rows.size() == 1) { + rowToEdit = rows.get(0) + 1; + model.insertRow(rowToEdit, new Object[] { new EmptyArrangementRuleComponent() }); + } + else { + model.add(new EmptyArrangementRuleComponent()); + rowToEdit = model.getSize() - 1; + } + control.showEditor(rowToEdit); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RemoveArrangementRuleAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RemoveArrangementRuleAction.java index d529f6ec9c1e..b184e66405b2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RemoveArrangementRuleAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RemoveArrangementRuleAction.java @@ -62,11 +62,5 @@ public class RemoveArrangementRuleAction extends AnAction { } } }); - - //int repaintMax = model.getSize() - 1; - //int min = rowsToRemove.get(rowsToRemove.size() - 1); - //if (repaintMax >= 0 && min <= repaintMax) { - // control.repaintRows(min, repaintMax, true); - //} } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java new file mode 100644 index 000000000000..53342c32fffa --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java @@ -0,0 +1,43 @@ +/* + * 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.application.options.codeStyle.arrangement.component; + +import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.util.ui.GridBag; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Denis Zhdanov + * @since 11/13/12 1:31 PM + */ +public class EmptyArrangementRuleComponent extends JPanel implements ArrangementRepresentationAware { + + public EmptyArrangementRuleComponent() { + super(new GridBagLayout()); + add(new JLabel(ApplicationBundle.message("arrangement.text.empty.rule")), new GridBag().anchor(GridBagConstraints.WEST)); + setBackground(UIUtil.getDecoratedRowColor()); + } + + @NotNull + @Override + public JComponent getComponent() { + return this; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java index fb5d8008f310..c2424d626c43 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java @@ -20,6 +20,7 @@ import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDis import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider; import com.intellij.application.options.codeStyle.arrangement.component.ArrangementAtomMatchConditionComponent; import com.intellij.application.options.codeStyle.arrangement.component.ArrangementMatchConditionComponent; +import com.intellij.application.options.codeStyle.arrangement.component.EmptyArrangementRuleComponent; import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil; import com.intellij.psi.codeStyle.arrangement.ArrangementConditionInfo; import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; @@ -89,16 +90,16 @@ public class ArrangementMatchingRuleEditor extends JPanel { setLayout(new GridBagLayout()); setBorder(IdeBorderFactory.createEmptyBorder(5)); - Map> supportedSettings = ArrangementConfigUtil.buildAvailableConditions(myFilter, null); + Map> supportedSettings = ArrangementConfigUtil.buildAvailableConditions(myFilter, null); addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager); addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager); } private void addRowIfPossible(@NotNull ArrangementSettingType key, - @NotNull Map> supportedSettings, + @NotNull Map> supportedSettings, @NotNull ArrangementNodeDisplayManager manager) { - Collection values = supportedSettings.get(key); + Set values = supportedSettings.get(key); if (values == null || values.isEmpty()) { return; } @@ -129,8 +130,14 @@ public class ArrangementMatchingRuleEditor extends JPanel { * '-1' as an indication that no settings should be active */ public void updateState(int row) { - myRow = row; - myConditionInfo = null; + updateState(row, true); + } + + private void updateState(int row, boolean newModel) { + if (newModel) { + myRow = row; + myConditionInfo = null; + } // Reset state. for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { @@ -145,15 +152,22 @@ public class ArrangementMatchingRuleEditor extends JPanel { } Object element = model.getElementAt(row); + if (element instanceof EmptyArrangementRuleComponent) { + for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { + ArrangementAtomMatchCondition condition = component.getMatchCondition(); + Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); + component.setEnabled(map.get(condition.getType()).contains(condition.getValue())); + } + return; + } if (!(element instanceof StdArrangementMatchRule)) { - myRow = -1; return; } ArrangementMatchCondition condition = ((StdArrangementMatchRule)element).getMatcher().getCondition(); myConditionInfo = ArrangementUtil.extractConditions(condition); - Map> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); + Map> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); for (Collection ids : available.values()) { for (Object id : ids) { ArrangementAtomMatchConditionComponent component = myComponents.get(id); @@ -169,9 +183,12 @@ public class ArrangementMatchingRuleEditor extends JPanel { private void updateState() { assert myConditionInfo != null; ArrangementMatchCondition newCondition = myConditionInfo.buildCondition(); - myControl.getModel().set(myRow, newCondition == null ? null : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition))); + Object modelValue = newCondition == null + ? new EmptyArrangementRuleComponent() + : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition)); + myControl.getModel().set(myRow, modelValue); myControl.repaintRows(myRow, myRow, true); - updateState(myRow); + updateState(myRow, false); } public void applyAvailableWidth(int width) { @@ -204,7 +221,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { component.setSelected(!remove); repaintComponent(component); if (remove) { - myConditionInfo.removeCondition(chosenCondition); + myConditionInfo.removeCondition(chosenCondition.getValue()); updateState(); return; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java index 4d685aa209a5..f1d6bd3dde05 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java @@ -46,12 +46,7 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide @NotNull ArrangementStandardSettingsAware settingsFilter) { super(new GridBagLayout()); - TitleWithToolbar top = new TitleWithToolbar( - ApplicationBundle.message("arrangement.settings.section.match"), - ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR, - ArrangementConstants.MATCHING_RULES_CONTROL_TOOLBAR_PLACE - ); - + JBScrollPane scrollPane = new JBScrollPane(); final JViewport viewport = scrollPane.getViewport(); ArrangementMatchingRulesControl.RepresentationCallback callback = new ArrangementMatchingRulesControl.RepresentationCallback() { @@ -76,6 +71,12 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide myControl = new ArrangementMatchingRulesControl(displayManager, colorsProvider, settingsFilter, callback); scrollPane.setViewportView(myControl); + TitleWithToolbar top = new TitleWithToolbar( + ApplicationBundle.message("arrangement.settings.section.match"), + ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR, + ArrangementConstants.MATCHING_RULES_CONTROL_TOOLBAR_PLACE, + myControl + ); add(top, new GridBag().coverLine().fillCellHorizontally().weightx(1)); add(scrollPane, new GridBag().fillCell().weightx(1).weighty(1)); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java index 5f453c9c6eb8..d1b2a7147fc3 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java @@ -25,8 +25,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.*; -import java.util.List; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * Contains various utility methods to be used during showing arrangement settings. @@ -49,10 +51,10 @@ public class ArrangementConfigUtil { * @return map which contains information on what new new settings are available at the current situation */ @NotNull - public static Map> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter, + public static Map> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter, @Nullable ArrangementMatchCondition condition) { - Map> result = new EnumMap>(ArrangementSettingType.class); + Map> result = new EnumMap>(ArrangementSettingType.class); processData(filter, condition, result, ArrangementSettingType.TYPE, ArrangementEntryType.values()); processData(filter, condition, result, ArrangementSettingType.MODIFIER, ArrangementModifier.values()); return result; @@ -60,17 +62,17 @@ public class ArrangementConfigUtil { private static void processData(@NotNull ArrangementStandardSettingsAware filter, @Nullable ArrangementMatchCondition settings, - @NotNull Map> result, + @NotNull Map> result, @NotNull ArrangementSettingType type, @NotNull T[] values) { - List data = null; + Set data = null; for (T v : values) { if (!isEnabled(v, filter, settings)) { continue; } if (data == null) { - data = new ArrayList(); + data = new HashSet(); } data.add(v); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/TitleWithToolbar.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/TitleWithToolbar.java index 79ff07a991b5..0c1aa24f52d7 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/TitleWithToolbar.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/TitleWithToolbar.java @@ -32,11 +32,16 @@ import java.awt.*; */ public class TitleWithToolbar extends JPanel { - public TitleWithToolbar(@NotNull String title, @NotNull String actionGroupId, @NotNull String place) { + public TitleWithToolbar(@NotNull String title, + @NotNull String actionGroupId, + @NotNull String place, + @NotNull JComponent targetComponent) + { super(new GridBagLayout()); ActionManager actionManager = ActionManager.getInstance(); ActionGroup group = (ActionGroup)actionManager.getAction(actionGroupId); ActionToolbar actionToolbar = actionManager.createActionToolbar(place, group, true); + actionToolbar.setTargetComponent(targetComponent); add(new MyTitleComponent(title), new GridBag().weightx(1).anchor(GridBagConstraints.WEST).fillCellHorizontally()); add(actionToolbar.getComponent(), new GridBag().anchor(GridBagConstraints.CENTER)); From 42b06ba7b73dd05c9f089b97e737f221d1314374 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 13 Nov 2012 15:23:34 +0400 Subject: [PATCH 19/24] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Removing 'linked condition' (e.g. on unchecking 'field' uncheck 'transient' automatically) --- .../match/ArrangementMatchingRuleEditor.java | 29 ++++++++++++++++++- .../util/ArrangementConfigUtil.java | 4 +-- .../util/ArrangementListRowDecorator.java | 4 +++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java index c2424d626c43..1fa0b7f663bb 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java @@ -60,7 +60,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { @NotNull private final Map myComponents = new HashMap(); - + @NotNull private final ArrangementMatchingRulesControl myControl; @NotNull private final ArrangementStandardSettingsAware myFilter; @NotNull private final ArrangementColorsProvider myColorsProvider; @@ -222,6 +222,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { repaintComponent(component); if (remove) { myConditionInfo.removeCondition(chosenCondition.getValue()); + ensureConsistency(); updateState(); return; } @@ -256,6 +257,32 @@ public class ArrangementMatchingRuleEditor extends JPanel { updateState(); } + private void ensureConsistency() { + if (myConditionInfo == null) { + return; + } + ArrangementMatchCondition condition = myConditionInfo.buildCondition(); + Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); + for (ArrangementAtomMatchConditionComponent c : myComponents.values()) { + Object v = c.getMatchCondition().getValue(); + if (!myConditionInfo.hasCondition(v)) { + continue; + } + boolean remain = false; + for (Set s : map.values()) { + if (s.contains(v)) { + remain = true; + break; + } + } + if (!remain) { + myConditionInfo.removeCondition(v); + ensureConsistency(); + return; + } + } + } + @Nullable private ArrangementAtomMatchConditionComponent getNodeComponentAt(@NotNull Point screenPoint) { for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java index d1b2a7147fc3..8434ea1cd031 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java @@ -44,11 +44,11 @@ public class ArrangementConfigUtil { } /** - * Allows to answer what new settings are available for a particular match condition. + * Allows to answer what settings are available for a particular match condition. * * @param filter filter to use * @param condition object that encapsulates information about current arrangement matcher settings - * @return map which contains information on what new new settings are available at the current situation + * @return map which contains information on what settings are available at the current situation */ @NotNull public static Map> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter, diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java index ed0d25544c30..981daa14e29f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java @@ -122,6 +122,10 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa if (!beingEdited && !myUnderMouse) { myEditButton.setVisible(false); } + if (beingEdited && !myBeingEdited) { + myEditButton.setVisible(true); + myEditButton.getPresentation().putClientProperty(Toggleable.SELECTED_PROPERTY, true); + } myBeingEdited = beingEdited; } From 81afdf56431f888185108ec851983ed90d4cbcd1 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 13 Nov 2012 16:19:15 +0400 Subject: [PATCH 20/24] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Correct new rule addition in case of open editor --- .../action/AddArrangementRuleAction.java | 10 ++++++---- .../EmptyArrangementRuleComponent.java | 12 +++++++++++- .../match/ArrangementMatchingRuleEditor.java | 3 ++- .../match/ArrangementMatchingRulesControl.java | 17 +++++------------ 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java index fec896ddb9b5..c368d1a8e2e4 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java @@ -42,18 +42,20 @@ public class AddArrangementRuleAction extends AnAction implements DumbAware { if (control == null) { return; } - + + control.hideEditor(); TIntArrayList rows = control.getSelectedModelRows(); ArrangementMatchingRulesModel model = control.getModel(); int rowToEdit; if (rows.size() == 1) { rowToEdit = rows.get(0) + 1; - model.insertRow(rowToEdit, new Object[] { new EmptyArrangementRuleComponent() }); + model.insertRow(rowToEdit, new Object[] { new EmptyArrangementRuleComponent(control.getRowHeight(rowToEdit)) }); } else { - model.add(new EmptyArrangementRuleComponent()); - rowToEdit = model.getSize() - 1; + rowToEdit = model.getSize(); + model.add(new EmptyArrangementRuleComponent(control.getRowHeight(rowToEdit))); } control.showEditor(rowToEdit); + control.getSelectionModel().setSelectionInterval(rowToEdit, rowToEdit); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java index 53342c32fffa..49672522bc1b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java @@ -15,6 +15,7 @@ */ package com.intellij.application.options.codeStyle.arrangement.component; +import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; @@ -29,8 +30,11 @@ import java.awt.*; */ public class EmptyArrangementRuleComponent extends JPanel implements ArrangementRepresentationAware { - public EmptyArrangementRuleComponent() { + private final int myHeight; + + public EmptyArrangementRuleComponent(int height) { super(new GridBagLayout()); + myHeight = height; add(new JLabel(ApplicationBundle.message("arrangement.text.empty.rule")), new GridBag().anchor(GridBagConstraints.WEST)); setBackground(UIUtil.getDecoratedRowColor()); } @@ -40,4 +44,10 @@ public class EmptyArrangementRuleComponent extends JPanel implements Arrangement public JComponent getComponent() { return this; } + + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + return new Dimension(size.width, myHeight); + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java index 1fa0b7f663bb..1244d6cb2dcf 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java @@ -158,6 +158,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); component.setEnabled(map.get(condition.getType()).contains(condition.getValue())); } + myConditionInfo = new ArrangementConditionInfo(); return; } if (!(element instanceof StdArrangementMatchRule)) { @@ -184,7 +185,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { assert myConditionInfo != null; ArrangementMatchCondition newCondition = myConditionInfo.buildCondition(); Object modelValue = newCondition == null - ? new EmptyArrangementRuleComponent() + ? new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow)) : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition)); myControl.getModel().set(myRow, modelValue); myControl.repaintRows(myRow, myRow, true); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java index 651b5a8edcc2..95379a9ae261 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java @@ -79,6 +79,7 @@ public class ArrangementMatchingRulesControl extends JBTable { setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); setShowColumns(false); setShowGrid(false); + putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); myEditor = new ArrangementMatchingRuleEditor(settingsFilter, colorsProvider, displayManager, this); addMouseMotionListener(new MouseAdapter() { @Override @@ -298,7 +299,6 @@ public class ArrangementMatchingRulesControl extends JBTable { } editor.applyAvailableWidth(width); myEditor.updateState(rowToEdit); - myComponents.shiftKeys(myEditorRow, 1); mySkipSelectionChange = true; try { getModel().insertRow(myEditorRow, new Object[]{editor}); @@ -411,14 +411,14 @@ public class ArrangementMatchingRulesControl extends JBTable { } } - private static class MyEditor extends AbstractTableCellEditor { + private class MyEditor extends AbstractTableCellEditor { - @Nullable private Object myValue; + private int myRow; @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { if (value instanceof ArrangementEditorAware) { - myValue = value; + myRow = row; return ((ArrangementEditorAware)value).getComponent(); } return null; @@ -426,14 +426,7 @@ public class ArrangementMatchingRulesControl extends JBTable { @Override public Object getCellEditorValue() { - return myValue; - } - - @Override - public boolean stopCellEditing() { - boolean result = super.stopCellEditing(); - myValue = null; - return result; + return myRow < getModel().getSize() ? getModel().getElementAt(myRow) : null; } } From 5fbf4e48d176bc0e8f5ca4c00901f9e979f1479a Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 13 Nov 2012 16:24:02 +0400 Subject: [PATCH 21/24] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Remove empty rule on editor close if necessary --- .../arrangement/match/ArrangementMatchingRulesControl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java index 95379a9ae261..1d45e8f73dbd 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java @@ -256,7 +256,11 @@ public class ArrangementMatchingRulesControl extends JBTable { } mySkipSelectionChange = true; try { - getModel().removeRow(myEditorRow); + ArrangementMatchingRulesModel model = getModel(); + model.removeRow(myEditorRow); + if (myEditorRow > 0 && model.getElementAt(myEditorRow - 1) instanceof EmptyArrangementRuleComponent) { + model.removeRow(myEditorRow - 1); + } } finally { mySkipSelectionChange = false; From 9ec3ef89b7716feb95d06b209beac4d305543f2a Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 13 Nov 2012 11:19:06 +0100 Subject: [PATCH 22/24] [^andres, yann] don't place create-app button to the right when creating a grails application on mac --- .../src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java index 83e7f3b66509..e163dfd956d9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java @@ -137,9 +137,10 @@ public abstract class MvcFramework { ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), ClasspathEditor.NAME); } module.putUserData(CREATE_APP_STRUCTURE, null); - final int result = Messages.showYesNoCancelDialog(module.getProject(), - "Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?", - "Create " + getDisplayName() + " application", "Run 'create-&app'", "Run 'create-&plugin'", "&Cancel", getIcon()); + String message = "Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?"; + final int result = Messages.showDialog(module.getProject(), message, + "Create " + getDisplayName() + " application", + new String[]{"Run 'create-&app'", "Run 'create-&plugin'", "&Cancel"}, 0, getIcon()); if (result < 0 || result > 1) { return; } From fda688e9d8689a3e3c3c4809c77636b420293a03 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 13 Nov 2012 12:29:33 +0100 Subject: [PATCH 23/24] [^andres, yann] IDEA-88872 Support additional flags when creating a Griffon application project --- .../griffon/GriffonCreateProjectDialog.form | 82 +++++++++++++++++++ .../griffon/GriffonCreateProjectDialog.java | 69 ++++++++++++++++ .../groovy/griffon/GriffonFramework.java | 19 ++++- .../plugins/groovy/mvc/MvcFramework.java | 22 +++-- 4 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.form create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.form new file mode 100644 index 000000000000..420b9b91d1a8 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.form @@ -0,0 +1,82 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java new file mode 100644 index 000000000000..e149c4e64c99 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java @@ -0,0 +1,69 @@ +/* + * 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 org.jetbrains.plugins.groovy.griffon; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * @author peter + */ +public class GriffonCreateProjectDialog extends DialogWrapper { + private JTextField myOptionField; + private JPanel myComponent; + private JRadioButton myCreateApp; + private JRadioButton myCreatePlugin; + private JRadioButton myCreateAddon; + private JRadioButton myCreateArchetype; + private JLabel myCreateLabel; + + public GriffonCreateProjectDialog(@NotNull Module module) { + super(module.getProject()); + setTitle("Create Griffon Structure"); + myCreateLabel.setText("Create Griffon structure in module '" + module.getName() + "':"); + init(); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return myComponent; + } + + String getCommand() { + if (myCreateAddon.isSelected()) return "create-addon"; + if (myCreateApp.isSelected()) return "create-app"; + if (myCreateArchetype.isSelected()) return "create-archetype"; + if (myCreatePlugin.isSelected()) return "create-plugin"; + throw new AssertionError("No selection"); + } + + String[] getArguments() { + String text = myOptionField.getText(); + if (StringUtil.isEmptyOrSpaces(text)) { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + return text.split(" "); + } + +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java index f6c905599f23..fedef4f47beb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.griffon; import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.JavaParameters; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.psi.PropertiesFile; @@ -36,9 +37,11 @@ import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.IgnoredBeanFactory; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; +import com.intellij.util.ArrayUtil; import gnu.trove.TIntArrayList; import icons.JetgroovyIcons; import org.jetbrains.annotations.NonNls; @@ -93,6 +96,18 @@ public class GriffonFramework extends MvcFramework { public void upgradeFramework(@NotNull Module module) { } + @Nullable + @Override + protected GeneralCommandLine getCreationCommandLine(Module module) { + GriffonCreateProjectDialog dialog = new GriffonCreateProjectDialog(module); + dialog.show(); + if (!dialog.isOK()) { + return null; + } + + return createCommandAndShowErrors(null, module, true, dialog.getCommand(), dialog.getArguments()); + } + @Override public boolean updatesWholeProject() { return false; @@ -269,7 +284,7 @@ public class GriffonFramework extends MvcFramework { throw new ExecutionException("Failed to initialize griffon module: module " + module.getName() + " contains more than one root"); } - args = new String[]{roots[0].getName()}; + args = ArrayUtil.mergeArrays(new String[]{roots[0].getName()}, args); rootFile = roots[0].getParent(); } else { @@ -279,7 +294,7 @@ public class GriffonFramework extends MvcFramework { } } - String workDir = VfsUtil.virtualToIoFile(rootFile).getAbsolutePath(); + String workDir = VfsUtilCore.virtualToIoFile(rootFile).getAbsolutePath(); if (jvmParams != null) { params.getVMParametersList().addParametersString(jvmParams); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java index e163dfd956d9..fa5528b657cd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java @@ -137,15 +137,7 @@ public abstract class MvcFramework { ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), ClasspathEditor.NAME); } module.putUserData(CREATE_APP_STRUCTURE, null); - String message = "Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?"; - final int result = Messages.showDialog(module.getProject(), message, - "Create " + getDisplayName() + " application", - new String[]{"Run 'create-&app'", "Run 'create-&plugin'", "&Cancel"}, 0, getIcon()); - if (result < 0 || result > 1) { - return; - } - - final GeneralCommandLine commandLine = createCommandAndShowErrors(null, module, true, result == 0 ? "create-app" : "create-plugin"); + final GeneralCommandLine commandLine = getCreationCommandLine(module); if (commandLine == null) return; MvcConsole.executeProcess(module, commandLine, new Runnable() { @@ -164,6 +156,18 @@ public abstract class MvcFramework { } + @Nullable + protected GeneralCommandLine getCreationCommandLine(Module module) { + String message = "Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?"; + final int result = Messages.showDialog(module.getProject(), message, "Create " + getDisplayName() + " application", + new String[]{"Run 'create-&app'", "Run 'create-&plugin'", "&Cancel"}, 0, getIcon()); + if (result < 0 || result > 1) { + return null; + } + + return createCommandAndShowErrors(null, module, true, result == 0 ? "create-app" : "create-plugin"); + } + public abstract void updateProjectStructure(@NotNull final Module module); public abstract void ensureRunConfigurationExists(@NotNull Module module); From b8553ce85b09e2a7ae7c60a3a047be58370325fc Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 13 Nov 2012 16:35:36 +0400 Subject: [PATCH 24/24] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Context menu for matching rules editing --- .../arrangement/ArrangementConstants.java | 4 ++-- .../action/EditArrangementRuleAction.java | 21 +++++++++++++++++-- .../match/ArrangementMatchingRulesPanel.java | 4 ++++ .../src/messages/ApplicationBundle.properties | 4 ++-- .../src/idea/LangActions.xml | 4 ++-- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java index 31bada03209e..eed611df2891 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java @@ -29,8 +29,8 @@ public class ArrangementConstants { public static final DataKey MATCHING_RULES_CONTROL_KEY = DataKey.create("Arrangement.RuleEditor"); - @NonNls public static final String ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU = "Arrangement.RuleEditor.Context.Menu"; - @NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR = "Arrangement.RuleEditor.ToolBar"; + @NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU = "Arrangement.Rule.Match.Control.Context.Menu"; + @NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR = "Arrangement.Rule.Match.Control.ToolBar"; @NonNls public static final String RULE_EDITOR_PLACE = "Arrangement.RuleEditor.Place"; @NonNls public static final String MATCHING_RULES_CONTROL_TOOLBAR_PLACE = "Arrangement.Rule.Match.Control.ToolBar.Place"; diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/EditArrangementRuleAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/EditArrangementRuleAction.java index 1ffb6f44b2ec..3667916c286b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/EditArrangementRuleAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/EditArrangementRuleAction.java @@ -15,11 +15,14 @@ */ package com.intellij.application.options.codeStyle.arrangement.action; +import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants; +import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Toggleable; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.project.DumbAware; +import gnu.trove.TIntArrayList; /** * @author Denis Zhdanov @@ -31,9 +34,23 @@ public class EditArrangementRuleAction extends AnAction implements DumbAware, To getTemplatePresentation().setText(ApplicationBundle.message("arrangement.action.rule.edit.text")); getTemplatePresentation().setDescription(ApplicationBundle.message("arrangement.action.rule.edit.description")); } - + + @Override + public void update(AnActionEvent e) { + ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext()); + e.getPresentation().setEnabled(control != null && control.getSelectedModelRows().size() == 1); + } + @Override public void actionPerformed(AnActionEvent e) { - // TODO den implement + ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext()); + if (control == null) { + return; + } + TIntArrayList rows = control.getSelectedModelRows(); + if (rows.size() != 1) { + return; + } + control.showEditor(rows.get(0)); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java index f1d6bd3dde05..03aa69933e25 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java @@ -19,6 +19,7 @@ import com.intellij.application.options.codeStyle.arrangement.ArrangementConstan import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager; import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider; import com.intellij.application.options.codeStyle.arrangement.util.TitleWithToolbar; +import com.intellij.ide.ui.customization.CustomizationUtil; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; @@ -70,6 +71,9 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide }; myControl = new ArrangementMatchingRulesControl(displayManager, colorsProvider, settingsFilter, callback); scrollPane.setViewportView(myControl); + CustomizationUtil.installPopupHandler( + myControl, ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU, ArrangementConstants.RULE_EDITOR_PLACE + ); TitleWithToolbar top = new TitleWithToolbar( ApplicationBundle.message("arrangement.settings.section.match"), diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index dc1d680e5f1f..3773961d4e55 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -561,8 +561,8 @@ arrangement.text.modifier=Modifier arrangement.text.negate=Negate arrangement.action.rule.add.text=Add rule arrangement.action.rule.add.description=Add new arrangement rule -arrangement.action.rule.remove.text=Remove rule -arrangement.action.rule.remove.description=Remove selected arrangement rule +arrangement.action.rule.remove.text=Remove rule(s) +arrangement.action.rule.remove.description=Remove selected arrangement rule(s) arrangement.action.rule.edit.text=Edit rule arrangement.action.rule.edit.description=Edit selected arrangement rule arrangement.action.rule.move.up.text=Move up diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 9dd10fa6fa87..e92b7899abc0 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -828,13 +828,13 @@ class="com.intellij.application.options.codeStyle.arrangement.action.MoveArrangementRuleDownAction" icon="AllIcons.ToolbarDecorator.MoveDown"/> - + - +