Merge branch 'master' of git@git.labs.intellij.net:idea/community
authorRoman Chernyatchik <roman.chernyatchik@jetbrains.com>
Sat, 24 Oct 2009 10:04:51 +0000 (14:04 +0400)
committerRoman Chernyatchik <roman.chernyatchik@jetbrains.com>
Sat, 24 Oct 2009 10:04:51 +0000 (14:04 +0400)
98 files changed:
bin/appletviewer.policy [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/ant/ProjectBuild.java
java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactModelImpl.java
java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactType.java
java/compiler/impl/src/com/intellij/packaging/impl/elements/FileCopyPackagingElement.java
java/compiler/impl/src/com/intellij/packaging/impl/elements/ManifestFileUtil.java
java/compiler/impl/src/com/intellij/packaging/impl/ui/FileCopyPresentation.java
java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.form
java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.java
java/compiler/openapi/src/com/intellij/compiler/ant/BuildProperties.java
java/compiler/openapi/src/com/intellij/packaging/artifacts/ModifiableArtifactModel.java
java/compiler/openapi/src/com/intellij/packaging/ui/ArtifactEditor.java
java/compiler/openapi/src/com/intellij/packaging/ui/ArtifactEditorContext.java
java/compiler/openapi/src/com/intellij/packaging/ui/ManifestFileConfiguration.java
java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java [new file with mode: 0644]
java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameDebuggerTree.java
java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java [new file with mode: 0644]
java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java
java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java
java/idea-ui/src/com/intellij/facet/impl/ProjectFacetsConfigurator.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorContextImpl.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContext.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContextImpl.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ManifestFilesInfo.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java
java/idea-ui/src/com/intellij/util/descriptors/impl/CustomConfigFileSetImpl.java
java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java
java/java-impl/src/com/intellij/application/options/JavaIndentOptionsEditor.java
java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java
java/java-impl/src/com/intellij/lang/java/JavaFormattingModelBuilder.java
java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java
java/java-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaHelper.java
java/java-tests/testData/refactoring/pushDown/staticImportsInsidePushedMethod/after/b/B.java
java/openapi/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java
java/openapi/src/com/intellij/util/descriptors/CustomConfigFileSet.java
java/testFramework/src/com/intellij/testFramework/codeInsight/hierarchy/HierarchyViewTestBase.java
platform/lang-api/src/com/intellij/application/options/IndentOptionsEditor.java
platform/lang-api/src/com/intellij/application/options/SmartIndentOptionsEditor.java
platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java [new file with mode: 0755]
platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java [new file with mode: 0755]
platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoController.java
platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java
platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockWithParent.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockFragmentWrapper.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlockFactory.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageFormattingModelBuilder.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
platform/lang-impl/src/com/intellij/psi/formatter/DocumentBasedFormattingModel.java
platform/lang-impl/src/com/intellij/psi/templateLanguages/SimpleTemplateLanguageFormattingModelBuilder.java [moved from platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateLanguageFormattingModelBuilder.java with 96% similarity]
platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java
platform/platform-api/src/com/intellij/openapi/progress/ProgressManager.java
platform/platform-api/src/com/intellij/openapi/ui/NamedItemsListEditor.java
platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java
platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java
platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java
platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FakeVirtualFile.java
platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
platform/platform-resources-en/src/misc/registry.properties
platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java
platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java
platform/util/src/com/intellij/openapi/util/text/StringUtil.java
platform/util/src/com/intellij/util/containers/ClassMap.java
platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManagerGate.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/local/AddList.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/pending/MockChangeListManagerGate.java
plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/annotate/CvsFileAnnotation.java
plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/RequestProcessor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/Context.groovy
plugins/junit/src/com/intellij/execution/junit2/SuiteState.java
plugins/junit/src/com/intellij/execution/junit2/TestProxy.java
plugins/junit/src/com/intellij/execution/junit2/states/NotFailedState.java
plugins/junit/src/com/intellij/execution/junit2/states/ReadableState.java
plugins/junit/src/com/intellij/execution/junit2/states/TestState.java
plugins/junit/src/com/intellij/execution/junit2/states/TestStateUpdater.java
plugins/junit/src/com/intellij/execution/junit2/ui/StatisticsPanel.java
plugins/junit/src/com/intellij/execution/junit2/ui/StatisticsTable.java
plugins/junit/src/com/intellij/execution/junit2/ui/TestRenderer.java
plugins/junit/src/com/intellij/execution/junit2/ui/model/TestTreeBuilder.java
resources-en/src/messages/CompilerBundle.properties

diff --git a/bin/appletviewer.policy b/bin/appletviewer.policy
new file mode 100644 (file)
index 0000000..b367045
--- /dev/null
@@ -0,0 +1,7 @@
+grant {
+  permission java.security.AllPermission;
+  permission java.net.SocketPermission "*", "accept, connect, listen, resolve";
+};
+
+
+
index 4b8bea36a2b69bae67815d940c0bb25677bac29c..eaf0c454a91e5a3b5e8569e3d2d7dec7e51cb50b 100644 (file)
@@ -42,10 +42,10 @@ public abstract class ProjectBuild extends Generator {
 
     // the sequence in which modules are imported is important cause output path properties for dependent modules should be defined first
 
-    final StringBuilder alltargetNames = new StringBuilder();
-    alltargetNames.append(BuildProperties.TARGET_INIT);
-    alltargetNames.append(", ");
-    alltargetNames.append(BuildProperties.TARGET_CLEAN);
+    final StringBuilder buildModulesTargetNames = new StringBuilder();
+    buildModulesTargetNames.append(BuildProperties.TARGET_INIT);
+    buildModulesTargetNames.append(", ");
+    buildModulesTargetNames.append(BuildProperties.TARGET_CLEAN);
     final ModuleChunk[] chunks = genOptions.getModuleChunks();
 
     if (chunks.length > 0) {
@@ -55,10 +55,10 @@ public abstract class ProjectBuild extends Generator {
         myAntProject.add(createModuleBuildGenerator(chunk, genOptions), 1);
         final String[] targets = ChunkBuildExtension.getAllTargets(chunk);
         for (String target : targets) {
-          if (alltargetNames.length() > 0) {
-            alltargetNames.append(", ");
+          if (buildModulesTargetNames.length() > 0) {
+            buildModulesTargetNames.append(", ");
           }
-          alltargetNames.append(target);
+          buildModulesTargetNames.append(target);
         }
       }
     }
@@ -78,19 +78,21 @@ public abstract class ProjectBuild extends Generator {
 
     myAntProject.add(new CleanProject(genOptions, artifactsGenerator), 1);
 
+    myAntProject.add(new Target(BuildProperties.TARGET_BUILD_MODULES, buildModulesTargetNames.toString(),
+                                CompilerBundle.message("generated.ant.build.build.all.modules.target.name"), null), 1);
+    
+    StringBuilder buildAllTargetNames = new StringBuilder();
+    buildAllTargetNames.append(BuildProperties.TARGET_BUILD_MODULES);
     if (artifactsGenerator != null) {
       List<Generator> generators = artifactsGenerator.generate();
       for (Generator generator : generators) {
         myAntProject.add(generator, 1);
       }
 
-      if (alltargetNames.length() > 0) {
-        alltargetNames.append(", ");
-      }
-      alltargetNames.append(ArtifactsGenerator.BUILD_ALL_ARTIFACTS_TARGET);
+      buildAllTargetNames.append(", ").append(ArtifactsGenerator.BUILD_ALL_ARTIFACTS_TARGET);
     }
 
-    myAntProject.add(new Target(BuildProperties.TARGET_ALL, alltargetNames.toString(),
+    myAntProject.add(new Target(BuildProperties.TARGET_ALL, buildAllTargetNames.toString(),
                                 CompilerBundle.message("generated.ant.build.build.all.target.name"), null), 1);
   }
 
index 442af50d39b038f6274582121bf7f1989ad8921b..bd4583e8073e95a0e083965ef673cb7090e479f9 100644 (file)
@@ -152,7 +152,8 @@ public class ArtifactModelImpl extends ArtifactModelBase implements ModifiableAr
   }
 
   @Nullable
-  public ArtifactImpl getModifiableCopy(ArtifactImpl artifact) {
+  public ArtifactImpl getModifiableCopy(Artifact artifact) {
+    //noinspection SuspiciousMethodCalls
     return myArtifact2ModifiableCopy.get(artifact);
   }
 
index 83e67590d8b7e092f63f9ad2e70606ffd271ed95..3fb3b23f6c541e4f8a516bb6b6def5dbf0cc4a70 100644 (file)
  */
 package com.intellij.packaging.impl.artifacts;
 
+import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.CompilerProjectExtension;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.SourceFolder;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.io.FileUtil;
@@ -355,56 +358,55 @@ public class ArtifactUtil {
     return files.isEmpty() ? null : files.get(0);
   }
 
-  public static List<VirtualFile> findSourceFilesByOutputPath(CompositePackagingElement<?> parent, String outputPath,
-                                                 PackagingElementResolvingContext context, ArtifactType artifactType) {
-    outputPath = StringUtil.trimStart(outputPath, "/");
-    if (outputPath.length() == 0) {
+  public static List<VirtualFile> findSourceFilesByOutputPath(CompositePackagingElement<?> parent, final String outputPath,
+                                                 final PackagingElementResolvingContext context, final ArtifactType artifactType) {
+    final String path = StringUtil.trimStart(outputPath, "/");
+    if (path.length() == 0) {
       return Collections.emptyList();
     }
 
-    int i = outputPath.indexOf('/');
-    final String firstName = i != -1 ? outputPath.substring(0, i) : outputPath;
-    String tail = i != -1 ? outputPath.substring(i+1) : "";
+    int i = path.indexOf('/');
+    final String firstName = i != -1 ? path.substring(0, i) : path;
+    final String tail = i != -1 ? path.substring(i+1) : "";
 
-    final List<CompositePackagingElement<?>> compositeChildren = new SmartList<CompositePackagingElement<?>>();
-    final List<FileCopyPackagingElement> fileCopies = new SmartList<FileCopyPackagingElement>();
-    final List<DirectoryCopyPackagingElement> dirCopies = new SmartList<DirectoryCopyPackagingElement>();
+    final List<VirtualFile> result = new SmartList<VirtualFile>();
     processElements(parent.getChildren(), context, artifactType, new Processor<PackagingElement<?>>() {
       public boolean process(PackagingElement<?> element) {
+        //todo[nik] replace by method findSourceFile() in PackagingElement
         if (element instanceof CompositePackagingElement) {
           final CompositePackagingElement<?> compositeElement = (CompositePackagingElement<?>)element;
           if (firstName.equals(compositeElement.getName())) {
-            compositeChildren.add(compositeElement);
+            result.addAll(findSourceFilesByOutputPath(compositeElement, tail, context, artifactType));
           }
         }
         else if (element instanceof FileCopyPackagingElement) {
           final FileCopyPackagingElement fileCopyElement = (FileCopyPackagingElement)element;
-          if (firstName.equals(fileCopyElement.getOutputFileName())) {
-            fileCopies.add(fileCopyElement);
+          if (firstName.equals(fileCopyElement.getOutputFileName()) && tail.length() == 0) {
+            ContainerUtil.addIfNotNull(fileCopyElement.findFile(), result);
           }
         }
         else if (element instanceof DirectoryCopyPackagingElement) {
-          dirCopies.add((DirectoryCopyPackagingElement)element);
+          final VirtualFile sourceRoot = ((DirectoryCopyPackagingElement)element).findFile();
+          if (sourceRoot != null) {
+            ContainerUtil.addIfNotNull(sourceRoot.findFileByRelativePath(path), result);
+          }
+        }
+        else if (element instanceof ModuleOutputPackagingElement) {
+          final Module module = ((ModuleOutputPackagingElement)element).findModule(context);
+          final ContentEntry[] contentEntries = context.getModulesProvider().getRootModel(module).getContentEntries();
+          for (ContentEntry contentEntry : contentEntries) {
+            for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
+              final VirtualFile sourceRoot = sourceFolder.getFile();
+              if (!sourceFolder.isTestSource() && sourceRoot != null) {
+                ContainerUtil.addIfNotNull(sourceRoot.findFileByRelativePath(path), result);
+              }
+            }
+          }
         }
         return true;
       }
     });
 
-    List<VirtualFile> result = new SmartList<VirtualFile>();
-    for (CompositePackagingElement<?> child : compositeChildren) {
-      result.addAll(findSourceFilesByOutputPath(child, tail, context, artifactType));
-    }
-    if (tail.length() == 0) {
-      for (FileCopyPackagingElement fileCopy : fileCopies) {
-        ContainerUtil.addIfNotNull(fileCopy.findFile(), result);
-      }
-    }
-    for (DirectoryCopyPackagingElement dirCopy : dirCopies) {
-      final VirtualFile sourceRoot = dirCopy.findFile();
-      if (sourceRoot != null) {
-        ContainerUtil.addIfNotNull(sourceRoot.findFileByRelativePath(outputPath), result);
-      }
-    }
     return result;
   }
 
index 45bae738a3ae898fb02f8d637239a69655736856..01bcd7153c86f64461833c88b4971aed51e4fcb0 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.packaging.impl.artifacts;
 
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.packaging.artifacts.ArtifactType;
 import com.intellij.packaging.elements.CompositePackagingElement;
 import com.intellij.packaging.elements.PackagingElementOutputKind;
@@ -45,6 +46,6 @@ public class JarArtifactType extends ArtifactType {
   @NotNull
   @Override
   public CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
-    return new ArchivePackagingElement(artifactName + ".jar");
+    return new ArchivePackagingElement(FileUtil.sanitizeFileName(artifactName) + ".jar");
   }
 }
index 6513c765e76e3a25470024184d2e06d11a2baee1..8835d077beecc5087cdda39c9ff5de3924861423 100644 (file)
@@ -58,7 +58,7 @@ public class FileCopyPackagingElement extends FileOrDirectoryCopyPackagingElemen
   }
 
   public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
-    return new FileCopyPresentation(myFilePath, getOutputFileName());
+    return new FileCopyPresentation(myFilePath, getOutputFileName(), context);
   }
 
   @Override
index dced5f8bd21abbd3691af067ee09fd2307e66ad0..4bea85e59f9c6def9a4a444cecb4b02d66118b66 100644 (file)
@@ -27,7 +27,6 @@ import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.packaging.artifacts.ArtifactType;
 import com.intellij.packaging.elements.CompositePackagingElement;
 import com.intellij.packaging.elements.PackagingElement;
-import com.intellij.packaging.elements.PackagingElementFactory;
 import com.intellij.packaging.elements.PackagingElementResolvingContext;
 import com.intellij.packaging.impl.artifacts.ArtifactUtil;
 import com.intellij.packaging.impl.artifacts.PackagingElementProcessor;
@@ -55,16 +54,19 @@ public class ManifestFileUtil {
   public static final String MANIFEST_FILE_NAME = PathUtil.getFileName(MANIFEST_PATH);
   public static final String MANIFEST_DIR_NAME = PathUtil.getParentPath(MANIFEST_PATH);
 
+  private ManifestFileUtil() {
+  }
+
   @Nullable
   public static VirtualFile findManifestFile(@NotNull CompositePackagingElement<?> root, PackagingElementResolvingContext context, ArtifactType artifactType) {
     return ArtifactUtil.findSourceFileByOutputPath(root, MANIFEST_PATH, context, artifactType);
   }
 
-  @NotNull 
-  public static String suggestManifestFilePathAndAddElement(@NotNull CompositePackagingElement<?> root, PackagingElementResolvingContext context, ArtifactType artifactType) {
+  @Nullable
+  public static VirtualFile suggestManifestFileDirectory(@NotNull CompositePackagingElement<?> root, PackagingElementResolvingContext context, ArtifactType artifactType) {
     final VirtualFile metaInfDir = ArtifactUtil.findSourceFileByOutputPath(root, MANIFEST_DIR_NAME, context, artifactType);
     if (metaInfDir != null) {
-      return metaInfDir.getPath() + "/" + MANIFEST_FILE_NAME;
+      return metaInfDir;
     }
 
     final Ref<VirtualFile> sourceDir = Ref.create(null);
@@ -89,17 +91,15 @@ public class ManifestFileUtil {
     });
 
     if (!sourceDir.isNull()) {
-      return sourceDir.get().getPath() + "/" + MANIFEST_PATH;
+      return sourceDir.get();
     }
 
 
     final Project project = context.getProject();
-    final VirtualFile dir = suggestBaseDir(project, sourceFile.get());
-    String filePath = dir.getPath() + "/" + MANIFEST_PATH;
-    PackagingElementFactory.getInstance().addFileCopy(root, MANIFEST_DIR_NAME, filePath);
-    return filePath;
+    return suggestBaseDir(project, sourceFile.get());
   }
 
+  @Nullable
   private static VirtualFile suggestBaseDir(Project project, final @Nullable VirtualFile file) {
     final VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots();
     if (file == null && contentRoots.length > 0) {
@@ -189,7 +189,11 @@ public class ManifestFileUtil {
   @NotNull
   public static ManifestFileConfiguration createManifestFileConfiguration(CompositePackagingElement<?> element,
                                                                     final PackagingElementResolvingContext context, final ArtifactType artifactType) {
-    final VirtualFile manifestFile = findManifestFile(element, context, artifactType);
+    return createManifestFileConfiguration(findManifestFile(element, context, artifactType));
+  }
+
+  @NotNull
+  public static ManifestFileConfiguration createManifestFileConfiguration(@Nullable VirtualFile manifestFile) {
     final List<String> classpath = new ArrayList<String>();
     String mainClass = null;
     final String path;
index ec304eb07a3af5feb32c900c52b55d7922fb717a..621ae5fcfb63a13b5da0d4f3faf2a9c31f25ced9 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.packaging.impl.elements.PackagingElementFactoryImpl;
+import com.intellij.packaging.ui.ArtifactEditorContext;
 import com.intellij.packaging.ui.PackagingElementPresentation;
 import com.intellij.packaging.ui.PackagingElementWeights;
 import com.intellij.ui.SimpleTextAttributes;
@@ -32,10 +33,12 @@ import org.jetbrains.annotations.NotNull;
 public class FileCopyPresentation extends PackagingElementPresentation {
   private final String mySourcePath;
   private final String myOutputFileName;
+  private final ArtifactEditorContext myContext;
   private final VirtualFile myFile;
 
-  public FileCopyPresentation(String filePath, String outputFileName) {
+  public FileCopyPresentation(String filePath, String outputFileName, ArtifactEditorContext context) {
     myOutputFileName = outputFileName;
+    myContext = context;
 
     String parentPath;
     myFile = LocalFileSystem.getInstance().findFileByPath(filePath);
@@ -61,8 +64,8 @@ public class FileCopyPresentation extends PackagingElementPresentation {
   }
 
   public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) {
-    if (myFile != null && !myFile.isDirectory()) {
-      presentationData.setIcons(myFile.getIcon());
+    if (myFile != null && !myFile.isDirectory() || myContext.isManifestFile(mySourcePath)) {
+      presentationData.setIcons(myFile != null ? myFile.getIcon() : PackagingElementFactoryImpl.FileCopyElementType.ICON);
       presentationData.addText(myOutputFileName, mainAttributes);
       presentationData.addText(" (" + mySourcePath + ")", commentAttributes);
     }
index fcc32a15653a6d743f5f4946f05038a8145646f4..e78575bd42f5c57419212da4d584f0fef74597f7 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.packaging.impl.ui.properties.ElementWithManifestPropertiesPanel">
-  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="5" left="5" bottom="5" right="5"/>
     <constraints>
       <xy x="20" y="20" width="500" height="400"/>
     <properties/>
     <border type="none"/>
     <children>
-      <component id="9a3d6" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="messages/CompilerBundle" key="label.text.main.class"/>
-        </properties>
-      </component>
       <vspacer id="e5716">
         <constraints>
-          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
-      <component id="d87aa" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myMainClassField">
-        <constraints>
-          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="40600" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="messages/CompilerBundle" key="label.text.class.path"/>
-        </properties>
-      </component>
-      <component id="a5121" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myClasspathField">
-        <constraints>
-          <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="e12c" class="javax.swing.JLabel" binding="myTitleLabel">
-        <constraints>
-          <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text value="element name"/>
-        </properties>
-      </component>
-      <component id="446b5" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text value="Manifest &amp;File:"/>
-        </properties>
-      </component>
-      <component id="52135" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myManifestFilePathField">
+      <grid id="98ebe" binding="myPropertiesPanel" layout-manager="CardLayout" hgap="0" vgap="0">
         <constraints>
-          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties/>
-      </component>
+        <border type="none"/>
+        <children>
+          <grid id="e398c" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <card name="properties"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="9a3d6" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="messages/CompilerBundle" key="label.text.main.class"/>
+                </properties>
+              </component>
+              <component id="d87aa" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myMainClassField">
+                <constraints>
+                  <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+              </component>
+              <component id="40600" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="messages/CompilerBundle" key="label.text.class.path"/>
+                </properties>
+              </component>
+              <component id="a5121" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myClasspathField">
+                <constraints>
+                  <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+              </component>
+              <component id="e12c" class="javax.swing.JLabel" binding="myTitleLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="element name"/>
+                </properties>
+              </component>
+              <component id="446b5" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <labelFor value="aca67"/>
+                  <text value="Manifest &amp;File:"/>
+                </properties>
+              </component>
+              <grid id="599de" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <component id="12e45" class="javax.swing.JButton" binding="myRemoveFromArtifactButton" default-binding="true">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text value="&amp;Remove from Artifact"/>
+                    </properties>
+                  </component>
+                  <hspacer id="7cf11">
+                    <constraints>
+                      <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                  </hspacer>
+                </children>
+              </grid>
+              <component id="aca67" class="javax.swing.JTextField" binding="myManifestPathField">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties>
+                  <editable value="false"/>
+                </properties>
+              </component>
+            </children>
+          </grid>
+          <grid id="4473f" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <card name="buttons"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="66e62" class="javax.swing.JButton" binding="myCreateManifestButton" default-binding="true">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="&amp;Create Manifest..."/>
+                </properties>
+              </component>
+              <hspacer id="970f7">
+                <constraints>
+                  <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </hspacer>
+              <vspacer id="bf917">
+                <constraints>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </vspacer>
+              <component id="c6af2" class="javax.swing.JButton" binding="myUseExistingManifestButton" default-binding="true">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="&amp;Use Existing Manifest..."/>
+                </properties>
+              </component>
+              <component id="a0a7b" class="javax.swing.JLabel" binding="myManifestNotFoundLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Manifest.mf file not found"/>
+                </properties>
+              </component>
+            </children>
+          </grid>
+        </children>
+      </grid>
     </children>
   </grid>
 </form>
index da62127e768d7b1b747021be50f47ed312f65b6c..e5d3b18da96af91786e5c7699472798d600d52be 100644 (file)
  */
 package com.intellij.packaging.impl.ui.properties;
 
+import com.intellij.CommonBundle;
 import com.intellij.ide.util.TreeClassChooser;
 import com.intellij.ide.util.TreeClassChooserFactory;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.elements.PackagingElementFactory;
 import com.intellij.packaging.impl.elements.CompositeElementWithManifest;
 import com.intellij.packaging.impl.elements.ManifestFileUtil;
 import com.intellij.packaging.ui.ArtifactEditorContext;
-import com.intellij.packaging.ui.PackagingElementPropertiesPanel;
 import com.intellij.packaging.ui.ManifestFileConfiguration;
+import com.intellij.packaging.ui.PackagingElementPropertiesPanel;
 import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -40,21 +48,29 @@ import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
+import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.io.IOException;
 import java.util.List;
 
 /**
  * @author nik
  */
 public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElementWithManifest<?>> extends PackagingElementPropertiesPanel {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.ui.properties.ElementWithManifestPropertiesPanel");
   private final E myElement;
   private final ArtifactEditorContext myContext;
   private JPanel myMainPanel;
   private TextFieldWithBrowseButton myMainClassField;
   private TextFieldWithBrowseButton myClasspathField;
   private JLabel myTitleLabel;
-  private TextFieldWithBrowseButton myManifestFilePathField;
+  private JButton myRemoveFromArtifactButton;
+  private JButton myCreateManifestButton;
+  private JButton myUseExistingManifestButton;
+  private JPanel myPropertiesPanel;
+  private JTextField myManifestPathField;
+  private JLabel myManifestNotFoundLabel;
   private ManifestFileConfiguration myManifestFileConfiguration;
 
   public ElementWithManifestPropertiesPanel(E element, final ArtifactEditorContext context) {
@@ -78,46 +94,123 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
       }
     });
 
-    myMainClassField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
-      @Override
-      protected void textChanged(DocumentEvent e) {
-        createManifestFileIfNeeded();
-      }
-    });
     myClasspathField.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
         Messages.showTextAreaDialog(myClasspathField.getTextField(), "Edit Classpath", "classpath-attribute-editor");
       }
     });
-    myManifestFilePathField.addBrowseFolderListener("Specify Path to MANIFEST.MF file", "", context.getProject(), new FileChooserDescriptor(true, false, false, false, false, false) {
-      @Override
-      public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
-        return super.isFileVisible(file, showHiddenFiles) && file.isDirectory() || file.getName().equalsIgnoreCase(ManifestFileUtil.MANIFEST_FILE_NAME);
-      }
-    });
     myClasspathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
       @Override
       protected void textChanged(DocumentEvent e) {
-        createManifestFileIfNeeded();
         myContext.queueValidation();
       }
     });
+    myUseExistingManifestButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        chooseManifest();
+      }
+    });
+    myCreateManifestButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        createManifest();
+      }
+    });
+
+    //todo[nik] do we really need this button?
+    myRemoveFromArtifactButton.setVisible(false);
+    myRemoveFromArtifactButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        removeManifest();
+      }
+    });
+  }
+
+  private void removeManifest() {
+  }
+
+  private void createManifest() {
+    FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
+    descriptor.setTitle("Select Directory for MANIFEST.MF file");
+    final VirtualFile[] files = FileChooser.chooseFiles(myContext.getProject(), descriptor, ManifestFileUtil.suggestManifestFileDirectory(myElement, myContext, myContext.getArtifactType()));
+    if (files.length != 1) return;
+
+    final Ref<IOException> exc = Ref.create(null);
+    final VirtualFile file = new WriteAction<VirtualFile>() {
+      protected void run(final Result<VirtualFile> result) {
+        VirtualFile dir = files[0];
+        try {
+          if (!dir.getName().equals(ManifestFileUtil.MANIFEST_DIR_NAME)) {
+            VirtualFile newDir = dir.findChild(ManifestFileUtil.MANIFEST_DIR_NAME);
+            if (newDir == null) {
+              newDir = dir.createChildDirectory(this, ManifestFileUtil.MANIFEST_DIR_NAME);
+            }
+            dir = newDir;
+          }
+          result.setResult(dir.createChildData(this, ManifestFileUtil.MANIFEST_FILE_NAME));
+        }
+        catch (IOException e) {
+          exc.set(e);
+        }
+      }
+    }.execute().getResultObject();
+
+    final IOException exception = exc.get();
+    if (exception != null) {
+      LOG.info(exception);
+      Messages.showErrorDialog(myMainPanel, exception.getMessage(), CommonBundle.getErrorTitle());
+      return;
+    }
+
+    PackagingElementFactory.getInstance().addFileCopy(myElement, ManifestFileUtil.MANIFEST_DIR_NAME, file.getPath());
+    myContext.getThisArtifactEditor().updateLayoutTree();
+    updateComponents(new ManifestFileConfiguration(null, null, file.getPath()));
+    apply();
+  }
+
+  private void chooseManifest() {
+    final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
+      @Override
+      public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+        return super.isFileVisible(file, showHiddenFiles) && (file.isDirectory() ||
+               file.getName().equalsIgnoreCase(ManifestFileUtil.MANIFEST_FILE_NAME));
+      }
+    };
+    descriptor.setTitle("Specify Path to MANIFEST.MF file");
+    final VirtualFile[] files = FileChooser.chooseFiles(myContext.getProject(), descriptor);
+    if (files.length != 1) return;
+
+    final String path = files[0].getPath();
+    PackagingElementFactory.getInstance().addFileCopy(myElement, ManifestFileUtil.MANIFEST_DIR_NAME, path);
+    myContext.getThisArtifactEditor().updateLayoutTree();
+    updateComponents(ManifestFileUtil.createManifestFileConfiguration(files[0]));
+    apply();
   }
 
-  private void createManifestFileIfNeeded() {
-    if ((myClasspathField.getText().trim().length() > 0 || myMainClassField.getText().trim().length() > 0)
-        && myManifestFilePathField.getText().length() == 0) {
-      final String path = ManifestFileUtil.suggestManifestFilePathAndAddElement(myElement, myContext, myContext.getArtifactType());
-      myManifestFilePathField.setText(FileUtil.toSystemDependentName(path));
+  private void updateComponents(@NotNull ManifestFileConfiguration configuration) {
+    final String manifestFilePath = configuration.getManifestFilePath();
+    final String card;
+    if (manifestFilePath != null) {
+      card = "properties";
+      myManifestPathField.setText(FileUtil.toSystemDependentName(manifestFilePath));
+      myMainClassField.setText(StringUtil.notNullize(configuration.getMainClass()));
+      myClasspathField.setText(StringUtil.join(configuration.getClasspath(), " "));
     }
+    else {
+      card = "buttons";
+      myManifestPathField.setText("");
+    }
+    ((CardLayout)myPropertiesPanel.getLayout()).show(myPropertiesPanel, card);
   }
 
   public void reset() {
     myTitleLabel.setText("'" + myElement.getName() + "' manifest properties:");
-    myMainClassField.setText(StringUtil.notNullize(myManifestFileConfiguration.getMainClass()));
-    myClasspathField.setText(StringUtil.join(myManifestFileConfiguration.getClasspath(), " "));
-    myManifestFilePathField.setText(FileUtil.toSystemDependentName(StringUtil.notNullize(myManifestFileConfiguration.getManifestFilePath())));
-    createManifestFileIfNeeded();
+    myManifestNotFoundLabel.setText("Manifest.mf file not found in '" + myElement.getName() + "'");
+    final VirtualFile file = ManifestFileUtil.findManifestFile(myElement, myContext, myContext.getArtifactType());
+    String path = file != null ? file.getPath() : null;
+    if (!Comparing.equal(path, myManifestFileConfiguration.getManifestFilePath())) {
+      myManifestFileConfiguration.copyFrom(ManifestFileUtil.createManifestFileConfiguration(file));
+    }
+    updateComponents(myManifestFileConfiguration);
   }
 
   public boolean isModified() {
@@ -128,7 +221,7 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
 
   @Nullable
   private String getConfiguredManifestPath() {
-    final String path = myManifestFilePathField.getText();
+    final String path = myManifestPathField.getText();
     return path.length() != 0 ? FileUtil.toSystemIndependentName(path) : null;
   }
 
index 5b2fb7bb1d0d99d387b11b60c889f297a2f423ec..a308f75c93473ff12446a235a17ee8e09a3ea6ed 100644 (file)
@@ -36,6 +36,7 @@ import java.util.Set;
 
 public abstract class BuildProperties extends CompositeGenerator {
     public static final @NonNls String TARGET_ALL = "all";
+    public static final @NonNls String TARGET_BUILD_MODULES = "build.modules";
     public static final @NonNls String TARGET_CLEAN = "clean";
     public static final @NonNls String TARGET_INIT = "init";
     public static final @NonNls String DEFAULT_TARGET = TARGET_ALL;
index da5a5ca5f0e5366a0edd6c35a51c0ab34e904ad8..50d16dad85c640ff392e303793bac97dd3f6e17f 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.packaging.artifacts;
 
 import com.intellij.packaging.elements.CompositePackagingElement;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author nik
@@ -38,4 +39,6 @@ public interface ModifiableArtifactModel extends ArtifactModel {
 
   void commit();
 
+  @Nullable
+  Artifact getModifiableCopy(Artifact artifact);
 }
index 8d9bb89573c3d84d4ce3bda444b450640e2ab99f..e8b481e277a8638ce3e1e4c90ec138a3c0b78e43 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
  * @author nik
  */
 public interface ArtifactEditor {
+  void updateLayoutTree();
 
   void putLibraryIntoDefaultLocation(@NotNull Library library);
 
index 0e4457319a1da3701e75cd5c41986062a96bcc26..f144832e6322489d5a5bf37a3c5465ba4805abc5 100644 (file)
@@ -43,12 +43,16 @@ public interface ArtifactEditorContext extends PackagingElementResolvingContext
   @NotNull
   ManifestFileConfiguration getManifestFile(CompositePackagingElement<?> element, ArtifactType artifactType);
 
+  boolean isManifestFile(String path);
+
+
   CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact);
 
   void editLayout(@NotNull Artifact artifact, Runnable runnable);
 
   ArtifactEditor getOrCreateEditor(Artifact originalArtifact);
 
+  ArtifactEditor getThisArtifactEditor();
 
   void selectArtifact(@NotNull Artifact artifact);
 
index 34b38455e97f337501103e02df0280dd2b2a395a..c3d26553eae62db06556030ee949cdb378937391 100644 (file)
@@ -15,6 +15,9 @@
  */
 package com.intellij.packaging.ui;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
 import java.util.List;
 import java.util.ArrayList;
 
@@ -26,18 +29,25 @@ public class ManifestFileConfiguration {
   private String myMainClass;
   private String myManifestFilePath;
 
-  public ManifestFileConfiguration(ManifestFileConfiguration configuration) {
-    myClasspath = new ArrayList<String>(configuration.getClasspath());
-    myMainClass = configuration.getMainClass();
-    myManifestFilePath = configuration.getManifestFilePath();
+  public ManifestFileConfiguration(@NotNull ManifestFileConfiguration configuration) {
+    copyFrom(configuration);
   }
 
-  public ManifestFileConfiguration(List<String> classpath, String mainClass, String manifestFilePath) {
-    myClasspath = classpath;
+  public ManifestFileConfiguration(@Nullable List<String> classpath, @Nullable String mainClass, @Nullable String manifestFilePath) {
+    if (classpath != null) {
+      myClasspath.addAll(classpath);
+    }
     myMainClass = mainClass;
     myManifestFilePath = manifestFilePath;
   }
 
+  public void copyFrom(@NotNull ManifestFileConfiguration configuration) {
+    myClasspath.clear();
+    myClasspath.addAll(configuration.getClasspath());
+    myMainClass = configuration.getMainClass();
+    myManifestFilePath = configuration.getManifestFilePath();
+  }
+
   public List<String> getClasspath() {
     return myClasspath;
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java b/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java
new file mode 100644 (file)
index 0000000..79038ce
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2009 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.debugger.impl.descriptors.data;
+
+import com.intellij.debugger.ui.impl.watch.ArgumentValueDescriptorImpl;
+import com.intellij.openapi.project.Project;
+import com.sun.jdi.Value;
+
+public class ArgValueData extends DescriptorData<ArgumentValueDescriptorImpl>{
+  private final int myIndex;
+  private final Value myValue;
+
+  public ArgValueData(int index, Value value) {
+    super();
+    myIndex = index;
+    myValue = value;
+  }
+
+  protected ArgumentValueDescriptorImpl createDescriptorImpl(Project project) {
+    return new ArgumentValueDescriptorImpl(project, myIndex, myValue);
+  }
+
+  public boolean equals(Object object) {
+    if(!(object instanceof ArgValueData)) return false;
+
+    return myIndex == ((ArgValueData)object).myIndex;
+  }
+
+  public int hashCode() {
+    return myIndex;
+  }
+
+  public DisplayKey<ArgumentValueDescriptorImpl> getDisplayKey() {
+    return new SimpleDisplayKey<ArgumentValueDescriptorImpl>(myIndex);
+  }
+}
\ No newline at end of file
index 72aa2d1a27b64efbf7cffc263d8dcac6f66bc191..cdc7c1ed2f2f8c5e449b884122eb68359079c278 100644 (file)
@@ -25,10 +25,13 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
 import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
 import com.intellij.debugger.engine.jdi.StackFrameProxy;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.ArrayUtil;
 import com.sun.jdi.*;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.*;
 
 public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
@@ -248,6 +251,34 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
     }
   }
 
+  public Collection<Value> getArgumentValues() throws EvaluateException {
+    DebuggerManagerThreadImpl.assertIsManagerThread();
+    try {
+      final StackFrame stackFrame = getStackFrame();
+      if (stackFrame != null) {
+        //return stackFrame.getArgumentValues();
+        try {
+          final Method method = StackFrame.class.getMethod("getArgumentValues");
+          //noinspection unchecked
+          return (Collection<Value>)method.invoke(stackFrame, ArrayUtil.EMPTY_OBJECT_ARRAY);
+        }
+        catch (NoSuchMethodException ignored) {
+        }
+        catch (InvocationTargetException e) {
+          throw new EvaluateException("", e.getCause());
+        }
+        catch (IllegalAccessException e) {
+          LOG.error(e);
+        }
+      }
+      return Collections.emptyList();
+    }
+    catch (InvalidStackFrameException e) {
+      clearCaches();
+      return getArgumentValues();
+    }
+  }
+
   private Map<LocalVariable, Value> getAllValues() throws EvaluateException{
     DebuggerManagerThreadImpl.assertIsManagerThread();
     checkValid();
index 1f228a4502f22e1b403bb5aee2f2a05023dc9bab..db0ac8c2e2ea3b29f3c1bb0cb185f660da4bbdad 100644 (file)
@@ -40,6 +40,7 @@ import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.jsp.JspFile;
+import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.util.Processor;
@@ -104,7 +105,16 @@ public class LineBreakpoint extends BreakpointWithHighlighter {
     myMethodName = LineBreakpoint.findMethodName(file, getHighlighter().getStartOffset());
   }
 
+  protected void createOrWaitPrepare(DebugProcessImpl debugProcess, String classToBeLoaded) {
+    if (isInScopeOf(debugProcess)) {
+      super.createOrWaitPrepare(debugProcess, classToBeLoaded);
+    }
+  }
+
   protected void createRequestForPreparedClass(final DebugProcessImpl debugProcess, final ReferenceType classType) {
+    if (!isInScopeOf(debugProcess)) {
+      return;
+    }
     ApplicationManager.getApplication().runReadAction(new Runnable() {
       public void run() {
         try {
@@ -160,6 +170,15 @@ public class LineBreakpoint extends BreakpointWithHighlighter {
     });
   }
 
+  private boolean isInScopeOf(DebugProcessImpl debugProcess) {
+    final SourcePosition position = getSourcePosition();
+    if (position != null) {
+      final GlobalSearchScope scope = debugProcess.getSearchScope();
+      return scope.accept(position.getFile().getVirtualFile());
+    }
+    return true;
+  }
+
   public boolean evaluateCondition(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
     if(CLASS_FILTERS_ENABLED){
       Value value = context.getThisObject();
@@ -173,9 +192,8 @@ public class LineBreakpoint extends BreakpointWithHighlighter {
       }
       ClassFilter [] filters = getClassFilters();
       boolean matches = false;
-      for (int i = 0; i < filters.length; i++) {
-        ClassFilter classFilter = filters[i];
-        if(classFilter.isEnabled() && classFilter.matches(name)) {
+      for (ClassFilter classFilter : filters) {
+        if (classFilter.isEnabled() && classFilter.matches(name)) {
           matches = true;
           break;
         }
@@ -185,9 +203,8 @@ public class LineBreakpoint extends BreakpointWithHighlighter {
       }
 
       ClassFilter [] ifilters = getClassExclusionFilters();
-      for (int i = 0; i < ifilters.length; i++) {
-        ClassFilter classFilter = ifilters[i];
-        if(classFilter.isEnabled() && classFilter.matches(name)) {
+      for (ClassFilter classFilter : ifilters) {
+        if (classFilter.isEnabled() && classFilter.matches(name)) {
           return false;
         }
       }
index f5e190b8bf5e6a8dbc0dcda1d2dd886c010ceb09..79ee2da471a3c413871eb34c5bfafb42e6ea26d1 100644 (file)
@@ -51,7 +51,9 @@ import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.text.CharArrayUtil;
 import com.intellij.util.ui.tree.TreeModelAdapter;
+import com.sun.jdi.AbsentInformationException;
 import com.sun.jdi.ObjectCollectedException;
+import com.sun.jdi.Value;
 
 import javax.swing.event.TreeModelEvent;
 import javax.swing.tree.TreeModel;
@@ -116,34 +118,54 @@ public class FrameDebuggerTree extends DebuggerTree {
       super(stackNode);
     }
     
-    protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext)
-      throws EvaluateException {
+    protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
       final SourcePosition sourcePosition = getDebuggerContext().getSourcePosition();
       if (sourcePosition == null) {
         return;
       }
-      final Map<String, LocalVariableProxyImpl> visibleVariables = getVisibleVariables(stackDescriptor);
-      final Pair<Set<String>, Set<TextWithImports>> usedVars =
-        ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
-          public Pair<Set<String>, Set<TextWithImports>> compute() {
-            return findReferencedVars(visibleVariables.keySet(), sourcePosition);
+      try {
+        final Map<String, LocalVariableProxyImpl> visibleVariables = getVisibleVariables(stackDescriptor);
+        final Pair<Set<String>, Set<TextWithImports>> usedVars =
+          ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
+            public Pair<Set<String>, Set<TextWithImports>> compute() {
+              return findReferencedVars(visibleVariables.keySet(), sourcePosition);
+            }
+          });
+        // add locals
+        if (myAutoWatchMode) {
+          for (String var : usedVars.first) {
+            final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, visibleVariables.get(var));
+            myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));
           }
-        });
-      // add locals
-      if (myAutoWatchMode) {
-        for (String var : usedVars.first) {
-          final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, visibleVariables.get(var));
-          myChildren.add(myNodeManager.createNode(descriptor, evaluationContext));
+        }
+        else {
+          super.buildVariables(stackDescriptor, evaluationContext);
+        }
+        // add expressions
+        final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
+        evalContextCopy.setAutoLoadClasses(false);
+        for (TextWithImports text : usedVars.second) {
+          myChildren.add(myNodeManager.createNode(myNodeManager.getWatchItemDescriptor(stackDescriptor, text, null), evalContextCopy));
         }
       }
-      else {
-        super.buildVariables(stackDescriptor, evaluationContext);
-      }
-      // add expressions
-      final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
-      evalContextCopy.setAutoLoadClasses(false);
-      for (TextWithImports text : usedVars.second) {
-        myChildren.add(myNodeManager.createNode(myNodeManager.getWatchItemDescriptor(stackDescriptor, text, null), evalContextCopy));
+      catch (EvaluateException e) {
+        if (e.getCause() instanceof AbsentInformationException) {
+          final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();
+          if (frame == null) {
+            throw e;
+          }
+          final Collection<Value> argValues = frame.getArgumentValues();
+          int index = 0;
+          for (Value argValue : argValues) {
+            final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(stackDescriptor, index++, argValue);
+            final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(descriptor, evaluationContext);
+            myChildren.add(variableNode);
+          }
+          myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
+        }
+        else {
+          throw e;
+        }
       }
     }
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java
new file mode 100644 (file)
index 0000000..b4b5cd9
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2009 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.debugger.ui.impl.watch;
+
+import com.intellij.debugger.DebuggerContext;
+import com.intellij.debugger.SourcePosition;
+import com.intellij.debugger.engine.ContextUtil;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiParameterList;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.sun.jdi.PrimitiveValue;
+import com.sun.jdi.Value;
+
+public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{
+  private final int myIndex;
+  private final Value myValue;
+  private String myName;
+
+  public ArgumentValueDescriptorImpl(Project project, int index, Value value) {
+    super(project);
+    myIndex = index;
+    myValue = value;
+    myName = "arg" + String.valueOf(index);
+    setLvalue(true);
+  }
+
+  public boolean isPrimitive() {
+    return myValue instanceof PrimitiveValue;
+  }
+
+  public Value calcValue(final EvaluationContextImpl evaluationContext) throws EvaluateException {
+    ApplicationManager.getApplication().runReadAction(new Runnable() {
+      public void run() {
+        final SourcePosition position = ContextUtil.getSourcePosition(evaluationContext);
+        if (position != null) {
+          final PsiMethod method = PsiTreeUtil.getParentOfType(position.getElementAt(), PsiMethod.class);
+          if (method != null) {
+            final PsiParameterList params = method.getParameterList();
+            if (myIndex < params.getParametersCount()) {
+              final PsiParameter param = params.getParameters()[myIndex];
+              myName = param.getName();
+            }
+          }
+        }
+      }
+    });
+    return myValue;
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public String calcValueName() {
+    return getName();
+  }
+
+  public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
+    return null;
+  }
+}
\ No newline at end of file
index 8d8ddbb4b58403dd4bb63e5d18a36e6094a5a7f1..b3f3393156eaf67f8fbed08b15dec5a8e8371650 100644 (file)
@@ -538,13 +538,14 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
       updateUI(true);
     }
 
-    protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext)
-      throws EvaluateException {
+    protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
       final StackFrameProxyImpl frame = stackDescriptor.getFrameProxy();
-      for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
-        final LocalVariableDescriptorImpl localVariableDescriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, local);
-        final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(localVariableDescriptor, evaluationContext);
-        myChildren.add(variableNode);
+      if (frame != null) {
+        for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
+          final LocalVariableDescriptorImpl localVariableDescriptor = myNodeManager.getLocalVariableDescriptor(stackDescriptor, local);
+          final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(localVariableDescriptor, evaluationContext);
+          myChildren.add(variableNode);
+        }
       }
     }
   }
index 5c34134a24547cd330fb476886a265ff4a3e4559..575f1260d37e4a81faddebea54af386ce3c528c8 100644 (file)
@@ -152,6 +152,10 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory {
     return getDescriptor(parent, new LocalData((LocalVariableProxyImpl)local));
   }
 
+  public ArgumentValueDescriptorImpl getArgumentValueDescriptor(NodeDescriptor parent, int index, Value value) {
+    return getDescriptor(parent, new ArgValueData(index, value));
+  }
+
   public StackFrameDescriptorImpl getStackFrameDescriptor(NodeDescriptorImpl parent, StackFrameProxyImpl frameProxy) {
     return getDescriptor(parent, new StackFrameData(frameProxy));
   }
index 33f15ad9f06da04b812643aee9fe6c9f845e1825..c082ab9d3899c2ea4b789b861ad1a060f066c7c3 100644 (file)
@@ -25,7 +25,6 @@ import com.intellij.facet.ui.FacetEditorContext;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.ModifiableRootModel;
 import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
 import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
@@ -47,7 +46,7 @@ import java.util.*;
  */
 public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.ChangeListener {
   private static final Logger LOG = Logger.getInstance("#com.intellij.facet.impl.ProjectFacetsConfigurator");
-  private final Map<Module, ModifiableFacetModel> myModels = new HashMap<Module, ModifiableFacetModel>();
+  private final Map<Module, ModifiableFacetModel> myModifiableModels = new HashMap<Module, ModifiableFacetModel>();
   private final Map<Facet, FacetEditorImpl> myEditors = new HashMap<Facet, FacetEditorImpl>();
   private final Map<Module, FacetTreeModel> myTreeModels = new HashMap<Module, FacetTreeModel>();
   private final Map<FacetInfo, Facet> myInfo2Facet = new HashMap<FacetInfo, Facet>();
@@ -57,12 +56,10 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
   private final Set<Facet> myChangedFacets = new HashSet<Facet>();
   private final Set<Facet> myCreatedFacets = new HashSet<Facet>();
   private final StructureConfigurableContext myContext;
-  private final Project myProject;
   private UserDataHolderBase myProjectData = new UserDataHolderBase();
 
-  public ProjectFacetsConfigurator(final StructureConfigurableContext context, Project project, ProjectFacetsConfigurator facetsConfigurator) {
+  public ProjectFacetsConfigurator(final StructureConfigurableContext context, ProjectFacetsConfigurator facetsConfigurator) {
     myContext = context;
-    myProject = project;
 
     if (facetsConfigurator != null) {
       initFrom(facetsConfigurator);
@@ -73,6 +70,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
     myFacet2Info.putAll(facetsConfigurator.myFacet2Info);
     myInfo2Facet.putAll(facetsConfigurator.myInfo2Facet);
     myTreeModels.putAll(facetsConfigurator.myTreeModels);
+    myEditors.putAll(facetsConfigurator.myEditors);
   }
 
   public List<Facet> removeFacet(Facet facet) {
@@ -136,7 +134,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
   }
 
   public void clearMaps() {
-    myModels.clear();
+    myModifiableModels.clear();
     myEditors.clear();
     myTreeModels.clear();
     myInfo2Facet.clear();
@@ -146,13 +144,13 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
   }
 
   private boolean isNewFacet(Facet facet) {
-    final ModifiableFacetModel model = myModels.get(facet.getModule());
+    final ModifiableFacetModel model = myModifiableModels.get(facet.getModule());
     return model != null && model.isNewFacet(facet);
   }
 
   @NotNull
   public ModifiableFacetModel getOrCreateModifiableModel(final Module module) {
-    ModifiableFacetModel model = myModels.get(module);
+    ModifiableFacetModel model = myModifiableModels.get(module);
     if (model == null) {
       model = FacetManager.getInstance(module).createModifiableModel();
       model.addListener(new ModifiableFacetModel.Listener() {
@@ -160,7 +158,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
           fireFacetModelChanged(module);
         }
       }, null);
-      myModels.put(module, model);
+      myModifiableModels.put(module, model);
     }
     return model;
   }
@@ -210,7 +208,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
 
   @NotNull
   public FacetModel getFacetModel(Module module) {
-    final ModifiableFacetModel model = myModels.get(module);
+    final ModifiableFacetModel model = myModifiableModels.get(module);
     if (model != null) {
       return model;
     }
@@ -218,7 +216,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
   }
 
   public void commitFacets() {
-    for (ModifiableFacetModel model : myModels.values()) {
+    for (ModifiableFacetModel model : myModifiableModels.values()) {
       model.commit();
     }
 
@@ -226,7 +224,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
       entry.getValue().onFacetAdded(entry.getKey());
     }
 
-    myModels.clear();
+    myModifiableModels.clear();
     for (Facet facet : myChangedFacets) {
       Module module = facet.getModule();
       if (!module.isDisposed()) {
@@ -253,7 +251,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
   }
 
   public boolean isModified() {
-    for (ModifiableFacetModel model : myModels.values()) {
+    for (ModifiableFacetModel model : myModifiableModels.values()) {
       if (model.isModified()) {
         return true;
       }
@@ -349,7 +347,7 @@ public class ProjectFacetsConfigurator implements FacetsProvider, ModuleEditor.C
       facets.addAll(removeFacet(facet));
     }
     mySharedModuleData.remove(module);
-    myModels.remove(module);
+    myModifiableModels.remove(module);
     return facets;
   }
 
index c2c035a86485a60bc61e9136324624fd734448f2..082be71429f9140fe92844fd9b5fcbdd7fbacf99 100644 (file)
@@ -180,7 +180,7 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
     return new ModuleConfigurationStateImpl(myProject, myModulesProvider) {
       @Override
       public ModifiableRootModel getRootModel() {
-        return getModifiableRootModel();
+        return getModifiableRootModelProxy();
       }
 
       @Override
index af831c50b30032ebc0d33a9f022bb2c4e64ee79d..5005d8fc7cc96ccd6d506da7dfb341573de86a8c 100644 (file)
@@ -242,8 +242,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
         catch (ConfigurationException e) {
           ex[0] = e;
         }
-        finally {
-          myFacetsConfigurator.disposeEditors();
+        finally {          
           ModuleStructureConfigurable.getInstance(myProject).getFacetEditorFacade().clearMaps();
 
           for (final ModuleEditor moduleEditor : myModuleEditors) {
@@ -275,7 +274,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
   }
 
   private ProjectFacetsConfigurator createFacetsConfigurator() {
-    return new ProjectFacetsConfigurator(myContext, myProject, myFacetsConfigurator);
+    return new ProjectFacetsConfigurator(myContext, myFacetsConfigurator);
   }
 
   public void setModified(final boolean modified) {
index c0cae5f5ccf8684ef4dd509476341a07e9123231..9ef57021c93536c394b70f6e69e95e6beccd7b01 100644 (file)
@@ -66,6 +66,10 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
     return myParent.getManifestFile(element, artifactType);
   }
 
+  public boolean isManifestFile(String path) {
+    return myParent.isManifestFile(path);
+  }
+
   @NotNull
   public Project getProject() {
     return myParent.getProject();
@@ -83,6 +87,10 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
     return myParent.getOrCreateEditor(artifact);
   }
 
+  public ArtifactEditor getThisArtifactEditor() {
+    return myEditor;
+  }
+
   public void selectArtifact(@NotNull Artifact artifact) {
     ProjectStructureConfigurable.getInstance(getProject()).select(artifact, true);
   }
index 782a77cf7e91e5639c6087022703dc996d4cef33..6700b1da30ca12ad29ca9267678c764d22acab0f 100644 (file)
@@ -356,13 +356,14 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
       setOutputPath(ArtifactUtil.getDefaultArtifactOutputPath(newArtifactName, myProject));
       final CompositePackagingElement<?> root = getRootElement();
       if (root instanceof ArchivePackagingElement) {
+        String oldFileName = FileUtil.sanitizeFileName(oldArtifactName);
         final String name = ((ArchivePackagingElement)root).getArchiveFileName();
         final String fileName = FileUtil.getNameWithoutExtension(name);
         final String extension = FileUtil.getExtension(name);
-        if (fileName.equals(oldArtifactName) && extension.length() > 0) {
+        if (fileName.equals(oldFileName) && extension.length() > 0) {
           myLayoutTreeComponent.editLayout(new Runnable() {
             public void run() {
-              ((ArchivePackagingElement)getRootElement()).setArchiveFileName(newArtifactName + "." + extension);
+              ((ArchivePackagingElement)getRootElement()).setArchiveFileName(FileUtil.sanitizeFileName(newArtifactName) + "." + extension);
             }
           });
           myLayoutTreeComponent.updateRootNode();
@@ -371,6 +372,10 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
     }
   }
 
+  public void updateLayoutTree() {
+    myLayoutTreeComponent.rebuildTree();
+  }
+
   public void putLibraryIntoDefaultLocation(@NotNull Library library) {
     myLayoutTreeComponent.putIntoDefaultLocations(Collections.singletonList(new LibrarySourceItem(library)));
   }
@@ -392,10 +397,8 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
 
     final CompositePackagingElement<?> oldRootElement = getRootElement();
     final CompositePackagingElement<?> newRootElement = artifactType.createRootElement(getArtifact().getName());
-    if (!newRootElement.getType().equals(oldRootElement.getType())) {
-      ArtifactUtil.copyChildren(oldRootElement, newRootElement, myProject);
-      myLayoutTreeComponent.setRootElement(newRootElement);
-    }
+    ArtifactUtil.copyChildren(oldRootElement, newRootElement, myProject);
+    myLayoutTreeComponent.setRootElement(newRootElement);
   }
 
   private class MyDataProvider implements TypeSafeDataProvider {
index 3096eb3b7b41eb474c04c4c33968ae3e9745f888..c4f992179cc62f547bcea0d30bae5736b068d0be 100644 (file)
@@ -34,6 +34,8 @@ public interface ArtifactsStructureConfigurableContext extends PackagingElementR
   @NotNull
   ManifestFileConfiguration getManifestFile(CompositePackagingElement<?> element, ArtifactType artifactType);
 
+  boolean isManifestFile(String path);
+
   CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact);
 
   void editLayout(@NotNull Artifact artifact, Runnable action);
index 8f6dc39bdff65a971834edd516576a158326f17b..6f3ade014cf355be573258bffa6f2256860c95ad 100644 (file)
@@ -77,15 +77,19 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
   public CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact) {
     artifact = getOriginalArtifact(artifact);
     if (myModifiableModel != null) {
-      final CompositePackagingElement<?> rootElement = myModifiableModel.getArtifactByOriginal(artifact).getRootElement();
-      if (rootElement != artifact.getRootElement()) {
-        myModifiableRoots.put(artifact, rootElement);
+      final Artifact modifiableArtifact = myModifiableModel.getModifiableCopy(artifact);
+      if (modifiableArtifact != null) {
+        myModifiableRoots.put(artifact, modifiableArtifact.getRootElement());
       }
     }
-    CompositePackagingElement<?> root = myModifiableRoots.get(artifact);
+    return getOrCreateModifiableRootElement(artifact);
+  }
+
+  private CompositePackagingElement<?> getOrCreateModifiableRootElement(Artifact originalArtifact) {
+    CompositePackagingElement<?> root = myModifiableRoots.get(originalArtifact);
     if (root == null) {
-      root = ArtifactUtil.copyFromRoot(artifact.getRootElement(), myProject);
-      myModifiableRoots.put(artifact, root);
+      root = ArtifactUtil.copyFromRoot(originalArtifact.getRootElement(), myProject);
+      myModifiableRoots.put(originalArtifact, root);
     }
     return root;
   }
@@ -94,7 +98,7 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
     artifact = getOriginalArtifact(artifact);
     final ModifiableArtifact modifiableArtifact = getModifiableArtifactModel().getOrCreateModifiableArtifact(artifact);
     if (modifiableArtifact.getRootElement() == artifact.getRootElement()) {
-      modifiableArtifact.setRootElement(getRootElement(artifact));
+      modifiableArtifact.setRootElement(getOrCreateModifiableRootElement(artifact));
     }
     action.run();
     myContext.getDaemonAnalyzer().queueUpdate(new ArtifactProjectStructureElement(myContext, this, artifact));
@@ -144,6 +148,10 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
     return myManifestFilesInfo.getManifestFile(element, artifactType, this);
   }
 
+  public boolean isManifestFile(String path) {
+    return myManifestFilesInfo.isManifestFile(path);
+  }
+
   public ManifestFilesInfo getManifestFilesInfo() {
     return myManifestFilesInfo;
   }
index c1810e4e75719438dc4fe2bc4ecd5866fad7835e..76c83417efe92f9051056d8c9103fef251b938a9 100644 (file)
@@ -130,7 +130,7 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
 
   public void updatePropertiesPanel(final boolean force) {
     final PackagingElement<?> selected = getSelection().getElementIfSingle();
-    if (force || Comparing.equal(selected, mySelectedElementInfo.myElement)) {
+    if (!force && Comparing.equal(selected, mySelectedElementInfo.myElement)) {
       return;
     }
     mySelectedElementInfo.save();
@@ -504,6 +504,7 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
       else {
         cardLayout.show(myPropertiesPanelWrapper, EMPTY_CARD);
       }
+      myPropertiesPanelWrapper.repaint();
     }
   }
 
index f937d26b2975766459dd814223b884d602aea1a0..5a643cfbc110edd1dc55aedfe156ae102bc263ac 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.packaging.elements.CompositePackagingElement;
 import com.intellij.packaging.elements.PackagingElementResolvingContext;
 import com.intellij.packaging.impl.elements.ManifestFileUtil;
 import com.intellij.packaging.ui.ManifestFileConfiguration;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
 import java.util.Map;
@@ -79,4 +80,13 @@ public class ManifestFilesInfo {
     myManifestFiles.clear();
     myOriginalManifestFiles.clear();
   }
+
+  public boolean isManifestFile(@NotNull String path) {
+    for (ManifestFileConfiguration configuration : myManifestFiles.values()) {
+      if (path.equals(configuration.getManifestFilePath())) {
+        return true;
+      }
+    }
+    return false;
+  }
 }
\ No newline at end of file
index 7753c4c652af3277747a118c05f8b7ee20daf9be..f7beb9aed5ba586a82f259ec0ccf4c97186f6a91 100644 (file)
@@ -25,7 +25,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
   private Set<ProjectStructureElement> myElementWithNotCalculatedUsages = new HashSet<ProjectStructureElement>();
   private MergingUpdateQueue myAnalyzerQueue;
   private List<Runnable> myListeners = new ArrayList<Runnable>();
-  private boolean myDisposed;
+  private boolean myStopped;
 
   public ProjectStructureDaemonAnalyzer(StructureConfigurableContext context) {
     Disposer.register(context, this);
@@ -33,7 +33,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
   }
 
   private void doUpdate(final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
-    if (myDisposed) return;
+    if (myStopped) return;
 
     if (check) {
       doCheck(element);
@@ -47,6 +47,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
     final ProjectStructureProblemsHolder problemsHolder = new ProjectStructureProblemsHolder();
     new ReadAction() {
       protected void run(final Result result) {
+        if (myStopped) return;
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("checking " + element);
         }
@@ -55,6 +57,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
     }.execute();
     invokeLater(new Runnable() {
       public void run() {
+        if (myStopped) return;
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("updating problems for " + element);
         }
@@ -74,6 +78,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
   private void doCollectUsages(final ProjectStructureElement element) {
     final List<ProjectStructureElementUsage> usages = new ReadAction<List<ProjectStructureElementUsage>>() {
       protected void run(final Result<List<ProjectStructureElementUsage>> result) {
+        if (myStopped) return;
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("collecting usages in " + element);
         }
@@ -83,6 +89,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
 
     invokeLater(new Runnable() {
       public void run() {
+        if (myStopped) return;
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("updating usages for " + element);
         }
@@ -158,6 +166,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
 
   public void stop() {
     LOG.debug("analyzer stopped");
+    myStopped = true;
     myAnalyzerQueue.cancelAllUpdates();
     clearCaches();
     myAnalyzerQueue.deactivate();
@@ -174,7 +183,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
   }
 
   public void dispose() {
-    myDisposed = true;
+    myStopped = true;
     myAnalyzerQueue.cancelAllUpdates();
   }
 
@@ -202,7 +211,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
     myAnalyzerQueue.activate();
     myAnalyzerQueue.queue(new Update("reset") {
       public void run() {
-        myDisposed = false;
+        myStopped = false;
       }
     });
   }
index 052238566e30fe1a9ebbaed0374b36b48b211727..2b715b33d15c3a210c72bc3471200c180633972e 100644 (file)
 
 package com.intellij.util.descriptors.impl;
 
-import com.intellij.util.descriptors.CustomConfigFileSet;
-import com.intellij.util.descriptors.CustomConfigFile;
-import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.util.descriptors.CustomConfigFile;
+import com.intellij.util.descriptors.CustomConfigFileSet;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * @author nik
@@ -58,7 +57,11 @@ public class CustomConfigFileSetImpl implements CustomConfigFileSet {
     myDescriptors.addAll(descriptors);
   }
 
-  public void readExternal(Element element) throws InvalidDataException {
+  public void readExternal(Element element) {
+    doReadExternal(element, new ArrayList<Element>());
+  }
+
+  public void doReadExternal(Element element, List<Element> descriptorElements) {
     myDescriptors.clear();
     List<Element> descriptors = element.getChildren(ELEMENT_NAME);
     for (Element descriptor : descriptors) {
@@ -66,6 +69,7 @@ public class CustomConfigFileSetImpl implements CustomConfigFileSet {
       String directory = getDefaultDirOption(descriptor);
       if (directory != null) {
         myDescriptors.add(new CustomConfigFile(url, directory));
+        descriptorElements.add(descriptor);
       }
     }
   }
index 52c45d7d6570c2e0c0e8ea558b62ae2a70c11276..7cea048cd910f26e90c68f3e7955258a39649af5 100644 (file)
 package com.intellij.application.options;
 
 import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.editor.SyntaxHighlighterColors;
+import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.ui.VerticalFlowLayout;
 import com.intellij.openapi.ui.ex.MultiLineLabel;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.PackageEntry;
+import com.intellij.psi.codeStyle.PackageEntryTable;
 import com.intellij.ui.*;
 import com.intellij.util.ui.Table;
 
 import javax.swing.*;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableCellEditor;
-import javax.swing.table.TableModel;
+import javax.swing.event.*;
+import javax.swing.table.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 
 public class CodeStyleImportsPanel extends JPanel {
   private JCheckBox myCbUseFQClassNames;
@@ -41,9 +44,8 @@ public class CodeStyleImportsPanel extends JPanel {
   private JCheckBox myCbAddUnambiguousImportsOnTheFly;
   private JTextField myClassCountField;
   private JTextField myNamesCountField;
-  private final CodeStyleSettings.ImportLayoutTable myImportLayoutList = new CodeStyleSettings.ImportLayoutTable();
-  private CodeStyleSettings.PackageTable myPackageList = new CodeStyleSettings.PackageTable();
-  private CodeStyleSettings.ImportLayoutTable.PackageEntry myOtherPackageEntry = null;
+  private final PackageEntryTable myImportLayoutList = new PackageEntryTable();
+  private final PackageEntryTable myPackageList = new PackageEntryTable();
 
   private Table myImportLayoutTable;
   private JButton myMoveUpButton;
@@ -60,6 +62,7 @@ public class CodeStyleImportsPanel extends JPanel {
   private JPanel myPackagesPanel;
   private JPanel myImportsLayoutPanel;
   private JPanel myWholePanel;
+  private JCheckBox myCbLayoutStaticImportsSeparately;
 
   public CodeStyleImportsPanel(CodeStyleSettings settings){
     mySettings = settings;
@@ -69,8 +72,8 @@ public class CodeStyleImportsPanel extends JPanel {
 
     myGeneralPanel.add(createGeneralOptionsPanel(), BorderLayout.CENTER);
     myJSPPanel.add(createJspImportLayoutPanel(), BorderLayout.CENTER);
-    myPackagesPanel.add(createPackagesPanel(), BorderLayout.NORTH);
     myImportsLayoutPanel.add(createImportLayoutPanel(), BorderLayout.NORTH);
+    myPackagesPanel.add(createPackagesPanel(), BorderLayout.NORTH);
   }
 
   private JPanel createJspImportLayoutPanel() {
@@ -157,12 +160,57 @@ public class CodeStyleImportsPanel extends JPanel {
   private JPanel createImportLayoutPanel() {
     JPanel panel = new JPanel(new BorderLayout());
     panel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("title.import.layout")));
+    myCbLayoutStaticImportsSeparately = new JCheckBox("Layout static imports separately");
+
+    myCbLayoutStaticImportsSeparately.addItemListener(new ItemListener(){
+      public void itemStateChanged(ItemEvent e) {
+        if (areStaticImportsEnabled()) {
+          boolean found = false;
+          for (int i=myImportLayoutList.getEntryCount()-1; i>=0; i--) {
+            PackageEntry entry = myImportLayoutList.getEntryAt(i);
+            if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
+              found = true;
+              break;
+            }
+          }
+          if (!found) {
+            int index = myImportLayoutList.getEntryCount();
+            if (index != 0 && myImportLayoutList.getEntryAt(index-1) != PackageEntry.BLANK_LINE_ENTRY) {
+              myImportLayoutList.addEntry(PackageEntry.BLANK_LINE_ENTRY);
+            }
+            myImportLayoutList.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
+          }
+        }
+        else {
+          for (int i=myImportLayoutList.getEntryCount()-1; i>=0; i--) {
+            PackageEntry entry = myImportLayoutList.getEntryAt(i);
+            if (entry.isStatic()) {
+              myImportLayoutList.removeEntryAt(i);
+            }
+          }
+        }
+        refreshTable(myImportLayoutTable, myImportLayoutList);
+        refreshTable(myPackageTable, myPackageList);
+      }
+    });
+    panel.add(myCbLayoutStaticImportsSeparately, BorderLayout.NORTH);
     panel.add(createImportLayoutTable(), BorderLayout.CENTER);
     panel.add(createImportLayoutButtonsPanel(), BorderLayout.EAST);
     panel.setPreferredSize(new Dimension(-1, 200));
     return panel;
   }
 
+  private void refreshTable(final Table table, final PackageEntryTable packageTable) {
+    AbstractTableModel model = (AbstractTableModel)table.getModel();
+    table.createDefaultColumnsFromModel();
+    model.fireTableDataChanged();
+    resizeColumns(packageTable, table);
+  }
+
+  private boolean areStaticImportsEnabled() {
+    return myCbLayoutStaticImportsSeparately.isSelected();
+  }
+
   private JPanel createImportLayoutButtonsPanel() {
     JPanel tableButtonsPanel = new JPanel(new VerticalFlowLayout());
 
@@ -258,7 +306,7 @@ public class CodeStyleImportsPanel extends JPanel {
     if(selected < 0) {
       selected = myImportLayoutList.getEntryCount();
     }
-    CodeStyleSettings.ImportLayoutTable.PackageEntry entry = new CodeStyleSettings.ImportLayoutTable.PackageEntry("", true);
+    PackageEntry entry = new PackageEntry(false,"", true);
     myImportLayoutList.insertEntryAt(entry, selected);
     refreshTableModel(selected, myImportLayoutTable);
   }
@@ -267,8 +315,6 @@ public class CodeStyleImportsPanel extends JPanel {
     AbstractTableModel model = (AbstractTableModel)table.getModel();
     model.fireTableRowsInserted(selectedRow, selectedRow);
     table.setRowSelectionInterval(selectedRow, selectedRow);
-//    myImportLayoutTable.requestFocus();
-//    myImportLayoutTable.editCellAt(selected, 0);
     TableUtil.editCellAt(table, selectedRow, 0);
     Component editorComp = table.getEditorComponent();
     if(editorComp != null) {
@@ -281,7 +327,7 @@ public class CodeStyleImportsPanel extends JPanel {
     if(selected < 0) {
       selected = myPackageList.getEntryCount();
     }
-    CodeStyleSettings.PackageTable.Entry entry = new CodeStyleSettings.PackageTable.Entry("", true);
+    PackageEntry entry = new PackageEntry(false,"", true);
     myPackageList.insertEntryAt(entry, selected);
     refreshTableModel(selected, myPackageTable);
   }
@@ -291,8 +337,7 @@ public class CodeStyleImportsPanel extends JPanel {
     if(selected < 0) {
       selected = myImportLayoutList.getEntryCount();
     }
-    CodeStyleSettings.ImportLayoutTable.EmptyLineEntry entry = new CodeStyleSettings.ImportLayoutTable.EmptyLineEntry();
-    myImportLayoutList.insertEntryAt(entry, selected);
+    myImportLayoutList.insertEntryAt(PackageEntry.BLANK_LINE_ENTRY, selected);
     AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel();
     model.fireTableRowsInserted(selected, selected);
     myImportLayoutTable.setRowSelectionInterval(selected, selected);
@@ -302,26 +347,11 @@ public class CodeStyleImportsPanel extends JPanel {
     int selected = myImportLayoutTable.getSelectedRow();
     if(selected < 0)
       return;
-    CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected);
-    if(isOtherEntry(entry)) {
-      boolean isFound = false;
-      CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries();
-      for(int i = 0; i < entries.length; i++){
-        if(i != selected && isOtherEntry(entries[i])) {
-          isFound = true;
-          break;
-        }
-      }
-      if(!isFound) {
-        return;
-      }
-    }
-    if(myImportLayoutTable.isEditing()) {
-      TableCellEditor editor = myImportLayoutTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
+    PackageEntry entry = myImportLayoutList.getEntryAt(selected);
+    if(entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) {
+      return;
     }
+    TableUtil.stopEditing(myImportLayoutTable);
     myImportLayoutList.removeEntryAt(selected);
     AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel();
     model.fireTableRowsDeleted(selected, selected);
@@ -335,14 +365,8 @@ public class CodeStyleImportsPanel extends JPanel {
 
   private void removeEntryFromPackages() {
     int selected = myPackageTable.getSelectedRow();
-    if(selected < 0)
-      return;
-    if(myPackageTable.isEditing()) {
-      TableCellEditor editor = myPackageTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
-    }
+    if(selected < 0) return;
+    TableUtil.stopEditing(myPackageTable);
     myPackageList.removeEntryAt(selected);
     AbstractTableModel model = (AbstractTableModel)myPackageTable.getModel();
     model.fireTableRowsDeleted(selected, selected);
@@ -359,14 +383,9 @@ public class CodeStyleImportsPanel extends JPanel {
     if(selected < 1) {
       return;
     }
-    if(myImportLayoutTable.isEditing()) {
-      TableCellEditor editor = myImportLayoutTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
-    }
-    CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected);
-    CodeStyleSettings.ImportLayoutTable.Entry previousEntry = myImportLayoutList.getEntryAt(selected-1);
+    TableUtil.stopEditing(myImportLayoutTable);
+    PackageEntry entry = myImportLayoutList.getEntryAt(selected);
+    PackageEntry previousEntry = myImportLayoutList.getEntryAt(selected-1);
     myImportLayoutList.setEntryAt(previousEntry, selected);
     myImportLayoutList.setEntryAt(entry, selected-1);
 
@@ -380,14 +399,9 @@ public class CodeStyleImportsPanel extends JPanel {
     if(selected >= myImportLayoutList.getEntryCount()-1) {
       return;
     }
-    if(myImportLayoutTable.isEditing()) {
-      TableCellEditor editor = myImportLayoutTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
-    }
-    CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected);
-    CodeStyleSettings.ImportLayoutTable.Entry nextEntry = myImportLayoutList.getEntryAt(selected+1);
+    TableUtil.stopEditing(myImportLayoutTable);
+    PackageEntry entry = myImportLayoutList.getEntryAt(selected);
+    PackageEntry nextEntry = myImportLayoutList.getEntryAt(selected+1);
     myImportLayoutList.setEntryAt(nextEntry, selected);
     myImportLayoutList.setEntryAt(entry, selected+1);
 
@@ -397,66 +411,110 @@ public class CodeStyleImportsPanel extends JPanel {
   }
 
   private JComponent createPackagesTable() {
+    myPackageTable = createTableForPackageEntries(myPackageList);
+    return ScrollPaneFactory.createScrollPane(myPackageTable);
+  }
+
+  private Table createTableForPackageEntries(final PackageEntryTable packageTable) {
     final String[] names = {
       ApplicationBundle.message("listbox.import.package"),
-      ApplicationBundle.message("listbox.import.with.subpackages")
+      ApplicationBundle.message("listbox.import.with.subpackages"),
     };
     // Create a model of the data.
     TableModel dataModel = new AbstractTableModel() {
-      public int getColumnCount() { return names.length; }
-      public int getRowCount() { return myPackageList.getEntryCount();}
+      public int getColumnCount() {
+        return names.length + (areStaticImportsEnabled()?1:0);
+      }
+
+      public int getRowCount() {
+        return packageTable.getEntryCount();
+      }
+
       public Object getValueAt(int row, int col) {
-        CodeStyleSettings.PackageTable.Entry entry = myPackageList.getEntryAt(row);
+        PackageEntry entry = packageTable.getEntryAt(row);
+        if (entry == null || !isCellEditable(row, col)) return null;
+        col += areStaticImportsEnabled() ? 0 : 1;
         if(col == 0) {
-          if(entry != null) {
-            return entry.getPackageName();
-          }
+          return entry.isStatic();
         }
-
         if(col == 1) {
-          if(entry != null) {
-            return entry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE;
-          }
+          return entry.getPackageName();
+        }
+        if(col == 2) {
+          return entry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE;
         }
-        return null;
+        throw new IllegalArgumentException(String.valueOf(col));
       }
-      public String getColumnName(int column) { return names[column]; }
-      public Class getColumnClass(int c) {
-        if(c == 0) {
+
+      public String getColumnName(int column) {
+        if (areStaticImportsEnabled() && column == 0) return "Static";
+        column -= areStaticImportsEnabled() ? 1 : 0;
+        return names[column];
+      }
+
+      public Class getColumnClass(int col) {
+        col += areStaticImportsEnabled() ? 0 : 1;
+        if(col == 0) {
+          return Boolean.class;
+        }
+        if(col == 1) {
           return String.class;
         }
-        if(c == 1) {
+        if(col == 2) {
           return Boolean.class;
         }
-        return null;
+        throw new IllegalArgumentException(String.valueOf(col));
       }
+
       public boolean isCellEditable(int row, int col) {
-        return true;
+        PackageEntry packageEntry = packageTable.getEntryAt(row);
+        return !packageEntry.isSpecial();
       }
 
       public void setValueAt(Object aValue, int row, int col) {
-        CodeStyleSettings.PackageTable.Entry packageEntry = myPackageList.getEntryAt(row);
+        PackageEntry packageEntry = packageTable.getEntryAt(row);
+        col += areStaticImportsEnabled() ? 0 : 1;
         if(col == 0) {
-          CodeStyleSettings.PackageTable.Entry newPackageEntry = new CodeStyleSettings.PackageTable.Entry(((String)aValue).trim(), packageEntry.isWithSubpackages());
-          myPackageList.setEntryAt(newPackageEntry, row);
+          PackageEntry newPackageEntry = new PackageEntry((Boolean)aValue, packageEntry.getPackageName(), packageEntry.isWithSubpackages());
+          packageTable.setEntryAt(newPackageEntry, row);
         }
-
-        if(col == 1) {
-          CodeStyleSettings.PackageTable.Entry newPackageEntry = new CodeStyleSettings.PackageTable.Entry(packageEntry.getPackageName(), ((Boolean)aValue).booleanValue());
-          myPackageList.setEntryAt(newPackageEntry, row);
+        else if(col == 1) {
+          PackageEntry newPackageEntry = new PackageEntry(packageEntry.isStatic(), ((String)aValue).trim(), packageEntry.isWithSubpackages());
+          packageTable.setEntryAt(newPackageEntry, row);
+        }
+        else if(col == 2) {
+          PackageEntry newPackageEntry = new PackageEntry(packageEntry.isStatic(), packageEntry.getPackageName(), ((Boolean)aValue).booleanValue());
+          packageTable.setEntryAt(newPackageEntry, row);
+        }
+        else {
+          throw new IllegalArgumentException(String.valueOf(col));
         }
       }
     };
 
     // Create the table
-    myPackageTable = new Table(dataModel);
-    myPackageTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    TableCellEditor editor = myPackageTable.getDefaultEditor(String.class);
-    myPackageTable.fixColumnWidthToHeader(1);
+    final Table result = new Table(dataModel);
+    result.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    resizeColumns(packageTable, result);
+
+    TableCellEditor editor = result.getDefaultEditor(String.class);
     if (editor instanceof DefaultCellEditor) {
       ((DefaultCellEditor)editor).setClickCountToStart(1);
     }
-    myPackageTable.getSelectionModel().addListSelectionListener(
+
+    TableCellEditor beditor = result.getDefaultEditor(Boolean.class);
+    beditor.addCellEditorListener(new CellEditorListener() {
+      public void editingStopped(ChangeEvent e) {
+        if (areStaticImportsEnabled()) {
+          result.repaint(); // add/remove static keyword
+        }
+      }
+
+      public void editingCanceled(ChangeEvent e) {
+      }
+    });
+
+    result.getSelectionModel().addListSelectionListener(
       new ListSelectionListener(){
         public void valueChanged(ListSelectionEvent e){
           updateButtons();
@@ -464,124 +522,64 @@ public class CodeStyleImportsPanel extends JPanel {
       }
     );
 
-    return ScrollPaneFactory.createScrollPane(myPackageTable);
+    return result;
   }
 
-  private void updateButtons(){
-    int selectedImport = myImportLayoutTable.getSelectedRow();
-    myMoveUpButton.setEnabled(selectedImport >= 1);
-    myMoveDownButton.setEnabled(selectedImport < myImportLayoutTable.getRowCount()-1);
-    if(selectedImport < 0 || myOtherPackageEntry == myImportLayoutList.getEntryAt(selectedImport)) {
-      myRemovePackageFromImportLayoutButton.setEnabled(false);
-    }
-    else {
-      myRemovePackageFromImportLayoutButton.setEnabled(true);
-    }
+  private void resizeColumns(final PackageEntryTable packageTable, Table result) {
+    ColoredTableCellRenderer packageRenderer = new ColoredTableCellRenderer() {
+      @Override
+      protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
+        PackageEntry entry = packageTable.getEntryAt(row);
 
-    int selectedPackage = myPackageTable.getSelectedRow();
-    myRemovePackageFromPackagesButton.setEnabled(selectedPackage >= 0);
-
-  }
-
-  private static boolean isOtherEntry(CodeStyleSettings.ImportLayoutTable.Entry entry) {
-    if(!(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry)) {
-      return false;
-    }
-    CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-    String packageName = packageEntry.getPackageName();
-    return packageName.length() == 0 && packageEntry.isWithSubpackages();
-  }
-
-  private JComponent createImportLayoutTable() {
-    final String[] names = {
-      ApplicationBundle.message("listbox.import.package"),
-      ApplicationBundle.message("listbox.import.with.subpackages")
-    };
-    // Create a model of the data.
-    TableModel dataModel = new AbstractTableModel() {
-      public int getColumnCount() { return names.length; }
-      public int getRowCount() { return myImportLayoutList.getEntryCount();}
-      public Object getValueAt(int row, int col) {
-        CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row);
-        if(col == 0) {
-          if(isOtherEntry(entry) && entry == myOtherPackageEntry) {
-            return ApplicationBundle.message("listbox.import.all.other.imports");
-          }
-          else if(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) {
-            CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-            return packageEntry.getPackageName();
-          }
-          else {
-            return ApplicationBundle.message("listbox.import.blank.line");
-          }
+        if (entry == PackageEntry.BLANK_LINE_ENTRY) {
+          append("                                               <blank line>", SimpleTextAttributes.LINK_ATTRIBUTES);
         }
-
-        if(col == 1) {
-          if(isOtherEntry(entry) && entry == myOtherPackageEntry) {
-            return null;
+        else {
+          TextAttributes attributes = SyntaxHighlighterColors.KEYWORD.getDefaultAttributes();
+          append("import", SimpleTextAttributes.fromTextAttributes(attributes));
+          if (entry.isStatic()) {
+            append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
+            append("static", SimpleTextAttributes.fromTextAttributes(attributes));
           }
-          else if(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) {
-            CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-            return packageEntry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE;
+          append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
+
+          if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
+            append("all other imports", SimpleTextAttributes.REGULAR_ATTRIBUTES);
           }
           else {
-            return null;
+            append(entry.getPackageName() + ".*", SimpleTextAttributes.REGULAR_ATTRIBUTES);
           }
         }
-        return null;
-      }
-      public String getColumnName(int column) { return names[column]; }
-      public Class getColumnClass(int c) {
-        if(c == 0) {
-          return String.class;
-        }
-        if(c == 1) {
-          return Boolean.class;
-        }
-        return null;
-//        return CodeStyleSettings.ImportLayoutTable.Entry.class;
-      }
-      public boolean isCellEditable(int row, int col) {
-        CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row);
-        if (isOtherEntry(entry) && entry == myOtherPackageEntry) {
-          return false;
-        }
-        return entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry;
-      }
-
-      public void setValueAt(Object aValue, int row, int col) {
-        CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row);
-        if(col == 0 && entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) {
-          CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-          CodeStyleSettings.ImportLayoutTable.PackageEntry newPackageEntry = new CodeStyleSettings.ImportLayoutTable.PackageEntry(((String)aValue).trim(), packageEntry.isWithSubpackages());
-          myImportLayoutList.setEntryAt(newPackageEntry, row);
-        }
-        if(col == 1 && entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) {
-          CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-          CodeStyleSettings.ImportLayoutTable.PackageEntry newPackageEntry = new CodeStyleSettings.ImportLayoutTable.PackageEntry(packageEntry.getPackageName(), aValue.equals(Boolean.TRUE));
-          myImportLayoutList.setEntryAt(newPackageEntry, row);
-        }
       }
     };
-
-    // Create the table
-    myImportLayoutTable = new Table(dataModel);
-    myImportLayoutTable.setDefaultRenderer(Boolean.class, new BooleanTableCellRenderer());
-    myImportLayoutTable.fixColumnWidthToHeader(1);
-    myImportLayoutTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    TableCellEditor editor = myImportLayoutTable.getDefaultEditor(String.class);
-    if (editor instanceof DefaultCellEditor) {
-      ((DefaultCellEditor)editor).setClickCountToStart(1);
+    if (areStaticImportsEnabled()) {
+      result.fixColumnWidthToHeader(0);
+      result.fixColumnWidthToHeader(2);
+      result.getColumnModel().getColumn(1).setCellRenderer(packageRenderer);
+      result.getColumnModel().getColumn(0).setCellRenderer(new BooleanTableCellRenderer());
+      result.getColumnModel().getColumn(2).setCellRenderer(new BooleanTableCellRenderer());
     }
+    else {
+      result.fixColumnWidthToHeader(1);
+      result.getColumnModel().getColumn(0).setCellRenderer(packageRenderer);
+      result.getColumnModel().getColumn(1).setCellRenderer(new BooleanTableCellRenderer());
+    }
+  }
 
-    myImportLayoutTable.getSelectionModel().addListSelectionListener(
-      new ListSelectionListener(){
-        public void valueChanged(ListSelectionEvent e){
-          updateButtons();
-        }
-      }
-    );
+  private void updateButtons(){
+    int selectedImport = myImportLayoutTable.getSelectedRow();
+    myMoveUpButton.setEnabled(selectedImport >= 1);
+    myMoveDownButton.setEnabled(selectedImport < myImportLayoutTable.getRowCount()-1);
+    PackageEntry entry = selectedImport < 0 ? null : myImportLayoutList.getEntryAt(selectedImport);
+    boolean canRemove =  entry != null && entry != PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY && entry != PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
+    myRemovePackageFromImportLayoutButton.setEnabled(canRemove);
 
+    int selectedPackage = myPackageTable.getSelectedRow();
+    myRemovePackageFromPackagesButton.setEnabled(selectedPackage >= 0);
+  }
+
+  private JComponent createImportLayoutTable() {
+    myImportLayoutTable = createTableForPackageEntries(myImportLayoutList);
     return ScrollPaneFactory.createScrollPane(myImportLayoutTable);
   }
 
@@ -596,14 +594,9 @@ public class CodeStyleImportsPanel extends JPanel {
     myCbOptimizeImportsOnTheFly.setSelected(mySettings.OPTIMIZE_IMPORTS_ON_THE_FLY);
 
     myImportLayoutList.copyFrom(mySettings.IMPORT_LAYOUT_TABLE);
-    CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries();
-    for (CodeStyleSettings.ImportLayoutTable.Entry entry : entries) {
-      if (isOtherEntry(entry)) {
-        myOtherPackageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry;
-      }
-    }
-    myPackageList = new CodeStyleSettings.PackageTable();
     myPackageList.copyFrom(mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
+    
+    myCbLayoutStaticImportsSeparately.setSelected(mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY);
 
     AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel();
     model.fireTableDataChanged();
@@ -630,6 +623,7 @@ public class CodeStyleImportsPanel extends JPanel {
   public void apply() {
     stopTableEditing();
 
+    mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = areStaticImportsEnabled();
     mySettings.USE_FQ_CLASS_NAMES = myCbUseFQClassNames.isSelected();
     mySettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = myCbUseFQClassNamesInJavaDoc.isSelected();
     mySettings.USE_SINGLE_CLASS_IMPORTS = myCbUseSingleClassImports.isSelected();
@@ -649,41 +643,25 @@ public class CodeStyleImportsPanel extends JPanel {
       //just a bad number
     }
 
+    myImportLayoutList.removeEmptyPackages();
     mySettings.IMPORT_LAYOUT_TABLE.copyFrom(myImportLayoutList);
 
-    CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries();
-    int removedEntryCount = 0;
-    for(int i = 0; i < entries.length; i++){
-      CodeStyleSettings.ImportLayoutTable.Entry entry = entries[i];
-      if(isOtherEntry(entry) && entry != myOtherPackageEntry) {
-        mySettings.IMPORT_LAYOUT_TABLE.removeEntryAt(i-removedEntryCount);
-        removedEntryCount++;
-      }
-    }
-
-    mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND = myPackageList;
+    myPackageList.removeEmptyPackages();
+    mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(myPackageList);
 
     mySettings.JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST = myJspImportCommaSeparated.isSelected();
   }
 
+
   private void stopTableEditing() {
-    if(myImportLayoutTable.isEditing()) {
-      TableCellEditor editor = myImportLayoutTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
-    }
-    if(myPackageTable.isEditing()) {
-      TableCellEditor editor = myPackageTable.getCellEditor();
-      if (editor != null) {
-        editor.stopCellEditing();
-      }
-    }
+    TableUtil.stopEditing(myImportLayoutTable);
+    TableUtil.stopEditing(myPackageTable);
   }
 
   public boolean isModified() {
-
-    boolean isModified = isModified(myCbUseFQClassNames, mySettings.USE_FQ_CLASS_NAMES);
+    boolean
+    isModified  = isModified(myCbLayoutStaticImportsSeparately, mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY);
+    isModified |= isModified(myCbUseFQClassNames, mySettings.USE_FQ_CLASS_NAMES);
     isModified |= isModified(myCbUseFQClassNamesInJavaDoc, mySettings.USE_FQ_CLASS_NAMES_IN_JAVADOC);
     isModified |= isModified(myCbUseSingleClassImports, mySettings.USE_SINGLE_CLASS_IMPORTS);
     isModified |= isModified(myCbInsertInnerClassImports, mySettings.INSERT_INNER_CLASS_IMPORTS);
@@ -713,30 +691,14 @@ public class CodeStyleImportsPanel extends JPanel {
     return checkBox.isSelected() != value;
   }
 
-  private static boolean isModified(CodeStyleSettings.ImportLayoutTable list, CodeStyleSettings.ImportLayoutTable table) {
-    if(list.getEntryCount() != table.getEntryCount()) {
-      return true;
-    }
-
-    for(int i=0; i<list.getEntryCount(); i++) {
-      CodeStyleSettings.ImportLayoutTable.Entry entry1 = list.getEntryAt(i);
-      CodeStyleSettings.ImportLayoutTable.Entry entry2 = table.getEntryAt(i);
-      if(!entry1.equals(entry2)) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  private static boolean isModified(CodeStyleSettings.PackageTable list, CodeStyleSettings.PackageTable table) {
+  private static boolean isModified(PackageEntryTable list, PackageEntryTable table) {
     if(list.getEntryCount() != table.getEntryCount()) {
       return true;
     }
 
     for(int i=0; i<list.getEntryCount(); i++) {
-      CodeStyleSettings.PackageTable.Entry entry1 = list.getEntryAt(i);
-      CodeStyleSettings.PackageTable.Entry entry2 = table.getEntryAt(i);
+      PackageEntry entry1 = list.getEntryAt(i);
+      PackageEntry entry2 = table.getEntryAt(i);
       if(!entry1.equals(entry2)) {
         return true;
       }
index db274ab1e3154fb2ab32c94579bf043196f2a7d9..54a551efe67d8708a64919be7696b683bd4520ed 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.application.options;
 
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 
@@ -65,7 +66,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
     settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = myCbDontIndentTopLevelMembers.isSelected();
   }
 
-  public void reset(final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions options) {
+  public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CodeStyleSettings.IndentOptions options) {
     super.reset(settings, options);
     myLabelIndent.setText(Integer.toString(options.LABEL_INDENT_SIZE));
     myLabelIndentAbsolute.setSelected(options.LABEL_INDENT_ABSOLUTE);
index 6334e10fca697f065ea6beeaaf8ea8c3fe6a33dd..b16138165cccd0d3c22f6c89f31849a73e8b3cb9 100644 (file)
@@ -211,4 +211,9 @@ public class PackageElementNode extends ProjectViewNode<PackageElement> {
   public int getTypeSortWeight(final boolean sortByType) {
     return 4;
   }
+
+  @Override
+  public boolean isAlwaysShowPlus() {
+    return true;
+  }
 }
index 4d7b9eaed580834b997127c82f1f748851a48abf..5947c80d683e7c28226717f1f07f770c3b355efa 100644 (file)
@@ -19,6 +19,7 @@
  */
 package com.intellij.lang.java;
 
+import com.intellij.formatting.Block;
 import com.intellij.formatting.FormattingModel;
 import com.intellij.formatting.FormattingModelBuilder;
 import com.intellij.lang.ASTNode;
@@ -47,9 +48,9 @@ public class JavaFormattingModelBuilder implements FormattingModelBuilder {
     public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
     final FileElement fileElement = TreeUtil.getFileElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(element));
     LOG.assertTrue(fileElement != null, "File element should not be null for " + element);
-    return new PsiBasedFormatterModelWithShiftIndentInside (element.getContainingFile(), AbstractJavaBlock.createJavaBlock(fileElement,
-                                                                                                                           settings),
-                                                            FormattingDocumentModelImpl.createOn(element.getContainingFile()));
+    Block block = AbstractJavaBlock.createJavaBlock(fileElement, settings);
+    FormattingDocumentModelImpl model = FormattingDocumentModelImpl.createOn(element.getContainingFile());
+    return new PsiBasedFormatterModelWithShiftIndentInside (element.getContainingFile(), block, model);
   }
 
   public TextRange getRangeAffectingIndent(final PsiFile file, final int offset, final ASTNode elementAtOffset) {
index e551b0ac9b37dd6d4e461089675a3b3091f5759b..40dc91e2a70c9f988b9e6554d04c7966160ce171 100644 (file)
@@ -37,32 +37,30 @@ public class JavaImportOptimizer implements ImportOptimizer {
 
   @NotNull
   public Runnable processFile(final PsiFile file) {
-    if (file instanceof PsiJavaFile) {
-      Project project = file.getProject();
-      final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file);
-      return new Runnable() {
-        public void run() {
-          try {
-            if (newImportList != null) {
-              final PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject());
-              final Document document = manager.getDocument(file);
-              if (document != null) {
-                manager.commitDocument(document);
-              }
-              final PsiImportList oldImportList = ((PsiJavaFile)file).getImportList();
-              assert oldImportList != null;
-              oldImportList.replace(newImportList);
+    if (!(file instanceof PsiJavaFile)) {
+      return EmptyRunnable.getInstance();
+    }
+    Project project = file.getProject();
+    final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file);
+    return new Runnable() {
+      public void run() {
+        try {
+          if (newImportList != null) {
+            final PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject());
+            final Document document = manager.getDocument(file);
+            if (document != null) {
+              manager.commitDocument(document);
             }
-          }
-          catch (IncorrectOperationException e) {
-            LOG.error(e);
+            final PsiImportList oldImportList = ((PsiJavaFile)file).getImportList();
+            assert oldImportList != null;
+            oldImportList.replace(newImportList);
           }
         }
-      };
-    }
-    else {
-      return EmptyRunnable.getInstance();
-    }
+        catch (IncorrectOperationException e) {
+          LOG.error(e);
+        }
+      }
+    };
   }
 
   public boolean supports(PsiFile file) {
index 30684f0c61bf7f021d9948ddc5cf4a450d345c58..f453e01fe5ad59a96de373ec11aee2ae2fadd60e 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.psi.impl;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -155,6 +156,7 @@ public class InheritanceImplUtil {
   }
 
   private static boolean checkInheritor(PsiClass aClass, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
+    ProgressManager.getInstance().checkCanceled();
     if (aClass != null) {
       PsiManager manager = baseClass.getManager();
       if (manager.areElementsEquivalent(baseClass, aClass)) {
index 4827da7d6e5c2067b32822664866b4b6f4cab1d8..07ac0a68ce1f4f6907654570348941cc9498cd6d 100644 (file)
@@ -20,13 +20,12 @@ import com.intellij.lang.StdLanguages;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
-import com.intellij.psi.codeStyle.CodeStyleSettings.ImportLayoutTable;
-import com.intellij.psi.codeStyle.CodeStyleSettings.ImportLayoutTable.EmptyLineEntry;
-import com.intellij.psi.codeStyle.CodeStyleSettings.ImportLayoutTable.Entry;
-import com.intellij.psi.codeStyle.CodeStyleSettings.ImportLayoutTable.PackageEntry;
+import com.intellij.psi.codeStyle.PackageEntry;
+import com.intellij.psi.codeStyle.PackageEntryTable;
 import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
 import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
@@ -58,44 +57,44 @@ public class ImportHelper{
   }
 
   public PsiImportList prepareOptimizeImportsResult(@NotNull final PsiJavaFile file) {
-    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject());
-
-    final Set<String> namesToImportStaticly = new THashSet<String>();
-    String[] names = collectNamesToImport(file, namesToImportStaticly); // Note: this array may contain "<packageOrClassName>.*" for unresolved imports!
-    Arrays.sort(names);
-
-    ArrayList<String> namesList = new ArrayList<String>();
-    ImportLayoutTable table = mySettings.IMPORT_LAYOUT_TABLE;
-    if (table != null){
-      int[] entriesForName = ArrayUtil.newIntArray(names.length);
-      for(int i = 0; i < names.length; i++){
-        entriesForName[i] = findEntryIndex(names[i]);
-      }
-
-      Entry[] entries = table.getEntries();
-      for(int i = 0; i < entries.length; i++){
-        Entry entry = entries[i];
-        if (entry instanceof PackageEntry){
-          for(int j = 0; j < names.length; j++){
-            if (entriesForName[j] == i){
-              namesList.add(names[j]);
-              names[j] = null;
-            }
-          }
+    // Note: this array may contain "<packageOrClassName>.*" for unresolved imports!
+    List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>(collectNamesToImport(file));
+    Collections.sort(names, new Comparator<Pair<String, Boolean>>() {
+      public int compare(Pair<String, Boolean> o1, Pair<String, Boolean> o2) {
+        return o1.getFirst().compareTo(o2.getFirst());
+      }
+    });
+
+    int[] entryForName = ArrayUtil.newIntArray(names.size());
+    PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
+    for(int i = 0; i < names.size(); i++){
+      Pair<String, Boolean> pair = names.get(i);
+      String packageName = pair.getFirst();
+      Boolean isStatic = pair.getSecond();
+      entryForName[i] = findEntryIndex(packageName, isStatic, entries);
+    }
+
+    List<Pair<String, Boolean>> resultList = new ArrayList<Pair<String, Boolean>>(names.size());
+    for(int i = 0; i < entries.length; i++){
+      for(int j = 0; j < names.size(); j++){
+        if (entryForName[j] == i){
+          resultList.add(names.get(j));
+          names.set(j, null);
         }
       }
     }
-    for (String name : names) {
-      if (name != null) namesList.add(name);
+    for (Pair<String, Boolean> name : names) {
+      if (name != null) resultList.add(name);
     }
-    names = ArrayUtil.toStringArray(namesList);
 
     TObjectIntHashMap<String> packageToCountMap = new TObjectIntHashMap<String>();
     TObjectIntHashMap<String> classToCountMap = new TObjectIntHashMap<String>();
-    for (String name : names) {
+    for (Pair<String, Boolean> pair : resultList) {
+      String name = pair.getFirst();
+      Boolean isStatic = pair.getSecond();
       String packageOrClassName = getPackageOrClassName(name);
       if (packageOrClassName.length() == 0) continue;
-      if (namesToImportStaticly.contains(name)) {
+      if (isStatic) {
         int count = classToCountMap.get(packageOrClassName);
         classToCountMap.put(packageOrClassName, count + 1);
       }
@@ -123,19 +122,20 @@ public class ImportHelper{
     classToCountMap.forEachEntry(new MyVisitorProcedure(false));
     packageToCountMap.forEachEntry(new MyVisitorProcedure(true));
 
-    Set<String> classesToUseSingle = findSingleImports(file, names, classesOrPackagesToImportOnDemand, namesToImportStaticly);
+    Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand);
 
     try {
-      final String text = buildImportListText(names, classesOrPackagesToImportOnDemand, classesToUseSingle, namesToImportStaticly);
+      StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle);
       String ext = StdFileTypes.JAVA.getDefaultExtension();
-      final PsiJavaFile dummyFile = (PsiJavaFile)PsiFileFactory.getInstance(file.getProject())
-        .createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text);
+      PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject());
+      final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text);
+      CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject());
       codeStyleManager.reformat(dummyFile);
 
-      PsiImportList resultList = dummyFile.getImportList();
+      PsiImportList result = dummyFile.getImportList();
       PsiImportList oldList = file.getImportList();
-      if (oldList.isReplaceEquivalent(resultList)) return null;
-      return resultList;
+      if (oldList.isReplaceEquivalent(result)) return null;
+      return result;
     }
     catch(IncorrectOperationException e) {
       LOG.error(e);
@@ -145,15 +145,17 @@ public class ImportHelper{
 
   @NotNull
   private static Set<String> findSingleImports(@NotNull final PsiJavaFile file,
-                                               @NotNull String[] names,
-                                               @NotNull final Set<String> onDemandImports,
-                                               @NotNull Set<String> namesToImportStaticly) {
+                                               @NotNull List<Pair<String,Boolean>> names,
+                                               @NotNull final Set<String> onDemandImports
+                                               ) {
     final GlobalSearchScope resolveScope = file.getResolveScope();
     Set<String> namesToUseSingle = new THashSet<String>();
     final String thisPackageName = file.getPackageName();
     final Set<String> implicitlyImportedPackages = new THashSet<String>(Arrays.asList(file.getImplicitlyImportedPackages()));
     final PsiManager manager = file.getManager();
-    for (String name : names) {
+    for (Pair<String, Boolean> pair : names) {
+      String name = pair.getFirst();
+      Boolean isStatic = pair.getSecond();
       String prefix = getPackageOrClassName(name);
       if (prefix.length() == 0) continue;
       final boolean isImplicitlyImported = implicitlyImportedPackages.contains(prefix);
@@ -174,7 +176,7 @@ public class ImportHelper{
       }
       for (String onDemandName : onDemandImports) {
         if (prefix.equals(onDemandName)) continue;
-        if (namesToImportStaticly.contains(name)) {
+        if (isStatic) {
           PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(onDemandName, resolveScope);
           if (aClass != null) {
             PsiField field = aClass.findFieldByName(shortName, true);
@@ -209,13 +211,14 @@ public class ImportHelper{
   }
 
   @NotNull
-  private static String buildImportListText(@NotNull String[] names,
-                                            @NotNull final Set<String> packagesOrClassesToImportOnDemand,
-                                            @NotNull final Set<String> namesToUseSingle,
-                                            @NotNull Set<String> namesToImportStaticly) {
+  private static StringBuilder buildImportListText(@NotNull List<Pair<String, Boolean>> names,
+                                                   @NotNull final Set<String> packagesOrClassesToImportOnDemand,
+                                                   @NotNull final Set<String> namesToUseSingle) {
     final Set<String> importedPackagesOrClasses = new THashSet<String>();
     @NonNls final StringBuilder buffer = new StringBuilder();
-    for (String name : names) {
+    for (Pair<String, Boolean> pair : names) {
+      String name = pair.getFirst();
+      Boolean isStatic = pair.getSecond();
       String packageOrClassName = getPackageOrClassName(name);
       final boolean implicitlyImported = JAVA_LANG_PACKAGE.equals(packageOrClassName);
       boolean useOnDemand = implicitlyImported || packagesOrClassesToImportOnDemand.contains(packageOrClassName);
@@ -224,7 +227,7 @@ public class ImportHelper{
       }
       if (useOnDemand && (importedPackagesOrClasses.contains(packageOrClassName) || implicitlyImported)) continue;
       buffer.append("import ");
-      if (namesToImportStaticly.contains(name)) buffer.append("static ");
+      if (isStatic) buffer.append("static ");
       if (useOnDemand) {
         importedPackagesOrClasses.add(packageOrClassName);
         buffer.append(packageOrClassName);
@@ -236,7 +239,7 @@ public class ImportHelper{
       buffer.append(";\n");
     }
 
-    return buffer.toString();
+    return buffer;
   }
 
   /**
@@ -326,7 +329,8 @@ public class ImportHelper{
       PsiImportStatement statement;
       if (useOnDemand) {
         statement = factory.createImportStatementOnDemand(packageName);
-      } else {
+      }
+      else {
         statement = factory.createImportStatement(refClass);
       }
       importList.add(statement);
@@ -463,14 +467,14 @@ public class ImportHelper{
       index1 = index2;
       index2 = t;
     }
-    Entry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
+    PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
     int maxSpace = 0;
     for(int i = index1 + 1; i < index2; i++){
-      if (entries[i] instanceof EmptyLineEntry){
+      if (entries[i] == PackageEntry.BLANK_LINE_ENTRY){
         int space = 0;
         do{
           space++;
-        } while(entries[++i] instanceof EmptyLineEntry);
+        } while(entries[++i] == PackageEntry.BLANK_LINE_ENTRY);
         maxSpace = Math.max(maxSpace, space);
       }
     }
@@ -483,34 +487,31 @@ public class ImportHelper{
                      mySettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
     if (classCount >= limitCount) return true;
     if (packageName.length() == 0) return false;
-    CodeStyleSettings.PackageTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
+    PackageEntryTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
     return table != null && table.contains(packageName);
   }
 
-  private int findEntryIndex(@NotNull String packageName){
-    Entry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
+  private static int findEntryIndex(@NotNull String packageName, boolean isStatic, @NotNull PackageEntry[] entries) {
     PackageEntry bestEntry = null;
     int bestEntryIndex = -1;
+    int allOtherStaticIndex = -1;
+    int allOtherIndex = -1;
     for(int i = 0; i < entries.length; i++){
-      Entry entry = entries[i];
-      if (entry instanceof PackageEntry){
-        PackageEntry packageEntry = (PackageEntry)entry;
-        if (packageEntry.matchesPackageName(packageName)){
-          if (bestEntry == null){
-            bestEntry = packageEntry;
-            bestEntryIndex = i;
-          }
-          else{
-            String package1 = bestEntry.getPackageName();
-            String package2 = packageEntry.getPackageName();
-            if (!bestEntry.isWithSubpackages()) continue;
-            if (!packageEntry.isWithSubpackages() || package2.length() > package1.length()) {
-              bestEntry = packageEntry;
-              bestEntryIndex = i;
-            }
-          }
-        }
+      PackageEntry entry = entries[i];
+      if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
+        allOtherStaticIndex = i;
+      }
+      if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) {
+        allOtherIndex = i;
       }
+      if (entry.isBetterMatchForPackageThan(bestEntry, packageName, isStatic)) {
+        bestEntry = entry;
+        bestEntryIndex = i;
+      }
+    }
+    if (bestEntryIndex == -1 && isStatic && allOtherStaticIndex == -1 && allOtherIndex != -1) {
+      // if no layout for static imports specified, put them among all others
+      bestEntryIndex = allOtherIndex;
     }
     return bestEntryIndex;
   }
@@ -526,46 +527,45 @@ public class ImportHelper{
       String className = ref.getCanonicalText();
       packageName = getPackageOrClassName(className);
     }
-    return findEntryIndex(packageName);
+    return findEntryIndex(packageName, statement instanceof PsiImportStaticStatement, mySettings.IMPORT_LAYOUT_TABLE.getEntries());
   }
 
   @NotNull
-  private static String[] collectNamesToImport(@NotNull PsiJavaFile file, @NotNull Set<String> namesToImportStaticly){
-    Set<String> names = new THashSet<String>();
+  // returns list of (name, isImportStatic) pairs
+  private static Collection<Pair<String,Boolean>> collectNamesToImport(@NotNull PsiJavaFile file){
+    Set<Pair<String,Boolean>> names = new THashSet<Pair<String,Boolean>>();
 
     final JspFile jspFile = JspPsiUtil.getJspFile(file);
-    collectNamesToImport(names, file, namesToImportStaticly, jspFile);
+    collectNamesToImport(names, file, jspFile);
     if (jspFile != null) {
       PsiFile[] files = ArrayUtil.mergeArrays(JspSpiUtil.getIncludingFiles(jspFile), JspSpiUtil.getIncludedFiles(jspFile), PsiFile.class);
       for (PsiFile includingFile : files) {
         final PsiFile javaRoot = includingFile.getViewProvider().getPsi(StdLanguages.JAVA);
         if (javaRoot instanceof PsiJavaFile && file != javaRoot) {
-          collectNamesToImport(names, (PsiJavaFile)javaRoot, namesToImportStaticly, jspFile);
+          collectNamesToImport(names, (PsiJavaFile)javaRoot, jspFile);
         }
       }
     }
 
-    addUnresolvedImportNames(names, file, namesToImportStaticly);
+    addUnresolvedImportNames(names, file);
 
-    return ArrayUtil.toStringArray(names);
+    return names;
   }
 
-  private static void collectNamesToImport(@NotNull final Set<String> names,
+  private static void collectNamesToImport(@NotNull final Set<Pair<String, Boolean>> names,
                                            @NotNull final PsiJavaFile file,
-                                           @NotNull final Set<String> namesToImportStaticly,
                                            PsiFile context) {
     String packageName = file.getPackageName();
 
     final PsiElement[] roots = file.getPsiRoots();
     for (PsiElement root : roots) {
-      addNamesToImport(names, root, packageName, namesToImportStaticly, context);
+      addNamesToImport(names, root, packageName, context);
     }
   }
 
-  private static void addNamesToImport(@NotNull Set<String> names,
+  private static void addNamesToImport(@NotNull Set<Pair<String, Boolean>> names,
                                        @NotNull PsiElement scope,
                                        @NotNull String thisPackageName,
-                                       @NotNull Set<String> namesToImportStaticly,
                                        PsiFile context){
     if (scope instanceof PsiImportList) return;
 
@@ -579,9 +579,7 @@ public class ImportHelper{
       for(final PsiReference reference : child.getReferences()){
         if (!(reference instanceof PsiJavaReference)) continue;
         final PsiJavaReference javaReference = (PsiJavaReference)reference;
-        if (javaReference instanceof JavaClassReference){
-          if(((JavaClassReference)javaReference).getContextReference() != null) continue;
-        }
+        if (javaReference instanceof JavaClassReference && ((JavaClassReference)javaReference).getContextReference() != null) continue;
         PsiJavaCodeReferenceElement referenceElement = null;
         if (reference instanceof PsiJavaCodeReferenceElement) {
           referenceElement = (PsiJavaCodeReferenceElement)child;
@@ -599,6 +597,7 @@ public class ImportHelper{
         if (refElement == null && referenceElement != null) {
           refElement = ResolveClassUtil.resolveClass(referenceElement); // might be uncomplete code
         }
+        if (refElement == null) continue;
 
         PsiElement currentFileResolveScope = resolveResult.getCurrentFileResolveScope();
         if (!(currentFileResolveScope instanceof PsiImportStatementBase)) continue;
@@ -606,35 +605,29 @@ public class ImportHelper{
           continue;
         }
 
-        if (refElement != null) {
-          //Add names imported statically
-          if (referenceElement != null) {
-            if (currentFileResolveScope instanceof PsiImportStaticStatement) {
-              PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)currentFileResolveScope;
-              String name = importStaticStatement.getImportReference().getCanonicalText();
-              if (importStaticStatement.isOnDemand()) {
-                String refName = referenceElement.getReferenceName();
-                if (refName != null) name = name + "." + refName;
-              }
-              names.add(name);
-              namesToImportStaticly.add(name);
-              continue;
+        if (referenceElement != null) {
+          if (currentFileResolveScope instanceof PsiImportStaticStatement) {
+            PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)currentFileResolveScope;
+            String name = importStaticStatement.getImportReference().getCanonicalText();
+            if (importStaticStatement.isOnDemand()) {
+              String refName = referenceElement.getReferenceName();
+              if (refName != null) name = name + "." + refName;
             }
+            names.add(Pair.create(name, Boolean.TRUE));
+            continue;
           }
+        }
 
-          if (refElement instanceof PsiClass) {
-            String qName = ((PsiClass)refElement).getQualifiedName();
-            if (hasPackage(qName, thisPackageName)) continue;
-            names.add(qName);
-          }
+        if (refElement instanceof PsiClass) {
+          String qName = ((PsiClass)refElement).getQualifiedName();
+          if (hasPackage(qName, thisPackageName)) continue;
+          names.add(Pair.create(qName, Boolean.FALSE));
         }
       }
     }
   }
 
-  private static void addUnresolvedImportNames(@NotNull Set<String> set,
-                                               @NotNull PsiJavaFile file,
-                                               @NotNull Set<String> namesToImportStaticly) {
+  private static void addUnresolvedImportNames(@NotNull Set<Pair<String, Boolean>> names, @NotNull PsiJavaFile file) {
     PsiImportStatementBase[] imports = file.getImportList().getAllImportStatements();
     for (PsiImportStatementBase anImport : imports) {
       PsiJavaCodeReferenceElement ref = anImport.getImportReference();
@@ -645,10 +638,7 @@ public class ImportHelper{
         if (anImport.isOnDemand()) {
           text += ".*";
         }
-        if (anImport instanceof PsiImportStaticStatement) {
-          namesToImportStaticly.add(text);
-        }
-        set.add(text);
+        names.add(Pair.create(text, anImport instanceof PsiImportStaticStatement));
       }
     }
   }
index a9f47c806db3a2b1a8ee88a4d1f58d34539e3f17..01e8b038951961934f69099bf51d59d13d885519 100644 (file)
@@ -36,9 +36,8 @@ public class JavaHelper extends Helper {
 
     if (element.getTreePrev() != null) {
       ASTNode prev = element.getTreePrev();
-      ASTNode lastCompositePrev;
       while (prev instanceof CompositeElement && !TreeUtil.isStrongWhitespaceHolder(prev.getElementType())) {
-        lastCompositePrev = prev;
+        ASTNode lastCompositePrev = prev;
         prev = prev.getLastChildNode();
         if (prev == null) { // element.prev is "empty composite"
           return getIndentInner(lastCompositePrev, includeNonSpace, recursionLevel + 1);
index 335e6b47226f53b40da8219dfc26d8ab7fa47af0..8f111a48586c143be8570410da445fd28283d8f9 100644 (file)
@@ -46,9 +46,9 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
 
   static {
     INSTANCE.registerExecutor(new QueryExecutor<PsiClass, SearchParameters>() {
-      public boolean execute(final SearchParameters p, final Processor<PsiClass> consumer) {
-        final PsiClass baseClass = p.getClassToProcess();
-        final SearchScope searchScope = p.getScope();
+      public boolean execute(final SearchParameters parameters, final Processor<PsiClass> consumer) {
+        final PsiClass baseClass = parameters.getClassToProcess();
+        final SearchScope searchScope = parameters.getScope();
 
         LOG.assertTrue(searchScope != null);
 
@@ -61,10 +61,7 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
                            PsiBundle.message("psi.search.inheritors.progress"));
         }
 
-        boolean result = processInheritors(consumer,
-                                           baseClass,
-                                           searchScope,
-                                           p);
+        boolean result = processInheritors(consumer, baseClass, searchScope, parameters);
 
         if (progress != null) {
           progress.popState();
@@ -83,11 +80,11 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
     private final boolean myIncludeAnonymous;
     private final Condition<String> myNameCondition;
 
-    public SearchParameters(@NotNull final PsiClass aClass, SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
+    public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
       this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, Condition.TRUE);
     }
 
-    public SearchParameters(@NotNull final PsiClass aClass, SearchScope scope, final boolean checkDeep, final boolean checkInheritance,
+    public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance,
                             boolean includeAnonymous, final Condition<String> nameCondition) {
       myClass = aClass;
       myScope = scope;
@@ -125,19 +122,19 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
 
   private ClassInheritorsSearch() {}
 
-  public static Query<PsiClass> search(@NotNull final PsiClass aClass, SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
+  public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
     return search(new SearchParameters(aClass, scope, checkDeep, checkInheritance, includeAnonymous));
   }
 
-  public static Query<PsiClass> search(final SearchParameters parameters) {
+  public static Query<PsiClass> search(@NotNull SearchParameters parameters) {
     return INSTANCE.createUniqueResultsQuery(parameters);
   }
 
-  public static Query<PsiClass> search(@NotNull final PsiClass aClass, SearchScope scope, final boolean checkDeep, final boolean checkInheritance) {
+  public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance) {
     return search(aClass, scope, checkDeep, checkInheritance, true);
   }
 
-  public static Query<PsiClass> search(@NotNull final PsiClass aClass, SearchScope scope, final boolean checkDeep) {
+  public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep) {
     return search(aClass, scope, checkDeep, true);
   }
 
@@ -145,14 +142,14 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
     return search(aClass, aClass.getUseScope(), checkDeep);
   }
 
-  public static Query<PsiClass> search(final PsiClass aClass) {
+  public static Query<PsiClass> search(@NotNull PsiClass aClass) {
     return search(aClass, true);
   }
 
-  private static boolean processInheritors(final Processor<PsiClass> consumer,
-                                           final PsiClass baseClass,
+  private static boolean processInheritors(@NotNull final Processor<PsiClass> consumer,
+                                           @NotNull final PsiClass baseClass,
                                            @NotNull final SearchScope searchScope,
-                                           final SearchParameters parameters) {
+                                           @NotNull final SearchParameters parameters) {
     if (baseClass instanceof PsiAnonymousClass) return true;
 
     if (isFinal(baseClass)) return true;
@@ -163,7 +160,12 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
       }
     });
     if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) {
-      return AllClassesSearch.search(searchScope, baseClass.getProject(), parameters.getNameCondition()).forEach(consumer);
+      return AllClassesSearch.search(searchScope, baseClass.getProject(), parameters.getNameCondition()).forEach(new Processor<PsiClass>() {
+        public boolean process(PsiClass aClass) {
+          ProgressManager.getInstance().checkCanceled();
+          return consumer.process(aClass);
+        }
+      });
     }
 
     final Ref<PsiClass> currentBase = Ref.create(null);
@@ -171,6 +173,8 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
     final Set<PsiClass> processed = new HashSet<PsiClass>();
     final Processor<PsiClass> processor = new Processor<PsiClass>() {
       public boolean process(final PsiClass candidate) {
+        ProgressManager.getInstance().checkCanceled();
+
         final Ref<Boolean> result = new Ref<Boolean>();
         ApplicationManager.getApplication().runReadAction(new Runnable() {
           public void run() {
index 7c8cf30753bd3855873b1715e3f55102195648fc..30e3ba6b6d3b916121be155a11860089faf9fc63 100644 (file)
@@ -672,6 +672,7 @@ public class TypeConversionUtil {
 
     if (left instanceof PsiArrayType) return false;
     if (right instanceof PsiPrimitiveType) {
+      if (isVoidType(right)) return false;
       if (!(left instanceof PsiPrimitiveType)) {
         return left instanceof PsiClassType && isBoxable((PsiClassType)left, (PsiPrimitiveType)right);
       }
index b883888ac77eb3ff08f8d4e30eb20f80d0cac738..5437ef8205fd3b782b22f08a6b37a9ef91ddc0a6 100644 (file)
@@ -22,6 +22,8 @@ import java.util.Collection;
 
 /**
  * @author nik
+ *
+ * todo[nik] delete
  */
 public interface CustomConfigFileSet extends JDOMExternalizable {
 
index cb1945c6c2c9caaa2f5d322c94f81dcd29f8e3ae..d35cb85284a292c20b70539d9b4fbf6d55e5fc8e 100755 (executable)
@@ -76,11 +76,14 @@ public abstract class HierarchyViewTestBase extends CodeInsightTestCase {
     final Object[] children = treeStructure.getChildElements(descriptor);
     //noinspection unchecked
     final List<Element> expectedChildren = new ArrayList<Element>(element.getChildren(NODE_ELEMENT_NAME));
-    assertEquals("Children of " + descriptor.getHighlightedText().getText(), expectedChildren.size(), children.length);
 
+    final StringBuilder messageBuilder = new StringBuilder("Actual children of [" + descriptor.getHighlightedText().getText() + "]:\n");
     for (Object child : children) {
-      ((HierarchyNodeDescriptor)child).update();
+      final HierarchyNodeDescriptor nodeDescriptor = (HierarchyNodeDescriptor)child;
+      nodeDescriptor.update();
+      messageBuilder.append("    [").append(nodeDescriptor.getHighlightedText().getText()).append("]\n");
     }
+    assertEquals(messageBuilder.toString(), expectedChildren.size(), children.length);
 
     Arrays.sort(children, new Comparator<Object>() {
       public int compare(final Object first, final Object second) {
index 9f1fa01de6e6ce96eb91502c2386e5b5eb2e6b42..040ad4d4f166914dce7d553cede214efdf22c658 100644 (file)
 
 package com.intellij.application.options;
 
-import com.intellij.ui.OptionGroup;
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.ui.OptionGroup;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 
@@ -108,7 +109,7 @@ public class IndentOptionsEditor extends OptionGroup {
     options.USE_TAB_CHARACTER = myCbUseTab.isSelected();
   }
 
-  public void reset(final CodeStyleSettings settings, CodeStyleSettings.IndentOptions options) {
+  public void reset(@NotNull CodeStyleSettings settings, @NotNull CodeStyleSettings.IndentOptions options) {
     myTabSizeField.setText(String.valueOf(options.TAB_SIZE));
     myCbUseTab.setSelected(options.USE_TAB_CHARACTER);
 
index a63b7ebd984ed3844c0b97d8ee66124483da21e2..927cb3d514c08cee6caa2d76e006ce09ce4341d5 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.application.options;
 
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 
@@ -63,7 +64,7 @@ public class SmartIndentOptionsEditor extends IndentOptionsEditor {
     options.SMART_TABS = isSmartTabValid(options.INDENT_SIZE, options.TAB_SIZE) && myCbSmartTabs.isSelected();
   }
 
-  public void reset(final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions options) {
+  public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CodeStyleSettings.IndentOptions options) {
     super.reset(settings, options);
     myContinuationIndentField.setText(String.valueOf(options.CONTINUATION_INDENT_SIZE));
     myCbSmartTabs.setSelected(options.SMART_TABS);
index 44c379554152d9d9fb6f9be219418b5811fe6a42..1dfe028514dd5888bd9993e89fffff08251bdb23 100644 (file)
@@ -35,7 +35,7 @@ import java.lang.reflect.Modifier;
 import java.util.*;
 
 public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
-  private ClassMap<CustomCodeStyleSettings> myCustomSettings = new ClassMap<CustomCodeStyleSettings>();
+  private final ClassMap<CustomCodeStyleSettings> myCustomSettings = new ClassMap<CustomCodeStyleSettings>();
   @NonNls private static final String ADDITIONAL_INDENT_OPTIONS = "ADDITIONAL_INDENT_OPTIONS";
   @NonNls private static final String FILETYPE = "fileType";
 
@@ -45,7 +45,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
   public CodeStyleSettings(boolean loadExtensions) {
     initTypeToName();
-    initImports();
+    initImportsByDefault();
 
     if (loadExtensions) {
       final CodeStyleSettingsProvider[] codeStyleSettingsProviders = Extensions.getExtensions(CodeStyleSettingsProvider.EXTENSION_POINT_NAME);
@@ -55,13 +55,15 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
     }
   }
 
-  private void initImports() {
-    PACKAGES_TO_USE_IMPORT_ON_DEMAND.insertEntryAt(new PackageTable.Entry("java.awt", false), 0);
-    PACKAGES_TO_USE_IMPORT_ON_DEMAND.insertEntryAt(new PackageTable.Entry("javax.swing", false), 1);
-    IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("", true), 0);
-    IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.EmptyLineEntry(), 1);
-    IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("javax", true), 2);
-    IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("java", true), 3);
+  private void initImportsByDefault() {
+    PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "java.awt", false));
+    PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false,"javax.swing", false));
+    IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
+    IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
+    IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "javax", true));
+    IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "java", true));
+    IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
+    IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
   }
 
   private void initTypeToName() {
@@ -102,67 +104,64 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
   }
 
   public CodeStyleSettings clone() {
-    try {
-      CodeStyleSettings clone = (CodeStyleSettings)super.clone();
-
-      copyCustomSettings(this, clone);
-      return clone;
-    }
-    catch (CloneNotSupportedException e) {
-      throw new RuntimeException(e);
-    }
+    CodeStyleSettings clone = new CodeStyleSettings();
+    clone.copyFrom(this);
+    return clone;
   }
 
-  private static void copyCustomSettings(CodeStyleSettings from, final CodeStyleSettings to) throws CloneNotSupportedException {
-    to.myCustomSettings = new ClassMap<CustomCodeStyleSettings>();
+  private void copyCustomSettingsFrom(CodeStyleSettings from) {
+    assert from != this;
+    myCustomSettings.clear();
     for (final CustomCodeStyleSettings settings : from.myCustomSettings.values()) {
-      to.addCustomSettings((CustomCodeStyleSettings) settings.clone());
+      addCustomSettings((CustomCodeStyleSettings) settings.clone());
     }
 
-    to.FIELD_TYPE_TO_NAME = (TypeToNameMap)from.FIELD_TYPE_TO_NAME.clone();
-    to.STATIC_FIELD_TYPE_TO_NAME = (TypeToNameMap)from.STATIC_FIELD_TYPE_TO_NAME.clone();
-    to.PARAMETER_TYPE_TO_NAME = (TypeToNameMap)from.PARAMETER_TYPE_TO_NAME.clone();
-    to.LOCAL_VARIABLE_TYPE_TO_NAME = (TypeToNameMap)from.LOCAL_VARIABLE_TYPE_TO_NAME.clone();
+    FIELD_TYPE_TO_NAME.copyFrom(from.FIELD_TYPE_TO_NAME);
+    STATIC_FIELD_TYPE_TO_NAME.copyFrom(from.STATIC_FIELD_TYPE_TO_NAME);
+    PARAMETER_TYPE_TO_NAME.copyFrom(from.PARAMETER_TYPE_TO_NAME);
+    LOCAL_VARIABLE_TYPE_TO_NAME.copyFrom(from.LOCAL_VARIABLE_TYPE_TO_NAME);
 
-    to.PACKAGES_TO_USE_IMPORT_ON_DEMAND = (PackageTable)from.PACKAGES_TO_USE_IMPORT_ON_DEMAND.clone();
-    to.IMPORT_LAYOUT_TABLE = (ImportLayoutTable)from.IMPORT_LAYOUT_TABLE.clone();
+    PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(from.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
+    IMPORT_LAYOUT_TABLE.copyFrom(from.IMPORT_LAYOUT_TABLE);
 
-    to.OTHER_INDENT_OPTIONS = (IndentOptions)from.OTHER_INDENT_OPTIONS.clone();
+    OTHER_INDENT_OPTIONS.copyFrom(from.OTHER_INDENT_OPTIONS);
 
-    to.myAdditionalIndentOptions = new LinkedHashMap<FileType, IndentOptions>();
+    myAdditionalIndentOptions.clear();
     for(Map.Entry<FileType, IndentOptions> optionEntry: from.myAdditionalIndentOptions.entrySet()) {
-      to.myAdditionalIndentOptions.put(optionEntry.getKey(),(IndentOptions)optionEntry.getValue().clone());
+      IndentOptions options = optionEntry.getValue();
+      myAdditionalIndentOptions.put(optionEntry.getKey(),(IndentOptions)options.clone());
     }
   }
 
-  public void copyFrom(CodeStyleSettings settings) {
-    Field[] fields = getClass().getDeclaredFields();
+  public void copyFrom(CodeStyleSettings from) {
+    copyPublicFields(from, this);
+
+    this.copyCustomSettingsFrom(from);
+  }
+
+  private static void copyPublicFields(Object from, Object to) {
+    assert from != to;
+    Field[] fields = to.getClass().getDeclaredFields();
     for (Field field : fields) {
       if (isPublic(field) && !isFinal(field)) {
         try {
-          copyFieldValue(settings, field);
+          copyFieldValue(from, to, field);
         }
         catch (Exception e) {
           throw new RuntimeException(e);
         }
       }
     }
-
-    try {
-      copyCustomSettings(settings,  this);
-    }
-    catch (CloneNotSupportedException e) {
-      throw new RuntimeException(e);
-    }
   }
-  private void copyFieldValue(final CodeStyleSettings settings, final Field field)
-    throws IllegalAccessException, CloneNotSupportedException {
+
+  private static void copyFieldValue(final Object from, Object to, final Field field)
+    throws IllegalAccessException {
     Class<?> fieldType = field.getType();
     if (fieldType.isPrimitive()) {
-      field.set(this, field.get(settings));
+      field.set(to, field.get(from));
     }
     else if (fieldType.equals(String.class)) {
-      field.set(this, field.get(settings));
+      field.set(to, field.get(from));
     }
     else {
       System.out.println("Field not copied " + field.getName());
@@ -248,18 +247,22 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
       result = 31 * result + (LABEL_INDENT_ABSOLUTE ? 1 : 0);
       return result;
     }
+
+    public void copyFrom(IndentOptions other) {
+      copyPublicFields(other, this);
+    }
   }
 
   @Deprecated
-  public IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions();
+  public final IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions();
   @Deprecated
-  public IndentOptions JSP_INDENT_OPTIONS = new IndentOptions();
+  public final IndentOptions JSP_INDENT_OPTIONS = new IndentOptions();
   @Deprecated
-  public IndentOptions XML_INDENT_OPTIONS = new IndentOptions();
+  public final IndentOptions XML_INDENT_OPTIONS = new IndentOptions();
 
-  public IndentOptions OTHER_INDENT_OPTIONS = new IndentOptions();
+  public final IndentOptions OTHER_INDENT_OPTIONS = new IndentOptions();
 
-  private Map<FileType,IndentOptions> myAdditionalIndentOptions = new LinkedHashMap<FileType, IndentOptions>();
+  private final Map<FileType,IndentOptions> myAdditionalIndentOptions = new LinkedHashMap<FileType, IndentOptions>();
 
   private static final String ourSystemLineSeparator = SystemProperties.getLineSeparator();
 
@@ -720,10 +723,10 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
   public boolean PREFER_LONGER_NAMES = true;
 
-  public TypeToNameMap FIELD_TYPE_TO_NAME = new TypeToNameMap();
-  public TypeToNameMap STATIC_FIELD_TYPE_TO_NAME = new TypeToNameMap();
-  @NonNls public TypeToNameMap PARAMETER_TYPE_TO_NAME = new TypeToNameMap();
-  public TypeToNameMap LOCAL_VARIABLE_TYPE_TO_NAME = new TypeToNameMap();
+  public final TypeToNameMap FIELD_TYPE_TO_NAME = new TypeToNameMap();
+  public final TypeToNameMap STATIC_FIELD_TYPE_TO_NAME = new TypeToNameMap();
+  @NonNls public final TypeToNameMap PARAMETER_TYPE_TO_NAME = new TypeToNameMap();
+  public final TypeToNameMap LOCAL_VARIABLE_TYPE_TO_NAME = new TypeToNameMap();
 
 //----------------- 'final' modifier settings -------
   public boolean GENERATE_FINAL_LOCALS = false;
@@ -735,14 +738,15 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
 //----------------- IMPORTS --------------------
 
+  public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
   public boolean USE_FQ_CLASS_NAMES = false;
   public boolean USE_FQ_CLASS_NAMES_IN_JAVADOC = true;
   public boolean USE_SINGLE_CLASS_IMPORTS = true;
   public boolean INSERT_INNER_CLASS_IMPORTS = false;
   public int CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 5;
   public int NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 3;
-  public PackageTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageTable();
-  public ImportLayoutTable IMPORT_LAYOUT_TABLE = new ImportLayoutTable();
+  public final PackageEntryTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable();
+  public final PackageEntryTable IMPORT_LAYOUT_TABLE = new PackageEntryTable();
   public boolean OPTIMIZE_IMPORTS_ON_THE_FLY = false;
   public boolean ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = false;
 
@@ -1115,6 +1119,23 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
   public void readExternal(Element element) throws InvalidDataException {
     DefaultJDOMExternalizer.readExternal(this, element);
+    if (LAYOUT_STATIC_IMPORTS_SEPARATELY) {
+      // add <all other static imports> entry if there is none
+      boolean found = false;
+      for (PackageEntry entry : IMPORT_LAYOUT_TABLE.getEntries()) {
+        if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        PackageEntry last = IMPORT_LAYOUT_TABLE.getEntryCount() == 0 ? null : IMPORT_LAYOUT_TABLE.getEntryAt(IMPORT_LAYOUT_TABLE.getEntryCount() - 1);
+        if (last != PackageEntry.BLANK_LINE_ENTRY) {
+          IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
+        }
+        IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
+      }
+    }
     importOldIndentOptions(element);
     for (final CustomCodeStyleSettings settings : myCustomSettings.values()) {
       settings.readExternal(element);
@@ -1269,9 +1290,9 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
     return getIndentOptions(fileType).USE_TAB_CHARACTER;
   }
 
-  public static class TypeToNameMap implements JDOMExternalizable, Cloneable {
-    private ArrayList<String> myPatterns = new ArrayList<String>();
-    private ArrayList<String> myNames = new ArrayList<String>();
+  public static class TypeToNameMap implements JDOMExternalizable {
+    private final List<String> myPatterns = new ArrayList<String>();
+    private final List<String> myNames = new ArrayList<String>();
 
     public void addPair(String pattern, String name) {
       myPatterns.add(pattern);
@@ -1323,11 +1344,12 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
       }
     }
 
-    public Object clone() throws CloneNotSupportedException {
-      TypeToNameMap clon = (TypeToNameMap)TypeToNameMap.super.clone();
-      clon.myPatterns = (ArrayList<String>)myPatterns.clone();
-      clon.myNames = (ArrayList<String>)myNames.clone();
-      return clon;
+    public void copyFrom(TypeToNameMap from) {
+      assert from != this;
+      myPatterns.clear();
+      myPatterns.addAll(from.myPatterns);
+      myNames.clear();
+      myNames.addAll(from.myNames);
     }
 
     public boolean equals(Object other) {
@@ -1371,311 +1393,6 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
   }
 
-  public static class PackageTable implements JDOMExternalizable, Cloneable {
-    public static class Entry implements Cloneable {
-      final String packageName;
-      final boolean withSubpackages;
-
-      public Entry(@NonNls String packageName, boolean withSubpackages) {
-        this.packageName = packageName;
-        this.withSubpackages = withSubpackages;
-      }
-
-      public String getPackageName() {
-        return packageName;
-      }
-
-      public boolean isWithSubpackages() {
-        return withSubpackages;
-      }
-
-      public boolean equals(Object obj) {
-        if (!(obj instanceof Entry)) {
-          return false;
-        }
-        Entry entry = (Entry)obj;
-        return entry.withSubpackages == withSubpackages
-               && Comparing.equal(entry.packageName, packageName);
-      }
-
-      public int hashCode() {
-        if (packageName == null) {
-          return 0;
-        }
-        return packageName.hashCode();
-      }
-
-    }
-
-    private ArrayList<Entry> myEntries = new ArrayList<Entry>();
-
-    public boolean equals(Object obj) {
-      if (!(obj instanceof PackageTable)) {
-        return false;
-      }
-      PackageTable other = (PackageTable)obj;
-      if (other.myEntries.size() != myEntries.size()) {
-        return false;
-      }
-      for (int i = 0; i < myEntries.size(); i++) {
-        Entry entry = myEntries.get(i);
-        Entry otherentry = other.myEntries.get(i);
-        if (!Comparing.equal(entry, otherentry)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    public int hashCode() {
-      if (!myEntries.isEmpty() && myEntries.get(0) != null) {
-        return myEntries.get(0).hashCode();
-      }
-      return 0;
-    }
-
-    public Object clone() throws CloneNotSupportedException {
-      PackageTable clon = (PackageTable)PackageTable.super.clone();
-      clon.myEntries = (ArrayList<Entry>)myEntries.clone();
-      return clon;
-    }
-
-    public void copyFrom(PackageTable packageTable) {
-      myEntries = (ArrayList<Entry>)packageTable.myEntries.clone();
-    }
-
-    public Entry[] getEntries() {
-      return myEntries.toArray(new Entry[myEntries.size()]);
-    }
-
-    public void insertEntryAt(Entry entry, int i) {
-      myEntries.add(i, entry);
-    }
-
-    public void removeEntryAt(int i) {
-      myEntries.remove(i);
-    }
-
-    public Entry getEntryAt(int i) {
-      return myEntries.get(i);
-    }
-
-    public int getEntryCount() {
-      return myEntries.size();
-    }
-
-    public void setEntryAt(Entry entry, int i) {
-      myEntries.set(i, entry);
-    }
-
-    public boolean contains(String packageName) {
-      for (Entry entry : myEntries) {
-        if (packageName.startsWith(entry.packageName)) {
-          if (packageName.length() == entry.packageName.length()) return true;
-          if (entry.withSubpackages) {
-            if (packageName.charAt(entry.packageName.length()) == '.') return true;
-          }
-        }
-      }
-      return false;
-    }
-
-    public void readExternal(@NonNls Element element) throws InvalidDataException {
-      myEntries.clear();
-
-      for (final Object o : element.getChildren("package")) {
-        @NonNls Element e = (Element)o;
-        String packageName = e.getAttributeValue("name");
-        boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages"));
-        if (packageName == null) {
-          throw new InvalidDataException();
-        }
-        myEntries.add(new Entry(packageName, withSubpackages));
-      }
-    }
-
-    public void writeExternal(Element parentNode) throws WriteExternalException {
-      for (Entry entry : myEntries) {
-        @NonNls Element element = new Element("package");
-        parentNode.addContent(element);
-        element.setAttribute("name", entry.packageName);
-        element.setAttribute("withSubpackages", Boolean.toString(entry.withSubpackages));
-      }
-    }
-  }
-
-  public static class ImportLayoutTable implements JDOMExternalizable, Cloneable {
-    private ArrayList<Entry> myEntries = new ArrayList<Entry>();
-
-    public interface Entry {
-    }
-
-    public static class PackageEntry implements Entry {
-      private final String myPackageName;
-      private final boolean myWithSubpackages;
-
-      public PackageEntry(@NonNls String packageName, boolean withSubpackages) {
-        myPackageName = packageName;
-        myWithSubpackages = withSubpackages;
-      }
-
-      public String getPackageName() {
-        return myPackageName;
-      }
-
-      public boolean isWithSubpackages() {
-        return myWithSubpackages;
-      }
-
-      public boolean matchesPackageName(String packageName) {
-        if (myPackageName.length() == 0 && myWithSubpackages) return true;
-        if (packageName.startsWith(myPackageName)) {
-          if (packageName.length() == myPackageName.length()) return true;
-          if (myWithSubpackages) {
-            if (packageName.charAt(myPackageName.length()) == '.') return true;
-          }
-        }
-        return false;
-      }
-
-      public boolean matchesClassName(String className) {
-        int dotIndex = className.lastIndexOf('.');
-        String packageName = dotIndex < 0 ? "" : className.substring(0, dotIndex);
-        return matchesPackageName(packageName);
-      }
-
-      public boolean equals(Object obj) {
-        if (!(obj instanceof PackageEntry)) {
-          return false;
-        }
-        PackageEntry entry = (PackageEntry)obj;
-        return entry.myWithSubpackages == myWithSubpackages
-               && Comparing.equal(entry.myPackageName, myPackageName);
-      }
-
-      public int hashCode() {
-        if (myPackageName == null) {
-          return 0;
-        }
-        return myPackageName.hashCode();
-      }
-    }
-
-    public static class EmptyLineEntry implements Entry {
-      public boolean equals(Object obj) {
-        return obj instanceof EmptyLineEntry;
-      }
-
-      public int hashCode() {
-        return 100;
-      }
-    }
-
-
-    public void copyFrom(ImportLayoutTable importLayoutTable) {
-      myEntries = (ArrayList<Entry>)importLayoutTable.myEntries.clone();
-    }
-
-    public Entry[] getEntries() {
-      return myEntries.toArray(new Entry[myEntries.size()]);
-    }
-
-    public void insertEntryAt(Entry entry, int i) {
-      myEntries.add(i, entry);
-    }
-
-    public void removeEntryAt(int i) {
-      myEntries.remove(i);
-    }
-
-    public Entry getEntryAt(int i) {
-      return myEntries.get(i);
-    }
-
-    public int getEntryCount() {
-      return myEntries.size();
-    }
-
-    public void setEntryAt(Entry entry, int i) {
-      myEntries.set(i, entry);
-    }
-
-    public void readExternal(Element element) throws InvalidDataException {
-      myEntries.clear();
-      List children = element.getChildren();
-      for (final Object aChildren : children) {
-        @NonNls Element e = (Element)aChildren;
-        @NonNls String name = e.getName();
-        if ("package".equals(name)) {
-          String packageName = e.getAttributeValue("name");
-          boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages"));
-          if (packageName == null) {
-            throw new InvalidDataException();
-          }
-          myEntries.add(new PackageEntry(packageName, withSubpackages));
-        }
-        else {
-          if ("emptyLine".equals(name)) {
-            myEntries.add(new EmptyLineEntry());
-          }
-        }
-
-      }
-
-    }
-
-    public void writeExternal(Element parentNode) throws WriteExternalException {
-      for (Entry myEntry : myEntries) {
-        if (myEntry instanceof PackageEntry) {
-          PackageEntry entry = (PackageEntry)myEntry;
-          @NonNls Element element = new Element("package");
-          parentNode.addContent(element);
-          element.setAttribute("name", entry.getPackageName());
-          element.setAttribute("withSubpackages", entry.isWithSubpackages() ? "true" : "false");
-        }
-        else {
-          if (myEntry instanceof EmptyLineEntry) {
-            @NonNls Element element = new Element("emptyLine");
-            parentNode.addContent(element);
-          }
-        }
-      }
-    }
-
-    public boolean equals(Object obj) {
-      if (!(obj instanceof ImportLayoutTable)) {
-        return false;
-      }
-      ImportLayoutTable other = (ImportLayoutTable)obj;
-      if (other.myEntries.size() != myEntries.size()) {
-        return false;
-      }
-      for (int i = 0; i < myEntries.size(); i++) {
-        Entry entry = myEntries.get(i);
-        Entry otherentry = other.myEntries.get(i);
-        if (!Comparing.equal(entry, otherentry)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    public int hashCode() {
-      if (!myEntries.isEmpty() && myEntries.get(0) != null) {
-        return myEntries.get(0).hashCode();
-      }
-      return 0;
-    }
-
-    public Object clone() throws CloneNotSupportedException {
-      ImportLayoutTable clon = (ImportLayoutTable)ImportLayoutTable.super.clone();
-      clon.myEntries = (ArrayList<Entry>)myEntries.clone();
-      return clon;
-    }
-
-
-  }
-
   private void registerAdditionalIndentOptions(FileType fileType, IndentOptions options) {
     myAdditionalIndentOptions.put(fileType, options);
   }
@@ -1689,9 +1406,8 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
 
   private void loadAdditionalIndentOptions() {
     myLoadedAdditionalIndentOptions = true;
-    final FileTypeIndentOptionsProvider[] fileTypeIndentOptionsProviders =
-      Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
-    for (final FileTypeIndentOptionsProvider provider : fileTypeIndentOptionsProviders) {
+    final FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
+    for (final FileTypeIndentOptionsProvider provider : providers) {
       if (!myAdditionalIndentOptions.containsKey(provider.getFileType())) {
         registerAdditionalIndentOptions(provider.getFileType(), provider.createIndentOptions());
       }
@@ -1701,16 +1417,13 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
   @TestOnly
   public void clearCodeStyleSettings() throws Exception {
     CodeStyleSettings cleanSettings = new CodeStyleSettings();
-    Element element = new Element("temp");
-    cleanSettings.writeExternal(element);
-
-    readExternal(element);
+    copyFrom(cleanSettings);
     myAdditionalIndentOptions.clear(); //hack
     myLoadedAdditionalIndentOptions = false;
   }
 
   private static class TempFileType implements FileType {
-    private String myExtension;
+    private final String myExtension;
 
     private TempFileType(@NotNull final String extension) {
       myExtension = extension;
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java
new file mode 100755 (executable)
index 0000000..18f189b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2009 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.psi.codeStyle;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: cdr
+ */
+public class PackageEntry {
+  private final String myPackageName;
+  private final boolean myWithSubpackages;
+  private final boolean isStatic;
+
+  public PackageEntry(boolean isStatic, @NotNull @NonNls String packageName, boolean withSubpackages) {
+    this.isStatic = isStatic;
+    myPackageName = packageName;
+    myWithSubpackages = withSubpackages;
+  }
+
+  public String getPackageName() {
+    return myPackageName;
+  }
+
+  public boolean isWithSubpackages() {
+    return myWithSubpackages;
+  }
+
+  public boolean isStatic() {
+    return isStatic;
+  }
+
+  public boolean matchesPackageName(String packageName) {
+    if (packageName.startsWith(myPackageName)) {
+      if (packageName.length() == myPackageName.length()) return true;
+      if (myWithSubpackages) {
+        if (packageName.charAt(myPackageName.length()) == '.') return true;
+      }
+    }
+    return false;
+  }
+
+  public boolean equals(Object obj) {
+    if (!(obj instanceof PackageEntry)) {
+      return false;
+    }
+    PackageEntry entry = (PackageEntry)obj;
+    return entry.myWithSubpackages == myWithSubpackages
+           && entry.isStatic() == isStatic()
+           && Comparing.equal(entry.myPackageName, myPackageName);
+  }
+
+  public int hashCode() {
+    return myPackageName.hashCode();
+  }
+  
+  public static final PackageEntry BLANK_LINE_ENTRY = new PackageEntry(false, "<blank line>", true){
+    @Override
+    public boolean matchesPackageName(String packageName) {
+      return false;
+    }
+  };
+  public static final PackageEntry ALL_OTHER_IMPORTS_ENTRY = new PackageEntry(false, "<all other imports>", true){
+    @Override
+    public boolean matchesPackageName(String packageName) {
+      return true;
+    }
+  };
+  public static final PackageEntry ALL_OTHER_STATIC_IMPORTS_ENTRY = new PackageEntry(true, "<all other static imports>", true){
+    @Override
+    public boolean matchesPackageName(String packageName) {
+      return true;
+    }
+  };
+
+  public boolean isSpecial() {
+    return this == BLANK_LINE_ENTRY || this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_STATIC_IMPORTS_ENTRY;
+  }
+
+  public boolean isBetterMatchForPackageThan(@Nullable PackageEntry entry, @NotNull String packageName, boolean isStatic) {
+    if (isStatic() != isStatic || !matchesPackageName(packageName)) return false;
+    if (entry == null) {
+      return true;
+    }
+    if (entry.isStatic() != isStatic) return false;
+    if (entry.isWithSubpackages() != isWithSubpackages()) {
+      return !isWithSubpackages();
+    }
+    if (entry == ALL_OTHER_IMPORTS_ENTRY || entry == ALL_OTHER_STATIC_IMPORTS_ENTRY) return true;
+    if (this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_STATIC_IMPORTS_ENTRY) return false;
+    return StringUtil.countChars(entry.getPackageName(), '.') < StringUtil.countChars(getPackageName(), '.');
+  }
+
+  @NonNls
+  @Override
+  public String toString() {
+    return (isStatic() ? "static " : "") + getPackageName();
+  }
+}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java
new file mode 100755 (executable)
index 0000000..15acfa8
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2000-2009 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.psi.codeStyle;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizable;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* User: cdr
+*/
+public class PackageEntryTable implements JDOMExternalizable, Cloneable {
+  private final List<PackageEntry> myEntries = new ArrayList<PackageEntry>();
+
+  public boolean equals(Object obj) {
+    if (!(obj instanceof PackageEntryTable)) {
+      return false;
+    }
+    PackageEntryTable other = (PackageEntryTable)obj;
+    if (other.myEntries.size() != myEntries.size()) {
+      return false;
+    }
+    for (int i = 0; i < myEntries.size(); i++) {
+      PackageEntry entry = myEntries.get(i);
+      PackageEntry otherentry = other.myEntries.get(i);
+      if (!Comparing.equal(entry, otherentry)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public int hashCode() {
+    if (!myEntries.isEmpty() && myEntries.get(0) != null) {
+      return myEntries.get(0).hashCode();
+    }
+    return 0;
+  }
+
+  public Object clone() throws CloneNotSupportedException {
+    PackageEntryTable clon = new PackageEntryTable();
+    clon.copyFrom(this);
+    return clon;
+  }
+
+  public void copyFrom(PackageEntryTable packageTable) {
+    myEntries.clear();
+    myEntries.addAll(packageTable.myEntries);
+  }
+
+  public PackageEntry[] getEntries() {
+    return myEntries.toArray(new PackageEntry[myEntries.size()]);
+  }
+
+  public void insertEntryAt(PackageEntry entry, int i) {
+    myEntries.add(i, entry);
+  }
+
+  public void removeEntryAt(int i) {
+    myEntries.remove(i);
+  }
+
+  public PackageEntry getEntryAt(int i) {
+    return myEntries.get(i);
+  }
+
+  public int getEntryCount() {
+    return myEntries.size();
+  }
+
+  public void setEntryAt(PackageEntry entry, int i) {
+    myEntries.set(i, entry);
+  }
+
+  public boolean contains(String packageName) {
+    for (PackageEntry entry : myEntries) {
+      if (packageName.startsWith(entry.getPackageName())) {
+        if (packageName.length() == entry.getPackageName().length()) return true;
+        if (entry.isWithSubpackages()) {
+          if (packageName.charAt(entry.getPackageName().length()) == '.') return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public void readExternal(Element element) throws InvalidDataException {
+    myEntries.clear();
+    List children = element.getChildren();
+    for (final Object aChildren : children) {
+      @NonNls Element e = (Element)aChildren;
+      @NonNls String name = e.getName();
+      if ("package".equals(name)) {
+        String packageName = e.getAttributeValue("name");
+        boolean isStatic = Boolean.parseBoolean(e.getAttributeValue("static"));
+        boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages"));
+        if (packageName == null) {
+          throw new InvalidDataException();
+        }
+        PackageEntry entry;
+        if (packageName.length() == 0) {
+          entry = isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
+        }
+        else {
+          entry = new PackageEntry(isStatic, packageName, withSubpackages);
+        }
+        myEntries.add(entry);
+      }
+      else {
+        if ("emptyLine".equals(name)) {
+          myEntries.add(PackageEntry.BLANK_LINE_ENTRY);
+        }
+      }
+    }
+  }
+
+  public void writeExternal(Element parentNode) throws WriteExternalException {
+    for (PackageEntry entry : myEntries) {
+      if (entry == PackageEntry.BLANK_LINE_ENTRY) {
+        @NonNls Element element = new Element("emptyLine");
+        parentNode.addContent(element);
+      }
+      else {
+        @NonNls Element element = new Element("package");
+        parentNode.addContent(element);
+        String packageName = entry.getPackageName();
+        element.setAttribute("name", entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY ? "": packageName);
+        element.setAttribute("withSubpackages", entry.isWithSubpackages() ? "true" : "false");
+        element.setAttribute("static", entry.isStatic() ? "true" : "false");
+      }
+    }
+  }
+
+  public void removeEmptyPackages() {
+    for(int i = myEntries.size()-1; i>=0; i--){
+      PackageEntry entry = myEntries.get(i);
+      if(StringUtil.isEmptyOrSpaces(entry.getPackageName())) {
+        removeEntryAt(i);
+      }
+    }
+  }
+
+  public void addEntry(PackageEntry entry) {
+    myEntries.add(entry);
+  }
+}
index a9fdb375e5bc0b42ebae6060a1dc218de6bf0d30..5e2d1a522b1efc20cad4765b438f4ddd467c633a 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.intellij.application.options;
 
-import com.intellij.openapi.Disposable;
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
@@ -129,13 +128,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
 
     for(Map.Entry<FileType, IndentOptionsEditor> entry: myAdditionalIndentOptions.entrySet()) {
       FileType ft = entry.getKey();
-      String tabName;
-      if (ft instanceof LanguageFileType) {
-        tabName = ((LanguageFileType) ft).getLanguage().getDisplayName();
-      }
-      else {
-        tabName = ft.getName();
-      }
+      String tabName = ft instanceof LanguageFileType ? ((LanguageFileType)ft).getLanguage().getDisplayName() : ft.getName();
       myIndentOptionsTabs.addTab(tabName, entry.getValue().createPanel());
     }
 
@@ -195,7 +188,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
   @Nullable
   private static FileTypeIndentOptionsProvider getDefaultIndentProvider() {
     FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
-    return (providers.length == 0) ? null : providers[0];
+    return providers.length == 0 ? null : providers[0];
   }
 
   public void apply(CodeStyleSettings settings) {
@@ -208,8 +201,10 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
     else {
       myOtherIndentOptions.apply(settings, settings.OTHER_INDENT_OPTIONS);
 
-      for(FileType fileType: myAdditionalIndentOptions.keySet()) {
-        myAdditionalIndentOptions.get(fileType).apply(settings, settings.getAdditionalIndentOptions(fileType));
+      for(Map.Entry<FileType, IndentOptionsEditor> entry : myAdditionalIndentOptions.entrySet()) {
+        FileType fileType = entry.getKey();
+        IndentOptionsEditor editor = entry.getValue();
+        editor.apply(settings, settings.getAdditionalIndentOptions(fileType));
       }
     }
 
@@ -221,14 +216,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
   }
 
   private IndentOptionsEditor findEditorForSameIndents() {
-    IndentOptionsEditor theEditor;
-    if (myAdditionalIndentOptions.isEmpty()) {
-      theEditor = myOtherIndentOptions;
-    }
-    else {
-      theEditor = myAdditionalIndentOptions.values().iterator().next();
-    }
-    return theEditor;
+    return myAdditionalIndentOptions.isEmpty() ? myOtherIndentOptions : myAdditionalIndentOptions.values().iterator().next();
   }
 
   private int getRightMarginImpl() {
@@ -275,18 +263,16 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
         return true;
       }
 
-      for(FileType fileType: myAdditionalIndentOptions.keySet()) {
-        if (myAdditionalIndentOptions.get(fileType).isModified(settings, settings.getAdditionalIndentOptions(fileType))) {
+      for(Map.Entry<FileType, IndentOptionsEditor> entry : myAdditionalIndentOptions.entrySet()) {
+        IndentOptionsEditor editor = entry.getValue();
+        FileType fileType = entry.getKey();
+        if (editor.isModified(settings, settings.getAdditionalIndentOptions(fileType))) {
           return true;
         }
       }
     }
 
-    if (!myRightMarginField.getText().equals(String.valueOf(settings.RIGHT_MARGIN))) {
-      return true;
-    }
-
-    return false;
+    return !myRightMarginField.getText().equals(String.valueOf(settings.RIGHT_MARGIN));
   }
 
   public JComponent getPanel() {
@@ -299,14 +285,15 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
     myOtherIndentOptions.reset(settings, settings.OTHER_INDENT_OPTIONS);
 
     boolean first = true;
-    for(FileType fileType: myAdditionalIndentOptions.keySet()) {
-      final IndentOptionsEditor editor = myAdditionalIndentOptions.get(fileType);
+    for(Map.Entry<FileType, IndentOptionsEditor> entry : myAdditionalIndentOptions.entrySet()) {
+      final IndentOptionsEditor editor = entry.getValue();
       if (settings.USE_SAME_INDENTS && first) {
         first = false;
         editor.reset(settings, settings.OTHER_INDENT_OPTIONS);
       }
       else {
-        editor.reset(settings, settings.getAdditionalIndentOptions(fileType));
+        FileType type = entry.getKey();
+        editor.reset(settings, settings.getAdditionalIndentOptions(type));
       }
     }
 
index b908edb019aa865bafd0e0fc12927ce85c21a26e..2b0d79bb953ada31c05fb304d7824a13f1828bef 100644 (file)
@@ -280,14 +280,13 @@ public class ParameterInfoController {
 
     if (elementForUpdating != null) {
       myHandler.updateParameterInfo(elementForUpdating, context);
-      myComponent.update();
       if (myHint.isVisible() && myEditor.getComponent().getRootPane() != null) {
+        myComponent.update();
         HintManagerImpl.adjustEditorHintPosition(myHint, myEditor, myProvider.getBestPointPosition(myHint, (PsiElement)elementForUpdating,offset));
       }
     }
     else {
       context.removeHint();
-      myComponent.update();
     }
   }
 
index 889f7a4c9484b9133982b4c78781c4b4d7a74c20..8b1cfbf669b7a6e380d0da09b86a8530e8209f30 100644 (file)
@@ -65,13 +65,14 @@ public class ConvertProjectDialog extends DialogWrapper {
     }
 
     myBackupDir = ProjectConversionUtil.getBackupDir(context.getProjectBaseDir());
-    JLabel templateLabel = new JLabel();
     myTextPane.setFont(UIUtil.getLabelFont());
     myTextPane.setContentType("text/html");
-    myTextPane.setEditorKit(new HTMLEditorKit());
+    final HTMLEditorKit editorKit = new HTMLEditorKit();
+    editorKit.getStyleSheet().addRule(UIUtil.displayPropertiesToCSS(UIUtil.getLabelFont(), UIUtil.getLabelForeground()));
+    myTextPane.setEditorKit(editorKit);
     myTextPane.setEditable(false);
-    myTextPane.setBackground(templateLabel.getBackground());
-    myTextPane.setForeground(templateLabel.getForeground());
+    myTextPane.setBackground(UIUtil.getLabelBackground());
+    myTextPane.setForeground(UIUtil.getLabelForeground());
     myTextPane.setText(IdeBundle.message("label.text.project.has.older.format", context.getProjectFile().getName(), myBackupDir.getAbsolutePath()));
 
     myTextPane.addHyperlinkListener(new HyperlinkListener() {
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java
new file mode 100644 (file)
index 0000000..3b9f8d0
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.formatting.ASTBlock;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Spacing;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jul 3, 2009
+ *         Time: 2:47:10 PM
+ */
+class BlockUtil {
+  private BlockUtil() {
+  }
+
+  public static List<DataLanguageBlockWrapper> buildChildWrappers(@NotNull final Block parent) {
+    assert !(parent instanceof DataLanguageBlockWrapper) : parent.getClass();
+    List<Block> children = parent.getSubBlocks();
+    if (children.size() == 0) return Collections.emptyList();
+    ArrayList<DataLanguageBlockWrapper> result = new ArrayList<DataLanguageBlockWrapper>(children.size());
+    DataLanguageBlockWrapper prevWrapper = null;
+    for (Block child : children) {
+      DataLanguageBlockWrapper currWrapper = createAndAddBlock(result, child, null);
+      if(currWrapper != null && prevWrapper != null) {
+        Spacing spacing = parent.getSpacing(prevWrapper.getOriginal(), currWrapper.getOriginal());
+        prevWrapper.setRightHandSpacing(currWrapper, spacing);
+      }
+      prevWrapper = currWrapper;
+    }
+    return result;
+  }
+
+  public static Pair<List<DataLanguageBlockWrapper>, List<DataLanguageBlockWrapper>> splitBlocksByRightBound(@NotNull Block parent, @NotNull TextRange bounds) {
+    final List<Block> subBlocks = parent.getSubBlocks();
+    if (subBlocks.size() == 0) return new Pair<List<DataLanguageBlockWrapper>, List<DataLanguageBlockWrapper>>(Collections.<DataLanguageBlockWrapper>emptyList(), Collections.<DataLanguageBlockWrapper>emptyList());
+    final ArrayList<DataLanguageBlockWrapper> before = new ArrayList<DataLanguageBlockWrapper>(subBlocks.size() / 2);
+    final ArrayList<DataLanguageBlockWrapper> after = new ArrayList<DataLanguageBlockWrapper>(subBlocks.size() / 2);
+    splitByRightBoundAndCollectBlocks(subBlocks, before, after, bounds);
+    return new Pair<List<DataLanguageBlockWrapper>, List<DataLanguageBlockWrapper>>(before, after);
+  }
+
+  private static void splitByRightBoundAndCollectBlocks(@NotNull List<Block> blocks,
+                                                        @NotNull List<DataLanguageBlockWrapper> before,
+                                                        @NotNull List<DataLanguageBlockWrapper> after,
+                                                        @NotNull TextRange bounds) {
+    for (Block block : blocks) {
+      final TextRange textRange = block.getTextRange();
+      if (bounds.contains(textRange)) {
+        createAndAddBlock(before, block, null);
+      }
+      else if (bounds.getEndOffset() < textRange.getStartOffset()) {
+        createAndAddBlock(after, block, null);
+      }
+      else {
+        splitByRightBoundAndCollectBlocks(block.getSubBlocks(), before, after, bounds);
+      }
+    }
+  }
+
+  @Nullable
+  private static DataLanguageBlockWrapper createAndAddBlock(List<DataLanguageBlockWrapper> list, Block block, @Nullable final Indent indent) {
+    DataLanguageBlockWrapper wrapper = DataLanguageBlockWrapper.create(block, indent);
+    if (wrapper != null) {
+      list.add(wrapper);
+    }
+    return wrapper;
+  }
+
+
+  public static List<Block> mergeBlocks(@NotNull List<TemplateLanguageBlock> tlBlocks, @NotNull List<DataLanguageBlockWrapper> foreignBlocks) {
+    ArrayList<Block> result = new ArrayList<Block>(tlBlocks.size() + foreignBlocks.size());
+    int vInd = 0;
+    int fInd = 0;
+    while (vInd < tlBlocks.size() && fInd < foreignBlocks.size()) {
+      final TemplateLanguageBlock v = tlBlocks.get(vInd);
+      final DataLanguageBlockWrapper f = foreignBlocks.get(fInd);
+      final TextRange vRange = v.getTextRange();
+      final TextRange fRange = f.getTextRange();
+      if (vRange.getStartOffset() >= fRange.getEndOffset()) {
+        // add leading foreign blocks
+        result.add(f);
+        fInd++;
+      }
+      else if (vRange.getEndOffset() <= fRange.getStartOffset()) {
+        // add leading TL blocks
+        result.add(v);
+        vInd++;
+      }
+      else if (vRange.getStartOffset() < fRange.getStartOffset() ||
+               vRange.getStartOffset() == fRange.getStartOffset() && vRange.getEndOffset() >= fRange.getEndOffset()) {
+        // add including TL blocks and split intersecting foreign blocks
+        result.add(v);
+        while (fInd < foreignBlocks.size() && vRange.contains(foreignBlocks.get(fInd).getTextRange())) {
+          v.addForeignChild(foreignBlocks.get(fInd++));
+        }
+        if (fInd < foreignBlocks.size()) {
+          final DataLanguageBlockWrapper notContainedF = foreignBlocks.get(fInd);
+          if (vRange.intersectsStrict(notContainedF.getTextRange())) {
+            Pair<List<DataLanguageBlockWrapper>, List<DataLanguageBlockWrapper>> splitBlocks = splitBlocksByRightBound(notContainedF.getOriginal(), vRange);
+            v.addForeignChildren(splitBlocks.getFirst());
+            foreignBlocks.remove(fInd);
+            if (splitBlocks.getSecond().size() > 0) {
+              foreignBlocks.addAll(fInd, splitBlocks.getSecond());
+            }
+          }
+        }
+        vInd++;
+      }
+      else if (vRange.getStartOffset() > fRange.getStartOffset() ||
+               vRange.getStartOffset() == fRange.getStartOffset() && vRange.getEndOffset() < fRange.getEndOffset()) {
+        // add including foreign blocks or split them if needed
+        int lastContainedTlInd = vInd;
+        while (lastContainedTlInd < tlBlocks.size() && fRange.intersectsStrict(tlBlocks.get(lastContainedTlInd).getTextRange())) {
+          lastContainedTlInd++;
+        }
+        if (fRange.contains(tlBlocks.get(lastContainedTlInd - 1).getTextRange())) {
+          result.add(f);
+          fInd++;
+          while (vInd < lastContainedTlInd) {
+            f.addTlChild(tlBlocks.get(vInd++));
+          }
+        }
+        else {
+          foreignBlocks.remove(fInd);
+          foreignBlocks.addAll(fInd, buildChildWrappers(f.getOriginal()));
+        }
+      }
+    }
+    while (vInd < tlBlocks.size()) {
+      result.add(tlBlocks.get(vInd++));
+    }
+    while (fInd < foreignBlocks.size()) {
+      result.add(foreignBlocks.get(fInd++));
+    }
+    return result;
+  }
+
+  @NotNull
+  public static List<DataLanguageBlockWrapper> filterBlocksByRange(@NotNull List<DataLanguageBlockWrapper> list, @NotNull TextRange textRange) {
+    int i = 0;
+    while (i < list.size()) {
+      final DataLanguageBlockWrapper wrapper = list.get(i);
+      final TextRange range = wrapper.getTextRange();
+      if (textRange.contains(range)) {
+        i++;
+      }
+      else if (range.intersectsStrict(textRange)) {
+        list.remove(i);
+        list.addAll(i, buildChildWrappers(wrapper.getOriginal()));
+      }
+      else {
+        list.remove(i);
+      }
+    }
+    return list;
+  }
+
+  static List<Block> splitBlockIntoFragments(@NotNull Block block, @NotNull List<TemplateLanguageBlock> subBlocks) {
+    final List<Block> children = new ArrayList<Block>(5);
+    final TextRange range = block.getTextRange();
+    int childStartOffset = range.getStartOffset();
+    for (TemplateLanguageBlock tlBlock : subBlocks) {
+      final TextRange tlTextRange = tlBlock.getTextRange();
+      if (tlTextRange.getStartOffset() > childStartOffset) {
+        children.add(new DataLanguageBlockFragmentWrapper(block, new TextRange(childStartOffset, tlTextRange.getStartOffset())));
+      }
+      children.add(tlBlock);
+      childStartOffset = tlTextRange.getEndOffset();
+    }
+    if (range.getEndOffset() > childStartOffset) {
+      children.add(new DataLanguageBlockFragmentWrapper(block, new TextRange(childStartOffset, range.getEndOffset())));
+    }
+    return children;
+  }
+
+  static void printBlocks(@Nullable TextRange textRange, @NotNull List<Block> list) {
+    StringBuilder sb = new StringBuilder(String.valueOf(textRange)).append(": ");
+    for (Block block : list) {
+      ASTNode node = block instanceof ASTBlock ? ((ASTBlock)block).getNode() : null;
+      TextRange r = block.getTextRange();
+      sb.append(" [").append(node != null ? node.getElementType() : null)//.append(" ").append(((BlockWithParent)block).getParent() != null)
+          .append(r).append(block.getIndent()).append(block.getAlignment()).append("] ");
+    }
+    System.out.println(sb);
+  }
+
+  static List<Block> setParent(List<Block> children, BlockWithParent parent) {
+    for (Block block : children) {
+      if (block instanceof BlockWithParent) ((BlockWithParent)block).setParent(parent);
+    }
+    return children;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockWithParent.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockWithParent.java
new file mode 100644 (file)
index 0000000..9d45eba
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jul 6, 2009
+ *         Time: 8:29:23 PM
+ */
+public interface BlockWithParent {
+  BlockWithParent getParent();
+  void setParent(BlockWithParent newParent);
+}
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockFragmentWrapper.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockFragmentWrapper.java
new file mode 100644 (file)
index 0000000..ab1a407
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.formatting.*;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jun 30, 2009
+ *         Time: 7:18:37 PM
+ */
+public class DataLanguageBlockFragmentWrapper implements Block {
+  private final Block myOwner;
+  private final TextRange myRange;
+
+  public DataLanguageBlockFragmentWrapper(@NotNull final Block owner, @NotNull final TextRange range) {
+    myOwner = owner;
+    myRange = range;
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    return myRange;
+  }
+
+  @NotNull
+  public List<Block> getSubBlocks() {
+    return AbstractBlock.EMPTY;
+  }
+
+  public Wrap getWrap() {
+    return myOwner.getWrap();
+  }
+
+  public Indent getIndent() {
+    return myOwner.getIndent();
+  }
+
+  public Alignment getAlignment() {
+    return myOwner.getAlignment();
+  }
+
+  @Nullable
+  public Spacing getSpacing(Block child1, Block child2) {
+    return Spacing.getReadOnlySpacing();
+  }
+
+  @NotNull
+  public ChildAttributes getChildAttributes(int newChildIndex) {
+    return myOwner.getChildAttributes(newChildIndex);
+  }
+
+  public boolean isIncomplete() {
+    return myOwner.isIncomplete();
+  }
+
+  public boolean isLeaf() {
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    return "Fragment " + getTextRange();
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java
new file mode 100644 (file)
index 0000000..f43eabb
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.templateLanguages.OuterLanguageElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jun 30, 2009
+ *         Time: 7:18:37 PM
+ */
+public class DataLanguageBlockWrapper implements ASTBlock, BlockWithParent {
+  private final Block myOriginal;
+  private final Indent myIndent;
+  private List<Block> myBlocks;
+  private List<TemplateLanguageBlock> myTlBlocks;
+  private BlockWithParent myParent;
+  private DataLanguageBlockWrapper myRightHandWrapper;
+  private Spacing mySpacing;
+
+  private DataLanguageBlockWrapper(@NotNull final Block original, @Nullable final Indent indent) {
+    assert !(original instanceof DataLanguageBlockWrapper) && !(original instanceof TemplateLanguageBlock);
+    myOriginal = original;
+    myIndent = indent;
+  }
+
+  @NotNull
+  public TextRange getTextRange() {
+    return myOriginal.getTextRange();
+  }
+
+  @NotNull
+  public List<Block> getSubBlocks() {
+    if (myBlocks == null) {
+      myBlocks = buildBlocks();
+    }
+    return myBlocks;
+  }
+
+  private List<Block> buildBlocks() {
+    assert myBlocks == null;
+    if (isLeaf()) {
+      return AbstractBlock.EMPTY;
+    }
+    final List<DataLanguageBlockWrapper> subWrappers = BlockUtil.buildChildWrappers(myOriginal);
+    final List<Block> children;
+    if (myTlBlocks == null) {
+      children = new ArrayList<Block>(subWrappers);
+    }
+    else if (subWrappers.size() == 0) {
+      //noinspection unchecked
+      children = (List<Block>)(subWrappers.size() > 0 ? myTlBlocks : BlockUtil.splitBlockIntoFragments(myOriginal, myTlBlocks));
+    }
+    else {
+      children = BlockUtil.mergeBlocks(myTlBlocks, subWrappers);
+    }
+    //BlockUtil.printBlocks(getTextRange(), children);
+    return BlockUtil.setParent(children, this);
+  }
+
+  public Wrap getWrap() {
+    return myOriginal.getWrap();
+  }
+
+  @NotNull
+  public ChildAttributes getChildAttributes(final int newChildIndex) {
+    return myOriginal.getChildAttributes(newChildIndex);
+  }
+
+  public Indent getIndent() {
+    return myOriginal.getIndent();
+  }
+
+  public Alignment getAlignment() {
+    return myOriginal.getAlignment();
+  }
+
+  @Nullable
+  public Spacing getSpacing(Block child1, Block child2) {
+    if (child1 instanceof DataLanguageBlockWrapper && child2 instanceof DataLanguageBlockWrapper) {
+      return myOriginal.getSpacing(((DataLanguageBlockWrapper)child1).myOriginal, ((DataLanguageBlockWrapper)child2).myOriginal);
+    }
+    return null;
+  }
+
+  public boolean isIncomplete() {
+    return myOriginal.isIncomplete();
+  }
+
+  public boolean isLeaf() {
+    return myTlBlocks == null && myOriginal.isLeaf();
+  }
+
+  void addTlChild(TemplateLanguageBlock tlBlock) {
+    assert myBlocks == null;
+    if (myTlBlocks == null) {
+      myTlBlocks = new ArrayList<TemplateLanguageBlock>(5);
+    }
+    myTlBlocks.add(tlBlock);
+    tlBlock.setParent(this);
+  }
+
+  Block getOriginal() {
+    return myOriginal;
+  }
+
+  @Override
+  public String toString() {
+    String tlBlocksInfo = " TlBlocks " + (myTlBlocks == null ? "0" : myTlBlocks.size()) + "|" + getTextRange() + "|";
+    return tlBlocksInfo + myOriginal.toString();
+  }
+
+  @Nullable
+  public static DataLanguageBlockWrapper create(@NotNull final Block original, @Nullable final Indent indent) {
+    final boolean doesntNeedWrapper = original instanceof ASTBlock && ((ASTBlock)original).getNode() instanceof OuterLanguageElement;
+    return doesntNeedWrapper ? null : new DataLanguageBlockWrapper(original, indent);
+  }
+
+  @Nullable
+  public ASTNode getNode() {
+    return myOriginal instanceof ASTBlock ? ((ASTBlock)myOriginal).getNode() : null;
+  }
+
+  public BlockWithParent getParent() {
+    return myParent;
+  }
+
+  public void setParent(BlockWithParent parent) {
+    myParent = parent;
+  }
+
+  public void setRightHandSpacing(DataLanguageBlockWrapper rightHandWrapper, Spacing spacing) {
+    myRightHandWrapper = rightHandWrapper;
+    mySpacing = spacing;
+  }
+
+  @Nullable
+  public Spacing getRightHandSpacing(DataLanguageBlockWrapper rightHandWrapper) {
+    return myRightHandWrapper == rightHandWrapper ? mySpacing : null;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java
new file mode 100644 (file)
index 0000000..dfec656
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.formatting.*;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.formatter.FormatterUtil;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jun 26, 2009
+ *         Time: 4:05:40 PM
+ */
+public abstract class TemplateLanguageBlock extends AbstractBlock implements BlockWithParent {
+  private final TemplateLanguageBlockFactory myBlockFactory;
+  private List<DataLanguageBlockWrapper> myForeignChildren;
+  private boolean myChildrenBuilt = false;
+  private BlockWithParent myParent;
+
+  protected TemplateLanguageBlock(@NotNull TemplateLanguageBlockFactory blockFactory, @NotNull ASTNode node, @Nullable List<DataLanguageBlockWrapper> foreignChildren) {
+    super(node, null, null);
+    myBlockFactory = blockFactory;
+    myForeignChildren = foreignChildren;
+  }
+
+  protected List<Block> buildChildren() {
+    myChildrenBuilt = true;
+    if (isLeaf()) {
+      return EMPTY;
+    }
+    final ArrayList<TemplateLanguageBlock> tlChildren = new ArrayList<TemplateLanguageBlock>(5);
+    for (ASTNode childNode = getNode().getFirstChildNode(); childNode != null; childNode = childNode.getTreeNext()) {
+      if (FormatterUtil.containsWhiteSpacesOnly(childNode)) continue;
+      if (childNode.getElementType() != getTemplateTextElementType() || noForeignChildren()) {
+        final TemplateLanguageBlock childBlock = myBlockFactory.createTemplateLanguageBlock(childNode, null);
+        childBlock.setParent(this);
+        tlChildren.add(childBlock);
+      }
+    }
+    final List<Block> children = (List<Block>)(myForeignChildren == null ? tlChildren : BlockUtil.mergeBlocks(tlChildren, myForeignChildren));
+    //BlockUtil.printBlocks(getTextRange(), children);
+    return BlockUtil.setParent(children, this);
+  }
+
+  private boolean noForeignChildren() {
+    return (myForeignChildren == null || myForeignChildren.isEmpty());
+  }
+
+  void addForeignChild(@NotNull DataLanguageBlockWrapper foreignChild) {
+    initForeignChildren();
+    myForeignChildren.add(foreignChild);
+  }
+
+  void addForeignChildren(List<DataLanguageBlockWrapper> foreignChildren) {
+    initForeignChildren();
+    myForeignChildren.addAll(foreignChildren);
+  }
+
+  private void initForeignChildren() {
+    assert !myChildrenBuilt;
+    if (myForeignChildren == null) {
+      myForeignChildren = new ArrayList<DataLanguageBlockWrapper>(5);
+    }
+  }
+
+  @Nullable
+  public Spacing getSpacing(Block child1, Block child2) {
+    if (child1 instanceof DataLanguageBlockWrapper && child2 instanceof DataLanguageBlockWrapper) {
+      return ((DataLanguageBlockWrapper)child1).getRightHandSpacing((DataLanguageBlockWrapper)child2);
+    }
+    return null;
+  }
+
+  public boolean isLeaf() {
+    return noForeignChildren() && getNode().getFirstChildNode() == null;
+  }
+
+  protected abstract IElementType getTemplateTextElementType();
+
+  public BlockWithParent getParent() {
+    return myParent;
+  }
+
+  public void setParent(BlockWithParent newParent) {
+    myParent = newParent;
+  }
+}
+
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlockFactory.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlockFactory.java
new file mode 100644 (file)
index 0000000..23aad11
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.lang.ASTNode;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Oct 22, 2009
+ *         Time: 6:56:55 PM
+ */
+public interface TemplateLanguageBlockFactory {
+  TemplateLanguageBlock createTemplateLanguageBlock(@NotNull ASTNode node, @Nullable List<DataLanguageBlockWrapper> foreignChildren); 
+}
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageFormattingModelBuilder.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageFormattingModelBuilder.java
new file mode 100644 (file)
index 0000000..f0037d8
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2009 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.formatting.templateLanguages;
+
+import com.intellij.formatting.*;
+import static com.intellij.formatting.templateLanguages.BlockUtil.buildChildWrappers;
+import static com.intellij.formatting.templateLanguages.BlockUtil.filterBlocksByRange;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.LanguageFormatting;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.DocumentBasedFormattingModel;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Alexey Chmutov
+ *         Date: Jun 26, 2009
+ *         Time: 4:07:09 PM
+ */
+public abstract class TemplateLanguageFormattingModelBuilder implements DelegatingFormattingModelBuilder, TemplateLanguageBlockFactory {
+
+  @NotNull
+  public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
+    final PsiFile file = element.getContainingFile();
+    Block rootBlock = getRootBlock(element, file.getViewProvider(), settings);
+    return new DocumentBasedFormattingModel(rootBlock, element.getProject(), settings, file.getFileType(), file);
+  }
+
+  private Block getRootBlock(PsiElement element, FileViewProvider viewProvider, CodeStyleSettings settings) {
+    ASTNode node = element.getNode();
+    if (node == null) {
+      return createDummyBlock(node);
+    }
+    final Language dataLanguage = ((TemplateLanguageFileViewProvider)viewProvider).getTemplateDataLanguage();
+    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forLanguage(dataLanguage);
+    if (builder instanceof DelegatingFormattingModelBuilder && ((DelegatingFormattingModelBuilder)builder).dontFormatMyModel()) {
+      return createDummyBlock(node);
+    }
+    if (builder == null) {
+      return createTemplateLanguageBlock(node, Collections.<DataLanguageBlockWrapper>emptyList());
+    }
+    final FormattingModel model = builder.createModel(viewProvider.getPsi(dataLanguage), settings);
+    List<DataLanguageBlockWrapper> childWrappers = buildChildWrappers(model.getRootBlock());
+    if (childWrappers.size() == 1) {
+      childWrappers = buildChildWrappers(childWrappers.get(0).getOriginal());
+    }
+    return createTemplateLanguageBlock(node, filterBlocksByRange(childWrappers, node.getTextRange()));
+  }
+
+  protected AbstractBlock createDummyBlock(final ASTNode node) {
+    return new AbstractBlock(node, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment()) {
+      protected List<Block> buildChildren() {
+        return Collections.emptyList();
+      }
+
+      public Spacing getSpacing(final Block child1, final Block child2) {
+        return Spacing.getReadOnlySpacing();
+      }
+
+      public boolean isLeaf() {
+        return true;
+      }
+    };
+  }
+
+  public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
+    return null;
+  }
+
+  public boolean dontFormatMyModel() {
+    return true;
+  }
+}
index 41a2b9a0f2844dd7d4232eba976833d009d5c6b0..289e283c0558333605cd153443d9f4d733c538d6 100644 (file)
@@ -239,4 +239,9 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> {
   public boolean shouldDrillDownOnEmptyElement() {
     return true;
   }
+
+  @Override
+  public boolean isAlwaysShowPlus() {
+    return true;
+  }
 }
index 45c7f3f0b94de478357904fc50b7b2db1b103f27..d8c54a6ac83e79553ad05371a5aba0c8e02f465b 100644 (file)
@@ -66,7 +66,7 @@ public class DocumentBasedFormattingModel implements FormattingModel {
     mySettings = settings;
     myFileType = fileType;
     myDocumentModel = FormattingDocumentModelImpl.createOn(file);
-    myDocument = ((FormattingDocumentModelImpl)myDocumentModel).getDocument();
+    myDocument = myDocumentModel.getDocument();
   }
 
   @NotNull
@@ -85,8 +85,8 @@ public class DocumentBasedFormattingModel implements FormattingModel {
 
     // When processing injection in cdata / comment we need not remove start / end markers that present as whitespace during check in
     // com.intellij.formatting.WhiteSpace and during building formatter model = blocks in e.g. com.intellij.psi.formatter.xml.XmlTagBlock
-    if ((removesStartMarker = (removesPattern(textRange, whiteSpace, marker = "<![CDATA[") ||
-        removesPattern(textRange, whiteSpace, marker ="<!--["))) ||
+    if ((removesStartMarker = removesPattern(textRange, whiteSpace, marker = "<![CDATA[") ||
+        removesPattern(textRange, whiteSpace, marker ="<!--[")) ||
         removesPattern(textRange, whiteSpace, marker = "]]>") ||
         removesPattern(textRange, whiteSpace, marker = "]-->")
       ) {
similarity index 96%
rename from platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateLanguageFormattingModelBuilder.java
rename to platform/lang-impl/src/com/intellij/psi/templateLanguages/SimpleTemplateLanguageFormattingModelBuilder.java
index 5546c87550777a531134be6895610c297136e50e..891b0d42384ce45b7cb22a23f20c534dff10c855 100644 (file)
@@ -34,7 +34,7 @@ import java.util.List;
 /**
  * @author peter
  */
-public class TemplateLanguageFormattingModelBuilder implements FormattingModelBuilder{
+public class SimpleTemplateLanguageFormattingModelBuilder implements FormattingModelBuilder{
   @NotNull
   public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
     if (element instanceof PsiFile) {
index 7c01f74ac33d0253534503d0e64f2d94b40bfcf2..a154adbc794d14cd2fa01ff68be4646d6760c6f5 100644 (file)
@@ -90,7 +90,7 @@ public abstract class AbstractTreeNode<T> extends PresentableNodeDescriptor impl
 
 
   public boolean isAlwaysShowPlus() {
-    return true;
+    return false;
   }
 
   public boolean isAlwaysExpand() {
index d12d4797f0fadfb9ea8134785a088c421dc76bc9..e3ea4a85705103051ed20cb5ef545e58482890cd 100644 (file)
@@ -33,6 +33,7 @@ public abstract class ProgressManager {
 
   public abstract boolean hasProgressIndicator();
   public abstract boolean hasModalProgressIndicator();
+  public abstract boolean hasUnsafeProgressIndicator();
 
   public abstract void runProcess(Runnable process, ProgressIndicator progress) throws ProcessCanceledException;
 
index 6169aa1760a3bb2ce0c2ed912a61a043f02d7164..cd83e19c9c6828955573417bf3ffb04e65ce9b7b 100644 (file)
@@ -25,19 +25,19 @@ import com.intellij.openapi.actionSystem.CommonShortcuts;
 import com.intellij.openapi.actionSystem.CustomShortcutSet;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.UnnamedConfigurable;
-import com.intellij.openapi.util.Cloner;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Factory;
+import com.intellij.openapi.util.*;
 import com.intellij.util.Icons;
+import com.intellij.util.ui.tree.TreeUtil;
 import gnu.trove.Equality;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
 import java.awt.event.KeyEvent;
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
@@ -62,7 +62,7 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         myOriginalItems = items;
         myResultItems = items;
         reset();
-        
+
         initTree();
     }
 
@@ -138,14 +138,36 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         return true;
     }
 
-    protected abstract UnnamedConfigurable createConfigurable(T item); 
+    protected abstract UnnamedConfigurable createConfigurable(T item);
 
     @Override
     protected void onItemDeleted(Object item) {
         myItems.remove((T)item);
     }
 
-    private class ItemConfigurable extends NamedConfigurable {
+    protected void setDisplayName(T item, String name) {
+      myNamer.setName(item, name);
+    }
+
+    @Nullable
+    protected UnnamedConfigurable getItemConfigurable(final T item) {
+      final Ref<UnnamedConfigurable> result = new Ref<UnnamedConfigurable>();
+      TreeUtil.traverse((TreeNode)myTree.getModel().getRoot(), new TreeUtil.Traverse() {
+        public boolean accept(Object node) {
+          final NamedConfigurable configurable = (NamedConfigurable)((DefaultMutableTreeNode)node).getUserObject();
+          if (configurable.getEditableObject() == item) {
+            result.set(((ItemConfigurable)configurable).myConfigurable);
+            return false;
+          }
+          else {
+            return true;
+          }
+        }
+      });
+      return result.get();
+    }
+
+  private class ItemConfigurable extends NamedConfigurable {
         private final T myItem;
         private final UnnamedConfigurable myConfigurable;
 
@@ -156,7 +178,7 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         }
 
         public void setDisplayName(String name) {
-            myNamer.setName(myItem, name);
+          NamedItemsListEditor.this.setDisplayName(myItem, name);
         }
 
         public Object getEditableObject() {
@@ -176,6 +198,9 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         }
 
         public Icon getIcon() {
+            if (myConfigurable instanceof Iconable) {
+              return ((Iconable)myConfigurable).getIcon(0);
+            }
             return null;
         }
 
@@ -216,6 +241,10 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         myResultItems = myItems;
     }
 
+    protected List<T> getCurrentItems() {
+      return Collections.unmodifiableList(myItems);
+    }
+
     public List<T> getItems() {
         return myResultItems;
     }
@@ -239,6 +268,7 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
             myNamer.setName(clone, profileName);
             addNewNode(clone);
             selectNodeInTree(clone);
+            onItemCloned(clone);
         }
 
 
@@ -248,30 +278,39 @@ public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
         }
     }
 
-    private class AddAction extends AnAction {
+    protected void onItemCloned(T clone) {
+    }
+
+  private class AddAction extends AnAction {
         public AddAction() {
             super("Add", "Add", Icons.ADD_ICON);
             registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
         }
 
         public void actionPerformed(AnActionEvent event) {
-            final String name = askForProfileName("Create new {0}");
-            if (name == null) return;
-            createItem(name);
+          final T newItem = createItem();
+          if (newItem != null) {
+            onItemCreated(newItem);
+          }
         }
-
     }
 
     public void selectItem(T item) {
         selectNodeInTree(findByName(myNamer.getName(item)));
     }
 
-    public void createItem(@NotNull String name) {
+    @Nullable
+    protected T createItem() {
+      final String name = askForProfileName("Create new {0}");
+      if (name == null) return null;
       final T newItem = myFactory.create();
       myNamer.setName(newItem, name);
+      return newItem;
+    }
 
+    protected void onItemCreated(T newItem) {
       addNewNode(newItem);
       selectNodeInTree(newItem);
     }
 
-}
\ No newline at end of file
+}
index 2faf9e618f76a88afe2113c30d377f5252da8036..720e4c1e2c04de959d2d039812d13d4d0fafef11 100644 (file)
@@ -53,8 +53,9 @@ public class BooleanTableCellRenderer extends JCheckBox implements TableCellRend
       setBackground(table.getBackground());
     }
     if (value instanceof String) {
-      setSelected((Boolean.parseBoolean((String)value)));            
-    } else {
+      setSelected(Boolean.parseBoolean((String)value));
+    }
+    else {
       setSelected(((Boolean)value).booleanValue());
     }
     return this;
index 502b89ba5d47bd147c5d5578c7b5fb78a26f445b..4cb9309342b6465e9b6661154876d6c61b8126ee 100644 (file)
@@ -648,8 +648,8 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
   }
 
   private static boolean showConfirmation() {
-    boolean hasBgTasks = ProgressManager.getInstance().hasProgressIndicator();
-    final ConfirmExitDialog confirmExitDialog = new ConfirmExitDialog(hasBgTasks);
+    final boolean hasUnsafeBgTasks = ProgressManager.getInstance().hasUnsafeProgressIndicator();
+    final ConfirmExitDialog confirmExitDialog = new ConfirmExitDialog(hasUnsafeBgTasks);
     if (confirmExitDialog.isToBeShown()) {
       confirmExitDialog.show();
       if (!confirmExitDialog.isOK()) {
index 96486eccfef5dbdb945fba1acf3226fa41765bf4..286d21c7aa58aec4cede1f108423c0693c4ba2b2 100644 (file)
@@ -44,6 +44,7 @@ public class ProgressManagerImpl extends ProgressManager {
 
   private static final ThreadLocal<ProgressIndicator> myThreadIndicator = new ThreadLocal<ProgressIndicator>();
   private final AtomicInteger myCurrentProgressCount = new AtomicInteger(0);
+  private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0);
   private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0);
 
   private static volatile int ourLockedCheckCounter = 0;
@@ -169,11 +170,15 @@ public class ProgressManagerImpl extends ProgressManager {
     return myCurrentProgressCount.get() > 0;
   }
 
+  public boolean hasUnsafeProgressIndicator() {
+    return myCurrentUnsafeProgressCount.get() > 0;
+  }
+
   public boolean hasModalProgressIndicator() {
     return myCurrentModalProgressCount.get() > 0;
   }
 
-  public void runProcess(@NotNull final Runnable process, final ProgressIndicator progress) throws ProcessCanceledException {
+  public void runProcess(@NotNull final Runnable process, final ProgressIndicator progress) {
     executeProcessUnderProgress(new Runnable(){
       public void run() {
         synchronized (process) {
@@ -205,6 +210,7 @@ public class ProgressManagerImpl extends ProgressManager {
 
     final boolean modal = progress != null && progress.isModal();
     if (modal) myCurrentModalProgressCount.incrementAndGet();
+    if (progress == null || progress instanceof ProgressWindow) myCurrentUnsafeProgressCount.incrementAndGet();
 
     try {
       process.run();
@@ -214,6 +220,7 @@ public class ProgressManagerImpl extends ProgressManager {
 
       myCurrentProgressCount.decrementAndGet();
       if (modal) myCurrentModalProgressCount.decrementAndGet();
+      if (progress == null || progress instanceof ProgressWindow) myCurrentUnsafeProgressCount.decrementAndGet();
     }
   }
 
index 31c2208ee8c8bc8a92150ae1df5b38badd5a7b27..6a068d3eec5cdd9c4b5922a4f5f7bee1a24fb8a2 100644 (file)
@@ -21,8 +21,10 @@ import com.intellij.openapi.components.ApplicationComponent;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.JarFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.impl.win32.Win32Kernel;
 import com.intellij.openapi.vfs.newvfs.ManagingFS;
 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
 import com.intellij.openapi.vfs.newvfs.RefreshQueue;
@@ -123,6 +125,9 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
   }
 
   public void disposeComponent() {
+    if (SystemInfo.isWindows && Registry.is("filesystem.useNative")) {
+      Win32Kernel.release();
+    }
   }
 
   @TestOnly
index 6787968237fded0a67b0eac647f500f3c9c6f8b1..6894209195826ecae3a6f156f851467c0439c5b4 100644 (file)
  */
 package com.intellij.openapi.vfs.impl.win32;
 
-import com.sun.jna.*;
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+import com.sun.jna.examples.win32.W32API;
 import com.sun.jna.win32.StdCallLibrary;
 import com.sun.jna.win32.W32APIFunctionMapper;
 import com.sun.jna.win32.W32APITypeMapper;
 
 import java.io.FileNotFoundException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @author Dmitry Avdeev
@@ -38,20 +44,6 @@ public class Win32Kernel {
   public static final int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
   public static final int FILE_ATTRIBUTE_READONLY = 0x0001;
 
-  private static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
-    {
-      super.setPointer(Pointer.createConstant(-1));
-    }};
-
-  public static class HANDLE extends PointerType {
-
-    public Object fromNative(Object nativeValue, FromNativeContext context) {
-      Object o = super.fromNative(nativeValue, context);
-      if (INVALID_HANDLE_VALUE.equals(o)) return INVALID_HANDLE_VALUE;
-      return o;
-    }
-  }
-
   private static class FileInfo {
     private FileInfo(WIN32_FIND_DATA data) {
       this.dwFileAttributes = data.dwFileAttributes;
@@ -62,7 +54,12 @@ public class Win32Kernel {
     long ftLastWriteTime;
   }
 
-  private final static WIN32_FIND_DATA DATA = new WIN32_FIND_DATA();
+  private static W32API.HANDLE INVALID_HANDLE_VALUE = new W32API.HANDLE(Pointer.createConstant(0xFFFFFFFFl));
+  private static WIN32_FIND_DATA DATA = new WIN32_FIND_DATA();
+
+  public static void release() {
+    DATA = null;
+  }
 
   private Map<String, FileInfo> myCache = new HashMap<String, FileInfo>();
 
@@ -71,8 +68,8 @@ public class Win32Kernel {
     myCache.clear();
 
     ArrayList<String> list = new ArrayList<String>();
-    HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", DATA);
-    if (hFind == INVALID_HANDLE_VALUE) return new String[0];
+    W32API.HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", DATA);
+    if (hFind.equals(INVALID_HANDLE_VALUE)) return new String[0];
     do {
       String name = toString(DATA.cFileName);
       if (name.equals(".") || name.equals("..")) {
@@ -113,8 +110,8 @@ public class Win32Kernel {
     FileInfo data = myCache.get(path);
     if (data == null) {
       myCache.clear();
-      HANDLE hFind = myKernel.FindFirstFile(path.replace('/', '\\'), DATA);
-      if (hFind == INVALID_HANDLE_VALUE) throw new FileNotFoundException(path);
+      W32API.HANDLE hFind = myKernel.FindFirstFile(path.replace('/', '\\'), DATA);
+      if (hFind.equals(INVALID_HANDLE_VALUE)) throw new FileNotFoundException(path);
       data = new FileInfo(DATA);
       myKernel.FindClose(hFind);
       myCache.put(path, data);
@@ -131,11 +128,11 @@ public class Win32Kernel {
 
   public interface Kernel32 extends StdCallLibrary {
 
-    HANDLE FindFirstFile(String lpFileName, WIN32_FIND_DATA lpFindFileData);
+    W32API.HANDLE FindFirstFile(String lpFileName, WIN32_FIND_DATA lpFindFileData);
 
-    boolean FindNextFile(HANDLE hFindFile, WIN32_FIND_DATA lpFindFileData);
+    boolean FindNextFile(W32API.HANDLE hFindFile, WIN32_FIND_DATA lpFindFileData);
 
-    boolean FindClose(HANDLE hFindFile);
+    boolean FindClose(W32API.HANDLE hFindFile);
   }
 
   public static class FILETIME extends Structure implements Structure.ByValue {
index 00e470fb8d6c9c007a8c22f58c1b43f513e87bc9..9f3446a51f3608f62e47a4228e45b2b967a348a0 100644 (file)
@@ -49,4 +49,9 @@ public class FakeVirtualFile extends StubVirtualFile {
   public String getName() {
     return myName;
   }
+
+  @Override
+  public String toString() {
+    return getPath();
+  }
 }
\ No newline at end of file
index b6aca5c3f35216da62993a2d333ac76fd4f014c3..e4fbdacfc36dbef7e536eb4c64ec41baf869b80b 100644 (file)
@@ -19,8 +19,6 @@
  */
 package com.intellij.openapi.vfs.newvfs.persistent;
 
-import com.intellij.openapi.application.ex.ApplicationEx;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.LocalFileSystem;
@@ -59,9 +57,8 @@ public class RefreshWorker {
       root.markClean();
     }
     else {
-      ApplicationEx applicationEx = ApplicationManagerEx.getApplicationEx();
       if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && SystemInfo.isWindows && root.isDirectory() &&
-          (applicationEx.isUnitTestMode() || Registry.is("filesystem.useNative"))) {
+          (Registry.is("filesystem.useNative"))) {
         delegate = new Win32LocalFileSystem();
       }
 
index 7d51aa49a4e37c84859a78d6a99aaef66ab19ef9..9afb7eaa830a96884b62a74568776d60b538e426 100644 (file)
@@ -39,4 +39,4 @@ ide.tabbedPane.bufferedPaint=true
 debugger.valueTooltipAutoShow=true
 debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over
 
-filesystem.useNative=true
\ No newline at end of file
+filesystem.useNative=false
\ No newline at end of file
index ac1816b2faa944b93b1e0c48f5e8a6a4d8abf359..2dfabea586c9a451866d4d8df92a3923ff25d2c2 100644 (file)
@@ -533,7 +533,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
       fileName), text, LocalTimeCounter.currentTime(), false);
   }
 
-  protected static PsiFile createPseudoPhysicalFile(String fileName, String text) throws IncorrectOperationException {
+  protected static PsiFile createPseudoPhysicalFile(@NonNls String fileName, String text) throws IncorrectOperationException {
     FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
     return PsiFileFactory.getInstance(getProject()).createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), true);
   }
index 32834d0e08ce8fd7cb1893a48c45cc6337e956bc..39a7eb0757fbcffb7ac22b78376d3dd4ad0656a3 100644 (file)
@@ -121,8 +121,12 @@ public abstract class UsefulTestCase extends TestCase {
 
     CodeStyleSettings codeStyleSettings = getCurrentCodeStyleSettings();
     codeStyleSettings.getIndentOptions(StdFileTypes.JAVA);
-    checkSettingsEqual(myOldCodeStyleSettings, codeStyleSettings, "Code style settings damaged");
-    codeStyleSettings.clearCodeStyleSettings();
+    try {
+      checkSettingsEqual(myOldCodeStyleSettings, codeStyleSettings, "Code style settings damaged");
+    }
+    finally {
+      codeStyleSettings.clearCodeStyleSettings();
+    }
     myOldCodeStyleSettings = null;
 
     VariableInplaceRenamer.checkCleared();
index aac51c89cbdac08c7c8846c874839994fdc8864c..68036bba9ca496be9ffd30530186be6727480108 100644 (file)
@@ -165,8 +165,20 @@ public class DefaultJDOMExternalizer {
         Field field = data.getClass().getField(fieldName);
         Class type = field.getType();
         int modifiers = field.getModifiers();
-        if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) != 0 || (modifiers & Modifier.FINAL) != 0) continue;
+        if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) != 0) continue;
         field.setAccessible(true); // class might be non-public
+        if ((modifiers & Modifier.FINAL) != 0) {
+          // read external contents of final field
+          Object value = field.get(data);
+          if (ReflectionCache.isInstance(value, JDOMExternalizable.class)) {
+            final List children = e.getChildren("value");
+            for (Object child : children) {
+              Element valueTag = (Element)child;
+              ((JDOMExternalizable)value).readExternal(valueTag);
+            }
+          }
+          continue;
+        }
         String value = e.getAttributeValue("value");
         if (type.isPrimitive()) {
           if (value != null) {
index bec0ccd24cb4ebb9d1fa42a1fca2066e7a8ce4f6..0be45c4b43cf1cc8ce18bf4d34863f18698cfcf1 100644 (file)
@@ -1274,17 +1274,20 @@ public class StringUtil {
     return result;
   }
 
-  public static int countNewLines(final CharSequence text) {
-    int lineShift = 0;
+  public static int countNewLines(@NotNull CharSequence text) {
+    return countChars(text, '\n');
+  }
+
+  public static int countChars(@NotNull CharSequence text, char c) {
+    int count = 0;
 
     for(int i = 0; i < text.length(); ++i) {
       final char ch = text.charAt(i);
-
-      if (ch == '\n') {
-        ++lineShift;
+      if (ch == c) {
+        ++count;
       }
     }
-    return lineShift;
+    return count;
   }
 
   public static String capitalsOnly(String s) {
index 66d1741db905fadd92d669be5f73888888518ece..de530228768dae940f68d479d31cab1797c85ec0 100644 (file)
@@ -31,7 +31,7 @@ public class ClassMap<T> {
     this(new THashMap<Class, T>());
   }
   protected ClassMap(Map<Class, T> map) {
-    myMap = map;
+    myMap = map; 
   }
 
   public void put(Class aClass, T value) {
@@ -67,4 +67,8 @@ public class ClassMap<T> {
   public final Collection<T> values() {
     return myMap.values();
   }
+
+  public void clear() {
+    myMap.clear();
+  }
 }
index 05e7e7ee94b7e1c4b0819127ac5601bf3e90b0b1..7a57e0206b18615b7f363bf6a14b7e3dd12c9df1 100644 (file)
@@ -36,5 +36,5 @@ public interface ChangeListManagerGate {
   void editName(final String oldName, final String newName);
   // must be allowed only for perforce change synchronizer, not during normal update
   void moveChanges(final String toList, final Collection<Change> changes);
-  void deleteIfEmpty(final String name);
+  void setListsToDisappear(final Collection<String> names);
 }
index a012c477b30647f5fffbe8efa876c01a89910f90..73397442fa3e7702c38ba61d154f33ef6d1eaf64 100644 (file)
@@ -47,6 +47,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
 
   private ChangeListsIndexes myIdx;
   private final ChangesDelta myDelta;
+  private final List<String> myListsToDisappear;
 
   public ChangeListWorker(final Project project, final PlusMinus<Pair<String, AbstractVcs>> deltaListener) {
     myProject = project;
@@ -56,6 +57,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
     mySwitchedHolder = new SwitchedFileHolder(project, FileHolder.HolderType.SWITCHED);
 
     myDelta = new ChangesDelta(project, deltaListener);
+    myListsToDisappear = new LinkedList<String>();
   }
 
   private ChangeListWorker(final ChangeListWorker worker) {
@@ -65,6 +67,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
     myLocallyDeleted = worker.myLocallyDeleted.copy();
     mySwitchedHolder = (SwitchedFileHolder) worker.mySwitchedHolder.copy();
     myDelta = worker.myDelta;
+    myListsToDisappear = new LinkedList<String>(worker.myListsToDisappear);
     
     LocalChangeList defaultList = null;
     for (LocalChangeList changeList : worker.myMap.values()) {
@@ -97,6 +100,9 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
     myMap.clear();
     myMap.putAll(worker.myMap);
     myDefault = worker.myDefault;
+
+    myListsToDisappear.clear();
+    myListsToDisappear.addAll(worker.myListsToDisappear);
     
     myDelta.step(myIdx, worker.myIdx);
     myIdx = new ChangeListsIndexes(worker.myIdx);
@@ -362,6 +368,14 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
       dispatcher.changeListChanged(changeList);
     }
     mySwitchedHolder.calculateChildren();
+
+    for (String name : myListsToDisappear) {
+      final LocalChangeList changeList = myMap.get(name);
+      if (changeList.getChanges().isEmpty()) {
+        removeChangeList(name);
+      }
+    }
+    myListsToDisappear.clear();
   }
 
   public List<LocalChangeList> getListsCopy() {
@@ -637,6 +651,10 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
     return changes;
   }
 
+  void setListsToDisappear(final Collection<String> names) {
+    myListsToDisappear.addAll(names);
+  }
+
   ChangeListManagerGate createSelfGate() {
     return new MyGate(this);
   }
@@ -682,11 +700,8 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
       myWorker.moveChangesTo(toList, changes.toArray(new Change[changes.size()]));
     }
 
-    public void deleteIfEmpty(String name) {
-      final LocalChangeList list = myWorker.getCopyByName(name);
-      if ((list != null) && (list.getChanges().isEmpty()) && (! list.isDefault())) {
-        myWorker.removeChangeList(name);
-      }
+    public void setListsToDisappear(final Collection<String> names) {
+      myWorker.setListsToDisappear(names);
     }
   }
 }
index 728616a8d165259c8e723d473fed967b0a213220..81e03e949270e820ddd665218195ea682e17f3e1 100644 (file)
@@ -31,7 +31,11 @@ public class AddList implements ChangeListCommand {
   }
 
   public void apply(final ChangeListWorker worker) {
-    myNewListCopy = worker.addChangeList(myName, myComment);
+    if (! worker.findListByName(myName)) {
+      myNewListCopy = worker.addChangeList(myName, myComment);
+    } else {
+      worker.editComment(myName, myComment);
+    }
   }
 
   public void doNotify(final EventDispatcher<ChangeListListener> dispatcher) {
index c552ddb54c66ce9294a48504d34414ca3794693f..43366b4fff16b4f7f6b75c32852ab5a2c2c0bbb1 100644 (file)
@@ -65,10 +65,6 @@ public class MockChangeListManagerGate implements ChangeListManagerGate {
     }
   }
 
-  public void deleteIfEmpty(String name) {
-    final LocalChangeList changeList = myManager.findChangeList(name);
-    if ((changeList != null) && (changeList.getChanges().isEmpty())) {
-      myManager.removeChangeList(name);
-    }
+  public void setListsToDisappear(Collection<String> names) {
   }
 }
index 19631180a6d16f0616c9d84bc296c1fb5ff9b4aa..67aa788b88e7af150afcbefe9e2e265afddcce1a 100644 (file)
@@ -90,8 +90,8 @@ public class CvsFileAnnotation implements FileAnnotation{
 
     myCvsEntriesListener = new CvsEntriesListener() {
       public void entriesChanged(VirtualFile parent) {
-        if (myFile == null) return;
-        fireAnnotationChanged();
+        /*if (myFile == null) return;
+        fireAnnotationChanged();*/
       }
 
       private void fireAnnotationChanged() {
index 589b3fa091a03878fc4703e271ff7948ead52259..630e26d9e0582465af24f489f9d92057b7b0a21a 100644 (file)
@@ -12,7 +12,6 @@
  */
 package org.netbeans.lib.cvsclient;
 
-import com.intellij.openapi.util.Ref;
 import com.intellij.util.concurrency.Semaphore;
 import org.jetbrains.annotations.NonNls;
 import org.netbeans.lib.cvsclient.command.CommandAbortedException;
@@ -164,55 +163,116 @@ public final class RequestProcessor implements IRequestProcessor {
 
     BugLog.getInstance().assertNotNull(requests);
 
-    final Semaphore semaphore = new Semaphore();
-    semaphore.down();
+    final ProcessRequestsHelper helper = (myTimeout == -1) ?
+                                         new DirectProcessRequestHelper() : new TimedOutProcessRequestHelper();
+    return helper.processRequests(requests, connectionStreams, communicationProgressHandler);
+  }
 
-    final Ref<IOException> ioExceptionRef = new Ref<IOException>();
-    final Ref<CommandException> commandExceptionRef = new Ref<CommandException>();
-    final Ref<Boolean> result = new Ref<Boolean>();
+  private abstract class ProcessRequestsHelper {
+    protected IOException myIOException;
+    protected CommandException myCommandException;
+    protected boolean myResult;
+
+    protected abstract void before();
+    protected abstract void callRunnable(final Runnable runnable);
+    protected abstract void afterInRunnable();
+    protected abstract void after() throws CommandException;
+
+    public boolean processRequests(final Requests requests,
+                                   final IConnectionStreams connectionStreams,
+                                   final IRequestsProgressHandler communicationProgressHandler)
+      throws CommandException, IOCommandException {
+      final Runnable runnable = new Runnable() {
+        public void run() {
+          try {
+            checkCanceled();
+            sendRequests(requests, connectionStreams, communicationProgressHandler);
+            checkCanceled();
+
+            sendRequest(requests.getResponseExpectingRequest(), connectionStreams);
+            connectionStreams.flushForReading();
+
+            myResult = handleResponses(connectionStreams, new DefaultResponseHandler());
+          }
+          catch (IOException e) {
+            myIOException = e;
+          }
+          catch (CommandException e) {
+            myCommandException = e;
+          }
+          finally {
+            afterInRunnable();
+          }
+        }
+      };
 
-    final Future<?> future = Executors.newSingleThreadExecutor().submit(new Runnable() {
-      public void run() {
-        try {
-          checkCanceled();
-          sendRequests(requests, connectionStreams, communicationProgressHandler);
-          checkCanceled();
+      before();
+      callRunnable(runnable);
+      if (myIOException != null) throw new IOCommandException(myIOException);
+      if (myCommandException != null) throw myCommandException;
+      after();
 
-          sendRequest(requests.getResponseExpectingRequest(), connectionStreams);
-          connectionStreams.flushForReading();
+      return myResult;
+    }
+  }
 
-          result.set(handleResponses(connectionStreams, new DefaultResponseHandler()));
-        }
-        catch (IOException e) {
-          ioExceptionRef.set(e);
-        }
-        catch (CommandException e) {
-          commandExceptionRef.set(e);
-        }
-        finally {
-          semaphore.up();
-        }
+  private class TimedOutProcessRequestHelper extends ProcessRequestsHelper {
+    private final Semaphore mySemaphore;
+    private Future<?> myFuture;
+
+    private TimedOutProcessRequestHelper() {
+      mySemaphore = new Semaphore();
+    }
+
+    @Override
+    protected void before() {
+      mySemaphore.down();
+    }
+
+    @Override
+    protected void callRunnable(Runnable runnable) {
+      myFuture = Executors.newSingleThreadExecutor().submit(runnable);
+
+      final long tOut = (myTimeout < 20000) ? 20000 : myTimeout;
+      while (true) {
+        mySemaphore.waitFor(tOut);
+        if (myFuture.isDone() || myFuture.isCancelled()) break;
+        if (! commandStopper.isAlive()) break;
+        commandStopper.resetAlive();
+      }
+    }
+
+    @Override
+    protected void afterInRunnable() {
+      mySemaphore.up();
+    }
+
+    @Override
+    protected void after() throws CommandException {
+      if ((! myFuture.isDone() && (! myFuture.isCancelled()) && (! commandStopper.isAlive()))) {
+        myFuture.cancel(true);
+        throw new CommandException(new CommandAbortedException(), "Command execution timed out");
       }
-    });
-
-    // todo: think more
-    final long tOut = (myTimeout < 20000) ? 20000 : myTimeout;
-    while (true) {
-      semaphore.waitFor(tOut);
-      if (future.isDone() || future.isCancelled()) break;
-      if (! commandStopper.isAlive()) break;
-      commandStopper.resetAlive();
+    }
+  }
+
+  private class DirectProcessRequestHelper extends ProcessRequestsHelper {
+    @Override
+    protected void before() {
     }
 
-    if (! ioExceptionRef.isNull()) throw new IOCommandException(ioExceptionRef.get());
-    if (! commandExceptionRef.isNull()) throw commandExceptionRef.get();
+    @Override
+    protected void callRunnable(Runnable runnable) {
+      runnable.run();
+    }
 
-    if ((! future.isDone() && (! future.isCancelled()) && (! commandStopper.isAlive()))) {
-      future.cancel(true);
-      throw new CommandException(new CommandAbortedException(), "Command execution timed out");
+    @Override
+    protected void afterInRunnable() {
     }
 
-    return result.isNull() ? false : result.get();
+    @Override
+    protected void after() throws CommandException {
+    }
   }
 
   private void sendRequests(Requests requests, IConnectionStreams connectionStreams, IRequestsProgressHandler communicationProgressHandler)
index cd67eb108737042808014dd66b1e63e1911c5ff8..a80439d3490f7205f14b026770b5f769146c3933 100644 (file)
@@ -3,8 +3,10 @@ package org.jetbrains.plugins.groovy.dsl.toplevel
 import com.intellij.openapi.progress.ProcessCanceledException
 import com.intellij.openapi.util.Pair
 import com.intellij.openapi.util.text.StringUtil
+import com.intellij.psi.*
 import com.intellij.psi.search.GlobalSearchScope
 import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.util.containers.*
 import com.intellij.util.containers.HashSet
 import org.jetbrains.plugins.groovy.GroovyFileType
 import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope
@@ -17,7 +19,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
-import com.intellij.psi.*
 
 /**
  * @author ilyas
@@ -26,8 +27,8 @@ class Context {
 
   private List<Closure> myFilters = []
 
-  private final Set<Pair<String, String>> ASSIGNABLE_TYPES = new HashSet<Pair<String, String>>();
-  private final Set<Pair<String, String>> NON_ASSIGNABLE_TYPES = new HashSet<Pair<String, String>>();
+  private final Set<Pair<String, String>> ASSIGNABLE_TYPES = new ConcurrentHashSet<Pair<String, String>>();
+  private final Set<Pair<String, String>> NON_ASSIGNABLE_TYPES = new ConcurrentHashSet<Pair<String, String>>();
 
   public Context(Map args) {
     // Basic filter, all contexts are applicable for reference expressions only
index 21b27d0eb150368557dba36559faaec6c4b150fb..7c335537db220f0ebdb5676bf3dfb9eccfd00d1e 100644 (file)
@@ -19,7 +19,6 @@ package com.intellij.execution.junit2;
 import com.intellij.execution.junit2.states.Statistics;
 import com.intellij.execution.junit2.states.TestState;
 import com.intellij.execution.testframework.AbstractTestProxy;
-import com.intellij.execution.testframework.Filter;
 import com.intellij.execution.testframework.Printer;
 import com.intellij.rt.execution.junit.states.PoolOfTestStates;
 
@@ -29,68 +28,31 @@ import java.util.List;
 
 public class SuiteState extends TestState {
   private final TestProxy myTest;
+  private int myMaxMagnitude = -1;
+  private boolean myHasRunning;
   private final StateCache myCache = new StateCache();
 
-  private static final CachedAcpect<List<TestProxy>> ALL_TESTS = new CachedAcpect<List<TestProxy>>(){
-        public List<TestProxy> calculate(final SuiteState state) {
-          final ArrayList<TestProxy> allTests = new ArrayList<TestProxy>();
-          state.myTest.collectAllTestsTo(allTests);
-          return allTests;
+  public SuiteState(final TestProxy test) {
+    myTest = test;
+    myTest.addListener(new TestProxyListener() {
+      public void onChildAdded(final AbstractTestProxy testProxy, final AbstractTestProxy newChild) {
+        if (newChild.getParent() == myTest) {
+          myCache.invalidate();
         }
-      };
-
-  private static final CachedAcpect<Statistics> GET_STATISTICS = new CachedAcpect<Statistics>() {
-    public Statistics calculate(final SuiteState state) {
-      final CumulativeStatistics result = new CumulativeStatistics();
-      for (final TestProxy testCase : state.myTest.getChildren()) {
-        result.add(testCase.getStatistics());
       }
-      return result;
-    }
-  };
 
-  private static final CachedAcpect<Boolean> IS_IN_PROGRESS = new CachedAcpect<Boolean>() {
-    public Boolean calculate(final SuiteState state) {
-      return IN_PROGRESS.detectIn(state.myTest.getChildren()) != null ?
-             Boolean.TRUE : Boolean.FALSE;
-    }
-  };
-
-  private static final CachedAcpect<StateInterval> STATE_INTERVAL = new CachedAcpect<StateInterval>() {
-    public StateInterval calculate(final SuiteState state) {
-      return state.myTest.calculateInterval(state);
-    }
-  };
-
-  private static final CachedAcpect<Integer> MAGNITUDE  = new CachedAcpect<Integer>() {
-    public Integer calculate(final SuiteState state) {
-      return calcIntMagnitude(state);
-    }
-
-    private int calcIntMagnitude(final SuiteState state) {
-      final StateInterval interval = state.getInterval();
-      final int maxState = interval.getMax().getMagnitude();
-      final int minState = interval.getMin().getMagnitude();
-      if (minState == maxState) return maxState;
-      if (maxState <= PoolOfTestStates.RUNNING_INDEX &&
-          minState < PoolOfTestStates.NOT_RUN_INDEX)
-        return PoolOfTestStates.RUNNING_INDEX;
-      return maxState;
-    }
-  };
-  public static final Filter IN_PROGRESS = new Filter() {
-    public boolean shouldAccept(final AbstractTestProxy test) {
-      return test.isInProgress();
-    }
-  };
+      public void onChanged(final AbstractTestProxy test) {
+        if (test == myTest) myCache.invalidate();
+      }
 
-  public SuiteState(final TestProxy test) {
-    myTest = test;
-    myTest.addListener(myCache);
+      public void onStatisticsChanged(final AbstractTestProxy test) {
+        if (test == myTest) myCache.invalidate();
+      }
+    });
   }
 
   public int getMagnitude() {
-    return myCache.get(MAGNITUDE).intValue();
+    return myHasRunning ? PoolOfTestStates.RUNNING_INDEX : myMaxMagnitude;
   }
 
   public void update() {
@@ -100,9 +62,6 @@ public class SuiteState extends TestState {
   public void printOn(final Printer printer) {
   }
 
-  public StateInterval getInterval() {
-    return myCache.get(STATE_INTERVAL);
-  }
 
   public boolean isFinal() {
     return true;
@@ -126,18 +85,56 @@ public class SuiteState extends TestState {
 
   public void changeStateAfterAddingChaildTo(final TestProxy test, final TestProxy child) {
     if (child.getState().getMagnitude() <= getMagnitude()) {
-      test.onStatisticsChanged(test);
+      test.onStatisticsChanged();
       return;
     }
     test.onChanged(test);
   }
 
+  public void setRunning(boolean running) {
+    myHasRunning = running;
+  }
+
+  public void updateMagnitude(int magnitude) {
+    if (myMaxMagnitude < magnitude) {
+      myMaxMagnitude = magnitude;
+    }
+  }
+
+  private static final CachedAcpect<List<TestProxy>> ALL_TESTS = new CachedAcpect<List<TestProxy>>() {
+    public List<TestProxy> calculate(final SuiteState state) {
+      final ArrayList<TestProxy> allTests = new ArrayList<TestProxy>();
+      state.myTest.collectAllTestsTo(allTests);
+      return allTests;
+    }
+  };
+
+  private static final CachedAcpect<Statistics> GET_STATISTICS = new CachedAcpect<Statistics>() {
+    public Statistics calculate(final SuiteState state) {
+      final CumulativeStatistics result = new CumulativeStatistics();
+      for (final TestProxy testCase : state.myTest.getChildren()) {
+        result.add(testCase.getStatistics());
+      }
+      return result;
+    }
+  };
+
+  private static final CachedAcpect<Boolean> IS_IN_PROGRESS = new CachedAcpect<Boolean>() {
+    public Boolean calculate(final SuiteState state) {
+      for (TestProxy proxy : state.myTest.getChildren()) {
+        if (proxy.isInProgress()) return Boolean.TRUE;
+      }
+      return Boolean.FALSE;
+    }
+  };
+
+
   private static abstract class CachedAcpect<T> {
     private static int ourNextInstanceIndex = 0;
     private final int myId;
 
     protected CachedAcpect() {
-      synchronized(CachedAcpect.class) {
+      synchronized (CachedAcpect.class) {
         myId = ourNextInstanceIndex;
         ourNextInstanceIndex++;
       }
@@ -150,36 +147,9 @@ public class SuiteState extends TestState {
     }
   }
 
-  public static class SuiteStateInterval extends StateInterval {
-    private TestState myMin;
-    private TestState myMax;
 
-    public SuiteStateInterval(final TestState state, final StateInterval interval) {
-      super(state);
-      myMin = interval.getMin();
-      myMax = interval.getMax();
-    }
-
-    public TestState getMin() {
-      return myMin;
-    }
-
-    public TestState getMax() {
-      return myMax;
-    }
-
-    public void updateFrom(final StateInterval interval) {
-      final TestState otherMax = interval.getMax();
-      if (myMax.getMagnitude() < otherMax.getMagnitude())
-        myMax = otherMax;
-      final TestState otherMin = interval.getMin();
-      if (myMin.getMagnitude() > otherMin.getMagnitude())
-        myMin = otherMin;
-    }
-  }
-
-  private class StateCache implements TestProxyListener {
-    private final Object[] myValues = new Object[5];
+  private class StateCache {
+    private final Object[] myValues = new Object[3];
 
     public <T> T get(final CachedAcpect<T> aspect) {
       final int id = aspect.getId();
@@ -191,21 +161,6 @@ public class SuiteState extends TestState {
       return value;
     }
 
-    public void onChildAdded(final AbstractTestProxy testProxy, final AbstractTestProxy newChild) {
-      if (newChild.getParent() == myTest)
-        invalidate();
-    }
-
-    public void onChanged(final AbstractTestProxy test) {
-      if (test == myTest)
-        invalidate();
-    }
-
-    public void onStatisticsChanged(final AbstractTestProxy test) {
-      if (test == myTest)
-        invalidate();
-    }
-
     public void invalidate() {
       Arrays.fill(myValues, null);
     }
index 90bf216e14ae7eaffa59ef2bab8a2a180cebc9a0..51d9bdf7f081398b927fe09cce651c29ca4f3f0f 100644 (file)
@@ -191,9 +191,6 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
     return myInfo;
   }
 
-  public void onChildAdded(final AbstractTestProxy parent, final AbstractTestProxy newChild) {
-    fireStatisticsChanged();
-  }
 
   public void onChanged(final AbstractTestProxy test) {
     myChildren.resetCache();
@@ -205,7 +202,7 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
     }
   }
 
-  public void onStatisticsChanged(final AbstractTestProxy testProxy) {
+  public void onStatisticsChanged() {
     myChildren.resetCache();
     fireStatisticsChanged();
   }
@@ -213,7 +210,7 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
   private void fireStatisticsChanged() {
     myChildren.resetCache();
     if (myParent != null)
-      myParent.onStatisticsChanged(this);
+      myParent.onStatisticsChanged();
     pullEvent(new StatisticsChanged(this));
     myNotifier.onStatisticsChanged(this);
   }
@@ -301,13 +298,4 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
     return getParent() == null;
   }
 
-
-
-  public TestState.StateInterval calculateInterval(final SuiteState state) {
-    final SuiteState.SuiteStateInterval result = new SuiteState.SuiteStateInterval(state, getChildAt(0).getState().getInterval());
-    for (TestProxy proxy : getChildren()) {
-      result.updateFrom(proxy.getState().getInterval());
-    }
-    return result;
-  }
 }
index f8a9b7c80f2dcb4ba78af027d1e806a2c98e4c0a..e94071b23859da6d892e82576862b43c32ead653 100644 (file)
@@ -20,7 +20,6 @@ import com.intellij.execution.testframework.Printer;
 import com.intellij.rt.execution.junit.states.PoolOfTestStates;
 
 public final class NotFailedState extends TestState {
-  private final int myMagnitude;
   private final boolean myIsFinal;
 
   public NotFailedState(final int magnitude, final boolean aFinal) {
index 35bd44f05a32f1fc7c424cbd26d01952be7f7646..6e7d36a780b28b72032bac110c0e9b5dca0a06b8 100644 (file)
@@ -19,7 +19,6 @@ package com.intellij.execution.junit2.states;
 import com.intellij.execution.junit2.segments.ObjectReader;
 
 abstract class ReadableState extends TestState {
-  private int myMagnitude;
 
   abstract void initializeFrom(ObjectReader reader);
 
index 8562fd68b7a272f357c6867541698dc67b669a4c..6ee58b073e2f21c30bd682972b4f09ee54a93e96 100644 (file)
@@ -31,36 +31,14 @@ public abstract class TestState implements Printable {
   public static final TestState DEFAULT = new NotFailedState(PoolOfTestStates.NOT_RUN_INDEX, false);
   public static final TestState RUNNING_STATE = new NotFailedState(PoolOfTestStates.RUNNING_INDEX, false);
 
-  private final StateInterval myInterval;
+  protected int myMagnitude;
 
   public List<TestProxy> getAllTestsOf(final TestProxy test) {
     return Collections.singletonList(test);
   }
 
-  public static class StateInterval {
-    private final TestState myState;
-
-    public StateInterval(final TestState state) {
-      myState = state;
-    }
-    public TestState getMin() {
-      return myState;
-    }
-    public TestState getMax() {
-      return myState;
-    }
-  }
-
-  public TestState() {
-    myInterval = new StateInterval(this);
-  }
-
   public abstract int getMagnitude();
 
-  public StateInterval getInterval() {
-    return myInterval;
-  }
-
   public abstract boolean isFinal();
 
   public boolean isDefect() {
index 3d5ca1fc4335e111536501755cee415e437eee41..014818de040e786223c5ddd248a570786e0ec804 100644 (file)
 
 package com.intellij.execution.junit2.states;
 
-import com.intellij.execution.junit2.TestProxy;
-import com.intellij.execution.junit2.TestProxyParent;
-import com.intellij.execution.junit2.TestRoot;
-import com.intellij.execution.junit2.TestRootImpl;
+import com.intellij.execution.junit2.*;
 import com.intellij.execution.junit2.segments.ObjectReader;
 import com.intellij.execution.junit2.segments.PacketConsumer;
 import com.intellij.execution.testframework.Filter;
@@ -59,6 +56,13 @@ public class TestStateUpdater implements PacketConsumer {
   private static class RunningStateSetter extends StateChanger {
     public void changeStateOf(final TestProxy testProxy, final ObjectReader reader) {
       testProxy.setState(TestState.RUNNING_STATE);
+      TestProxy parent = testProxy.getParent();
+      while (parent != null) {
+        final TestState state = parent.getState();
+        LOG.assertTrue(state instanceof SuiteState);
+        ((SuiteState)state).setRunning(true);
+        parent = parent.getParent();
+      }
     }
 
     public void modifyTestStack(final TestProxyParent globalRoot, final TestProxy test) {
@@ -101,6 +105,21 @@ public class TestStateUpdater implements PacketConsumer {
       }
       testProxy.setState(state);
       testProxy.setStatistics(new Statistics(reader));
+      final int magnitude = state.getMagnitude();
+
+      TestProxy parent = testProxy.getParent();
+      TestProxy child = testProxy;
+      while (parent != null) {
+        final List<TestProxy> children = parent.getChildren();
+        final TestState parentState = parent.getState();
+        LOG.assertTrue(parentState instanceof SuiteState);
+        if (children.indexOf(child) == children.size() - 1) {
+          ((SuiteState)parentState).setRunning(false);
+        }
+        ((SuiteState)parentState).updateMagnitude(magnitude);
+        child = parent;
+        parent = parent.getParent();
+      }
     }
   }
 
index b707d2a37e66562b1b39e721a7ad4b5097460977..9b792c789991dbcff9c24fe37e1bab0dfb439395 100644 (file)
@@ -98,6 +98,7 @@ class StatisticsPanel extends JPanel implements DataProvider{
 
   private class MyJUnitListener extends JUnitAdapter {
     public void onTestChanged(final TestEvent event) {
+      if (!StatisticsPanel.this.isShowing()) return;
       if (event instanceof StatisticsChanged) {
         if (myCurrentTest == event.getSource())
           updateStatistics();
@@ -108,6 +109,7 @@ class StatisticsPanel extends JPanel implements DataProvider{
     }
 
     public void onTestSelected(final TestProxy test) {
+      if (!StatisticsPanel.this.isShowing()) return;
       if (myCurrentTest == test)
         return;
       if (test == null) {
index dd00817ceb890e384184e8427816f3b840f1c5ea..2bd2cb6076f1416d2f8b9c52d009aac9b43acb09 100644 (file)
 
 package com.intellij.execution.junit2.ui;
 
-import com.intellij.execution.testframework.Filter;
-import com.intellij.execution.junit2.StateChangedEvent;
-import com.intellij.execution.junit2.TestEvent;
+import com.intellij.execution.ExecutionBundle;
 import com.intellij.execution.junit2.TestProxy;
-import com.intellij.execution.junit2.ui.model.JUnitAdapter;
 import com.intellij.execution.junit2.ui.model.JUnitRunningModel;
-import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.testframework.Filter;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.util.ui.ColumnInfo;
 import com.intellij.util.ui.ListTableModel;
@@ -42,18 +39,6 @@ public class StatisticsTable extends ListTableModel {
   public void setModel(final JUnitRunningModel model) {
     myModel = model;
     setTest(myModel.getRoot());
-    myModel.addListener(new JUnitAdapter() {
-      public void doDispose() {
-        myTest = null;
-        resetTests();
-        myModel = null;
-      }
-
-      public void onTestChanged(final TestEvent event) {
-        if (event instanceof StateChangedEvent) return;
-        if (event.getSource() == myTest) changeTableData();
-      }
-    });
   }
 
   public void onSelectionChanged(final TestProxy test) {
index 6f478670ab50f507252c5fe8de28c12f9f29fc4c..5283fd55c10789c4cef6c855a46d00edf34f628d 100644 (file)
@@ -54,6 +54,8 @@ class TestRenderer {
     mapIcon(PoolOfTestStates.COMPARISON_FAILURE, PoolOfTestIcons.FAILED_ICON);
     mapIcon(PoolOfTestStates.ERROR_INDEX, PoolOfTestIcons.ERROR_ICON);
     mapIcon(PoolOfTestStates.IGNORED_INDEX, PoolOfTestIcons.IGNORED_ICON);
+
+    mapIcon(-1, PoolOfTestIcons.NOT_RAN);
   }
 
   private static void mapIcon(final int index, final Icon icon) {