Merge branch 'nz/remainWhenUnshelve'
authorNadya Zabrodina <Nadya.Zabrodina@jetbrains.com>
Fri, 13 Nov 2015 12:54:15 +0000 (15:54 +0300)
committerNadya Zabrodina <Nadya.Zabrodina@jetbrains.com>
Fri, 13 Nov 2015 12:54:15 +0000 (15:54 +0300)
98 files changed:
.idea/compiler.xml
community-resources/community-resources.iml
java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/ExpressionTypeMemoryState.java
java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractChecker.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaTypeValue.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java
java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java
java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ProvablyDistinctForWildcardsWithArrayBounds.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/EliminateIntersectionTypeWildcardElimination.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java
java/java-tests/testData/codeInsight/slice/backward/TryCatchFinally.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
java/java-tests/testSrc/com/intellij/project/LoadProjectTest.java
java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java
java/java-tests/testSrc/com/intellij/slicer/SliceBackwardTest.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/TypeMigrationVariableTypeFixProvider.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertAtomicToLongAdderIntention.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java
java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java
java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java
java/typeMigration/testData/inspections/guava/fluentIterableChainSeparatedByMethods_after.java
java/typeMigration/testData/inspections/guava/fluentIterableWithStaticallyImportedFrom_after.java
java/typeMigration/testData/inspections/guava/migrateArrays.java [new file with mode: 0644]
java/typeMigration/testData/inspections/guava/migrateArrays_after.java [new file with mode: 0644]
java/typeMigration/testData/inspections/guava/optional2_after.java
java/typeMigration/testData/inspections/guava/optionalTransform2_after.java
java/typeMigration/testData/inspections/guava/optionalTransform_after.java
java/typeMigration/testData/inspections/guava/removeMethodReference_after.java
java/typeMigration/testData/inspections/guava/returnType_after.java
java/typeMigration/testData/inspections/guava/simplifyOptionalComposition_after.java
platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java
platform/core-impl/src/com/intellij/util/CachedValueChecker.java
platform/core-impl/src/com/intellij/util/CachedValuesManagerImpl.java
platform/core-impl/src/com/intellij/util/DebugReflectionUtil.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/AbstractModuleNode.java
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/NamedLibraryElementNode.java
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFileNode.java
platform/lang-impl/src/com/intellij/moduleDependencies/DependenciesAnalyzeManager.java
platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java
platform/lang-impl/src/com/intellij/moduleDependencies/ShowModuleDependenciesAction.java
platform/lang-impl/src/com/intellij/packageDependencies/ui/ModuleNode.java
platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
platform/platform-resources-en/platform-resources-en.iml
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/platform-resources-en/src/messages/AnalysisScopeBundle.properties
platform/platform-resources/platform-resources.iml
platform/platform-tests/testSrc/com/intellij/concurrency/JobUtilTest.java
platform/platform-tests/testSrc/com/intellij/openapi/application/impl/LaterInvocatorTest.java
platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java
platform/platform-tests/testSrc/com/intellij/util/messages/MessageBusTest.java
platform/platform-tests/testSrc/com/intellij/util/net/ssl/CertificateTest.java
platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelBase.java
platform/smRunner/testSrc/com/intellij/execution/testframework/sm/OutputLineSplitterTest.java
platform/testFramework/src/com/intellij/testFramework/LeakHunter.java
platform/util/src/com/intellij/util/messages/impl/MessageBusImpl.java
plugins/generate-tostring/src/org/jetbrains/java/generate/template/toString/DefaultConcatMemberSuperGroovy.vm [new file with mode: 0644]
plugins/generate-tostring/src/org/jetbrains/java/generate/template/toString/ToStringTemplatesManager.java
plugins/groovy/src/META-INF/plugin.xml
plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/tostring/GroovyGenerateToStringAction.java [new file with mode: 0644]
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateActionsTest.groovy [new file with mode: 0644]
plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesStressTest.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnBusyOnAddTest.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRepositoryPoolTest.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn/VcsWaitForUpdateForTest.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn16/VcsWaitForUpdateForTest.java
python/helpers/pydev/pydev_ipython_console_011.py
python/testSrc/com/jetbrains/env/python/console/PyConsoleTask.java
python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java
spellchecker/src/com/intellij/spellchecker/english.dic
xml/dom-tests/tests/com/intellij/util/xml/DomConcurrencyStressTest.java
xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java

index 1bbf91eb72d0c97f0f4d3c63e933264a07ecc998..59860660a3eddb0fe550e0f751a77b54e1c468f3 100644 (file)
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel>
-      <module name="gradle-jps-plugin" target="1.6" />
-      <module name="intellilang-jps-plugin" target="1.6" />
       <module name="java-runtime" target="1.1" />
-      <module name="javaFX-jps-plugin" target="1.6" />
-      <module name="jps-builders" target="1.6" />
-      <module name="jps-launcher" target="1.6" />
-      <module name="jps-model-api" target="1.6" />
-      <module name="jps-model-impl" target="1.6" />
-      <module name="jps-model-serialization" target="1.6" />
-      <module name="jps-standalone-builder" target="1.6" />
       <module name="junit_rt" target="1.1" />
-      <module name="maven-jps-plugin" target="1.6" />
-      <module name="ui-designer-jps-plugin" target="1.6" />
-      <module name="util-rt" target="1.6" />
     </bytecodeTargetLevel>
   </component>
   <component name="EclipseCompilerSettings">
index c053808175a3403f411f4b01719927b491283c5e..47b8d551b85eb8d277f49d359ee2e810fe633c94 100644 (file)
@@ -3,10 +3,9 @@
   <component name="NewModuleRootManager" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
index 7b1af3b24ae9d13e43527a8ed94a7f7572a95d20..01239024a52b3be1707c0464ccd343cd4c9e3474 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -63,6 +63,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
     super(toCopy);
   }
 
+  @NotNull
   @Override
   public DfaMemoryStateImpl createCopy() {
     final ExpressionTypeMemoryState copy = new ExpressionTypeMemoryState(this);
index b7e4660e5260a6b368dd5be7b2e2bdc357ff2af5..65be476e4b3e58bd19b015472148b661ec5094cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -17,10 +17,10 @@ package com.intellij.codeInsight.guess.impl;
 
 import com.intellij.codeInsight.guess.GuessManager;
 import com.intellij.codeInspection.dataFlow.*;
-import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
-import com.intellij.codeInspection.dataFlow.instructions.TypeCastInstruction;
 import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
 import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
+import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
+import com.intellij.codeInspection.dataFlow.instructions.TypeCastInstruction;
 import com.intellij.codeInspection.dataFlow.value.DfaInstanceofValue;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
@@ -31,8 +31,8 @@ import com.intellij.psi.search.PsiElementProcessorAdapter;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.psi.search.searches.ClassInheritorsSearch;
 import com.intellij.psi.search.searches.ReferencesSearch;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.containers.ContainerUtil;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
@@ -151,6 +151,7 @@ public class GuessManagerImpl extends GuessManager {
     }
 
     DataFlowRunner runner = new DataFlowRunner() {
+      @NotNull
       @Override
       protected DfaMemoryState createMemoryState() {
         return new ExpressionTypeMemoryState(getFactory());
index a7e41a910892c10e826fa32e98dac833b9cc8b8e..ad1fc779e46b2a16442cd74d2f2e3c674f20a556 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -25,6 +25,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
 import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
 import com.intellij.psi.*;
 import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 
@@ -39,7 +40,7 @@ class ContractChecker extends DataFlowRunner {
   private final Set<PsiElement> myNonViolations = ContainerUtil.newHashSet();
   private final Set<PsiElement> myFailures = ContainerUtil.newHashSet();
 
-  ContractChecker(PsiMethod method, MethodContract contract, final boolean onTheFly) {
+  private ContractChecker(PsiMethod method, MethodContract contract, final boolean onTheFly) {
     myMethod = method;
     myContract = contract;
     myOnTheFly = onTheFly;
@@ -77,8 +78,9 @@ class ContractChecker extends DataFlowRunner {
     return super.shouldCheckTimeLimit();
   }
 
+  @NotNull
   @Override
-  protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
+  protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
     DfaMemoryState memState = instructionState.getMemoryState();
     if (memState.isEphemeral()) {
       return DfaInstructionState.EMPTY_ARRAY;
index 1adc7fa781d2928545952aa1d7faba17781279df..ec8fbf673817239cef5b438e672be02870945a8a 100644 (file)
@@ -52,11 +52,12 @@ public class DataFlowRunner {
 
   private Instruction[] myInstructions;
   private final MultiMap<PsiElement, DfaMemoryState> myNestedClosures = new MultiMap<PsiElement, DfaMemoryState>();
+  @NotNull
   private final DfaValueFactory myValueFactory;
 
   // Maximum allowed attempts to process instruction. Fail as too complex to process if certain instruction
   // is executed more than this limit times.
-  public static final int MAX_STATES_PER_BRANCH = 300;
+  static final int MAX_STATES_PER_BRANCH = 300;
 
   protected DataFlowRunner() {
     this(false, true);
@@ -66,12 +67,13 @@ public class DataFlowRunner {
     myValueFactory = new DfaValueFactory(honorFieldInitializers, unknownMembersAreNullable);
   }
 
+  @NotNull
   public DfaValueFactory getFactory() {
     return myValueFactory;
   }
 
   @Nullable
-  private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
+  private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
     PsiClass containingClass = PsiTreeUtil.getParentOfType(psiBlock, PsiClass.class);
     if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) {
       final PsiElement parent = containingClass.getParent();
@@ -91,16 +93,17 @@ public class DataFlowRunner {
     return Collections.singletonList(createMemoryState());
   }
 
-  public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
+  @NotNull
+  public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
     Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
     return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, false, initialStates);
   }
 
   @NotNull
-  public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
-                                          InstructionVisitor visitor,
-                                          boolean ignoreAssertions,
-                                          @NotNull Collection<DfaMemoryState> initialStates) {
+  final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
+                                   @NotNull InstructionVisitor visitor,
+                                   boolean ignoreAssertions,
+                                   @NotNull Collection<DfaMemoryState> initialStates) {
     if (PsiTreeUtil.findChildOfType(psiBlock, OuterLanguageElement.class) != null) return RunnerResult.NOT_APPLICABLE;
 
     try {
@@ -127,7 +130,7 @@ public class DataFlowRunner {
       if (LOG.isDebugEnabled()) {
         LOG.debug("Analyzing code block: " + psiBlock.getText());
         for (int i = 0; i < myInstructions.length; i++) {
-          LOG.debug(i + ": " + myInstructions[i].toString());
+          LOG.debug(i + ": " + myInstructions[i]);
         }
       }
       //for (int i = 0; i < myInstructions.length; i++) System.out.println(i + ": " + myInstructions[i].toString());
@@ -220,10 +223,11 @@ public class DataFlowRunner {
   private void handleStepOutOfLoop(@NotNull final Instruction prevInstruction,
                                    @NotNull Instruction nextInstruction,
                                    @NotNull final int[] loopNumber,
-                                   MultiMap<BranchingInstruction, DfaMemoryState> processedStates,
-                                   MultiMap<BranchingInstruction, DfaMemoryState> incomingStates,
-                                   List<DfaInstructionState> inFlightStates,
-                                   DfaInstructionState[] afterStates, StateQueue queue) {
+                                   @NotNull MultiMap<BranchingInstruction, DfaMemoryState> processedStates,
+                                   @NotNull MultiMap<BranchingInstruction, DfaMemoryState> incomingStates,
+                                   @NotNull List<DfaInstructionState> inFlightStates,
+                                   @NotNull DfaInstructionState[] afterStates,
+                                   @NotNull StateQueue queue) {
     if (loopNumber[prevInstruction.getIndex()] == 0 || inSameLoop(prevInstruction, nextInstruction, loopNumber)) {
       return;
     }
@@ -247,10 +251,7 @@ public class DataFlowRunner {
       @Override
       public boolean process(DfaInstructionState state) {
         Instruction instruction = state.getInstruction();
-        if (inSameLoop(prevInstruction, instruction, loopNumber)) {
-          return false;
-        }
-        return true;
+        return !inSameLoop(prevInstruction, instruction, loopNumber);
       }
     })) return;
 
@@ -276,7 +277,8 @@ public class DataFlowRunner {
     return !ApplicationManager.getApplication().isUnitTestMode();
   }
 
-  protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
+  @NotNull
+  protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
     Instruction instruction = instructionState.getInstruction();
     PsiElement closure = DfaUtil.getClosureInside(instruction);
     if (closure instanceof PsiClass) {
@@ -288,7 +290,7 @@ public class DataFlowRunner {
     return instruction.accept(this, instructionState.getMemoryState(), visitor);
   }
 
-  private void registerNestedClosures(DfaInstructionState instructionState, PsiClass nestedClass) {
+  private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiClass nestedClass) {
     DfaMemoryState state = instructionState.getMemoryState();
     for (PsiMethod method : nestedClass.getMethods()) {
       PsiCodeBlock body = method.getBody();
@@ -304,7 +306,7 @@ public class DataFlowRunner {
     }
   }
   
-  private void registerNestedClosures(DfaInstructionState instructionState, PsiLambdaExpression expr) {
+  private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiLambdaExpression expr) {
     DfaMemoryState state = instructionState.getMemoryState();
     PsiElement body = expr.getBody();
     if (body != null) {
@@ -312,22 +314,27 @@ public class DataFlowRunner {
     }
   }
 
+  @NotNull
   protected DfaMemoryState createMemoryState() {
     return new DfaMemoryStateImpl(myValueFactory);
   }
 
+  @NotNull
   public Instruction[] getInstructions() {
     return myInstructions;
   }
 
+  @NotNull
   public Instruction getInstruction(int index) {
     return myInstructions[index];
   }
 
-  public MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
+  @NotNull
+  MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
     return new MultiMap<PsiElement, DfaMemoryState>(myNestedClosures);
   }
 
+  @NotNull
   public Pair<Set<Instruction>,Set<Instruction>> getConstConditionalExpressions() {
     Set<Instruction> trueSet = new HashSet<Instruction>();
     Set<Instruction> falseSet = new HashSet<Instruction>();
@@ -362,7 +369,8 @@ public class DataFlowRunner {
     return Pair.create(trueSet, falseSet);
   }
 
-  private static DfaMemoryStateImpl createClosureState(DfaMemoryState memState) {
+  @NotNull
+  private static DfaMemoryStateImpl createClosureState(@NotNull DfaMemoryState memState) {
     DfaMemoryStateImpl copy = (DfaMemoryStateImpl)memState.createCopy();
     copy.flushFields();
     Set<DfaVariableValue> vars = new HashSet<DfaVariableValue>(copy.getVariableStates().keySet());
index 2fb0de1705e31c0719e1cb43d58cfd3644ae617d..326a7c76cf2189d7bd60de02951d44fb4d0b37f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
  * To change this template use Options | File Templates.
  */
 public interface DfaMemoryState {
+  @NotNull
   DfaMemoryState createCopy();
 
   DfaValue pop();
@@ -40,7 +41,7 @@ public interface DfaMemoryState {
 
   void setVarValue(DfaVariableValue var, DfaValue value);
 
-  boolean applyInstanceofOrNull(DfaRelationValue dfaCond);
+  boolean applyInstanceofOrNull(@NotNull DfaRelationValue dfaCond);
 
   boolean applyCondition(DfaValue dfaCond);
 
@@ -55,7 +56,7 @@ public interface DfaMemoryState {
   boolean isNotNull(DfaValue dfaVar);
 
   @Nullable
-  DfaConstValue getConstantValue(DfaVariableValue value);
+  DfaConstValue getConstantValue(@NotNull DfaVariableValue value);
 
   /**
    * Ephemeral means a state that was created when considering a method contract and checking if one of its arguments is null.
index b015f5bfa80d726a6d31746b2b442bbb19264e5b..30eae15890a5380b2a9639bb6bb1354638ddac4b 100644 (file)
@@ -59,7 +59,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
   private final LinkedHashSet<DfaVariableValue> myUnknownVariables;
   private boolean myEphemeral;
 
-  public DfaMemoryStateImpl(final DfaValueFactory factory) {
+  protected DfaMemoryStateImpl(final DfaValueFactory factory) {
     myFactory = factory;
     myDefaultVariableStates = ContainerUtil.newTroveMap();
     myEqClasses = ContainerUtil.newArrayList();
@@ -95,10 +95,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     myCachedHash = toCopy.myCachedHash;
   }
 
+  @NotNull
   public DfaValueFactory getFactory() {
     return myFactory;
   }
 
+  @NotNull
   @Override
   public DfaMemoryStateImpl createCopy() {
     return new DfaMemoryStateImpl(this);
@@ -112,7 +114,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return equalsSuperficially(that) && equalsByUnknownVariables(that) && equalsByRelations(that) && equalsByVariableStates(that);
   }
 
-  boolean equalsByUnknownVariables(DfaMemoryStateImpl that) {
+  private boolean equalsByUnknownVariables(DfaMemoryStateImpl that) {
     return myUnknownVariables.equals(that.myUnknownVariables);
   }
 
@@ -178,7 +180,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return hash;
   }
 
-  @SuppressWarnings({"HardCodedStringLiteral"})
+  @SuppressWarnings("HardCodedStringLiteral")
   public String toString() {
     StringBuilder result = new StringBuilder();
     result.append('<');
@@ -285,7 +287,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
   }
 
   @Nullable("for boxed values which can't be compared by ==")
-  private Integer getOrCreateEqClassIndex(DfaValue dfaValue) {
+  private Integer getOrCreateEqClassIndex(@NotNull DfaValue dfaValue) {
     int i = getEqClassIndex(dfaValue);
     if (i != -1) return i;
     if (!canBeInRelation(dfaValue) ||
@@ -340,7 +342,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
   }
 
 
-  private static boolean canBeInRelation(DfaValue dfaValue) {
+  private static boolean canBeInRelation(@NotNull DfaValue dfaValue) {
     DfaValue unwrapped = unwrap(dfaValue);
     return unwrapped instanceof DfaVariableValue || unwrapped instanceof DfaConstValue;
   }
@@ -393,7 +395,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return result;
   }
 
-  private boolean canBeReused(final DfaValue dfaValue) {
+  private boolean canBeReused(@NotNull DfaValue dfaValue) {
     if (dfaValue instanceof DfaBoxedValue) {
       DfaValue valueToWrap = ((DfaBoxedValue)dfaValue).getWrappedValue();
       if (valueToWrap instanceof DfaConstValue) {
@@ -410,12 +412,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return true;
   }
 
-  private static boolean cacheable(DfaConstValue dfaConstValue) {
+  private static boolean cacheable(@NotNull DfaConstValue dfaConstValue) {
     Object value = dfaConstValue.getValue();
     return box(value) == box(value);
   }
 
-  @SuppressWarnings({"UnnecessaryBoxing"})
+  @SuppressWarnings("UnnecessaryBoxing")
   private static Object box(final Object value) {
     Object newBoxedValue;
     if (value instanceof Integer) {
@@ -577,7 +579,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
 
   @Override
   @Nullable
-  public DfaConstValue getConstantValue(DfaVariableValue value) {
+  public DfaConstValue getConstantValue(@NotNull DfaVariableValue value) {
     int index = getEqClassIndex(value);
     EqClass ec = index == -1 ? null : myEqClasses.get(index);
     return ec == null ? null : (DfaConstValue)unwrap(ec.findConstant(true));
@@ -594,7 +596,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
   }
 
   @Override
-  public boolean applyInstanceofOrNull(DfaRelationValue dfaCond) {
+  public boolean applyInstanceofOrNull(@NotNull DfaRelationValue dfaCond) {
     DfaValue left = unwrap(dfaCond.getLeftOperand());
 
     if (!(left instanceof DfaVariableValue)) return true;
@@ -648,7 +650,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return applyRelationCondition((DfaRelationValue)dfaCond);
   }
 
-  private boolean applyRelationCondition(DfaRelationValue dfaRelation) {
+  private boolean applyRelationCondition(@NotNull DfaRelationValue dfaRelation) {
     DfaValue dfaLeft = dfaRelation.getLeftOperand();
     DfaValue dfaRight = dfaRelation.getRightOperand();
     if (dfaLeft instanceof DfaUnknownValue || dfaRight instanceof DfaUnknownValue) return true;
@@ -702,7 +704,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
   }
 
-  private void updateVarStateOnComparison(DfaVariableValue dfaVar, DfaValue value) {
+  private void updateVarStateOnComparison(@NotNull DfaVariableValue dfaVar, DfaValue value) {
     if (!isUnknownState(dfaVar)) {
       if (value instanceof DfaConstValue && ((DfaConstValue)value).getValue() == null) {
         setVariableState(dfaVar, getVariableState(dfaVar).withNullability(Nullness.NULLABLE));
@@ -713,7 +715,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     }
   }
 
-  private boolean applyEquivalenceRelation(DfaRelationValue dfaRelation, DfaValue dfaLeft, DfaValue dfaRight) {
+  private boolean applyEquivalenceRelation(@NotNull DfaRelationValue dfaRelation, DfaValue dfaLeft, DfaValue dfaRight) {
     boolean isNegated = dfaRelation.isNonEquality();
     if (!isNegated && !dfaRelation.isEquality()) {
       return true;
@@ -761,7 +763,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return true;
   }
 
-  private boolean applyBoxedRelation(DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
+  private boolean applyBoxedRelation(@NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
     if (!TypeConversionUtil.isPrimitiveAndNotNull(dfaLeft.getVariableType())) return true;
 
     DfaBoxedValue.Factory boxedFactory = myFactory.getBoxedFactory();
@@ -770,7 +772,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return boxedLeft == null || boxedRight == null || applyRelation(boxedLeft, boxedRight, negated);
   }
 
-  private boolean applyUnboxedRelation(DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
+  private boolean applyUnboxedRelation(@NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
     PsiType type = dfaLeft.getVariableType();
     if (!TypeConversionUtil.isPrimitiveWrapper(type)) {
       return true;
@@ -912,7 +914,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     myCachedHash = null;
   }
   
-  public DfaVariableState getVariableState(DfaVariableValue dfaVar) {
+  DfaVariableState getVariableState(DfaVariableValue dfaVar) {
     DfaVariableState state = myVariableStates.get(dfaVar);
 
     if (state == null) {
@@ -935,11 +937,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return state;
   }
 
-  protected Map<DfaVariableValue, DfaVariableState> getVariableStates() {
+  @NotNull
+  Map<DfaVariableValue, DfaVariableState> getVariableStates() {
     return myVariableStates;
   }
 
-  protected DfaVariableState createVariableState(final DfaVariableValue var) {
+  @NotNull
+  protected DfaVariableState createVariableState(@NotNull DfaVariableValue var) {
     return new DfaVariableState(var);
   }
 
@@ -958,7 +962,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     }
   }
 
-  private boolean shouldMarkUnknown(DfaVariableValue value) {
+  private boolean shouldMarkUnknown(@NotNull DfaVariableValue value) {
     int eqClassIndex = getEqClassIndex(value);
     if (eqClassIndex < 0) return false;
 
@@ -975,6 +979,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     return false;
   }
 
+  @NotNull
   Set<DfaVariableValue> getChangedVariables() {
     return myVariableStates.keySet();
   }
@@ -999,17 +1004,18 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
     myCachedHash = null;
   }
 
-  public void flushDependencies(DfaVariableValue variable) {
+  void flushDependencies(@NotNull DfaVariableValue variable) {
     for (DfaVariableValue dependent : myFactory.getVarFactory().getAllQualifiedBy(variable)) {
       doFlush(dependent, false);
     }
   }
 
+  @NotNull
   Set<DfaVariableValue> getUnknownVariables() {
     return myUnknownVariables;
   }
 
-  void doFlush(DfaVariableValue varPlain, boolean markUnknown) {
+  void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) {
     DfaVariableValue varNegated = varPlain.getNegatedValue();
 
     final int idPlain = varPlain.getID();
index 4c78c4807069d21eb0fb286f639aa85786e1c828..f6f72dbb32d7912898461b75ef1964dc2d99808d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -155,8 +155,9 @@ public class DfaPsiUtil {
             return false;
           }
 
+          @NotNull
           @Override
-          protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
+          protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
             Instruction instruction = instructionState.getInstruction();
             if (isCallExposingNonInitializedFields(instruction) ||
                 instruction instanceof ReturnInstruction && !((ReturnInstruction)instruction).isViaException()) {
index ae54ff7817cb7d02859701fa9a770040be9c0bca..fa6208115eb0b32ff86cc907c77641c08efbe33f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -70,7 +70,7 @@ public class DfaUtil {
       @Override
       public Result<Map<PsiElement, ValuableInstructionVisitor.PlaceResult>> compute() {
         final ValuableInstructionVisitor visitor = new ValuableInstructionVisitor();
-        RunnerResult runnerResult = new ValuableDataFlowRunner(codeBlock).analyzeMethod(codeBlock, visitor);
+        RunnerResult runnerResult = new ValuableDataFlowRunner().analyzeMethod(codeBlock, visitor);
         return Result.create(runnerResult == RunnerResult.OK ? visitor.myResults : null, codeBlock);
       }
     });
@@ -242,11 +242,11 @@ public class DfaUtil {
         final ValuableDataFlowRunner.ValuableDfaVariableState curState = (ValuableDataFlowRunner.ValuableDfaVariableState)memState.getVariableState(var);
         final FList<PsiExpression> curValue = curState.myConcatenation;
         final FList<PsiExpression> nextValue;
-        if (type == JavaTokenType.PLUSEQ && !prevValue.isEmpty()) {
+        if (type == JavaTokenType.PLUSEQ && !prevValue.isEmpty() && rightValue != null) {
           nextValue = prevValue.prepend(rightValue);
         }
         else {
-          nextValue = curValue.isEmpty() ? curValue.prepend(rightValue) : curValue;
+          nextValue = curValue.isEmpty() && rightValue != null ? curValue.prepend(rightValue) : curValue;
         }
         memState.setVariableState(var, curState.withExpression(nextValue));
       }
index 43657cd75ded96907b6861b0ad6b015209714b38..80e1f64cac161b3af30b75f7d158df3b05c1bb04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -40,18 +40,19 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-public class DfaVariableState {
-  protected final Set<DfaPsiType> myInstanceofValues;
-  protected final Set<DfaPsiType> myNotInstanceofValues;
-  protected final Nullness myNullability;
+class DfaVariableState {
+  @NotNull final Set<DfaPsiType> myInstanceofValues;
+  @NotNull final Set<DfaPsiType> myNotInstanceofValues;
+  @NotNull final Nullness myNullability;
   private final int myHash;
 
-  public DfaVariableState(@NotNull DfaVariableValue dfaVar) {
+  DfaVariableState(@NotNull DfaVariableValue dfaVar) {
     this(Collections.<DfaPsiType>emptySet(), Collections.<DfaPsiType>emptySet(), dfaVar.getInherentNullability());
   }
 
-  protected DfaVariableState(Set<DfaPsiType> instanceofValues,
-                             Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
+  DfaVariableState(@NotNull Set<DfaPsiType> instanceofValues,
+                   @NotNull Set<DfaPsiType> notInstanceofValues,
+                   @NotNull Nullness nullability) {
     myInstanceofValues = instanceofValues;
     myNotInstanceofValues = notInstanceofValues;
     myNullability = nullability;
@@ -62,7 +63,7 @@ public class DfaVariableState {
     return myNullability == Nullness.NULLABLE;
   }
 
-  private boolean checkInstanceofValue(DfaPsiType dfaType) {
+  private boolean checkInstanceofValue(@NotNull DfaPsiType dfaType) {
     if (myInstanceofValues.contains(dfaType)) return true;
 
     for (DfaPsiType dfaTypeValue : myNotInstanceofValues) {
@@ -77,7 +78,7 @@ public class DfaVariableState {
   }
 
   @Nullable
-  public DfaVariableState withInstanceofValue(DfaTypeValue dfaType) {
+  DfaVariableState withInstanceofValue(@NotNull DfaTypeValue dfaType) {
     if (dfaType.getDfaType().getPsiType() instanceof PsiPrimitiveType) return this;
 
     if (checkInstanceofValue(dfaType.getDfaType())) {
@@ -103,7 +104,7 @@ public class DfaVariableState {
   }
 
   @Nullable
-  public DfaVariableState withNotInstanceofValue(DfaTypeValue dfaType) {
+  DfaVariableState withNotInstanceofValue(@NotNull DfaTypeValue dfaType) {
     if (myNotInstanceofValues.contains(dfaType.getDfaType())) return this;
 
     for (DfaPsiType dfaTypeValue : myInstanceofValues) {
@@ -126,7 +127,8 @@ public class DfaVariableState {
     return createCopy(myInstanceofValues, newNotInstanceof, myNullability);
   }
 
-  DfaVariableState withoutType(DfaPsiType type) {
+  @NotNull
+  DfaVariableState withoutType(@NotNull DfaPsiType type) {
     if (myInstanceofValues.contains(type)) {
       HashSet<DfaPsiType> newInstanceof = ContainerUtil.newHashSet(myInstanceofValues);
       newInstanceof.remove(type);
@@ -154,7 +156,8 @@ public class DfaVariableState {
            myNotInstanceofValues.equals(aState.myNotInstanceofValues);
   }
 
-  protected DfaVariableState createCopy(Set<DfaPsiType> instanceofValues, Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
+  @NotNull
+  protected DfaVariableState createCopy(@NotNull Set<DfaPsiType> instanceofValues, @NotNull Set<DfaPsiType> notInstanceofValues, @NotNull Nullness nullability) {
     return new DfaVariableState(instanceofValues, notInstanceofValues, nullability);
   }
 
@@ -172,7 +175,8 @@ public class DfaVariableState {
     return buf.toString();
   }
 
-  public Nullness getNullability() {
+  @NotNull
+  Nullness getNullability() {
     return myNullability;
   }
 
@@ -180,14 +184,17 @@ public class DfaVariableState {
     return myNullability == Nullness.NOT_NULL;
   }
 
+  @NotNull
   DfaVariableState withNullability(@NotNull Nullness nullness) {
     return myNullability == nullness ? this : createCopy(myInstanceofValues, myNotInstanceofValues, nullness);
   }
 
-  public DfaVariableState withNullable(final boolean nullable) {
+  @NotNull
+  DfaVariableState withNullable(final boolean nullable) {
     return myNullability != Nullness.NOT_NULL ? withNullability(nullable ? Nullness.NULLABLE : Nullness.UNKNOWN) : this;
   }
 
+  @NotNull
   public DfaVariableState withValue(DfaValue value) {
     return this;
   }
index fb866355d0526389fecc3f5d147024d71469f044..e07ed22d6681d5bc0bf8d038a73ff79a5b890b63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -32,11 +32,11 @@ import java.util.*;
  * @author peter
  */
 class StateMerger {
-  private final Map<DfaMemoryStateImpl, LinkedHashSet<Fact>> myFacts = ContainerUtil.newIdentityHashMap();
+  private final Map<DfaMemoryStateImpl, Set<Fact>> myFacts = ContainerUtil.newIdentityHashMap();
   private final Map<DfaMemoryState, Map<DfaVariableValue, DfaMemoryStateImpl>> myCopyCache = ContainerUtil.newIdentityHashMap();
 
   @Nullable
-  List<DfaMemoryStateImpl> mergeByFacts(List<DfaMemoryStateImpl> states) {
+  List<DfaMemoryStateImpl> mergeByFacts(@NotNull List<DfaMemoryStateImpl> states) {
     MultiMap<Fact, DfaMemoryStateImpl> statesByFact = MultiMap.createLinked();
     for (DfaMemoryStateImpl state : states) {
       ProgressManager.checkCanceled();
@@ -84,8 +84,8 @@ class StateMerger {
   }
 
   @NotNull
-  private MultiMap<Set<Fact>, DfaMemoryStateImpl> mapByUnrelatedFacts(Fact fact,
-                                                                      Collection<DfaMemoryStateImpl> states1) {
+  private MultiMap<Set<Fact>, DfaMemoryStateImpl> mapByUnrelatedFacts(@NotNull Fact fact,
+                                                                      @NotNull Collection<DfaMemoryStateImpl> states1) {
     MultiMap<Set<Fact>, DfaMemoryStateImpl> statesByUnrelatedFacts1 = MultiMap.createLinked();
     for (DfaMemoryStateImpl state : states1) {
       statesByUnrelatedFacts1.putValue(getUnrelatedFacts(fact, state), state);
@@ -93,7 +93,8 @@ class StateMerger {
     return statesByUnrelatedFacts1;
   }
 
-  private LinkedHashSet<Fact> getUnrelatedFacts(final Fact fact, DfaMemoryStateImpl state) {
+  @NotNull
+  private LinkedHashSet<Fact> getUnrelatedFacts(@NotNull final Fact fact, @NotNull DfaMemoryStateImpl state) {
     return new LinkedHashSet<Fact>(ContainerUtil.filter(getFacts(state), new Condition<Fact>() {
       @Override
       public boolean value(Fact another) {
@@ -102,10 +103,10 @@ class StateMerger {
     }));
   }
 
-  private void restoreOtherInequalities(Fact removedFact, Collection<DfaMemoryStateImpl> mergedGroup, DfaMemoryStateImpl state) {
+  private void restoreOtherInequalities(@NotNull Fact removedFact, @NotNull Collection<DfaMemoryStateImpl> mergedGroup, @NotNull DfaMemoryStateImpl state) {
     Set<DfaConstValue> inequalitiesToRestore = null;
     for (DfaMemoryStateImpl member : mergedGroup) {
-      LinkedHashSet<Fact> memberFacts = getFacts(member);
+      Set<Fact> memberFacts = getFacts(member);
       if (memberFacts.contains(removedFact)) {
         Set<DfaConstValue> otherInequalities = getOtherInequalities(removedFact, memberFacts, member);
         if (inequalitiesToRestore == null) {
@@ -123,7 +124,8 @@ class StateMerger {
     }
   }
 
-  private static Set<DfaConstValue> getOtherInequalities(Fact removedFact, LinkedHashSet<Fact> memberFacts, DfaMemoryStateImpl state) {
+  @NotNull
+  private static Set<DfaConstValue> getOtherInequalities(@NotNull Fact removedFact, @NotNull Set<Fact> memberFacts, @NotNull DfaMemoryStateImpl state) {
     Set<DfaConstValue> otherInequalities = ContainerUtil.newLinkedHashSet();
     Set<DfaValue> eqValues = ContainerUtil.newHashSet(state.getEquivalentValues((DfaValue)removedFact.myArg));
     for (Fact candidate : memberFacts) {
@@ -136,7 +138,8 @@ class StateMerger {
     return otherInequalities;
   }
 
-  private static Set<DfaVariableValue> getAllUnknownVariables(Collection<DfaMemoryStateImpl> complementary) {
+  @NotNull
+  private static Set<DfaVariableValue> getAllUnknownVariables(@NotNull Collection<DfaMemoryStateImpl> complementary) {
     final Set<DfaVariableValue> toFlush = ContainerUtil.newLinkedHashSet();
     for (DfaMemoryStateImpl removedState : complementary) {
       toFlush.addAll(removedState.getUnknownVariables());
@@ -144,7 +147,8 @@ class StateMerger {
     return toFlush;
   }
 
-  private static DfaMemoryStateImpl withUnknownVariables(DfaMemoryStateImpl original, Set<DfaVariableValue> toFlush) {
+  @NotNull
+  private static DfaMemoryStateImpl withUnknownVariables(@NotNull DfaMemoryStateImpl original, @NotNull Set<DfaVariableValue> toFlush) {
     DfaMemoryStateImpl copy = original.createCopy();
     for (DfaVariableValue value : toFlush) {
       copy.doFlush(value, true);
@@ -153,7 +157,7 @@ class StateMerger {
   }
 
   @Nullable
-  public List<DfaMemoryStateImpl> mergeByUnknowns(List<DfaMemoryStateImpl> states) {
+  List<DfaMemoryStateImpl> mergeByUnknowns(@NotNull List<DfaMemoryStateImpl> states) {
     MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
     for (DfaMemoryStateImpl state : states) {
       ProgressManager.checkCanceled();
@@ -181,7 +185,7 @@ class StateMerger {
   }
   
   @Nullable
-  public List<DfaMemoryStateImpl> mergeByNullability(List<DfaMemoryStateImpl> states) {
+  List<DfaMemoryStateImpl> mergeByNullability(List<DfaMemoryStateImpl> states) {
     MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
     for (DfaMemoryStateImpl state : states) {
       ProgressManager.checkCanceled();
@@ -217,7 +221,7 @@ class StateMerger {
     return replacements.getMergeResult();
   }
 
-  private static boolean mergeUnknowns(Replacements replacements, List<DfaMemoryStateImpl> complementary) {
+  private static boolean mergeUnknowns(@NotNull Replacements replacements, @NotNull List<DfaMemoryStateImpl> complementary) {
     if (complementary.size() < 2) return false;
 
     final Set<DfaVariableValue> toFlush = getAllUnknownVariables(complementary);
@@ -231,13 +235,14 @@ class StateMerger {
     });
   }
 
-  private boolean areEquivalentModuloVar(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
+  private boolean areEquivalentModuloVar(@NotNull DfaMemoryStateImpl state1, @NotNull DfaMemoryStateImpl state2, @NotNull DfaVariableValue var) {
     DfaMemoryStateImpl copy1 = copyWithoutVar(state1, var);
     DfaMemoryStateImpl copy2 = copyWithoutVar(state2, var);
     return copy2.equalsByRelations(copy1) && copy2.equalsByVariableStates(copy1);
   }
 
-  private DfaMemoryStateImpl copyWithoutVar(DfaMemoryStateImpl state, DfaVariableValue var) {
+  @NotNull
+  private DfaMemoryStateImpl copyWithoutVar(@NotNull DfaMemoryStateImpl state, @NotNull DfaVariableValue var) {
     Map<DfaVariableValue, DfaMemoryStateImpl> map = myCopyCache.get(state);
     if (map == null) {
       myCopyCache.put(state, map = ContainerUtil.newIdentityHashMap());
@@ -251,12 +256,13 @@ class StateMerger {
     return copy;
   }
 
-  private static boolean areVarStatesEqualModuloNullability(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
+  private static boolean areVarStatesEqualModuloNullability(@NotNull DfaMemoryStateImpl state1, @NotNull DfaMemoryStateImpl state2, @NotNull DfaVariableValue var) {
     return state1.getVariableState(var).withNullability(Nullness.UNKNOWN).equals(state2.getVariableState(var).withNullability(Nullness.UNKNOWN));
   }
 
-  private LinkedHashSet<Fact> getFacts(DfaMemoryStateImpl state) {
-    LinkedHashSet<Fact> result = myFacts.get(state);
+  @NotNull
+  private Set<Fact> getFacts(@NotNull DfaMemoryStateImpl state) {
+    Set<Fact> result = myFacts.get(state);
     if (result != null) {
       return result;
     }
@@ -317,12 +323,13 @@ class StateMerger {
   private enum FactType { equality, instanceOf }
 
   private static class Fact {
-    final FactType myType;
-    final DfaVariableValue myVar;
-    final boolean myPositive;
-    final Object myArg; // DfaValue for equality fact, DfaPsiType for instanceOf fact
+    @NotNull final FactType myType;
+    @NotNull private final DfaVariableValue myVar;
+    private final boolean myPositive;
+    @NotNull
+    private final Object myArg; // DfaValue for equality fact, DfaPsiType for instanceOf fact
 
-    private Fact(FactType type, DfaVariableValue var, boolean positive, Object arg) {
+    private Fact(@NotNull FactType type, @NotNull DfaVariableValue var, boolean positive, @NotNull Object arg) {
       myType = type;
       myVar = var;
       myPositive = positive;
@@ -358,18 +365,20 @@ class StateMerger {
       return myVar + " " + (myPositive ? "" : "!") + myType + " " + myArg;
     }
 
-    static Fact createEqualityFact(DfaVariableValue var, DfaValue val, boolean equal) {
+    @NotNull
+    private static Fact createEqualityFact(@NotNull DfaVariableValue var, @NotNull DfaValue val, boolean equal) {
       if (val instanceof DfaVariableValue && val.getID() < var.getID()) {
         return new Fact(FactType.equality, (DfaVariableValue)val, equal, var);
       }
       return new Fact(FactType.equality, var, equal, val);
     }
 
-    Fact getPositiveCounterpart() {
+    @NotNull
+    private Fact getPositiveCounterpart() {
       return new Fact(myType, myVar, true, myArg);
     }
 
-    boolean invalidatesFact(Fact another) {
+    boolean invalidatesFact(@NotNull Fact another) {
       if (another.myType != myType) return false;
       if (myType == FactType.equality) {
         return aboutSame(myVar, another.myVar) || aboutSame(myVar, another.myArg);
@@ -377,18 +386,18 @@ class StateMerger {
       return aboutSame(myVar, another.myVar) && aboutSame(myArg, another.myArg);
     }
     
-    static boolean aboutSame(Object v1, Object v2) {
+    private static boolean aboutSame(Object v1, Object v2) {
       return normalize(v1) == normalize(v2);
     }
 
-    static Object normalize(Object value) {
+    private static Object normalize(Object value) {
       if (value instanceof DfaVariableValue && ((DfaVariableValue)value).isNegated()) {
         return ((DfaVariableValue)value).createNegated();
       }
       return value;
     }
 
-    void removeFromState(DfaMemoryStateImpl state) {
+    void removeFromState(@NotNull DfaMemoryStateImpl state) {
       DfaVariableState varState = state.getVariableState(myVar);
       if (myType == FactType.equality) {
         state.flushVariable(myVar);
@@ -400,18 +409,18 @@ class StateMerger {
   }
 
   private static class Replacements {
-    private final List<DfaMemoryStateImpl> myAllStates;
+    @NotNull private final List<DfaMemoryStateImpl> myAllStates;
     private final Set<DfaMemoryStateImpl> myRemovedStates = ContainerUtil.newIdentityTroveSet();
     private final List<DfaMemoryStateImpl> myMerged = ContainerUtil.newArrayList();
 
-    Replacements(List<DfaMemoryStateImpl> allStates) {
+    private Replacements(@NotNull List<DfaMemoryStateImpl> allStates) {
       myAllStates = allStates;
     }
 
-    boolean hasMerges() { return !myMerged.isEmpty(); }
+    private boolean hasMerges() { return !myMerged.isEmpty(); }
 
     @Nullable
-    List<DfaMemoryStateImpl> getMergeResult() {
+    private List<DfaMemoryStateImpl> getMergeResult() {
       if (hasMerges()) {
         List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList(myMerged);
         for (DfaMemoryStateImpl state : myAllStates) {
@@ -424,15 +433,15 @@ class StateMerger {
       return null;
     }
 
-    boolean stripAndMerge(Collection<DfaMemoryStateImpl> group,
-                               Function<DfaMemoryStateImpl, DfaMemoryStateImpl> stripper) {
+    private boolean stripAndMerge(@NotNull Collection<DfaMemoryStateImpl> group,
+                                  @NotNull Function<DfaMemoryStateImpl, DfaMemoryStateImpl> stripper) {
       if (group.size() <= 1) return false;
 
-      boolean hasMerges = false;
       MultiMap<DfaMemoryStateImpl, DfaMemoryStateImpl> strippedToOriginals = MultiMap.create();
       for (DfaMemoryStateImpl original : group) {
         strippedToOriginals.putValue(stripper.fun(original), original);
       }
+      boolean hasMerges = false;
       for (Map.Entry<DfaMemoryStateImpl, Collection<DfaMemoryStateImpl>> entry : strippedToOriginals.entrySet()) {
         Collection<DfaMemoryStateImpl> merged = entry.getValue();
         if (merged.size() > 1) {
index bf78faf17b66dc1edef835c9cbd047c522435102..51daae3aa476f610fac536b9a24411b56b3a29ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -20,7 +20,6 @@ import com.intellij.codeInspection.dataFlow.value.DfaPsiType;
 import com.intellij.codeInspection.dataFlow.value.DfaValue;
 import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
 import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
-import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiExpression;
 import com.intellij.util.containers.FList;
 import org.jetbrains.annotations.NotNull;
@@ -31,33 +30,31 @@ import java.util.Set;
 /**
  * @author Gregory.Shrago
  */
-public class ValuableDataFlowRunner extends DataFlowRunner {
-
-  protected ValuableDataFlowRunner(PsiElement block) {
-    super();
-  }
-
+class ValuableDataFlowRunner extends DataFlowRunner {
+  @NotNull
   @Override
   protected DfaMemoryState createMemoryState() {
     return new MyDfaMemoryState(getFactory());
   }
 
   static class MyDfaMemoryState extends DfaMemoryStateImpl {
-    private MyDfaMemoryState(final DfaValueFactory factory) {
+    private MyDfaMemoryState(@NotNull DfaValueFactory factory) {
       super(factory);
     }
 
-    MyDfaMemoryState(DfaMemoryStateImpl toCopy) {
+    private MyDfaMemoryState(@NotNull DfaMemoryStateImpl toCopy) {
       super(toCopy);
     }
 
+    @NotNull
     @Override
     public DfaMemoryStateImpl createCopy() {
       return new MyDfaMemoryState(this);
     }
 
+    @NotNull
     @Override
-    protected DfaVariableState createVariableState(DfaVariableValue var) {
+    protected DfaVariableState createVariableState(@NotNull DfaVariableValue var) {
       return new ValuableDfaVariableState(var);
     }
 
@@ -68,35 +65,38 @@ public class ValuableDataFlowRunner extends DataFlowRunner {
   }
 
   static class ValuableDfaVariableState extends DfaVariableState {
-    final DfaValue myValue;
+    private final DfaValue myValue;
     @NotNull final FList<PsiExpression> myConcatenation;
 
-    private ValuableDfaVariableState(final DfaVariableValue psiVariable) {
+    private ValuableDfaVariableState(@NotNull DfaVariableValue psiVariable) {
       super(psiVariable);
       myValue = null;
       myConcatenation = FList.emptyList();
     }
 
     private ValuableDfaVariableState(Set<DfaPsiType> instanceofValues,
-                             Set<DfaPsiType> notInstanceofValues,
-                             Nullness nullability, DfaValue value, @NotNull FList<PsiExpression> concatenation) {
+                                     Set<DfaPsiType> notInstanceofValues,
+                                     Nullness nullability, DfaValue value,
+                                     @NotNull FList<PsiExpression> concatenation) {
       super(instanceofValues, notInstanceofValues, nullability);
       myValue = value;
       myConcatenation = concatenation;
     }
 
+    @NotNull
     @Override
-    protected DfaVariableState createCopy(Set<DfaPsiType> instanceofValues, Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
+    protected DfaVariableState createCopy(@NotNull Set<DfaPsiType> instanceofValues, @NotNull Set<DfaPsiType> notInstanceofValues, @NotNull Nullness nullability) {
       return new ValuableDfaVariableState(instanceofValues, notInstanceofValues, nullability, myValue, myConcatenation);
     }
 
+    @NotNull
     @Override
     public DfaVariableState withValue(@Nullable final DfaValue value) {
       if (value == myValue) return this;
       return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, value, myConcatenation);
     }
 
-    public ValuableDfaVariableState withExpression(@NotNull final FList<PsiExpression> concatenation) {
+    ValuableDfaVariableState withExpression(@NotNull final FList<PsiExpression> concatenation) {
       if (concatenation == myConcatenation) return this;
       return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, myValue, concatenation);
     }
index 7037613ff003c892242801f397b32e7904e04ff7..b86085c4bb2dabb7f371d7163c187a4cf757715c 100644 (file)
@@ -35,19 +35,21 @@ import java.util.Map;
 public class DfaTypeValue extends DfaValue {
   public static class Factory {
     private final Map<DfaPsiType,ArrayList<DfaTypeValue>> myCache = ContainerUtil.newHashMap();
+    @NotNull
     private final DfaValueFactory myFactory;
 
-    Factory(DfaValueFactory factory) {
+    Factory(@NotNull DfaValueFactory factory) {
       myFactory = factory;
     }
 
     @NotNull
-    public DfaTypeValue createTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness) {
+    DfaTypeValue createTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness) {
       ArrayList<DfaTypeValue> conditions = myCache.get(type);
       if (conditions == null) {
         conditions = new ArrayList<DfaTypeValue>();
         myCache.put(type, conditions);
-      } else {
+      }
+      else {
         for (DfaTypeValue aType : conditions) {
           if (aType.myNullness == nullness) return aType;
         }
@@ -60,15 +62,18 @@ public class DfaTypeValue extends DfaValue {
 
   }
 
+  @NotNull
   private final DfaPsiType myType;
+  @NotNull
   private final Nullness myNullness;
 
-  private DfaTypeValue(DfaPsiType type, Nullness nullness, DfaValueFactory factory) {
+  private DfaTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness, @NotNull DfaValueFactory factory) {
     super(factory);
     myType = type;
     myNullness = nullness;
   }
 
+  @NotNull
   public DfaPsiType getDfaType() {
     return myType;
   }
@@ -81,6 +86,7 @@ public class DfaTypeValue extends DfaValue {
     return myNullness == Nullness.NOT_NULL;
   }
 
+  @NotNull
   public Nullness getNullness() {
     return myNullness;
   }
index 4a260d7c827b1efc6091e9baa075c4fe35da479c..9a20ae691695aa30916e72377271f780b84e375b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -64,7 +64,8 @@ public class DfaValueFactory {
     return myUnknownMembersAreNullable;
   }
 
-  public DfaValue createTypeValue(@Nullable PsiType type, Nullness nullability) {
+  @NotNull
+  public DfaValue createTypeValue(@Nullable PsiType type, @NotNull Nullness nullability) {
     type = TypeConversionUtil.erasure(type);
     if (type == null) return DfaUnknownValue.getInstance();
     return getTypeFactory().createTypeValue(internType(type), nullability);
index f8f6d16aed13fa91b8744a2d790234ad30043c0a..ae3107236e11bbed2b7bc0f0dc11e83e297db74e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -81,10 +81,10 @@ public class DfaVariableValue extends DfaValue {
       return result;
     }
 
-    public List<DfaVariableValue> getAllQualifiedBy(DfaVariableValue value) {
+    @NotNull
+    public List<DfaVariableValue> getAllQualifiedBy(@NotNull DfaVariableValue value) {
       return value.myDependents;
     }
-
   }
 
   private final PsiModifierListOwner myVariable;
@@ -159,6 +159,7 @@ public class DfaVariableValue extends DfaValue {
     return myQualifier;
   }
 
+  @NotNull
   public Nullness getInherentNullability() {
     if (myInherentNullability != null) {
       return myInherentNullability;
@@ -167,6 +168,7 @@ public class DfaVariableValue extends DfaValue {
     return myInherentNullability = calcInherentNullability();
   }
 
+  @NotNull
   private Nullness calcInherentNullability() {
     PsiModifierListOwner var = getPsiVariable();
     Nullness nullability = DfaPsiUtil.getElementNullability(getVariableType(), var);
index 1c69fae0762596808d368df0ae20d9028389a13e..d33afa27c24586237fb1afe298d2be2c97d3ef05 100644 (file)
@@ -17,19 +17,23 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.completion.JavaInheritorsGetter;
+import com.intellij.codeInsight.completion.PrefixMatcher;
+import com.intellij.codeInsight.completion.StatisticsWeigher;
 import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInsight.lookup.*;
+import com.intellij.codeInsight.lookup.ExpressionLookupItem;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
 import com.intellij.codeInsight.template.*;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
-import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.filters.getters.JavaMembersGetter;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiTypesUtil;
 import com.intellij.psi.util.PsiUtil;
-import com.intellij.refactoring.util.RefactoringUtil;
 import com.intellij.util.Consumer;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
@@ -38,11 +42,13 @@ import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-import static com.intellij.util.containers.ContainerUtil.*;
+import static com.intellij.util.containers.ContainerUtil.map;
+import static com.intellij.util.containers.ContainerUtil.sorted;
 
 public class AddVariableInitializerFix implements IntentionAction {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AddReturnFix");
@@ -76,11 +82,10 @@ public class AddVariableInitializerFix implements IntentionAction {
   @Override
   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
     if (!FileModificationService.getInstance().prepareFileForWrite(myVariable.getContainingFile())) return;
-
     final LookupElement[] suggestedInitializers = suggestInitializer(myVariable);
     LOG.assertTrue(suggestedInitializers.length > 0);
     LOG.assertTrue(suggestedInitializers[0] instanceof ExpressionLookupItem);
-    final PsiExpression initializer = (PsiExpression) suggestedInitializers[0].getObject();
+    final PsiExpression initializer = (PsiExpression)suggestedInitializers[0].getObject();
     if (myVariable instanceof PsiLocalVariable) {
       ((PsiLocalVariable)myVariable).setInitializer(initializer);
     }
@@ -88,7 +93,7 @@ public class AddVariableInitializerFix implements IntentionAction {
       ((PsiField)myVariable).setInitializer(initializer);
     }
     else {
-      LOG.error("Unknown variable type: "+myVariable);
+      LOG.error("Unknown variable type: " + myVariable);
     }
     runAssignmentTemplate(Collections.singletonList(myVariable.getInitializer()), suggestedInitializers, editor);
   }
@@ -130,80 +135,20 @@ public class AddVariableInitializerFix implements IntentionAction {
   public static LookupElement[] suggestInitializer(final PsiVariable variable) {
     PsiType type = variable.getType();
     final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(variable.getProject());
+
+    final List<LookupElement> result = new SmartList<LookupElement>();
+    final String defaultValue = PsiTypesUtil.getDefaultValueOfType(type);
+    final ExpressionLookupItem defaultExpression = new ExpressionLookupItem(elementFactory.createExpressionFromText(defaultValue, variable));
+    result.add(defaultExpression);
     if (type instanceof PsiClassType) {
       final PsiClass aClass = PsiTypesUtil.getPsiClass(type);
-      if (aClass != null) {
-        final LookupElement nullLookupItem = new ExpressionLookupItem(elementFactory.createExpressionFromText(PsiKeyword.NULL, variable));
-        if (InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_LANG_ITERABLE) ||
-            InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_MAP)) {
-          final List<PsiType> suggestedTypes = new SmartList<PsiType>();
-          JavaInheritorsGetter.processInheritors(variable.getContainingFile(), variable, Collections.singleton((PsiClassType) type), PrefixMatcher.ALWAYS_TRUE, new Consumer<PsiType>() {
-            @Override
-            public void consume(PsiType type) {
-              LOG.assertTrue(type instanceof PsiClassType);
-              final PsiClass psiClass = PsiTypesUtil.getPsiClass(type);
-              if (psiClass != null &&
-                  !psiClass.isInterface() &&
-                  !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
-                  psiClass.hasModifierProperty(PsiModifier.PUBLIC) &&
-                  PsiUtil.hasDefaultConstructor(psiClass)) {
-                suggestedTypes.add(type);
-              }
-            }
-          });
-
-          List<LookupElement> sortedLookups = map(sorted(map(suggestedTypes, new Function<PsiType, LookupElement>() {
-            @Override
-            public LookupElement fun(PsiType type) {
-              return PsiTypeLookupItem.createLookupItem(type, variable);
-            }
-          }), new Comparator<LookupElement>() {
-            @Override
-            public int compare(LookupElement o1, LookupElement o2) {
-              final int count1 = StatisticsWeigher.getBaseStatisticsInfo(o1, null).getUseCount();
-              final int count2 = StatisticsWeigher.getBaseStatisticsInfo(o2, null).getUseCount();
-              return count2 - count1;
-            }
-          }), new Function<LookupElement, LookupElement>() {
-            @Override
-            public LookupElement fun(LookupElement element) {
-              final LookupElementDecorator<LookupElement> constructorLookupElement =
-                LookupElementDecorator.withInsertHandler(element, ConstructorInsertHandler.BASIC_INSTANCE);
-              return new LookupElementDecorator<LookupElement>(constructorLookupElement) {
-                @Override
-                public void renderElement(LookupElementPresentation presentation) {
-                  super.renderElement(presentation);
-                  presentation.setTailText("");
-                  presentation.setItemText(PsiKeyword.NEW + " " + presentation.getItemText() + "()");
-                }
-
-                @Override
-                public void handleInsert(InsertionContext context) {
-                  super.handleInsert(context);
-                  context.getDocument().insertString(context.getStartOffset(), PsiKeyword.NEW + " ");
-                }
-              };
-            }
-          });
-          LookupElement[] result = new LookupElement[sortedLookups.size() + 1];
-          result[0] = nullLookupItem;
-          for (int i = 0; i < sortedLookups.size(); i++) {
-            LookupElement lookup = sortedLookups.get(i);
-            result[i + 1] = lookup;
-          }
-          return result;
-        } else {
-          if (PsiUtil.hasDefaultConstructor(aClass)) {
-            final PsiExpression newExpression = elementFactory
-              .createExpressionFromText(PsiKeyword.NEW + " " + type.getCanonicalText(false) + "()", variable);
-            return new LookupElement[]{nullLookupItem, new ExpressionLookupItem(newExpression)};
-          }
-        }
+      if (aClass != null && PsiUtil.hasDefaultConstructor(aClass)) {
+        final String expressionText = PsiKeyword.NEW + " " + type.getCanonicalText(false) + "()";
+        ExpressionLookupItem newExpression = new ExpressionLookupItem(elementFactory.createExpressionFromText(expressionText, variable));
+        result.add(newExpression);
       }
     }
-    final String defaultValue = PsiTypesUtil.getDefaultValueOfType(type);
-    final PsiExpression expression = elementFactory.createExpressionFromText(defaultValue, variable);
-    return new LookupElement[] {new ExpressionLookupItem(expression)};
+    return result.toArray(new LookupElement[result.size()]);
   }
 
   @Override
index 8081efe89c3d9daf28d22314f76b3e3600711101..7d113d760938b83c0ca5c012a94e2ea8211a7d17 100644 (file)
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.refactoring.BaseRefactoringProcessor;
 import com.intellij.refactoring.typeMigration.ui.FailedConversionsDialog;
@@ -36,11 +37,13 @@ import com.intellij.usageView.UsageViewManager;
 import com.intellij.util.Consumer;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.SmartList;
+import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
 import static com.intellij.util.ObjectUtils.assertNotNull;
 
@@ -59,10 +62,19 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
     myRules = rules;
   }
 
+
+  public static void runHighlightingTypeMigration(final Project project,
+                                                          final Editor editor,
+                                                          final TypeMigrationRules rules,
+                                                          final PsiElement root) {
+    runHighlightingTypeMigration(project, editor, rules, root, false);
+  }
+
   public static void runHighlightingTypeMigration(final Project project,
-                                                  final Editor editor,
-                                                  final TypeMigrationRules rules,
-                                                  final PsiElement root) {
+                                                          final Editor editor,
+                                                          final TypeMigrationRules rules,
+                                                          final PsiElement root,
+                                                          final boolean optimizeImports) {
     final PsiFile containingFile = root.getContainingFile();
     final TypeMigrationProcessor processor = new TypeMigrationProcessor(project, root, rules) {
       @Override
@@ -89,6 +101,20 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
             }
           });
         }
+        if (optimizeImports) {
+          final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(myProject);
+          final Set<PsiFile> affectedFiles = new THashSet<PsiFile>();
+          for (UsageInfo usage : usages) {
+            final PsiFile usageFile = usage.getFile();
+            if (usageFile != null) {
+              affectedFiles.add(usageFile);
+            }
+          }
+          for (PsiFile file : affectedFiles) {
+            javaCodeStyleManager.optimizeImports(file);
+            javaCodeStyleManager.shortenClassReferences(file);
+          }
+        }
       }
     };
     processor.run();
index c7086fc455d8b9e927116329cb9fb290160ea2ca..3f184ea5064094da46bce0f28157f8286ad20a41 100644 (file)
@@ -85,8 +85,7 @@ public class PsiIntersectionType extends PsiType.Stub {
         for (PsiType existing : array) {
           if (type != existing) {
             final boolean allowUncheckedConversion = type instanceof PsiClassType && ((PsiClassType)type).isRaw();
-            if (TypeConversionUtil.isAssignable(type, existing, allowUncheckedConversion) ||
-                TypeConversionUtil.isAssignable(GenericsUtil.eliminateWildcards(type), GenericsUtil.eliminateWildcards(existing), allowUncheckedConversion)) {
+            if (TypeConversionUtil.isAssignable(type, existing, allowUncheckedConversion)) {
               iterator.remove();
               break;
             }
index 0ae0fd87a5f8f42fe4b009fc0ccf8627ffea4113..88012cfaa3ed5d4e53bb5b51c8f41f47093a8860 100644 (file)
@@ -259,6 +259,9 @@ public class TypesDistinctProver {
     else if (bound instanceof PsiWildcardType) {
       final PsiType boundBound = ((PsiWildcardType)bound).getBound();
       if (boundBound != null && !boundBound.equals(type)) {
+        if (boundBound instanceof PsiArrayType && !((PsiWildcardType)bound).isSuper()) {
+          return proveArrayTypeDistinct(type, boundBound);
+        }
         final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(boundBound);
         if (psiClass == null) {
           return true;
index 40bf53507b54427f3aec125e1def98842b34a4e6..edf53a6179b9d8f1dcb2db57694133bff34f62a7 100644 (file)
@@ -177,16 +177,19 @@ public class FunctionalInterfaceParameterizationUtil {
       for (int i = 0; i < parameters.length; i++) {
         PsiType paramType = parameters[i];
         if (paramType instanceof PsiWildcardType) {
-          final PsiType bound = GenericsUtil.eliminateWildcards(((PsiWildcardType)paramType).getBound(), false, false);
+          for (PsiClassType paramBound : typeParameters[i].getExtendsListTypes()) {
+            if (PsiPolyExpressionUtil.mentionsTypeParameters(paramBound, typeParametersSet)) {
+              return null;
+            }
+          }
+          final PsiType bound = ((PsiWildcardType)paramType).getBound();
           if (((PsiWildcardType)paramType).isSuper()) {
             newParameters[i] = bound;
           }
           else {
             newParameters[i] = bound != null ? bound : PsiType.getJavaLangObject(psiClass.getManager(), psiClassType.getResolveScope());
             for (PsiClassType paramBound : typeParameters[i].getExtendsListTypes()) {
-              if (!PsiPolyExpressionUtil.mentionsTypeParameters(paramBound, typeParametersSet)) {
-                newParameters[i] = GenericsUtil.getGreatestLowerBound(newParameters[i], paramBound);
-              }
+              newParameters[i] = GenericsUtil.getGreatestLowerBound(newParameters[i], paramBound);
             }
           }
         } else {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ProvablyDistinctForWildcardsWithArrayBounds.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ProvablyDistinctForWildcardsWithArrayBounds.java
new file mode 100644 (file)
index 0000000..c5d62f1
--- /dev/null
@@ -0,0 +1,9 @@
+class Test {
+  public static <T> void fooBar(final Class<?> aClass,
+                                final Class<? super Number[]> aSuperClass,
+                                final Class<? extends Number[]> anExtendsClass) {
+    Class<T[]> klazz = (Class<T[]>) aClass;
+               klazz = <error descr="Inconvertible types; cannot cast 'java.lang.Class<capture<? super java.lang.Number[]>>' to 'java.lang.Class<T[]>'">(Class<T[]>) aSuperClass</error>;
+               klazz = (Class<T[]>) anExtendsClass;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/EliminateIntersectionTypeWildcardElimination.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/EliminateIntersectionTypeWildcardElimination.java
new file mode 100644 (file)
index 0000000..8bd1bb5
--- /dev/null
@@ -0,0 +1,13 @@
+import java.util.Map;
+
+class Main {
+
+  public static <T extends Map<? extends String, ? extends String>> T test() {
+    return null;
+  }
+
+  public static void main(String[] args) {
+    Map<String, String> m = Main.test();
+  }
+}
+
index fa9df550e9361086b8335552bd2f2f8f08c83b18..55ba03955d9a189244bfcb7d4bd3e36320593db3 100644 (file)
@@ -7,16 +7,16 @@ class SimpleDependency  {
   }
 
   {
-    I<? extends String, ? extends  String> k = () -> null;
-    I<? extends String, String> k1 = () -> null;
-    I<? extends List<String>, List<String>> k2 = () -> null;
-    I<? extends List<String>, ? extends List<String>> k3 = () -> null;
+    I<? extends String, ? extends  String> k = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends String, String> k1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<String>, List<String>> k2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<String>, ? extends List<String>> k3 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends List<? extends String>, ? extends List<String>> k4 = <error descr="Cannot infer functional interface type">() -> null</error>;
-    I<? extends List<? extends String>, List<? extends String>> k5 = () -> null;
-    I<? extends List<? extends String>, ? extends List<? extends String>> k6 = () -> null;
+    I<? extends List<? extends String>, List<? extends String>> k5 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<? extends String>, ? extends List<? extends String>> k6 = <error descr="Cannot infer functional interface type">() -> null</error>;
 
-    I<? super String, String> s = () -> null;
-    I<? super List<String>, List<? extends String>> s1 = () -> null;
+    I<? super String, String> s = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? super List<String>, List<? extends String>> s1 = <error descr="Cannot infer functional interface type">() -> null</error>;
   }
 }
 
@@ -43,11 +43,11 @@ class ExtendsList {
 
     I<? extends List<?>, String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends List<?>, ?> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
-    I<? extends List<String>, ? extends String> e3 = () -> null;
+    I<? extends List<String>, ? extends String> e3 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends List<? extends String>, ? extends String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
 
-    I<? super List<String>, ? extends String> s1 = () -> null;
-    I<? super List<String>, String> s2 = () -> null;
+    I<? super List<String>, ? extends String> s1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? super List<String>, String> s2 = <error descr="Cannot infer functional interface type">() -> null</error>;
   }
 }
 
@@ -63,8 +63,8 @@ class MultipleBounds {
 
     I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
-    I<? extends LC<String>, ? extends String> e3 = () -> null;
-    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<String>, ? extends String> e3 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
   }
 }
@@ -80,9 +80,9 @@ class FirstIndependentBound {
     I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
 
     I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
-    I<? extends Comparable<String>, ? extends String> e2 = () -> null;
-    I<? extends LC<String>, ? extends String> e3 = () -> null;
-    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, ? extends String> e3 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
   }
 }
@@ -98,10 +98,10 @@ class SecondIndependentBound {
   {
     I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
 
-    I<? extends List<String>, ? extends String> e1 = () -> null;
+    I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
-    I<? extends LC<String>, ? extends String> e3 = () -> null;
-    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<String>, ? extends String> e3 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
     I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">()  -> null</error>;
     I<? extends LC<? extends String>, ? extends String> e6 = <error descr="Cannot infer functional interface type">()  -> null</error>;
   }
diff --git a/java/java-tests/testData/codeInsight/slice/backward/TryCatchFinally.java b/java/java-tests/testData/codeInsight/slice/backward/TryCatchFinally.java
new file mode 100644 (file)
index 0000000..df38d98
--- /dev/null
@@ -0,0 +1,17 @@
+package x;
+
+class X {
+  void f(Throwable p) {
+    Throwable error = <flown1>null;
+
+    try {
+      f(p);
+    }
+    catch (Throwable <flown21>e) {
+      error = <flown2>e;
+    }
+    finally {
+      f(<caret>error);
+    }
+  }
+}
\ No newline at end of file
index dba68689d646f3434a95be7b35a73d28b4c7c171..22f93eb08f538c906f6d3948359db315350237f5 100644 (file)
@@ -536,6 +536,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
     doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
   }
 
+  public void testProvablyDistinctForWildcardsWithArrayBounds() throws Exception {
+    doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
+  }
+
   public void testJavaUtilCollections_NoVerify() throws Exception {
     PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
     assertNotNull(collectionsClass);
index 580cae3595d950b47988ed13b33ff765ac07ad80..ecb4270d735c193149ecb965604a5ed8ff0d5aea 100644 (file)
@@ -331,6 +331,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
     doTest();
   }
 
+  public void testEliminateIntersectionTypeWildcardElimination() throws Exception {
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest(false);
   }
index 44ca10bc82973e9a4237f6b1e8dc426f39efbc04..0d169020bcaf47918073847b0f61badd6c7776c3 100644 (file)
@@ -35,6 +35,7 @@ import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.util.ProgressIndicatorBase;
 import com.intellij.openapi.project.DumbServiceImpl;
 import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.ProperTextRange;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
@@ -75,6 +76,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
+import static com.intellij.find.impl.FindInProjectUtil.buildStringToFindForIndicesFromRegExp;
+import static com.intellij.find.impl.FindInProjectUtil.createFileMaskCondition;
+
 /**
  * @author MYakovlev
  * @since Oct 17, 2002
@@ -95,7 +99,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
     super.tearDown();
   }
 
-  public void testFindString() {
+  public void testFindString() throws InterruptedException {
     FindModel findModel = FindManagerTestUtils.configureFindModel("done");
 
     String text = "public static class MyClass{\n/*done*/\npublic static void main(){}}";
@@ -145,7 +149,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
     findModel.setProjectScope(true);
 
     final FindResult[] findResultArr = new FindResult[1];
-    findInNewThread(findModel, myFindManager, text, 0, findResultArr);
+    Thread thread = findInNewThread(findModel, myFindManager, text, 0, findResultArr);
     new WaitFor(30 *1000){
       @Override
       protected boolean condition() {
@@ -154,6 +158,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
     }.assertCompleted();
 
     assertFalse(findResultArr[0].isStringFound());
+    thread.join();
   }
 
   private static Thread findInNewThread(final FindModel model,
@@ -842,6 +847,22 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
     assertSize(0, findUsages(findModel));
   }
 
+  public void testRegexReplacementStringForIndices() {
+    assertEquals("public static   MyType my   = 1;", buildStringToFindForIndicesFromRegExp("public static (@A)? MyType my\\w+?  = 1;", myProject));
+    assertEquals(" Foo ", buildStringToFindForIndicesFromRegExp("\\bFoo\\b", myProject));
+    assertEquals("", buildStringToFindForIndicesFromRegExp("foo|bar", myProject));
+  }
+
+  public void testCreateFileMaskCondition() {
+    final Condition<String> condition = createFileMaskCondition("*.java, *.js, !Foo.java, !*.min.js");
+    assertTrue(condition.value("Bar.java"));
+    assertTrue(!condition.value("Bar.javac"));
+    assertTrue(!condition.value("Foo.java"));
+    assertTrue(!condition.value("Foo.jav"));
+    assertTrue(!condition.value("Foo.min.js"));
+    assertTrue(condition.value("Foo.js"));
+  }
+
   public void testRegExpSearchDoesCheckCancelled() throws InterruptedException {
     String text = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
     FindModel findModel = FindManagerTestUtils.configureFindModel("(x+x+)+y");
index f04dc8491ec9d01d19e984028d249f7661038207..2274af5b711ae731b933d4b6b95afa4310401d20 100644 (file)
@@ -34,7 +34,6 @@ import com.intellij.psi.impl.source.PsiFileImpl;
 import com.intellij.testFramework.LeakHunter;
 import com.intellij.testFramework.PlatformTestCase;
 import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
-import com.intellij.util.Processor;
 
 public class LoadProjectTest extends PlatformTestCase {
   @Override
@@ -82,12 +81,8 @@ public class LoadProjectTest extends PlatformTestCase {
     FileEditorManager.getInstance(getProject()).closeFile(b);
     ProjectManagerEx.getInstanceEx().closeAndDispose(getProject());
 
-    LeakHunter.checkLeak(ApplicationManager.getApplication(), PsiFileImpl.class, new Processor<PsiFileImpl>() {
-      @Override
-      public boolean process(PsiFileImpl psiFile) {
-        return  psiFile.getViewProvider().getVirtualFile().getFileSystem() instanceof LocalFileSystem;
-      }
-    });
+    LeakHunter.checkLeak(ApplicationManager.getApplication(), PsiFileImpl.class,
+                         psiFile -> psiFile.getViewProvider().getVirtualFile().getFileSystem() instanceof LocalFileSystem);
   }
 
   @Override
index 5e2f89a10f3c6088c42049f938d62f3af9bb3261..94d71a667e7ae4c1e3d768f1df3678f42c8fc0a0 100644 (file)
@@ -110,15 +110,9 @@ public class PsiConcurrencyStressTest extends DaemonAnalyzerTestCase {
     }
 
     assertTrue("Timed out", reads.await(5, TimeUnit.MINUTES));
-    ContainerUtil.process(threads, thread -> {
-      try {
-        thread.join();
-        return true;
-      }
-      catch (InterruptedException e) {
-        throw new RuntimeException(e);
-      }
-    });
+    for (Thread thread : threads) {
+      thread.join();
+    }
   }
 
   private static void mark(final String s) {
index 8e76bf4cb914388d7b7a67ee678255882b1f1066..c9f8d7e760017bd1541bc41fede3b4636bd7d51e 100644 (file)
@@ -15,9 +15,7 @@
  */
 package com.intellij.psi.impl.file.impl;
 
-import com.intellij.ide.IdeEventQueue;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.impl.LaterInvocator;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -193,9 +191,7 @@ public class PsiEventsTest extends PsiTestCase {
           return directory.getVirtualFile().equals(myPrjDir1);
         }
       };
-      LeakHunter.checkLeak(ApplicationManager.getApplication(), PsiDirectory.class, isReallyLeak);
-      LeakHunter.checkLeak(IdeEventQueue.getInstance(), PsiDirectory.class, isReallyLeak);
-      LeakHunter.checkLeak(LaterInvocator.getLaterInvocatorQueue(), PsiDirectory.class, isReallyLeak);
+      LeakHunter.checkLeak(LeakHunter.allRoots(), PsiDirectory.class, isReallyLeak);
 
       String dumpPath = FileUtil.createTempFile(
         new File(System.getProperty("teamcity.build.tempDir", System.getProperty("java.io.tmpdir"))), "testRenameFileWithoutDir", ".hprof",
@@ -792,7 +788,7 @@ public class PsiEventsTest extends PsiTestCase {
     assertTrue(documentManager.isCommitted(document));
   }
 
-  private void checkCommitted(boolean shouldBeCommitted, PsiTreeChangeEvent event) {
+  private static void checkCommitted(boolean shouldBeCommitted, PsiTreeChangeEvent event) {
     PsiFile file = event.getFile();
     PsiDocumentManager documentManager = PsiDocumentManager.getInstance(file.getProject());
     Document document = documentManager.getDocument(file);
index 8d8638dc02d4bff475ca0fd8681afa7a34282ec7..edfa73b4a5cec182e8a7e0618989434393d530eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -17,23 +17,14 @@ package com.intellij.slicer;
 
 import com.intellij.analysis.AnalysisScope;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.editor.RangeMarker;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.CommonProcessors;
 import com.intellij.util.containers.IntArrayList;
-import gnu.trove.THashMap;
 import gnu.trove.TIntObjectHashMap;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.Map;
 
 /**
  * @author cdr
@@ -89,4 +80,5 @@ public class SliceBackwardTest extends SliceTestCase {
   public void testVarArgsPartial() throws Exception { doTest();}
 
   public void testListTrackToArray() throws Exception { doTest();}
+  public void testTryCatchFinally() throws Exception { doTest();}
 }
index 0fd721002f4c929ea57bd49953d5d81ff761476b..b04d40638052e17b0d1f0766e04b06ef31461de0 100644 (file)
@@ -31,7 +31,15 @@ public class TypeMigrationVariableTypeFixProvider implements ChangeVariableTypeQ
   }
 
   @NotNull
-  public static VariableTypeFix createTypeMigrationFix(@NotNull final PsiVariable variable, @NotNull final PsiType toReturn) {
+  public static VariableTypeFix createTypeMigrationFix(@NotNull final PsiVariable variable,
+                                                       @NotNull final PsiType toReturn) {
+    return createTypeMigrationFix(variable, toReturn, false);
+  }
+
+  @NotNull
+  public static VariableTypeFix createTypeMigrationFix(@NotNull final PsiVariable variable,
+                                                       @NotNull final PsiType toReturn,
+                                                       final boolean optimizeImports) {
     return new VariableTypeFix(variable, toReturn) {
       @NotNull
       @Override
@@ -45,7 +53,7 @@ public class TypeMigrationVariableTypeFixProvider implements ChangeVariableTypeQ
                          @Nullable("is null when called from inspection") Editor editor,
                          @NotNull PsiElement startElement,
                          @NotNull PsiElement endElement) {
-        runTypeMigrationOnVariable((PsiVariable)startElement, getReturnType(), editor);
+        runTypeMigrationOnVariable((PsiVariable)startElement, getReturnType(), editor, optimizeImports);
       }
 
       @Override
@@ -57,7 +65,8 @@ public class TypeMigrationVariableTypeFixProvider implements ChangeVariableTypeQ
 
   public static void runTypeMigrationOnVariable(@NotNull PsiVariable variable,
                                                 @NotNull PsiType targetType,
-                                                @Nullable("is null when called from inspection") Editor editor) {
+                                                @Nullable("is null when called from inspection") Editor editor,
+                                                boolean optimizeImports) {
     Project project = variable.getProject();
     if (!FileModificationService.getInstance().prepareFileForWrite(variable.getContainingFile())) return;
     try {
@@ -65,7 +74,7 @@ public class TypeMigrationVariableTypeFixProvider implements ChangeVariableTypeQ
       final TypeMigrationRules rules = new TypeMigrationRules(TypeMigrationLabeler.getElementType(variable));
       rules.setMigrationRootType(targetType);
       rules.setBoundScope(GlobalSearchScope.projectScope(project));
-      TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, variable);
+      TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, variable, optimizeImports);
       JavaCodeStyleManager.getInstance(project).shortenClassReferences(variable);
       UndoUtil.markPsiFileForUndo(variable.getContainingFile());
     }
index 439c34666198a2a6ae462a300ff6b96dcb87da57..b08aca469a9062c9d8568df125771d781aefdc44 100644 (file)
@@ -118,11 +118,11 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
       public void visitVariable(PsiVariable variable) {
         if (!checkVariables) return;
         final PsiType type = variable.getType();
-        final PsiClassType targetType = getConversionClassType(type);
+        PsiType targetType = getConversionClassType(type);
         if (targetType != null) {
           holder.registerProblem(variable,
                                  PROBLEM_DESCRIPTION_FOR_VARIABLE,
-                                 TypeMigrationVariableTypeFixProvider.createTypeMigrationFix(variable, targetType));
+                                 TypeMigrationVariableTypeFixProvider.createTypeMigrationFix(variable, targetType, true));
         }
       }
 
@@ -130,7 +130,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
       public void visitMethod(PsiMethod method) {
         super.visitMethod(method);
         if (!checkReturnTypes) return;
-        final PsiClassType targetType = getConversionClassType(method.getReturnType());
+        final PsiType targetType = getConversionClassType(method.getReturnType());
         if (targetType != null) {
           final PsiTypeElement typeElement = method.getReturnTypeElement();
           if (typeElement != null) {
@@ -172,15 +172,18 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
         holder.registerProblem(chain, PROBLEM_DESCRIPTION_FOR_METHOD_CHAIN, new MigrateFluentIterableChainQuickFix(chain, initialType, targetType));
       }
 
-      private PsiClassType getConversionClassType(PsiType initialType) {
-        if (initialType instanceof PsiClassType) {
-          final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)initialType).resolveGenerics();
+      private PsiType getConversionClassType(PsiType initialType) {
+        if (initialType == null) return null;
+        final PsiType type = initialType.getDeepComponentType();
+        if (type instanceof PsiClassType) {
+          final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
           final PsiClass psiClass = resolveResult.getElement();
           if (psiClass != null) {
             final String qName = psiClass.getQualifiedName();
             final PsiClass targetClass = myGuavaClassConversions.getValue().get(qName);
             if (targetClass != null) {
-              return addTypeParameters(initialType, resolveResult, targetClass);
+              final PsiClassType createdType = addTypeParameters(type, resolveResult, targetClass);
+              return initialType instanceof PsiArrayType ? new PsiArrayType(createdType) : createdType;
             }
           }
         }
@@ -220,6 +223,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
         }
       }
 
+      @NotNull
       private PsiClassType addTypeParameters(PsiType currentType, PsiClassType.ClassResolveResult currentTypeResolveResult, PsiClass targetClass) {
         final Map<PsiTypeParameter, PsiType> substitutionMap = currentTypeResolveResult.getSubstitutor().getSubstitutionMap();
         final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(holder.getProject());
@@ -330,9 +334,9 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
 
   public static class MigrateMethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement {
 
-    private final PsiClassType myTargetType;
+    private final PsiType myTargetType;
 
-    private MigrateMethodReturnTypeFix(@NotNull PsiMethod method, PsiClassType targetType) {
+    private MigrateMethodReturnTypeFix(@NotNull PsiMethod method, PsiType targetType) {
       super(method);
       myTargetType = targetType;
     }
@@ -349,7 +353,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
         final TypeMigrationRules rules = new TypeMigrationRules(TypeMigrationLabeler.getElementType(method));
         rules.setMigrationRootType(myTargetType);
         rules.setBoundScope(method.getUseScope());
-        TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, method);
+        TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, method, true);
         UndoUtil.markPsiFileForUndo(file);
       }
       catch (IncorrectOperationException e) {
index 8062e6baabba1b40aa2da0532e759953b5d79524..5b30001450ad261a7e5a741163c1576f79421727 100644 (file)
@@ -18,9 +18,7 @@ package com.intellij.refactoring.typeMigration.intentions;
 import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
 import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiTypesUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.refactoring.typeMigration.TypeMigrationVariableTypeFixProvider;
@@ -43,7 +41,7 @@ public class ConvertAtomicToLongAdderIntention extends PsiElementBaseIntentionAc
     if (variable != null) {
       final PsiType longAdder =
         JavaPsiFacade.getElementFactory(project).createTypeFromText(LongAdderConversionRule.JAVA_UTIL_CONCURRENT_ATOMIC_LONG_ADDER, element);
-      TypeMigrationVariableTypeFixProvider.runTypeMigrationOnVariable(variable, longAdder, null);
+      TypeMigrationVariableTypeFixProvider.runTypeMigrationOnVariable(variable, longAdder, null, false);
     }
   }
 
index 4129b61725346b10919f2545d6a3a53138419457..6392f28fb69b5a12b78d6fbed48fdeec91b124d9 100644 (file)
@@ -80,6 +80,8 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule {
     if (member instanceof PsiMethod) {
       PsiMethod method = (PsiMethod)member;
       final String methodName = method.getName();
+      final PsiClass aClass = method.getContainingClass();
+      if (!isValidMethodQualifierToConvert(aClass)) return null;
       final TypeConversionDescriptorBase descriptor = mySimpleDescriptors.getValue().get(methodName);
       if (descriptor != null) {
         return descriptor;
@@ -105,10 +107,14 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule {
     return null;
   }
 
-  public static boolean canConvert(@Nullable PsiType from,
-                                   @Nullable  PsiType to,
-                                   @NotNull String fromClassName,
-                                   @NotNull String toClassName) {
+  protected boolean isValidMethodQualifierToConvert(PsiClass aClass) {
+    return aClass != null && ruleFromClass().equals(aClass.getQualifiedName());
+  }
+
+  static boolean canConvert(@Nullable PsiType from,
+                            @Nullable PsiType to,
+                            @NotNull String fromClassName,
+                            @NotNull String toClassName) {
     if (!(from instanceof PsiClassType)) {
       return false;
     }
index 5984e69c83e60527b3e3b23bcdb8b7bbfabb0741..41f7cae3c9262a49765fdfc02c6d0b100d65d5a8 100644 (file)
@@ -110,6 +110,12 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu
     DESCRIPTORS_MAP.put("toSortedSet", new TypeConversionDescriptorFactory("$it$.toSortedSet($c$)", "$it$.sorted($c$).collect(java.util.stream.Collectors.toSet())", false));
   }
 
+  @Override
+  protected boolean isValidMethodQualifierToConvert(PsiClass aClass) {
+    return super.isValidMethodQualifierToConvert(aClass) ||
+           (aClass != null && GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(aClass.getQualifiedName()));
+  }
+
   @Nullable
   @Override
   protected TypeConversionDescriptorBase findConversionForMethod(@NotNull PsiType from,
index 9a9fb5ec4c290b7f1b7257845bbb6c79ac5d78bf..7fb5ed6bd1ec47aad7b4d16b6b662d7bdfeb4a68 100644 (file)
@@ -103,6 +103,12 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule {
     return GuavaFluentIterableConversionRule.buildCompoundDescriptor((PsiMethodCallExpression) context, to, labeler);
   }
 
+  @Override
+  protected boolean isValidMethodQualifierToConvert(PsiClass aClass) {
+    return super.isValidMethodQualifierToConvert(aClass) ||
+           (aClass != null && GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(aClass.getQualifiedName()));
+  }
+
   @Nullable
   @Override
   protected TypeConversionDescriptorBase findConversionForVariableReference(@NotNull PsiReferenceExpression referenceExpression,
index 8ac65d0a2ae891a55da40bdfe5563a8862e4b3d3..3a3894b5e95696dfeaac470cfc93b453fcfd5383 100644 (file)
@@ -202,6 +202,10 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
     doTest();
   }
 
+  public void testMigrateArrays() {
+    doTest();
+  }
+
   private void doTestNoQuickFixes(final Class<? extends IntentionAction>... quickFixesClasses) {
     myFixture.configureByFile(getTestName(true) + ".java");
     myFixture.enableInspections(new GuavaInspection());
index 29b3b2a4bbdd105302db4b003c83088e63c65243..63dbc4d144f19553ce949c81ed1b841bccca67ad 100644 (file)
@@ -1,4 +1,5 @@
 import java.util.ArrayList;
+import java.util.Optional;
 import java.util.stream.Stream;
 
 public class Main {
@@ -6,7 +7,7 @@ public class Main {
     return new ArrayList<String>().stream().map(s -> s + s);
   }
 
-  java.util.Optional<String> m2() {
+  Optional<String> m2() {
     return m1().filter(s -> s.indexOf('s') == 123).findFirst();
   }
 
index 4dcc7384d44d19cf8afe0d2f2d510292323495b0..d6f0846d5adb05090b0f2d37d9b85b0bad857ab3 100644 (file)
@@ -1,7 +1,5 @@
 import com.google.common.base.Function;
 
-import static com.google.common.collect.FluentIterable.from
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
diff --git a/java/typeMigration/testData/inspections/guava/migrateArrays.java b/java/typeMigration/testData/inspections/guava/migrateArrays.java
new file mode 100644 (file)
index 0000000..e0ebde5
--- /dev/null
@@ -0,0 +1,6 @@
+import com.google.common.base.Optional;
+public class SubOrder {
+  public void useArray(Opti<caret>onal<String>[] pa) {
+    Optional<String> v = pa[0];
+  }
+}
\ No newline at end of file
diff --git a/java/typeMigration/testData/inspections/guava/migrateArrays_after.java b/java/typeMigration/testData/inspections/guava/migrateArrays_after.java
new file mode 100644 (file)
index 0000000..0d56f5a
--- /dev/null
@@ -0,0 +1,7 @@
+import java.util.Optional;
+
+public class SubOrder {
+  public void useArray(Optional<String>[] pa) {
+    Optional<String> v = pa[0];
+  }
+}
\ No newline at end of file
index 4ca032234920167b3b5a44d55616d1767633ac22..a3900e2edffdf44a72c81fee03dae4760ab73387 100644 (file)
@@ -3,14 +3,14 @@ import java.util.Optional;
 
 class A {
 
-  java.util.Optional<String> m1() {
+  Optional<String> m1() {
     Optional<String> o = Optional.empty();
     String s = o.get();
     return o;
   }
 
   void w1() {
-    java.util.Optional<String> someVar = m1();
+    Optional<String> someVar = m1();
     System.out.println(someVar.get());
     System.out.println(someVar.isPresent() ? Collections.singleton(someVar.get()) : Collections.emptySet());
   }
index 71d6cb3509f4f43c136e2ac9ae328d9a10d61a92..c365debc0ab190274dc7d5cba83ba167fc7e0b55 100644 (file)
@@ -1,7 +1,9 @@
 import com.google.common.base.Function;
 
+import java.util.Optional;
+
 class Transformer {
-  public java.util.Optional<String> transform(java.util.Optional<Integer> p1, Function<Integer, String> p2) {
+  public Optional<String> transform(Optional<Integer> p1, Function<Integer, String> p2) {
     return p1.map(p2::apply);
   }
 }
\ No newline at end of file
index cfc3a77c9693ce7bf051b2a15ab7a2311d013d62..f49a53b3d9bf24d5fcfe73b13df3e6a686a89adb 100644 (file)
@@ -3,7 +3,7 @@ import com.google.common.base.Function;
 import java.util.Optional;
 
 class A {
-  public java.util.Optional<String> transform(Optional<Integer> p1) {
+  public Optional<String> transform(Optional<Integer> p1) {
     return p1.map(new MyFunction()::apply);
   }
 
index 83af339185e16db8e84df69362543a8c0ab01120..d0a8e242c814b94950db6e23576cb53f5ca97dba 100644 (file)
@@ -1,7 +1,8 @@
+import java.util.Optional;
 import java.util.function.Supplier;
 
 public class OptionSupply {
-  public void ors(java.util.Optional<String> p1, Supplier<String> p3) {
+  public void ors(Optional<String> p1, Supplier<String> p3) {
     String v = p1.orElseGet(p3);
   }
 }
\ No newline at end of file
index 7a5a52322580f601cbc33c1312bdb7bb3a939383..ec3eb8f45c4a81a74ff538b031c509aa6517a07d 100644 (file)
@@ -1,4 +1,5 @@
 import java.util.ArrayList;
+import java.util.Optional;
 
 public class Main8 {
 
@@ -6,7 +7,7 @@ public class Main8 {
     String value = getOptional().orElse(null);
   }
 
-  java.util.Optional<String> getOptional() {
+  Optional<String> getOptional() {
     return new ArrayList<String>().stream().map(x -> x + x).filter(String::isEmpty).findFirst();
   }
 }
\ No newline at end of file
index 15e86a6a6f612ed6308ada7933bcec03e70173d3..e278a0117b878468a041addbfb4625cb3eb0f47e 100644 (file)
@@ -1,7 +1,7 @@
 import java.util.Optional;
 
 class SecondChoice {
-  public void ors(Optional<String> p1, java.util.Optional<String> p2) {
-    java.util.Optional<String> o = java.util.Optional.ofNullable(p1.orElseGet(p2::get));
+  public void ors(Optional<String> p1, Optional<String> p2) {
+    Optional<String> o = Optional.ofNullable(p1.orElseGet(p2::get));
   }
 }
\ No newline at end of file
index 29f0a79b06662fa3e52a9e3f04617d5fe8b90b4c..2335049b97177004dbdeb048af8c8ff48fc95cb4 100644 (file)
@@ -153,8 +153,7 @@ public class VirtualFilePointerContainerImpl extends TraceableDisposable impleme
     assert !myDisposed;
     dropCaches();
 
-    List<VirtualFilePointer> thatList = ((VirtualFilePointerContainerImpl)that).myList;
-    for (final VirtualFilePointer pointer : thatList) {
+    for (final VirtualFilePointer pointer : that.getList()) {
       myList.add(duplicate(pointer));
     }
   }
index 24ba444b816d3f8dc5b2edc0a064f9f6d08661d8..130cb9ce0df6a88f6592f1e194b95c1afebc7b04 100644 (file)
  */
 package com.intellij.util;
 
+import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.UserDataHolder;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.DebugReflectionUtil.BackLink;
 import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.lang.reflect.Field;
 import java.util.Set;
@@ -31,26 +40,48 @@ import java.util.Set;
 class CachedValueChecker {
   private static final Logger LOG = Logger.getInstance("#com.intellij.util.CachedValueChecker");
   private static final boolean DO_CHECKS = ApplicationManager.getApplication().isUnitTestMode();
-  private static Set<Class> ourCheckedClasses = ContainerUtil.newConcurrentSet();
+  private static final Set<String> ourCheckedKeys = ContainerUtil.newConcurrentSet();
 
-  static void checkProvider(CachedValueProvider provider, UserDataHolder userDataHolder) {
+  static void checkProvider(@NotNull final CachedValueProvider provider,
+                            @NotNull final Key key,
+                            @NotNull final UserDataHolder userDataHolder) {
     if (!DO_CHECKS) return;
+    if (!ourCheckedKeys.add(key.toString())) return; // store strings because keys are created afresh in each (test) project
 
-    Class<? extends CachedValueProvider> providerClass = provider.getClass();
-    if (!ourCheckedClasses.add(providerClass)) return;
+    Set<Object> visited = ContainerUtil.newIdentityTroveSet();
+    BackLink path = findReferencedPsi(provider, userDataHolder, 6, visited, null);
+    if (path != null) {
+      LOG.error("Incorrect CachedValue use. Provider references PSI, causing memory leaks and possible invalid element access, provider=" +
+                provider + "\n" + path);
+    }
+  }
 
-    for (Field field : providerClass.getDeclaredFields()) {
-      try {
-        field.setAccessible(true);
-        Object o = field.get(provider);
-        if (o instanceof PsiElement && o != userDataHolder) {
-          LOG.error("Incorrect CachedValue use. Provider references PSI, causing memory leaks and possible invalid element access: field " + field.getName() + " of " + provider);
-          return;
-        }
-      }
-      catch (IllegalAccessException e) {
-        LOG.error(e);
+  @Nullable
+  private static synchronized BackLink findReferencedPsi(@NotNull Object o,
+                                                         @Nullable final UserDataHolder toIgnore,
+                                                         final int depth,
+                                                         @NotNull final Set<Object> visited,
+                                                         @Nullable final BackLink backLink) {
+    if (depth == 0 || o == toIgnore || !visited.add(o)) return null;
+    if (o instanceof Project || o instanceof Module || o instanceof Application) return null;
+    if (o instanceof PsiElement) {
+      if (toIgnore instanceof PsiElement &&
+          ((PsiElement)toIgnore).getContainingFile() != null &&
+          PsiTreeUtil.isAncestor((PsiElement)o, (PsiElement)toIgnore, true)) {
+        // allow to capture PSI parents, assuming that they stay valid at least as long as the element itself
+        return null;
       }
+      return backLink;
     }
+
+    final Ref<BackLink> result = Ref.create();
+    DebugReflectionUtil.processStronglyReferencedValues(o, new PairProcessor<Object, Field>() {
+      @Override
+      public boolean process(Object next, Field field) {
+        result.set(findReferencedPsi(next, toIgnore, depth - 1, visited, new BackLink(next, field, backLink)));
+        return result.isNull();
+      }
+    });
+    return result.get();
   }
 }
index 9253688da18ea418daecbd2a0cdace16eec836a6..3b9016e74677d0b8ba6948e743d3d762e8fca725 100644 (file)
@@ -54,7 +54,7 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
                                                         @NotNull Key<CachedValue<T>> key,
                                                         @NotNull CachedValueProvider<T> provider,
                                                         boolean trackValue) {
-    CachedValueChecker.checkProvider(provider, dataHolder);
+    CachedValueChecker.checkProvider(provider, key, dataHolder);
     CachedValue<T> value;
     if (dataHolder instanceof UserDataHolderEx) {
       UserDataHolderEx dh = (UserDataHolderEx)dataHolder;
diff --git a/platform/core-impl/src/com/intellij/util/DebugReflectionUtil.java b/platform/core-impl/src/com/intellij/util/DebugReflectionUtil.java
new file mode 100644 (file)
index 0000000..21f9331
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2000-2015 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.util;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.concurrency.AtomicFieldUpdater;
+import com.intellij.util.containers.FList;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import sun.misc.Unsafe;
+
+import java.lang.ref.Reference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class DebugReflectionUtil {
+  private static final Map<Class, Field[]> allFields = new THashMap<Class, Field[]>();
+  private static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
+  private static final Method Unsafe_shouldBeInitialized = ReflectionUtil.getDeclaredMethod(Unsafe.class, "shouldBeInitialized", Class.class);
+
+  @NotNull
+  private static Field[] getAllFields(@NotNull Class aClass) {
+    Field[] cached = allFields.get(aClass);
+    if (cached == null) {
+      try {
+        Field[] declaredFields = aClass.getDeclaredFields();
+        List<Field> fields = new ArrayList<Field>(declaredFields.length + 5);
+        for (Field declaredField : declaredFields) {
+          declaredField.setAccessible(true);
+          Class<?> type = declaredField.getType();
+          if (isTrivial(type)) continue; // unable to hold references, skip
+          fields.add(declaredField);
+        }
+        Class superclass = aClass.getSuperclass();
+        if (superclass != null) {
+          for (Field sup : getAllFields(superclass)) {
+            if (!fields.contains(sup)) {
+              fields.add(sup);
+            }
+          }
+        }
+        cached = fields.isEmpty() ? EMPTY_FIELD_ARRAY : fields.toArray(new Field[fields.size()]);
+      }
+      catch (IncompatibleClassChangeError e) {
+        //this exception may be thrown because there are two different versions of org.objectweb.asm.tree.ClassNode from different plugins
+        //I don't see any sane way to fix it until we load all the plugins by the same classloader in tests
+        cached = EMPTY_FIELD_ARRAY;
+      }
+      catch (SecurityException e) {
+        cached = EMPTY_FIELD_ARRAY;
+      }
+      catch (NoClassDefFoundError e) {
+        cached = EMPTY_FIELD_ARRAY;
+      }
+
+      allFields.put(aClass, cached);
+    }
+    return cached;
+  }
+
+  private static boolean isTrivial(@NotNull Class<?> type) {
+    return type.isPrimitive() || type == String.class || type == Class.class || type.isArray() && isTrivial(type.getComponentType());
+  }
+
+  public static boolean processStronglyReferencedValues(@NotNull Object root, PairProcessor<Object, Field> processor) {
+    Class rootClass = root.getClass();
+    for (Field field : getAllFields(rootClass)) {
+      String fieldName = field.getName();
+      if (root instanceof Reference && "referent".equals(fieldName)) continue; // do not follow weak/soft refs
+      Object value;
+      try {
+        value = field.get(root);
+      }
+      catch (IllegalArgumentException e) {
+        throw new RuntimeException(e);
+      }
+      catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      }
+      if (value == null) continue;
+      if (!processor.process(value, field)) return false;
+    }
+    if (rootClass.isArray()) {
+      try {
+        //noinspection ConstantConditions
+        for (Object o : (Object[])root) {
+          if (o == null) continue;
+          if (isTrivial(o.getClass())) continue;
+          if (!processor.process(o, null)) return false;
+        }
+      }
+      catch (ClassCastException ignored) {
+      }
+    }
+    // check for objects leaking via static fields. process classes which already were initialized only
+    if (root instanceof Class && isLoadedAlready((Class)root)) {
+      try {
+        for (Field field : getAllFields((Class)root)) {
+          if ((field.getModifiers() & Modifier.STATIC) == 0) continue;
+          Object value = field.get(null);
+          if (value == null) continue;
+          if (!processor.process(value, field)) return false;
+        }
+      }
+      catch (IllegalAccessException ignored) {
+      }
+    }
+    return true;
+  }
+
+  private static boolean isLoadedAlready(Class root) {
+    if (Unsafe_shouldBeInitialized == null) return false;
+    boolean isLoadedAlready = false;
+    try {
+      isLoadedAlready = !(Boolean)Unsafe_shouldBeInitialized.invoke(AtomicFieldUpdater.getUnsafe(), root);
+    }
+    catch (Exception ignored) {
+    }
+    //AtomicFieldUpdater.getUnsafe().shouldBeInitialized((Class<?>)root);
+    return isLoadedAlready;
+  }
+
+  public static class BackLink {
+    public final Object value;
+    private final Field field;
+    private final BackLink backLink;
+
+    public BackLink(@NotNull Object value, @Nullable Field field, @Nullable BackLink backLink) {
+      this.value = value;
+      this.field = field;
+      this.backLink = backLink;
+    }
+
+    @Override
+    public String toString() {
+      BackLink backLink = this;
+      String result = "";
+      while (backLink != null) {
+        String valueStr;
+        try {
+          valueStr = backLink.value instanceof FList
+                     ? "FList" : backLink.value instanceof Collection ? "Collection" : String.valueOf(backLink.value);
+          valueStr = StringUtil.trimLog(StringUtil.convertLineSeparators(valueStr, "//"), 100);
+        }
+        catch (Throwable e) {
+          valueStr = "(" + e.getMessage() + " while computing .toString())";
+        }
+        Field field = backLink.field;
+        String fieldStr = field == null ? "?" : field.getName() + " of " + field.getDeclaringClass();
+        result += "via " + fieldStr + "; Value: " + valueStr + " of " + backLink.value.getClass() + "\n";
+        backLink = backLink.backLink;
+      }
+      return result;
+    }
+  }
+}
index 4c3181f92741917bcadee160aefe8cfa63e28c41..54cdffbcd73af999bc96cd3c7bb915f1dec55a18 100644 (file)
@@ -375,7 +375,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
     }
     if (myFlushAlarm.isDisposed()) return;
     cancelAllFlushRequests();
-    addFlushRequest(new MyClearRunnable());
+    UIUtil.invokeLaterIfNeeded(new MyClearRunnable());
     cancelHeavyAlarm();
   }
 
index 629fd42c13868f7f8f0c1370e4cc9309842cc0dc..8931ddb97c2fb2eeb0556349fc295f50482ba0ec 100644 (file)
@@ -87,6 +87,7 @@ class FindInProjectTask {
   private final Set<VirtualFile> myLargeFiles = ContainerUtil.newTroveSet();
   private final Set<VirtualFile> myFilesToScanInitially;
   private boolean myWarningShown;
+  private final String myStringToFindInIndices;
 
   FindInProjectTask(@NotNull final FindModel findModel, @NotNull final Project project, @NotNull Set<VirtualFile> filesToScanInitially) {
     myFindModel = findModel;
@@ -116,6 +117,14 @@ class FindInProjectTask {
 
     final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
     myProgress = progress != null ? progress : new EmptyProgressIndicator();
+
+    String stringToFind = myFindModel.getStringToFind();
+
+    if (myFindModel.isRegularExpressions()) {
+      stringToFind = FindInProjectUtil.buildStringToFindForIndicesFromRegExp(stringToFind, myProject);
+    }
+
+    myStringToFindInIndices = stringToFind;
   }
 
   public void findUsages(@NotNull final Processor<UsageInfo> consumer, @NotNull final FindUsagesProcessPresentation processPresentation) {
@@ -271,7 +280,7 @@ class FindInProjectTask {
     final GlobalSearchScope globalCustomScope = customScope == null ? null : toGlobal(customScope);
 
     final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
-    final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
+    final boolean hasTrigrams = hasTrigrams(myStringToFindInIndices);
 
     class EnumContentIterator implements ContentIterator {
       private final Set<VirtualFile> myFiles = new LinkedHashSet<VirtualFile>();
@@ -410,12 +419,10 @@ class FindInProjectTask {
   private boolean canRelyOnIndices() {
     if (DumbService.isDumb(myProject)) return false;
 
-    if (myFindModel.isRegularExpressions()) return false;
-
     // a local scope may be over a non-indexed file
     if (myFindModel.getCustomScope() instanceof LocalSearchScope) return false;
 
-    String text = myFindModel.getStringToFind();
+    String text = myStringToFindInIndices;
     if (StringUtil.isEmptyOrSpaces(text)) return false;
 
     if (hasTrigrams(text)) return true;
@@ -439,11 +446,7 @@ class FindInProjectTask {
 
   @NotNull
   private Set<VirtualFile> getFilesForFastWordSearch() {
-    String stringToFind = myFindModel.getStringToFind();
-
-    if (myFindModel.isRegularExpressions()) {
-      stringToFind = FindInProjectUtil.buildStringToFindForIndicesFromRegExp(stringToFind);
-    }
+    String stringToFind = myStringToFindInIndices;
 
     if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) {
       return Collections.emptySet();
index 18295bdabae2dc01c1d0421d65b28700a72761f2..989d4f027a74bb31dd826b9b5c90c47fa876cc3d 100644 (file)
@@ -57,6 +57,7 @@ import com.intellij.usages.UsageViewPresentation;
 import com.intellij.util.Function;
 import com.intellij.util.PatternUtil;
 import com.intellij.util.Processor;
+import com.intellij.util.SystemProperties;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -166,9 +167,9 @@ public class FindInProjectUtil {
     for(String mask:masks) {
       mask = mask.trim();
       if (StringUtil.startsWith(mask, "!")) {
-        negativePattern += "(" + PatternUtil.convertToRegex(mask.substring(1)) + ")";
+        negativePattern += (negativePattern.isEmpty() ? "" : "|") + "(" + PatternUtil.convertToRegex(mask.substring(1)) + ")";
       } else {
-        pattern += "(" + PatternUtil.convertToRegex(mask) + ")";
+        pattern += (pattern.isEmpty() ? "" : "|") + "(" + PatternUtil.convertToRegex(mask) + ")";
       }
     }
 
@@ -397,8 +398,37 @@ public class FindInProjectUtil {
     return processPresentation;
   }
 
-  public static @NotNull String buildStringToFindForIndicesFromRegExp(@NotNull String stringToFind) {
-    return "";
+  private static List<PsiElement> getTopLevelRegExpChars(String regExpText, Project project) {
+    @SuppressWarnings("deprecation") PsiFile file = PsiFileFactory.getInstance(project).createFileFromText("A.regexp", regExpText);
+    List<PsiElement> result = null;
+    final PsiElement[] children = file.getChildren();
+
+    for (PsiElement child:children) {
+      PsiElement[] grandChildren = child.getChildren();
+      if (grandChildren.length != 1) return Collections.emptyList(); // a | b, more than one branch, can not predict in current way
+
+      for(PsiElement grandGrandChild:grandChildren[0].getChildren()) {
+        if (result == null) result = new ArrayList<PsiElement>();
+        result.add(grandGrandChild);
+      }
+    }
+    return result != null ? result : Collections.<PsiElement>emptyList();
+  }
+
+  public static @NotNull String buildStringToFindForIndicesFromRegExp(@NotNull String stringToFind, Project project) {
+    if (!SystemProperties.getBooleanProperty("idea.regexp.search.uses.indices", true)) return "";
+
+    final List<PsiElement> topLevelRegExpChars = getTopLevelRegExpChars("a", project);
+    if (topLevelRegExpChars.size() != 1) return "";
+
+    // leave only top level regExpChars
+    return StringUtil.join(getTopLevelRegExpChars(stringToFind, project), new Function<PsiElement, String>() {
+      final Class regExpCharPsiClass = topLevelRegExpChars.get(0).getClass();
+      @Override
+      public String fun(PsiElement element) {
+        return regExpCharPsiClass.isInstance(element) ? element.getText() : " ";
+      }
+    }, "");
   }
 
   public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation, TypeSafeDataProvider {
index 58591a13994995d0220b2eeeaf7e074edfd4d53d..9e70d67bf2894622602a07d023e3a50d5de22603 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -18,6 +18,7 @@ package com.intellij.ide.projectView.impl.nodes;
 import com.intellij.ide.projectView.PresentationData;
 import com.intellij.ide.projectView.ProjectViewNode;
 import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.project.Project;
@@ -32,6 +33,7 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 
 public abstract class AbstractModuleNode extends ProjectViewNode<Module> implements NavigatableWithText {
   protected AbstractModuleNode(Project project, Module module, ViewSettings viewSettings) {
@@ -40,32 +42,31 @@ public abstract class AbstractModuleNode extends ProjectViewNode<Module> impleme
 
   @Override
   public void update(PresentationData presentation) {
-    if (getValue().isDisposed()) {
+    Module module = getValue();
+    if (module == null || module.isDisposed()) {
       setValue(null);
       return;
     }
-    presentation.setPresentableText(getValue().getName());
+
+    presentation.setPresentableText(module.getName());
     if (showModuleNameInBold()) {
-      presentation.addText(getValue().getName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
+      presentation.addText(module.getName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
     }
 
-    presentation.setIcon(ModuleType.get(getValue()).getIcon());
+    presentation.setIcon(ModuleType.get(module).getIcon());
+
+    presentation.setTooltip(ModuleType.get(module).getName());
   }
 
   protected boolean showModuleNameInBold() {
     return true;
   }
 
-
-  @Override
-  public String getTestPresentation() {
-    return "Module";
-  }
-
   @NotNull
   @Override
   public Collection<VirtualFile> getRoots() {
-    return Arrays.asList(ModuleRootManager.getInstance(getValue()).getContentRoots());
+    Module module = getValue();
+    return module != null ? Arrays.asList(ModuleRootManager.getInstance(module).getContentRoots()) : Collections.<VirtualFile>emptyList();
   }
 
   @Override
@@ -73,24 +74,17 @@ public abstract class AbstractModuleNode extends ProjectViewNode<Module> impleme
     Module module = getValue();
     if (module == null || module.isDisposed()) return false;
 
-    final VirtualFile testee;
     if (file.getFileSystem() instanceof JarFileSystem) {
-      testee = JarFileSystem.getInstance().getVirtualFileForJar(file);
-      if (testee == null) return false;
-    }
-    else {
-      testee = file;
+      VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(file);
+      if (local == null) return false;
+      file = local;
     }
+
     for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) {
-      if (VfsUtilCore.isAncestor(root, testee, false)) return true;
+      if (VfsUtilCore.isAncestor(root, file, false)) return true;
     }
-    return false;
-  }
 
-  @Override
-  public String getToolTip() {
-    final Module module = getValue();
-    return ModuleType.get(module).getName();
+    return false;
   }
 
   @Override
@@ -103,11 +97,17 @@ public abstract class AbstractModuleNode extends ProjectViewNode<Module> impleme
 
   @Override
   public String getNavigateActionText(boolean focusEditor) {
-    return "Open Module Settings";
+    return ActionsBundle.message("action.ModuleSettings.navigate");
   }
 
   @Override
   public boolean canNavigate() {
     return ProjectSettingsService.getInstance(myProject).canOpenModuleSettings() && getValue() != null;
   }
+
+  @SuppressWarnings("deprecation")
+  @Override
+  public String getTestPresentation() {
+    return "Module";
+  }
 }
index 001159faca81b53fb872e084482e11a8e515bc8a..2eef9d4e312fad355a42a2fbb65984b1a8707218 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.ide.projectView.impl.nodes;
 
 import com.intellij.icons.AllIcons;
@@ -22,6 +21,7 @@ import com.intellij.ide.projectView.PresentationData;
 import com.intellij.ide.projectView.ProjectViewNode;
 import com.intellij.ide.projectView.ViewSettings;
 import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.projectRoots.SdkType;
@@ -47,16 +47,14 @@ public class NamedLibraryElementNode extends ProjectViewNode<NamedLibraryElement
   @Override
   @NotNull
   public Collection<AbstractTreeNode> getChildren() {
-    final List<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>();
-    LibraryGroupNode.addLibraryChildren(getValue().getOrderEntry(), children, getProject(), this);
+    List<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>();
+    NamedLibraryElement libraryElement = getValue();
+    if (libraryElement != null) {
+      LibraryGroupNode.addLibraryChildren(libraryElement.getOrderEntry(), children, getProject(), this);
+    }
     return children;
   }
 
-  @Override
-  public String getTestPresentation() {
-    return "Library: " + getValue().getName();
-  }
-
   private static Icon getJdkIcon(JdkOrderEntry entry) {
     final Sdk sdk = entry.getJdk();
     if (sdk == null) {
@@ -68,40 +66,39 @@ public class NamedLibraryElementNode extends ProjectViewNode<NamedLibraryElement
 
   @Override
   public String getName() {
-    return getValue().getName();
+    NamedLibraryElement library = getValue();
+    return library != null ? library.getName() : "";
   }
 
   @Override
   public boolean contains(@NotNull VirtualFile file) {
-    return orderEntryContainsFile(getValue().getOrderEntry(), file);
-  }
+    NamedLibraryElement library = getValue();
+    if (library == null) return false;
 
-  private static boolean orderEntryContainsFile(LibraryOrSdkOrderEntry orderEntry, VirtualFile file) {
-    for(OrderRootType rootType: OrderRootType.getAllTypes()) {
-      if (containsFileInOrderType(orderEntry, rootType, file)) return true;
+    for (OrderRootType rootType : OrderRootType.getAllTypes()) {
+      LibraryOrSdkOrderEntry orderEntry = library.getOrderEntry();
+      if (orderEntry.isValid()) {
+        for (VirtualFile virtualFile : orderEntry.getRootFiles(rootType)) {
+          if (VfsUtilCore.isAncestor(virtualFile, file, false)) return true;
+        }
+      }
     }
-    return false;
-  }
 
-  private static boolean containsFileInOrderType(final LibraryOrSdkOrderEntry orderEntry, final OrderRootType orderType, final VirtualFile file) {
-    if (!orderEntry.isValid()) return false;
-    VirtualFile[] files = orderEntry.getRootFiles(orderType);
-    for (VirtualFile virtualFile : files) {
-      boolean ancestor = VfsUtilCore.isAncestor(virtualFile, file, false);
-      if (ancestor) return true;
-    }
     return false;
   }
 
   @Override
   public void update(PresentationData presentation) {
-    presentation.setPresentableText(getValue().getName());
-    final OrderEntry orderEntry = getValue().getOrderEntry();
+    NamedLibraryElement library = getValue();
+    if (library == null) return;
+
+    OrderEntry orderEntry = library.getOrderEntry();
+    presentation.setPresentableText(library.getName());
     Icon closedIcon = orderEntry instanceof JdkOrderEntry ? getJdkIcon((JdkOrderEntry)orderEntry) : AllIcons.Nodes.PpLibFolder;
     presentation.setIcon(closedIcon);
     if (orderEntry instanceof JdkOrderEntry) {
-      final JdkOrderEntry jdkOrderEntry = (JdkOrderEntry)orderEntry;
-      final Sdk projectJdk = jdkOrderEntry.getJdk();
+      JdkOrderEntry jdkOrderEntry = (JdkOrderEntry)orderEntry;
+      Sdk projectJdk = jdkOrderEntry.getJdk();
       if (projectJdk != null) { //jdk not specified
         final String path = projectJdk.getHomePath();
         if (path != null) {
@@ -117,16 +114,27 @@ public class NamedLibraryElementNode extends ProjectViewNode<NamedLibraryElement
 
   @Override
   public void navigate(final boolean requestFocus) {
-    ProjectSettingsService.getInstance(myProject).openLibraryOrSdkSettings(getValue().getOrderEntry());
+    NamedLibraryElement library = getValue();
+    if (library != null) {
+      ProjectSettingsService.getInstance(myProject).openLibraryOrSdkSettings(library.getOrderEntry());
+    }
   }
 
   @Override
   public boolean canNavigate() {
-    return ProjectSettingsService.getInstance(myProject).canOpenLibraryOrSdkSettings(getValue().getOrderEntry());
+    NamedLibraryElement library = getValue();
+    return library != null && ProjectSettingsService.getInstance(myProject).canOpenLibraryOrSdkSettings(library.getOrderEntry());
   }
 
   @Override
   public String getNavigateActionText(boolean focusEditor) {
-    return "Open Library Settings";
+    return ActionsBundle.message("action.LibrarySettings.navigate");
+  }
+
+  @SuppressWarnings("deprecation")
+  @Override
+  public String getTestPresentation() {
+    NamedLibraryElement library = getValue();
+    return "Library: " + (library != null ? library.getName() : "(null)");
   }
 }
index dc2288b0ed81f99c159eac6215fcdfbfeebaafe5..72f58eeac8a2f34edeaa40a9f1c8db217fcc7154 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.ide.projectView.ViewSettings;
 import com.intellij.ide.projectView.impl.ProjectRootsUtil;
 import com.intellij.ide.projectView.impl.ProjectViewImpl;
 import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileTypes.FileTypeRegistry;
 import com.intellij.openapi.module.Module;
@@ -256,10 +257,10 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
 
     if (file != null && project != null) {
       if (ProjectRootsUtil.isModuleContentRoot(file, project) || ProjectRootsUtil.isModuleSourceRoot(file, project)) {
-        return "Open Module Settings";
+        return ActionsBundle.message("action.ModuleSettings.navigate");
       }
       if (ProjectRootsUtil.isLibraryRoot(file, project)) {
-        return "Open Library Settings";
+        return ActionsBundle.message("action.LibrarySettings.navigate");
       }
     }
 
index 068a97160c169a3639ee6e03492039bcc0f13758..5f4d3a783638a41cdcb97bf6c1ea7cb003897fab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -21,6 +21,7 @@ import com.intellij.ide.projectView.PresentationData;
 import com.intellij.ide.projectView.ViewSettings;
 import com.intellij.ide.projectView.impl.ProjectRootsUtil;
 import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.editor.colors.CodeInsightColors;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.project.Project;
@@ -134,10 +135,7 @@ public class PsiFileNode extends BasePsiNode<PsiFile> implements NavigatableWith
 
   @Override
   public String getNavigateActionText(boolean focusEditor) {
-    if (isNavigatableLibraryRoot()) {
-      return "Open Library Settings";
-    }
-    return null;
+    return isNavigatableLibraryRoot() ? ActionsBundle.message("action.LibrarySettings.navigate") : null;
   }
 
   @Override
index f9c19d400cbb8f3583347627969baa1cac003093..91916bb00c2928d6f39760af6dbad73c72c3e526 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.moduleDependencies;
 
 import com.intellij.icons.AllIcons;
@@ -27,35 +26,31 @@ import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.ui.content.Content;
 import com.intellij.ui.content.ContentManager;
+import org.jetbrains.annotations.NotNull;
 
 /**
- * User: anna
- * Date: Feb 10, 2005
+ * @author anna
+ * @since Feb 10, 2005
  */
-@State(
-    name = "DependenciesAnalyzeManager",
-    storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}
-)
+@State(name = "DependenciesAnalyzeManager", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)})
 public class DependenciesAnalyzeManager implements PersistentStateComponent<DependenciesAnalyzeManager.State> {
   private final Project myProject;
   private ContentManager myContentManager;
 
   public static class State {
-    public boolean myForwardDirection;
+    public boolean forwardDirection = true;
+    public boolean includeTests = false;
   }
 
-  private State myState;
+  private State myState = new State();
 
   public DependenciesAnalyzeManager(final Project project) {
     myProject = project;
     StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() {
       @Override
       public void run() {
-        ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
-        ToolWindow toolWindow = toolWindowManager.registerToolWindow(ToolWindowId.MODULES_DEPENDENCIES,
-                                                                     true,
-                                                                     ToolWindowAnchor.RIGHT,
-                                                                     project);
+        ToolWindowManager manager = ToolWindowManager.getInstance(myProject);
+        ToolWindow toolWindow = manager.registerToolWindow(ToolWindowId.MODULES_DEPENDENCIES, true, ToolWindowAnchor.RIGHT, project);
         myContentManager = toolWindow.getContentManager();
         toolWindow.setIcon(AllIcons.Toolwindows.ToolWindowModuleDependencies);
         new ContentManagerWatcher(toolWindow, myContentManager);
@@ -63,7 +58,7 @@ public class DependenciesAnalyzeManager implements PersistentStateComponent<Depe
     });
   }
 
-  public static DependenciesAnalyzeManager getInstance(Project project){
+  public static DependenciesAnalyzeManager getInstance(Project project) {
     return ServiceManager.getService(project, DependenciesAnalyzeManager.class);
   }
 
@@ -78,12 +73,13 @@ public class DependenciesAnalyzeManager implements PersistentStateComponent<Depe
   }
 
   @Override
+  @NotNull
   public State getState() {
     return myState;
   }
 
   @Override
-  public void loadState(final State state) {
-    myState = state;
+  public void loadState(State state) {
+    myState = state != null ? state : new State();
   }
-}
+}
\ No newline at end of file
index 2119c91cf230d5901bf7e90d6feae09ad14338e9..e93a527a38afffe2300289cd85e94d4ec4020767 100644 (file)
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.moduleDependencies;
 
 import com.intellij.CommonBundle;
@@ -23,39 +22,41 @@ import com.intellij.icons.AllIcons;
 import com.intellij.ide.CommonActionsManager;
 import com.intellij.ide.TreeExpander;
 import com.intellij.ide.actions.ContextHelpAction;
-import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.module.ModuleType;
-import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootAdapter;
 import com.intellij.openapi.roots.ModuleRootEvent;
-import com.intellij.openapi.roots.ModuleRootListener;
 import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
 import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.pom.NavigatableWithText;
 import com.intellij.ui.*;
 import com.intellij.ui.content.Content;
 import com.intellij.ui.treeStructure.Tree;
 import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.Convertor;
-import com.intellij.util.containers.HashMap;
 import com.intellij.util.graph.DFSTBuilder;
 import com.intellij.util.graph.Graph;
 import com.intellij.util.graph.GraphAlgorithms;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.tree.TreeUtil;
-import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.TreeExpansionEvent;
 import javax.swing.event.TreeExpansionListener;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
+import javax.swing.text.JTextComponent;
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.DefaultTreeModel;
 import javax.swing.tree.TreePath;
@@ -65,419 +66,333 @@ import java.util.*;
 import java.util.List;
 
 /**
- * User: anna
- * Date: Feb 10, 2005
+ * @author anna
+ * @since Feb 10, 2005
  */
-public class ModulesDependenciesPanel extends JPanel implements ModuleRootListener, Disposable {
-  @NonNls private static final String DIRECTION = "FORWARD_ANALIZER";
-  private Content myContent;
-  private final Project myProject;
-  private Tree myLeftTree;
-  private DefaultTreeModel myLeftTreeModel;
+public class ModulesDependenciesPanel extends JPanel implements Disposable {
+  private static final String HELP_ID = "module.dependencies.tool.window";
 
-  private final Tree myRightTree;
-  private final DefaultTreeModel myRightTreeModel;
+  private static final Comparator<DefaultMutableTreeNode> NODE_COMPARATOR = new Comparator<DefaultMutableTreeNode>() {
+    @Override
+    public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) {
+      if (!(o1.getUserObject() instanceof MyUserObject)) return 1;
+      if (!(o2.getUserObject() instanceof MyUserObject)) return -1;
+      return (o1.getUserObject().toString().compareToIgnoreCase(o2.getUserObject().toString()));
+    }
+  };
 
-  private Graph<Module> myModulesGraph;
-  private final Module[] myModules;
+  private static final ColoredTreeCellRenderer NODE_RENDERER = new ColoredTreeCellRenderer() {
+    @Override
+    public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+      Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
+      if (userObject instanceof MyUserObject) {
+        MyUserObject node = (MyUserObject)userObject;
+        setIcon(ModuleType.get(node.myModule).getIcon());
+        append(node.myModule.getName(), node.myInCycle ? SimpleTextAttributes.ERROR_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
+      }
+      else if (userObject != null) {
+        append(userObject.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
+      }
+    }
+  };
 
-  private final JTextField myPathField = new JTextField();
+  private final Project myProject;
+  private final Module[] myModules;
+  private final DependenciesAnalyzeManager.State myState;
 
+  private final Tree myLeftTree;
+  private final Tree myRightTree;
   private final Splitter mySplitter;
-  @NonNls private static final String ourHelpID = "module.dependencies.tool.window";
+  private final JTextComponent myPathField;
+
+  private Content myContent;
+  private Graph<Module> myModuleGraph;
+  private final Map<Module, Boolean> myCycleMap = ContainerUtil.newHashMap();
 
-  public ModulesDependenciesPanel(final Project project, final Module[] modules) {
+  public ModulesDependenciesPanel(@NotNull Project project, @Nullable Module[] modules) {
     super(new BorderLayout());
+
     myProject = project;
-    myModules = modules;
+    myModules = modules != null ? modules : ModuleManager.getInstance(project).getModules();
+    myState = DependenciesAnalyzeManager.getInstance(project).getState();
+    updateModuleGraph();
 
-    //noinspection HardCodedStringLiteral
-    myRightTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));
-    myRightTree = new Tree(myRightTreeModel);
-    initTree(myRightTree, true);
+    myLeftTree = new Tree(new DefaultTreeModel(new DefaultMutableTreeNode("Root")));
+    installLeftTreeListeners();
+    installTreeActions(myLeftTree, false);
 
-    initLeftTree();
+    myRightTree = new Tree(new DefaultTreeModel(new DefaultMutableTreeNode("Root")));
+    installTreeActions(myRightTree, true);
 
     mySplitter = new Splitter();
     mySplitter.setFirstComponent(new MyTreePanel(myLeftTree, myProject));
     mySplitter.setSecondComponent(new MyTreePanel(myRightTree, myProject));
-
-    setSplitterProportion();
     add(mySplitter, BorderLayout.CENTER);
-    add(createNorthPanel(), BorderLayout.NORTH);
 
-    project.getMessageBus().connect(this).subscribe(ProjectTopics.PROJECT_ROOTS, this);
-  }
+    myPathField = new JTextField();
+    myPathField.setEditable(false);
+    add(createNorthPanel(), BorderLayout.NORTH);
 
-  private void setSplitterProportion() {
-    if (mySplitter == null){
-      return;
-    }
-    myModulesGraph = buildGraph();
-    DFSTBuilder<Module> builder = new DFSTBuilder<Module>(myModulesGraph);
-    if (builder.isAcyclic()){
-      mySplitter.setProportion(1.f);
-    } else {
-      mySplitter.setProportion(0.5f);
-    }
-  }
+    project.getMessageBus().connect(this).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+      @Override
+      public void rootsChanged(ModuleRootEvent event) {
+        updateModuleGraph();
+        updateSplitterProportion();
+        updateLeftTree();
+      }
+    });
 
-  @Override
-  public void dispose() {
+    updateSplitterProportion();
+    updateLeftTree();
   }
 
-  public ModulesDependenciesPanel(final Project project) {
-    this(project, ModuleManager.getInstance(project).getModules());
+  private void updateModuleGraph() {
+    myModuleGraph = ModuleManager.getInstance(myProject).moduleGraph(myState.includeTests);
+    myCycleMap.clear();
   }
 
-  private JComponent createNorthPanel(){
-    DefaultActionGroup group = new DefaultActionGroup();
-
-    group.add(new AnAction(CommonBundle.message("action.close"), AnalysisScopeBundle.message("action.close.modules.dependencies.description"),
-                           AllIcons.Actions.Cancel){
+  private Iterable<Module> getModuleDependencies(Module module) {
+    final Iterator<Module> iterator = myState.forwardDirection ? myModuleGraph.getIn(module) : myModuleGraph.getOut(module);
+    return new Iterable<Module>() {
       @Override
-      public void actionPerformed(AnActionEvent e) {
-        DependenciesAnalyzeManager.getInstance(myProject).closeContent(myContent);
+      public Iterator<Module> iterator() {
+        return iterator;
       }
-    });
+    };
+  }
 
-    appendDependenciesAction(group);
+  private boolean isInCycle(Module module) {
+    Boolean inCycle = myCycleMap.get(module);
+    if (inCycle == null) {
+      Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModuleGraph, module);
+      inCycle = !cycles.isEmpty();
+      myCycleMap.put(module, inCycle);
+      for (List<Module> cycle : cycles) {
+        for (Module moduleInCycle : cycle) {
+          myCycleMap.put(moduleInCycle, true);
+        }
+      }
+    }
+    return inCycle;
+  }
 
-    group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.direction"), "", isForwardDirection() ? AllIcons.Actions.SortAsc
-                                                                                                                             : AllIcons.Actions.SortDesc){
+  private void installLeftTreeListeners() {
+    myLeftTree.addTreeExpansionListener(new TreeExpansionListener() {
       @Override
-      public boolean isSelected(AnActionEvent e) {
-        return isForwardDirection();
-      }
+      public void treeCollapsed(TreeExpansionEvent event) { }
 
       @Override
-      public void setSelected(AnActionEvent e, boolean state) {
-        PropertiesComponent.getInstance(myProject).setValue(DIRECTION, String.valueOf(state));
-        initLeftTreeModel();
+      public void treeExpanded(TreeExpansionEvent event) {
+        DefaultMutableTreeNode expandedNode = (DefaultMutableTreeNode)event.getPath().getLastPathComponent();
+        for (int i = 0; i < expandedNode.getChildCount(); i++) {
+          DefaultMutableTreeNode child = (DefaultMutableTreeNode)expandedNode.getChildAt(i);
+          if (child.getChildCount() == 0 && !isLooped(event.getPath(), child)) {
+            Module module = ((MyUserObject)child.getUserObject()).myModule;
+            for (Module dependency : getModuleDependencies(module)) {
+              child.add(new DefaultMutableTreeNode(new MyUserObject(isInCycle(dependency), dependency)));
+            }
+            TreeUtil.sort(child, NODE_COMPARATOR);
+          }
+        }
       }
 
-      @Override
-      public void update(final AnActionEvent e) {
-        e.getPresentation().setIcon(isForwardDirection() ? AllIcons.Actions.SortAsc : AllIcons.Actions.SortDesc);
+      private boolean isLooped(TreePath path, DefaultMutableTreeNode child) {
+        for (Object o : path.getPath()) {
+          DefaultMutableTreeNode node = (DefaultMutableTreeNode)o;
+          if (node != child && Comparing.equal(node.getUserObject(), child.getUserObject())) {
+            return true;
+          }
+        }
+        return false;
       }
     });
 
-    group.add(new ContextHelpAction(ourHelpID));
+    myLeftTree.addTreeSelectionListener(new TreeSelectionListener() {
+      @Override
+      public void valueChanged(TreeSelectionEvent e) {
+        TreePath selectionPath = myLeftTree.getSelectionPath();
+        if (selectionPath != null) {
+          myPathField.setText(StringUtil.join(selectionPath.getPath(), new Function<Object, String>() {
+            @Override
+            public String fun(Object o) {
+              Object userObject = ((DefaultMutableTreeNode)o).getUserObject();
+              return userObject instanceof MyUserObject ? ((MyUserObject)userObject).myModule.getName() : "";
+            }
+          }, " : "));
 
-    ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
-    final JPanel panel = new JPanel(new BorderLayout());
-    panel.add(toolbar.getComponent(), BorderLayout.NORTH);
-    panel.add(myPathField, BorderLayout.SOUTH);
-    myPathField.setEditable(false);
-    return panel;
+          DefaultMutableTreeNode selection = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
+          if (selection != null) {
+            updateRightTree(((MyUserObject)selection.getUserObject()).myModule);
+          }
+        }
+      }
+    });
   }
 
-  private boolean isForwardDirection() {
-    final String value = PropertiesComponent.getInstance(myProject).getValue(DIRECTION);
-    return value == null || Boolean.parseBoolean(value);
-  }
+  private static void installTreeActions(Tree tree, boolean enableExpandAll) {
+    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+    tree.setCellRenderer(NODE_RENDERER);
+    tree.setRootVisible(false);
+    tree.setShowsRootHandles(true);
+    UIUtil.setLineStyleAngled(tree);
 
-  private static void appendDependenciesAction(final DefaultActionGroup group) {
-    final AnAction analyzeDepsAction = ActionManager.getInstance().getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES);
-    group.add(new AnAction(analyzeDepsAction.getTemplatePresentation().getText(),
-                           analyzeDepsAction.getTemplatePresentation().getDescription(),
-                           AllIcons.Toolwindows.ToolWindowInspection){
+    TreeUtil.installActions(tree);
 
+    new TreeSpeedSearch(tree, new Convertor<TreePath, String>() {
       @Override
-      public void actionPerformed(AnActionEvent e) {
-        analyzeDepsAction.actionPerformed(e);
+      public String convert(TreePath o) {
+        return o.getLastPathComponent().toString();
       }
+    }, true);
 
+    DefaultActionGroup group = new DefaultActionGroup();
+    CommonActionsManager commonActionManager = CommonActionsManager.getInstance();
+    ActionManager globalActionManager = ActionManager.getInstance();
 
-      @Override
-      public void update(AnActionEvent e) {
-        analyzeDepsAction.update(e);
-      }
-    });
-  }
+    TreeExpander treeExpander = new MyTreeExpander(tree, enableExpandAll);
+    group.add(commonActionManager.createExpandAllAction(treeExpander, tree));
+    group.add(commonActionManager.createCollapseAllAction(treeExpander, tree));
+    group.add(globalActionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
+    group.add(Separator.getInstance());
+    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES));
+    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_BACK_DEPENDENCIES));
+    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_CYCLIC_DEPENDENCIES));
+    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_MODULE_DEPENDENCIES));
 
-  private void buildRightTree(Module module){
-    final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myRightTreeModel.getRoot();
-    root.removeAllChildren();
-    final Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModulesGraph, module);
-    int index = 1;
-    for (List<Module> modules : cycles) {
-      final DefaultMutableTreeNode cycle = new DefaultMutableTreeNode(
-        AnalysisScopeBundle.message("module.dependencies.cycle.node.text", Integer.toString(index++).toUpperCase()));
-      root.add(cycle);
-      cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, module)));
-      for (Module moduleInCycle : modules) {
-        cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, moduleInCycle)));
-      }
-    }
-    ((DefaultTreeModel)myRightTree.getModel()).reload();
-    TreeUtil.expandAll(myRightTree);
+    PopupHandler.installUnknownPopupHandler(tree, group, ActionManager.getInstance());
   }
 
-  private void initLeftTreeModel(){
-    final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myLeftTreeModel.getRoot();
-    root.removeAllChildren();
-    myModulesGraph = buildGraph();
-    setSplitterProportion();
-    ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
-      @Override
-      public void run() {
-        final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
-        final Map<Module, Boolean> inCycle = new HashMap<Module, Boolean>();
-        for (Module module : myModules) {
-          if (progressIndicator != null) {
-            if (progressIndicator.isCanceled()) return;
-            progressIndicator.setText(AnalysisScopeBundle.message("update.module.tree.progress.text", module.getName()));
-          }
-          if (!module.isDisposed()) {
-            Boolean isInCycle = inCycle.get(module);
-            if (isInCycle == null) {
-              isInCycle = !GraphAlgorithms.getInstance().findCycles(myModulesGraph, module).isEmpty();
-              inCycle.put(module, isInCycle);
-            }
-            final DefaultMutableTreeNode moduleNode = new DefaultMutableTreeNode(new MyUserObject(isInCycle.booleanValue(), module));
-            root.add(moduleNode);
-            final Iterator<Module> out = myModulesGraph.getOut(module);
-            while (out.hasNext()) {
-              moduleNode.add(new DefaultMutableTreeNode(new MyUserObject(false, out.next())));
-            }
-          }
-        }
-      }
-    }, AnalysisScopeBundle.message("update.module.tree.progress.title"), true, myProject);
-    sortSubTree(root);
-    myLeftTreeModel.reload();
+  private void updateSplitterProportion() {
+    DFSTBuilder<Module> builder = new DFSTBuilder<Module>(myModuleGraph);
+    mySplitter.setProportion(builder.isAcyclic() ? 1.0f : 0.6f);
   }
 
-  private static void sortSubTree(final DefaultMutableTreeNode root) {
-    TreeUtil.sort(root, new Comparator() {
+  private JComponent createNorthPanel() {
+    DefaultActionGroup group = new DefaultActionGroup();
+
+    group.add(new AnAction(CommonBundle.message("action.close"), null, AllIcons.Actions.Cancel) {
       @Override
-      public int compare(final Object o1, final Object o2) {
-        DefaultMutableTreeNode node1 = (DefaultMutableTreeNode)o1;
-        DefaultMutableTreeNode node2 = (DefaultMutableTreeNode)o2;
-        if (!(node1.getUserObject() instanceof MyUserObject)){
-          return 1;
-        }
-        else if (!(node2.getUserObject() instanceof MyUserObject)){
-          return -1;
-        }
-        return (node1.getUserObject().toString().compareToIgnoreCase(node2.getUserObject().toString()));
+      public void actionPerformed(AnActionEvent e) {
+        DependenciesAnalyzeManager.getInstance(myProject).closeContent(myContent);
       }
     });
-  }
-
-  private void selectCycleUpward(final DefaultMutableTreeNode selection){
-    ArrayList<DefaultMutableTreeNode> selectionNodes = new ArrayList<DefaultMutableTreeNode>();
-    selectionNodes.add(selection);
-    DefaultMutableTreeNode current = (DefaultMutableTreeNode)selection.getParent();
-    boolean flag = false;
-    while (current != null && current.getUserObject() != null){
-      if (current.getUserObject().equals(selection.getUserObject())){
-        flag = true;
-        selectionNodes.add(current);
-        break;
-      }
-      selectionNodes.add(current);
-      current = (DefaultMutableTreeNode)current.getParent();
-    }
-    if (flag){
-      for (DefaultMutableTreeNode node : selectionNodes) {
-        ((MyUserObject)node.getUserObject()).setInCycle(true);
-      }
-    }
-    if (current != null) current = (DefaultMutableTreeNode)current.getParent();
-    while (current != null) {
-      final Object userObject = current.getUserObject();
-      if (userObject instanceof MyUserObject) {
-        ((MyUserObject)userObject).setInCycle(false);
-      }
-      current = (DefaultMutableTreeNode)current.getParent();
-    }
-    myLeftTree.repaint();
-  }
 
-  private void initLeftTree(){
-    //noinspection HardCodedStringLiteral
-    final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
-    myLeftTreeModel = new DefaultTreeModel(root);
-    initLeftTreeModel();
-    myLeftTree = new Tree(myLeftTreeModel);
-    initTree(myLeftTree, false);
-
-    myLeftTree.addTreeExpansionListener(new TreeExpansionListener() {
+    final AnAction analyzeDepsAction = ActionManager.getInstance().getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES);
+    group.add(new AnAction(analyzeDepsAction.getTemplatePresentation().getText(), null, AllIcons.Toolwindows.ToolWindowInspection) {
       @Override
-      public void treeCollapsed(TreeExpansionEvent event) {
+      public void actionPerformed(AnActionEvent e) {
+        analyzeDepsAction.actionPerformed(e);
       }
 
       @Override
-      public void treeExpanded(TreeExpansionEvent event) {
-        final DefaultMutableTreeNode expandedNode = (DefaultMutableTreeNode)event.getPath().getLastPathComponent();
-        for(int i = 0; i < expandedNode.getChildCount(); i++){
-          DefaultMutableTreeNode child = (DefaultMutableTreeNode)expandedNode.getChildAt(i);
-          if (child.getChildCount() == 0){
-            Module module = ((MyUserObject)child.getUserObject()).getModule();
-            final Iterator<Module> out = myModulesGraph.getOut(module);
-            while (out.hasNext()) {
-              final Module nextModule = out.next();
-              child.add(new DefaultMutableTreeNode(new MyUserObject(false, nextModule)));
-            }
-            sortSubTree(child);
-          }
-        }
+      public void update(AnActionEvent e) {
+        analyzeDepsAction.update(e);
       }
     });
 
-    myLeftTree.addTreeSelectionListener(new TreeSelectionListener() {
+    group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.direction")) {
       @Override
-      public void valueChanged(TreeSelectionEvent e) {
-        final TreePath selectionPath = myLeftTree.getSelectionPath();
-        if (selectionPath != null) {
-
-          myPathField.setText(StringUtil.join(selectionPath.getPath(), new Function<Object, String>() {
-            @Override
-            public String fun(Object o) {
-              final Object userObject = ((DefaultMutableTreeNode)o).getUserObject();
-              if (userObject instanceof MyUserObject) {
-                return ((MyUserObject)userObject).getModule().getName();
-              }
-              return "";
-            }
-          }, ":"));
-
-          final DefaultMutableTreeNode selection = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
-          if (selection != null){
-            TreeUtil.traverseDepth(selection, new TreeUtil.Traverse() {
-              @Override
-              public boolean accept(Object node) {
-                DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
-                if (treeNode.getUserObject() instanceof MyUserObject){
-                  ((MyUserObject)treeNode.getUserObject()).setInCycle(false);
-                }
-                return true;
-              }
-            });
-            selectCycleUpward(selection);
-            buildRightTree(((MyUserObject)selection.getUserObject()).getModule());
-          }
-        }
+      public boolean isSelected(AnActionEvent e) {
+        return !myState.forwardDirection;
       }
-    });
-    TreeUtil.selectFirstNode(myLeftTree);
-  }
 
-  private static ActionGroup createTreePopupActions(final boolean isRightTree, final Tree tree) {
-    DefaultActionGroup group = new DefaultActionGroup();
-    final TreeExpander treeExpander = new TreeExpander() {
       @Override
-      public void expandAll() {
-        TreeUtil.expandAll(tree);
+      public void setSelected(AnActionEvent e, boolean state) {
+        myState.forwardDirection = !state;
+        updateLeftTree();
       }
 
       @Override
-      public boolean canExpand() {
-        return isRightTree;
+      public void update(@NotNull AnActionEvent e) {
+        e.getPresentation().setIcon(myState.forwardDirection ? AllIcons.Hierarchy.Subtypes : AllIcons.Hierarchy.Supertypes);
+        super.update(e);
       }
+    });
 
+    group.add(new ToggleAction(AnalysisScopeBundle.message("action.module.dependencies.tests"), null, AllIcons.Modules.TestSourceFolder) {
       @Override
-      public void collapseAll() {
-        TreeUtil.collapseAll(tree, 3);
+      public boolean isSelected(AnActionEvent e) {
+        return myState.includeTests;
       }
 
       @Override
-      public boolean canCollapse() {
-        return true;
+      public void setSelected(AnActionEvent e, boolean state) {
+        myState.includeTests = state;
+        updateModuleGraph();
+        updateLeftTree();
       }
-    };
+    });
 
-    final CommonActionsManager actionManager = CommonActionsManager.getInstance();
-    if (isRightTree){
-      group.add(actionManager.createExpandAllAction(treeExpander, tree));
-    }
-    group.add(actionManager.createCollapseAllAction(treeExpander, tree));
-    final ActionManager globalActionManager = ActionManager.getInstance();
-    group.add(globalActionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
-    group.add(Separator.getInstance());
-    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES));
-    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_BACK_DEPENDENCIES));
-    group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_CYCLIC_DEPENDENCIES));
-    return group;
+    group.add(new ContextHelpAction(HELP_ID));
+
+    ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
+    JPanel panel = new JPanel(new BorderLayout());
+    panel.add(toolbar.getComponent(), BorderLayout.WEST);
+    panel.add(myPathField, BorderLayout.CENTER);
+    return panel;
   }
 
-  private static void initTree(Tree tree, boolean isRightTree) {
-    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-    tree.setCellRenderer(new MyTreeCellRenderer());
-    tree.setRootVisible(false);
-    tree.setShowsRootHandles(true);
-    UIUtil.setLineStyleAngled(tree);
+  private void updateLeftTree() {
+    final DefaultMutableTreeNode root = (DefaultMutableTreeNode)myLeftTree.getModel().getRoot();
+    root.removeAllChildren();
 
-    TreeUtil.installActions(tree);
-    new TreeSpeedSearch(tree, new Convertor<TreePath, String>() {
+    ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
       @Override
-      public String convert(TreePath o) {
-        return o.getLastPathComponent().toString();
+      public void run() {
+        for (Module module : myModules) {
+          if (module.isDisposed()) continue;
+          ProgressManager.progress(AnalysisScopeBundle.message("update.module.tree.progress.text", module.getName()));
+
+          DefaultMutableTreeNode moduleNode = new DefaultMutableTreeNode(new MyUserObject(isInCycle(module), module));
+          root.add(moduleNode);
+          for (Module dependency : getModuleDependencies(module)) {
+            moduleNode.add(new DefaultMutableTreeNode(new MyUserObject(isInCycle(dependency), dependency)));
+          }
+        }
       }
-    }, true);
-    PopupHandler.installUnknownPopupHandler(tree, createTreePopupActions(isRightTree, tree), ActionManager.getInstance());
+    }, AnalysisScopeBundle.message("update.module.tree.progress.title"), true, myProject);
+
+    TreeUtil.sort(root, NODE_COMPARATOR);
+    ((DefaultTreeModel)myLeftTree.getModel()).reload();
+    TreeUtil.selectFirstNode(myLeftTree);
   }
 
+  private void updateRightTree(Module module) {
+    DefaultMutableTreeNode root = (DefaultMutableTreeNode)myRightTree.getModel().getRoot();
+    root.removeAllChildren();
 
-  private Graph<Module> buildGraph() {
-    final Graph<Module> graph = ModuleManager.getInstance(myProject).moduleGraph();
-    if (isForwardDirection()) {
-      return graph;
-    }
-    else {
-      return GraphAlgorithms.getInstance().invertEdgeDirections(graph);
+    Set<List<Module>> cycles = GraphAlgorithms.getInstance().findCycles(myModuleGraph, module);
+    int index = 1;
+    for (List<Module> modules : cycles) {
+      DefaultMutableTreeNode cycle = new DefaultMutableTreeNode(AnalysisScopeBundle.message("module.dependencies.cycle.node.text", index++));
+      root.add(cycle);
+      cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, module)));
+      for (Module moduleInCycle : modules) {
+        cycle.add(new DefaultMutableTreeNode(new MyUserObject(false, moduleInCycle)));
+      }
     }
+
+    ((DefaultTreeModel)myRightTree.getModel()).reload();
+    TreeUtil.expandAll(myRightTree);
   }
 
-  public void setContent(final Content content) {
+  public void setContent(Content content) {
     myContent = content;
   }
 
   @Override
-  public void beforeRootsChange(ModuleRootEvent event) {
-  }
+  public void dispose() { }
 
-  @Override
-  public void rootsChanged(ModuleRootEvent event) {
-    initLeftTreeModel();
-    TreeUtil.selectFirstNode(myLeftTree);
-  }
 
-  private static class MyUserObject implements NavigatableWithText{
-    private boolean myInCycle;
+  private static class MyUserObject implements NavigatableWithText {
     private final Module myModule;
+    private final boolean myInCycle;
 
-    public MyUserObject(final boolean inCycle, final Module module) {
+    public MyUserObject(boolean inCycle, Module module) {
       myInCycle = inCycle;
       myModule = module;
     }
 
-    public boolean isInCycle() {
-      return myInCycle;
-    }
-
-    public void setInCycle(final boolean inCycle) {
-      myInCycle = inCycle;
-    }
-
-    public Module getModule() {
-      return myModule;
-    }
-
-    public boolean equals(Object object) {
-      return object instanceof MyUserObject && myModule.equals(((MyUserObject)object).getModule());
-    }
-
-    public int hashCode() {
-      return myModule.hashCode();
-    }
-
-    public String toString() {
-      return myModule.getName();
-    }
-
     @Override
     public void navigate(boolean requestFocus) {
       ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule);
@@ -485,7 +400,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
 
     @Override
     public boolean canNavigate() {
-      return myModule != null && !myModule.isDisposed();
+      return !myModule.isDisposed();
     }
 
     @Override
@@ -495,14 +410,30 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
 
     @Override
     public String getNavigateActionText(boolean focusEditor) {
-      return "Open Module Settings";
+      return ActionsBundle.message("action.ModuleSettings.navigate");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      return o == this || o instanceof MyUserObject && myModule.equals(((MyUserObject)o).myModule);
+    }
+
+    @Override
+    public int hashCode() {
+      return myModule.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return myModule.getName();
     }
   }
 
-  private static class MyTreePanel extends JPanel implements DataProvider{
+  private static class MyTreePanel extends JPanel implements DataProvider {
     private final Tree myTree;
     private final Project myProject;
-    public MyTreePanel(final Tree tree, Project project) {
+
+    public MyTreePanel(Tree tree, Project project) {
       super(new BorderLayout());
       myTree = tree;
       myProject = project;
@@ -511,26 +442,26 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
 
     @Override
     public Object getData(String dataId) {
-      if (CommonDataKeys.PROJECT.is(dataId)){
+      if (CommonDataKeys.PROJECT.is(dataId)) {
         return myProject;
       }
-      if (LangDataKeys.MODULE_CONTEXT.is(dataId)){
-        final TreePath selectionPath = myTree.getLeadSelectionPath();
-        if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){
+      if (LangDataKeys.MODULE_CONTEXT.is(dataId)) {
+        TreePath selectionPath = myTree.getLeadSelectionPath();
+        if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode) {
           DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
-          if (node.getUserObject() instanceof MyUserObject){
-            return ((MyUserObject)node.getUserObject()).getModule();
+          if (node.getUserObject() instanceof MyUserObject) {
+            return ((MyUserObject)node.getUserObject()).myModule;
           }
         }
       }
       if (PlatformDataKeys.HELP_ID.is(dataId)) {
-        return ourHelpID;
+        return HELP_ID;
       }
       if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
-        final TreePath selectionPath = myTree.getLeadSelectionPath();
-        if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){
+        TreePath selectionPath = myTree.getLeadSelectionPath();
+        if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode) {
           DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
-          if (node.getUserObject() instanceof MyUserObject){
+          if (node.getUserObject() instanceof MyUserObject) {
             return node.getUserObject();
           }
         }
@@ -538,32 +469,34 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
       return null;
     }
   }
-   private static class MyTreeCellRenderer extends ColoredTreeCellRenderer {
+
+  private static class MyTreeExpander implements TreeExpander {
+    private final Tree myTree;
+    private final boolean myEnableExpandAll;
+
+    public MyTreeExpander(Tree tree, boolean enableExpandAll) {
+      myTree = tree;
+      myEnableExpandAll = enableExpandAll;
+    }
+
     @Override
-    public void customizeCellRenderer(
-    JTree tree,
-    Object value,
-    boolean selected,
-    boolean expanded,
-    boolean leaf,
-    int row,
-    boolean hasFocus
-  ){
-      final Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
-      if (!(userObject instanceof MyUserObject)){
-        if (userObject != null){
-          append(userObject.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
-        }
-        return;
-      }
-      MyUserObject node = (MyUserObject)userObject;
-      Module module = node.getModule();
-      setIcon(ModuleType.get(module).getIcon());
-      if (node.isInCycle()){
-        append(module.getName(), SimpleTextAttributes.ERROR_ATTRIBUTES);
-      } else {
-        append(module.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
-      }
+    public void expandAll() {
+      TreeUtil.expandAll(myTree);
+    }
+
+    @Override
+    public boolean canExpand() {
+      return myEnableExpandAll;
+    }
+
+    @Override
+    public void collapseAll() {
+      TreeUtil.collapseAll(myTree, 3);
+    }
+
+    @Override
+    public boolean canCollapse() {
+      return true;
     }
   }
-}
+}
\ No newline at end of file
index e4bc7db8b6bd58d2834790ae43f357d6c4a21116..1de7690c3f259c45bf1ac367fc6de542106b41f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.moduleDependencies;
 
 import com.intellij.analysis.AnalysisScope;
 import com.intellij.analysis.AnalysisScopeBundle;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.ui.content.Content;
 import com.intellij.ui.content.ContentFactory;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
 
 /**
- * User: anna
- * Date: Feb 9, 2005
+ * @author anna
+ * @since Feb 9, 2005
  */
-public class ShowModuleDependenciesAction extends AnAction{
+public class ShowModuleDependenciesAction extends AnAction {
   @Override
-  public void actionPerformed(AnActionEvent e) {
-    final DataContext dataContext = e.getDataContext();
-    final Project project = CommonDataKeys.PROJECT.getData(dataContext);
-    if (project == null){
-      return;
-    }
-    ModulesDependenciesPanel panel;
-    AnalysisScope scope = new AnalysisScope(project);
-    final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext);
-    if (modules != null){
-      panel = new ModulesDependenciesPanel(project, modules);
-      scope = new AnalysisScope(modules);
-    } else {
-      final PsiElement element = CommonDataKeys.PSI_FILE.getData(dataContext);
-      final Module module = element != null ? ModuleUtil.findModuleForPsiElement(element) : null;
+  public void update(@NotNull AnActionEvent e) {
+    e.getPresentation().setEnabled(e.getProject() != null);
+  }
+
+  @Override
+  public void actionPerformed(@NotNull AnActionEvent e) {
+    Project project = e.getProject();
+    if (project == null) return;
+
+    Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(e.getDataContext());
+    if (modules == null) {
+      PsiElement element = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
+      Module module = element != null ? ModuleUtilCore.findModuleForPsiElement(element) : null;
       if (module != null && ModuleManager.getInstance(project).getModules().length > 1) {
         MyModuleOrProjectScope dlg = new MyModuleOrProjectScope(module.getName());
-        if (dlg.showAndGet()) {
-          if (!dlg.useProjectScope()) {
-            panel = new ModulesDependenciesPanel(project, new Module[]{module});
-            scope = new AnalysisScope(module);
-          }
-          else {
-            panel = new ModulesDependenciesPanel(project);
-          }
-        }
-        else {
+        if (!dlg.showAndGet()) {
           return;
         }
-      } else {
-        panel = new ModulesDependenciesPanel(project);
+        if (!dlg.useProjectScope()) {
+          modules = new Module[]{module};
+        }
       }
     }
 
-    Content content = ContentFactory.SERVICE.getInstance().createContent(panel,
-                                                                                  AnalysisScopeBundle.message(
-                                                                                    "module.dependencies.toolwindow.title",
-                                                                                    StringUtil.capitalize(scope.getDisplayName())),
-                                                                                  false);
+    ModulesDependenciesPanel panel = new ModulesDependenciesPanel(project, modules);
+    AnalysisScope scope = modules != null ? new AnalysisScope(modules) : new AnalysisScope(project);
+    Content content = ContentFactory.SERVICE.getInstance().createContent(panel, scope.getDisplayName(), false);
     content.setDisposer(panel);
     panel.setContent(content);
     DependenciesAnalyzeManager.getInstance(project).addContent(content);
   }
 
-  @Override
-  public void update(AnActionEvent e) {
-    final DataContext dataContext = e.getDataContext();
-    final Project project = CommonDataKeys.PROJECT.getData(dataContext);
-    e.getPresentation().setEnabled(project != null);
-  }
-
-  private static class MyModuleOrProjectScope extends DialogWrapper{
+  private static class MyModuleOrProjectScope extends DialogWrapper {
     private final JRadioButton myProjectScope;
     private final JRadioButton myModuleScope;
+
     protected MyModuleOrProjectScope(String moduleName) {
       super(false);
       setTitle(AnalysisScopeBundle.message("module.dependencies.scope.dialog.title"));
@@ -112,8 +96,8 @@ public class ShowModuleDependenciesAction extends AnAction{
       return panel;
     }
 
-    public boolean useProjectScope(){
+    public boolean useProjectScope() {
       return myProjectScope.isSelected();
     }
   }
-}
+}
\ No newline at end of file
index abfd133461a08be3ed2154ee2d0336241872a36e..5d49f81da6070e24130129032771846730b6a97a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.packageDependencies.ui;
 
 import com.intellij.analysis.AnalysisScopeBundle;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
@@ -27,7 +27,7 @@ import com.intellij.psi.PsiFile;
 import javax.swing.*;
 import java.util.Set;
 
-public class ModuleNode extends PackageDependenciesNode implements NavigatableWithText{
+public class ModuleNode extends PackageDependenciesNode implements NavigatableWithText {
   private final Module myModule;
 
   public ModuleNode(Module module) {
@@ -65,6 +65,7 @@ public class ModuleNode extends PackageDependenciesNode implements NavigatableWi
     return myModule == null || myModule.isDisposed() ? super.getIcon() : ModuleType.get(myModule).getIcon();
   }
 
+  @Override
   public String toString() {
     return myModule == null ? AnalysisScopeBundle.message("unknown.node.text") : myModule.getName();
   }
@@ -90,15 +91,14 @@ public class ModuleNode extends PackageDependenciesNode implements NavigatableWi
     if (!(o instanceof ModuleNode)) return false;
 
     final ModuleNode moduleNode = (ModuleNode)o;
-
     return Comparing.equal(myModule, moduleNode.myModule);
   }
 
+  @Override
   public int hashCode() {
     return myModule == null ? 0 : myModule.hashCode();
   }
 
-
   @Override
   public boolean isValid() {
     return myModule != null && !myModule.isDisposed();
@@ -106,6 +106,6 @@ public class ModuleNode extends PackageDependenciesNode implements NavigatableWi
 
   @Override
   public String getNavigateActionText(boolean focusEditor) {
-    return "Open Module Settings";
+    return ActionsBundle.message("action.ModuleSettings.navigate");
   }
 }
index 1e99dade5d6a817d06d8c15965a4a7b158f9a7d8..c784a8fccd74a66b7ab063ab0b5fa61bba3a0ed1 100644 (file)
@@ -287,6 +287,7 @@ public interface IdeActions {
   @NonNls String ACTION_ANALYZE_DEPENDENCIES = "ShowPackageDeps";
   @NonNls String ACTION_ANALYZE_BACK_DEPENDENCIES = "ShowBackwardPackageDeps";
   @NonNls String ACTION_ANALYZE_CYCLIC_DEPENDENCIES = "ShowPackageCycles";
+  @NonNls String ACTION_ANALYZE_MODULE_DEPENDENCIES = "ShowModulesDependencies";
   @NonNls String GROUP_MOVE_MODULE_TO_GROUP = "MoveModuleToGroup";
   @NonNls String ACTION_CLEAR_TEXT = "TextComponent.ClearAction";
   @NonNls String ACTION_HIGHLIGHT_USAGES_IN_FILE = "HighlightUsagesInFile";
index 7fbb410d12ff73ae8f975afe1d9c9c544899f4ad..d0433da9a714f33be57499c6650438d0d848f495 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.util.ui;
 
+import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Disposer;
@@ -389,7 +390,8 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI {
     if (sb != null) {
       sb.repaint();
 
-      if (!myMouseOverScrollbar && !sb.getValueIsAdjusting() && !ApplicationManager.getApplication().isUnitTestMode()) {
+      Application application = ApplicationManager.getApplication();
+      if (!myMouseOverScrollbar && !sb.getValueIsAdjusting() && (application == null || !application.isUnitTestMode())) {
         myMacScrollbarFadeTimer.addRequest(new Runnable() {
           @Override
           public void run() {
index 48d99affd51d0dce923a9f242769519d85d2744a..f10599533ac45508bdc207f7ea1fcf2b3ae74fff 100644 (file)
@@ -1848,16 +1848,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
   private void bulkUpdateFinished() {
     myFoldingModel.onBulkDocumentUpdateFinished();
     mySoftWrapModel.onBulkDocumentUpdateFinished();
+    if (myUseNewRendering) {
+      myView.reset();
+    }
     myCaretModel.onBulkDocumentUpdateFinished();
 
     clearTextWidthCache();
 
     setMouseSelectionState(MOUSE_SELECTION_STATE_NONE);
 
-    if (myUseNewRendering) {
-      myView.reset();
-    }
-    else {
+    if (!myUseNewRendering) {
       mySizeContainer.reset();
     }
     validateSize();
index c053808175a3403f411f4b01719927b491283c5e..47b8d551b85eb8d277f49d359ee2e810fe633c94 100644 (file)
@@ -3,10 +3,9 @@
   <component name="NewModuleRootManager" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
index 883ca8331e2407682d312b8ef7117dea79eee79d..09a1e69d0d6de8304035bb740b1788a06294f03d 100644 (file)
@@ -1491,3 +1491,5 @@ action.StructuralSearchPlugin.StructuralSearchAction.description=Structural Sear
 action.StructuralSearchPlugin.StructuralReplaceAction.text=Repla_ce Structurally...
 action.StructuralSearchPlugin.StructuralReplaceAction.description=Structural Replace
 
+action.ModuleSettings.navigate=Open Module Settings
+action.LibrarySettings.navigate=Open Library Settings
\ No newline at end of file
index 0ec0bb4caa1aa57283909628113af8dcab617b6b..15b14276c18737e8113b796757ec40ba9a376346 100644 (file)
@@ -21,8 +21,8 @@ action.group.by.scope.type.description=Group by Scope Type (production, test, li
 action.show.files=Show Files
 action.show.files.description=Show/Hide Files
 action.close.dependency.description=Close Dependency Viewer
-action.close.modules.dependencies.description=Close Modules Dependencies Viewer
-action.module.dependencies.direction=Dependencies Direction
+action.module.dependencies.direction=Backward Dependencies (Usages)
+action.module.dependencies.tests=Include Test Dependencies
 action.analyzing.cyclic.dependencies.in.scope=Cyclic Dependencies of {0}
 action.analyze.verb=Analyze
 action.analysis.noun=Analysis
@@ -39,6 +39,8 @@ action.select.in.left.tree.description=Select in left tree (to browse dependenci
 action.forward.dependency.analysis=Dependency Analysis
 action.backward.dependency.analysis=Backward Dependency Analysis
 
+update.module.tree.progress.title=Updating Module Tree
+update.module.tree.progress.text=Processing module ''{0}'' cycles
 
 cyclic.dependencies.scope.dialog.title=Specify {0} Scope
 cyclic.dependencies.scope.dialog.project.button={0} the whole &project
@@ -48,11 +50,10 @@ cyclic.dependencies.usage.view.root.node.text=Usages of package ''{0}'' in packa
 cyclic.dependencies.usage.view.initial.text=Select package to analyze from the left tree
 cyclic.dependencies.progress.text=Building dependencies graph
 
-module.dependencies.cycle.node.text=Cycle{0}
+module.dependencies.cycle.node.text=Cycle {0}
 module.dependencies.scope.dialog.module.button=Inspect &module ''{0}''
 module.dependencies.scope.dialog.project.button=Inspect the whole &project
 module.dependencies.scope.dialog.title=Specify Analysis Scope
-module.dependencies.toolwindow.title={0}
 
 backward.dependencies.usage.view.root.node.text=Usages of the left tree scope selection in the right tree scope selection
 backward.dependencies.usage.view.initial.text=Select where to search in right tree and what to search in left tree.
@@ -83,7 +84,6 @@ dependencies.tree.node.default.package.abbreviation=<default package>
 
 #scope selector
 dependencies.libraries.node.text=Libraries
-error.packageset.common.expectations=(test|lib|src)[modulename] expected before :
 error.packageset.token.expectations=Unexpected ''{0}''
 error.packageset.pattern.expectations=Package pattern expected
 error.packageset.rparen.expected=')' expected
@@ -110,6 +110,4 @@ project.is.out.of.date=Project Is Out Of Date
 skip.import.statements.checkbox.title=Skip import statements
 mark.dependency.illegal.text=Mark Illegal
 scope.selected.files=Selected files
-update.module.tree.progress.title=Update modules tree
-update.module.tree.progress.text=Process module ''{0}'' cycles
 scope.virtual.files=selection
\ No newline at end of file
index f2d82f60ed672cdd0f5a0bce27394cd928e9007d..c5e527a1d0da4195f33c08f69b109a41c81fe744 100644 (file)
@@ -3,7 +3,7 @@
   <component name="NewModuleRootManager" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
@@ -11,5 +11,4 @@
     <orderEntry type="module" module-name="lvcs-impl" scope="RUNTIME" />
     <orderEntry type="module" module-name="json" scope="RUNTIME" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
index b4db0b59eb0469fbfe5b41a67d53b635ac1422eb..339d070f4762530a7ecd4df97d0833fb7928be03 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.concurrency;
 
 import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
+import com.intellij.diagnostic.ThreadDumper;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.progress.EmptyProgressIndicator;
 import com.intellij.openapi.progress.ProgressIndicator;
@@ -23,15 +24,15 @@ import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
 import com.intellij.openapi.progress.util.ProgressIndicatorBase;
 import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.util.Processor;
 import com.intellij.util.TimeoutUtil;
+import com.intellij.util.ui.UIUtil;
 
+import javax.swing.*;
 import java.math.BigDecimal;
 import java.util.*;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -444,4 +445,50 @@ public class JobUtilTest extends PlatformTestCase {
       assertTrue(finished.get());
     }
   }
+
+  public void testDaemonDoesNotPauseWhenEventDispatcherHasEventsInTheQueue() throws Throwable {
+    assertTrue(SwingUtilities.isEventDispatchThread());
+
+    PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
+    final AtomicInteger jobsStarted = new AtomicInteger();
+    final int N_EVENTS = 50;
+    final int N_JOBS = 10000 * JobSchedulerImpl.CORES_COUNT;
+    ProgressIndicator indicator = new DaemonProgressIndicator();
+
+    Job<Void> job = JobLauncher.getInstance().submitToJobThread(
+      () -> JobLauncher.getInstance().invokeConcurrentlyUnderProgress(Collections.nCopies(N_JOBS, null), indicator, false, o -> {
+        jobsStarted.incrementAndGet();
+        TimeoutUtil.sleep(10);
+        return true;
+      }), null);
+
+    for (int i = 0; i < N_EVENTS; i++) {
+      //noinspection SSBasedInspection
+      SwingUtilities.invokeLater(() -> {
+        int jobs0 = jobsStarted.get();
+        long start = System.currentTimeMillis();
+        while (jobsStarted.get() < jobs0 + JobSchedulerImpl.CORES_COUNT && jobsStarted.get() < N_JOBS) {
+          if (System.currentTimeMillis() > start + 10000) {
+            System.err.println(ThreadDumper.dumpThreadsToString());
+            fail();
+            break;
+          }
+        }
+        //int jobs1 = jobsStarted.get();
+        //System.out.println("jobs0 = "+jobs0+"; jobs1 = "+jobs1);
+      });
+      UIUtil.dispatchAllInvocationEvents();
+    }
+    indicator.cancel();
+    job.cancel();
+    while (!job.isDone()) {
+      try {
+        job.waitForCompletion(1000);
+        UIUtil.dispatchAllInvocationEvents();
+        break;
+      }
+      catch (TimeoutException ignored) {
+      }
+    }
+  }
 }
index 500b5844ffaf80d15f6018bc176e311bd9fee1c7..68cd2845e6905c56f129ba7893d448c26cd6b83f 100644 (file)
@@ -417,6 +417,7 @@ public class LaterInvocatorTest extends PlatformTestCase {
       flushSwingQueue();
       checkOrder(1);
     });
+    thread.join();
   }
 
   private static void flushSwingQueue() {
index dfa1302adc94a3278a37283f1716270d13db9294..f9edfdb55c207e5a069b67c9ee465cd91e08cb02 100644 (file)
@@ -214,4 +214,13 @@ public class EditorImplTest extends AbstractEditorTest {
     myEditor.getSettings().setUseSoftWraps(false);
     assertEquals(new Dimension(70, 10), myEditor.getContentComponent().getPreferredSize());
   }
+  
+  public void testUpdatingCaretPositionAfterBulkMode() throws Exception {
+    initText("a<caret>bc");
+    DocumentEx document = (DocumentEx)myEditor.getDocument();
+    document.setInBulkUpdate(true);
+    document.insertString(0, "\n "); // we're changing number of visual lines, and invalidating text layout for caret line
+    document.setInBulkUpdate(false);
+    checkResultByText("\n a<caret>bc");
+  }
 }
index 064868eb170dcfde9db43974e9afbb6ea249c20b..ecb6a45b3b9b73979311a849dc6fef39b1919f9e 100644 (file)
@@ -28,9 +28,10 @@ import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
 import com.intellij.testFramework.BombedProgressIndicator;
 import com.intellij.testFramework.LightPlatformTestCase;
-import com.intellij.testFramework.PlatformTestCase;
 import com.intellij.testFramework.PlatformTestUtil;
-import com.intellij.util.*;
+import com.intellij.util.Alarm;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.TimeoutUtil;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.DoubleArrayList;
 import com.intellij.util.containers.Stack;
@@ -64,17 +65,14 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
   public void testProgressManagerCheckCanceledWorksRightAfterIndicatorBeenCanceled() {
     for (int i=0; i<1000;i++) {
       final ProgressIndicatorBase indicator = new ProgressIndicatorBase();
-      ProgressManager.getInstance().runProcess(new Runnable() {
-        @Override
-        public void run() {
+      ProgressManager.getInstance().runProcess(() -> {
+        ProgressManager.checkCanceled();
+        try {
+          indicator.cancel();
           ProgressManager.checkCanceled();
-          try {
-            indicator.cancel();
-            ProgressManager.checkCanceled();
-            fail("checkCanceled() must have caught just canceled indicator");
-          }
-          catch (ProcessCanceledException ignored) {
-          }
+          fail("checkCanceled() must have caught just canceled indicator");
+        }
+        catch (ProcessCanceledException ignored) {
         }
       }, indicator);
     }
@@ -88,29 +86,26 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
     final TLongArrayList times = new TLongArrayList();
     final long end = warmupEnd + 1000;
 
-    ApplicationManagerEx.getApplicationEx().runProcessWithProgressSynchronously(new Runnable() {
-      @Override
-      public void run() {
-        final Alarm alarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, getTestRootDisposable());
-        ProgressIndicatorEx indicator = (ProgressIndicatorEx)ProgressIndicatorProvider.getGlobalProgressIndicator();
-        prevTime = System.currentTimeMillis();
-        assert indicator != null;
-        indicator.addStateDelegate(new ProgressIndicatorStub() {
-          @Override
-          public void checkCanceled() throws ProcessCanceledException {
-            now = System.currentTimeMillis();
-            if (now > warmupEnd) {
-              int delta = (int)(now - prevTime);
-              times.add(delta);
-            }
-            prevTime = now;
+    ApplicationManagerEx.getApplicationEx().runProcessWithProgressSynchronously(() -> {
+      final Alarm alarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, getTestRootDisposable());
+      ProgressIndicatorEx indicator = (ProgressIndicatorEx)ProgressIndicatorProvider.getGlobalProgressIndicator();
+      prevTime = System.currentTimeMillis();
+      assert indicator != null;
+      indicator.addStateDelegate(new ProgressIndicatorStub() {
+        @Override
+        public void checkCanceled() throws ProcessCanceledException {
+          now = System.currentTimeMillis();
+          if (now > warmupEnd) {
+            int delta = (int)(now - prevTime);
+            times.add(delta);
           }
-        });
-        while (System.currentTimeMillis() < end) {
-          ProgressManager.checkCanceled();
+          prevTime = now;
         }
-        alarm.cancelAllRequests();
+      });
+      while (System.currentTimeMillis() < end) {
+        ProgressManager.checkCanceled();
       }
+      alarm.cancelAllRequests();
     }, "", false, getProject(), null, "");
     long averageDelay = ArrayUtil.averageAmongMedians(times.toNativeArray(), 5);
     System.out.println("averageDelay = " + averageDelay);
@@ -137,11 +132,8 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
     while (!insideReadAction.get()) {
 
     }
-    ApplicationManager.getApplication().runWriteAction(new Runnable() {
-      @Override
-      public void run() {
-        assertTrue(indicator.isCanceled());
-      }
+    ApplicationManager.getApplication().runWriteAction(() -> {
+      assertTrue(indicator.isCanceled());
     });
     assertTrue(indicator.isCanceled());
   }
@@ -149,44 +141,24 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
   public void testThereIsNoDelayBetweenIndicatorCancelAndProgressManagerCheckCanceled() throws Throwable {
     for (int i=0; i<100;i++) {
       final ProgressIndicatorBase indicator = new ProgressIndicatorBase();
-      List<Thread> threads = ContainerUtil.map(Collections.nCopies(10, ""), new Function<String, Thread>() {
-        @Override
-        public Thread fun(String s) {
-          return new Thread(new Runnable() {
-            @Override
-            public void run() {
-              ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-                @Override
-                public void run() {
-                  try {
-                    Thread.sleep(new Random().nextInt(100));
-                    indicator.cancel();
-                    ProgressManager.checkCanceled();
-                    fail("checkCanceled() must know about canceled indicator even from different thread");
-                  }
-                  catch (ProcessCanceledException ignored) {
-                  }
-                  catch (Throwable e) {
-                    exception = e;
-                  }
-                }
-              }, indicator);
-            }
-          },"indicator test"){{start();}};
-        }
-      });
-      ContainerUtil.process(threads, new Processor<Thread>() {
-        @Override
-        public boolean process(Thread thread) {
-          try {
-            thread.join();
-          }
-          catch (InterruptedException e) {
-            throw new RuntimeException(e);
-          }
-          return true;
-        }
-      });
+      List<Thread> threads = ContainerUtil.map(Collections.nCopies(10, ""),
+                                               s -> new Thread(() -> ProgressManager.getInstance().executeProcessUnderProgress(() -> {
+                                                 try {
+                                                   Thread.sleep(new Random().nextInt(100));
+                                                   indicator.cancel();
+                                                   ProgressManager.checkCanceled();
+                                                   fail("checkCanceled() must know about canceled indicator even from different thread");
+                                                 }
+                                                 catch (ProcessCanceledException ignored) {
+                                                 }
+                                                 catch (Throwable e) {
+                                                   exception = e;
+                                                 }
+                                               }, indicator), "indicator test"));
+      threads.forEach(Thread::start);
+      for (Thread thread : threads) {
+        thread.join();
+      }
     }
     if (exception != null) throw exception;
   }
@@ -203,7 +175,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
     taskCanceled = taskSucceeded = false;
     exception = null;
     Future<?> future = ((ProgressManagerImpl)ProgressManager.getInstance()).runProcessWithProgressAsynchronously(
-      new Task.Backgroundable(getProject(), "xxx") {
+      new Task.Backgroundable(getProject(), "Xxx") {
         @Override
         public void run(@NotNull ProgressIndicator indicator) {
           try {
@@ -218,11 +190,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
             checkCanceledCalled = true;
             throw e;
           }
-          catch (RuntimeException e) {
-            exception = e;
-            throw e;
-          }
-          catch (Error e) {
+          catch (RuntimeException | Error e) {
             exception = e;
             throw e;
           }
@@ -274,20 +242,12 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
   private void ensureCheckCanceledCalled(@NotNull ProgressIndicator indicator) {
     myFlag = false;
     Alarm alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, myTestRootDisposable);
-    alarm.addRequest(new Runnable() {
-      @Override
-      public void run() {
-        myFlag = true;
-      }
-    }, 100);
+    alarm.addRequest(() -> myFlag = true, 100);
     final long start = System.currentTimeMillis();
     try {
-      ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-        @Override
-        public void run() {
-          while (System.currentTimeMillis() - start < 10000) {
-            ProgressManager.checkCanceled();
-          }
+      ProgressManager.getInstance().executeProcessUnderProgress(() -> {
+        while (System.currentTimeMillis() - start < 10000) {
+          ProgressManager.checkCanceled();
         }
       }, indicator);
       fail("must have thrown PCE");
@@ -315,38 +275,32 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
 
   public void testNestedIndicatorsAreCanceledRight() {
     checkCanceledCalled = false;
-    ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-      @Override
-      public void run() {
+    ProgressManager.getInstance().executeProcessUnderProgress(() -> {
+      assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
+      ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
+      assertTrue(indicator != null && !indicator.isCanceled());
+      indicator.cancel();
+      assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
+      assertTrue(indicator.isCanceled());
+      final ProgressIndicatorEx nested = new ProgressIndicatorBase();
+      nested.addStateDelegate(new ProgressIndicatorStub() {
+        @Override
+        public void checkCanceled() throws ProcessCanceledException {
+          checkCanceledCalled = true;
+        }
+      });
+      ProgressManager.getInstance().executeProcessUnderProgress(() -> {
         assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-        ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
-        assertTrue(indicator != null && !indicator.isCanceled());
-        indicator.cancel();
-        assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-        assertTrue(indicator.isCanceled());
-        final ProgressIndicatorEx nested = new ProgressIndicatorBase();
-        nested.addStateDelegate(new ProgressIndicatorStub() {
-          @Override
-          public void checkCanceled() throws ProcessCanceledException {
-            checkCanceledCalled = true;
-          }
-        });
-        ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-          @Override
-          public void run() {
-            assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-            ProgressIndicator indicator2 = ProgressIndicatorProvider.getGlobalProgressIndicator();
-            assertTrue(indicator2 != null && !indicator2.isCanceled());
-            assertSame(indicator2, nested);
-            ProgressManager.checkCanceled();
-          }
-        }, nested);
+        ProgressIndicator indicator2 = ProgressIndicatorProvider.getGlobalProgressIndicator();
+        assertTrue(indicator2 != null && !indicator2.isCanceled());
+        assertSame(indicator2, nested);
+        ProgressManager.checkCanceled();
+      }, nested);
 
-        ProgressIndicator indicator3 = ProgressIndicatorProvider.getGlobalProgressIndicator();
-        assertSame(indicator, indicator3);
+      ProgressIndicator indicator3 = ProgressIndicatorProvider.getGlobalProgressIndicator();
+      assertSame(indicator, indicator3);
 
-        assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-      }
+      assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
     }, new EmptyProgressIndicator());
     assertFalse(checkCanceledCalled);
   }
@@ -355,24 +309,18 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
     EmptyProgressIndicator indicator1 = new EmptyProgressIndicator();
     DelegatingProgressIndicator indicator2 = new DelegatingProgressIndicator(indicator1);
     final DelegatingProgressIndicator indicator3 = new DelegatingProgressIndicator(indicator2);
-    ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-      @Override
-      public void run() {
-        ProgressIndicator current = ProgressIndicatorProvider.getGlobalProgressIndicator();
-        assertSame(indicator3, current);
-      }
+    ProgressManager.getInstance().executeProcessUnderProgress(() -> {
+      ProgressIndicator current = ProgressIndicatorProvider.getGlobalProgressIndicator();
+      assertSame(indicator3, current);
     }, indicator3);
     assertFalse(checkCanceledCalled);
   }
 
   public void testProgressPerformance() {
-    PlatformTestUtil.startPerformanceTest("progress", 100, new ThrowableRunnable() {
-      @Override
-      public void run() throws Throwable {
-        EmptyProgressIndicator indicator = new EmptyProgressIndicator();
-        for (int i=0;i<100000;i++) {
-          ProgressManager.getInstance().executeProcessUnderProgress(EmptyRunnable.getInstance(), indicator);
-        }
+    PlatformTestUtil.startPerformanceTest("progress", 100, () -> {
+      EmptyProgressIndicator indicator = new EmptyProgressIndicator();
+      for (int i=0;i<100000;i++) {
+        ProgressManager.getInstance().executeProcessUnderProgress(EmptyRunnable.getInstance(), indicator);
       }
     }).assertTiming();
   }
@@ -385,17 +333,14 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
       }
     };
     try {
-      ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-        @Override
-        public void run() {
-          assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-          assertTrue(!progress.isCanceled());
-          progress.cancel();
-          assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
-          assertTrue(progress.isCanceled());
-          while (true) { // wait for PCE
-            ProgressManager.checkCanceled();
-          }
+      ProgressManager.getInstance().executeProcessUnderProgress(() -> {
+        assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
+        assertTrue(!progress.isCanceled());
+        progress.cancel();
+        assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread()));
+        assertTrue(progress.isCanceled());
+        while (true) { // wait for PCE
+          ProgressManager.checkCanceled();
         }
       }, ProgressWrapper.wrap(progress));
       fail("PCE must have been thrown");
@@ -407,22 +352,19 @@ public class ProgressIndicatorTest extends LightPlatformTestCase {
 
   public void testBombedIndicator() {
     final int count = 10;
-    new BombedProgressIndicator(count).runBombed(new Runnable() {
-      @Override
-      public void run() {
-        for (int i = 0; i < count * 2; i++) {
-          TimeoutUtil.sleep(10);
-          try {
+    new BombedProgressIndicator(count).runBombed(() -> {
+      for (int i = 0; i < count * 2; i++) {
+        TimeoutUtil.sleep(10);
+        try {
+          ProgressManager.checkCanceled();
+          if (i >= count) {
             ProgressManager.checkCanceled();
-            if (i >= count) {
-              ProgressManager.checkCanceled();
-              fail("PCE expected on " + i + "th check");
-            }
+            fail("PCE expected on " + i + "th check");
           }
-          catch (ProcessCanceledException e) {
-            if (i < count) {
-              fail("Too early PCE");
-            }
+        }
+        catch (ProcessCanceledException e) {
+          if (i < count) {
+            fail("Too early PCE");
           }
         }
       }
index 22fc071451329a629c5e9cd3642f1909042443b5..ae4546fe2f87368fbb63983083b6ef012f47c4f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -43,8 +43,8 @@ public class MessageBusTest extends TestCase {
     void t22();
   }
 
-  private static final Topic<T1Listener> TOPIC1 = new Topic<T1Listener>("T1", T1Listener.class);
-  private static final Topic<T2Listener> TOPIC2 = new Topic<T2Listener>("T2", T2Listener.class);
+  private static final Topic<T1Listener> TOPIC1 = new Topic<>("T1", T1Listener.class);
+  private static final Topic<T2Listener> TOPIC2 = new Topic<>("T2", T2Listener.class);
 
   private class T1Handler implements T1Listener {
     private final String id;
@@ -86,7 +86,7 @@ public class MessageBusTest extends TestCase {
   protected void setUp() throws Exception {
     super.setUp();
     myBus = MessageBusFactory.newMessageBus(this);
-    myLog = new ArrayList<String>();
+    myLog = new ArrayList<>();
   }
 
   public void testNoListenersSubscribed() {
@@ -217,13 +217,10 @@ public class MessageBusTest extends TestCase {
       new MessageBusImpl(this, childBus);
     }
 
-    PlatformTestUtil.assertTiming("Too long", 3000, new Runnable() {
-      @Override
-      public void run() {
-        T1Listener publisher = myBus.syncPublisher(TOPIC1);
-        for (int i = 0; i < 1000000; i++) {
-          publisher.t11();
-        }
+    PlatformTestUtil.assertTiming("Too long", 3000, () -> {
+      T1Listener publisher = myBus.syncPublisher(TOPIC1);
+      for (int i = 0; i < 1000000; i++) {
+        publisher.t11();
       }
     });
   }
@@ -231,15 +228,16 @@ public class MessageBusTest extends TestCase {
   public void testStress() throws Throwable {
     final int threadsNumber = 10;
     final int iterationsNumber = 100;
-    final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
+    final AtomicReference<Throwable> exception = new AtomicReference<>();
     final CountDownLatch latch = new CountDownLatch(threadsNumber);
     final MessageBus parentBus = MessageBusFactory.newMessageBus("parent");
+    List<Thread> threads = new ArrayList<>();
     for (int i = 0; i < threadsNumber; i++) {
-      new Thread(String.valueOf(i)) {
+      Thread thread = new Thread(String.valueOf(i)) {
         @Override
         public void run() {
-          int remains = iterationsNumber;
           try {
+            int remains = iterationsNumber;
             while (remains-- > 0) {
               //noinspection ThrowableResultOfMethodCallIgnored
               if (exception.get() != null) {
@@ -255,13 +253,18 @@ public class MessageBusTest extends TestCase {
             latch.countDown();
           }
         }
-      }.start();
+      };
+      thread.start();
+      threads.add(thread);
     }
     latch.await();
     final Throwable e = exception.get();
     if (e != null) {
       throw e;
     }
+    for (Thread thread : threads) {
+      thread.join();
+    }
   }
 
 
index 40038839ec7064c4a9c2720ab339b79eb5c03dc1..4f6d87ab64a914574906685f0443af76018e623e 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2015 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.util.net.ssl;
 
 import com.intellij.openapi.application.ApplicationManager;
@@ -112,6 +127,7 @@ public class CertificateTest extends LightPlatformTestCase {
 
     final long interruptionTimeout = CertificateManager.DIALOG_VISIBILITY_TIMEOUT + 1000;
     // Will be interrupted after at most interruptionTimeout (6 seconds originally)
+    Thread[] t = {null};
     ApplicationManager.getApplication().invokeAndWait(new Runnable() {
       @Override
       public void run() {
@@ -147,11 +163,13 @@ public class CertificateTest extends LightPlatformTestCase {
             fail("Deadlock was not detected in time");
           }
         }
+        t[0] = thread;
       }
     }, ModalityState.any());
     if (!throwableRef.isNull()) {
       throw new AssertionError(throwableRef.get());
     }
+    t[0].join();
   }
 
   @Override
index 106cb60160282e0e391ff5ca167a0bf8f1d91f0a..e30ad7280481e7736520956aca17f8306158334a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -205,18 +205,17 @@ public abstract class RootModelBase implements ModuleRootModel {
   @Override
   @NotNull
   public Module[] getModuleDependencies(boolean includeTests) {
-    final List<Module> result = new ArrayList<Module>();
+    OrderEntry[] entries = getOrderEntries();
+    List<Module> result = new ArrayList<Module>(entries.length);
 
-    for (OrderEntry entry : getOrderEntries()) {
+    for (OrderEntry entry : entries) {
       if (entry instanceof ModuleOrderEntry) {
-        ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
-        final DependencyScope scope = moduleOrderEntry.getScope();
-        if (!includeTests && !scope.isForProductionCompile() && !scope.isForProductionRuntime()) {
-          continue;
-        }
-        final Module module1 = moduleOrderEntry.getModule();
-        if (module1 != null) {
-          result.add(module1);
+        DependencyScope scope = ((ModuleOrderEntry)entry).getScope();
+        if (includeTests || scope.isForProductionCompile() || scope.isForProductionRuntime()) {
+          Module module = ((ModuleOrderEntry)entry).getModule();
+          if (module != null) {
+            result.add(module);
+          }
         }
       }
     }
index 6fd0ca976b40ebe15356386c5829bb74f4dcca26..35bc91d2837e099b05fbd5d0c08916a7ecece1aa 100644 (file)
@@ -17,10 +17,10 @@ package com.intellij.execution.testframework.sm;
 
 import com.intellij.execution.process.ProcessOutputTypes;
 import com.intellij.execution.testframework.sm.runner.OutputLineSplitter;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.testFramework.UsefulTestCase;
-import com.intellij.util.concurrency.FutureResult;
+import com.intellij.testFramework.PlatformTestCase;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 
@@ -28,7 +28,7 @@ import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class OutputLineSplitterTest extends UsefulTestCase {
+public class OutputLineSplitterTest extends PlatformTestCase {
   private static final Key RED = Key.create(OutputLineSplitterTest.class + ".RED");
   private static final Key GREEN = Key.create(OutputLineSplitterTest.class + ".GREEN");
   private static final Key BLUE = Key.create(OutputLineSplitterTest.class + ".BLUE");
@@ -183,7 +183,7 @@ public class OutputLineSplitterTest extends UsefulTestCase {
         isFinished.set(true);
 
         for (Future<?> each : futures) {
-          each.get(10, TimeUnit.SECONDS);
+          each.get();
         }
       }
       catch (Exception e) {
@@ -193,19 +193,6 @@ public class OutputLineSplitterTest extends UsefulTestCase {
   }
 
   private Future<?> execute(final Runnable runnable) {
-    final FutureResult<?> result = new FutureResult<Object>();
-    new Thread(new Runnable() {
-      @Override
-      public void run() {
-        try {
-          runnable.run();
-          result.set(null);
-        }
-        catch (Throwable e) {
-          result.setException(e);
-        }
-      }
-    },"line split").start();
-    return result;
+    return ApplicationManager.getApplication().executeOnPooledThread(runnable);
   }
 }
index 28a302765a832962719faba2ff8ef7342fbe0e8e..ee7ffa897cdc3e874452e0c9159d9d09faf6fa4e 100644 (file)
  */
 package com.intellij.testFramework;
 
+import com.intellij.ide.IdeEventQueue;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.application.impl.LaterInvocator;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.impl.ProjectImpl;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.UserDataHolder;
 import com.intellij.openapi.util.UserDataHolderEx;
+import com.intellij.util.DebugReflectionUtil;
+import com.intellij.util.DebugReflectionUtil.BackLink;
+import com.intellij.util.PairProcessor;
 import com.intellij.util.Processor;
 import com.intellij.util.ReflectionUtil;
-import com.intellij.util.concurrency.AtomicFieldUpdater;
-import com.intellij.util.containers.FList;
 import com.intellij.util.containers.Queue;
 import com.intellij.util.io.PersistentEnumeratorBase;
 import com.intellij.util.ui.UIUtil;
-import gnu.trove.THashMap;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
-import sun.misc.Unsafe;
 
 import javax.swing.*;
-import java.lang.ref.Reference;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.*;
 
 /**
  * User: cdr
  */
 public class LeakHunter {
-  private static final Map<Class, Field[]> allFields = new THashMap<Class, Field[]>();
-  private static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
 
-  @NotNull
-  private static Field[] getAllFields(@NotNull Class aClass) {
-    Field[] cached = allFields.get(aClass);
-    if (cached == null) {
-      try {
-        Field[] declaredFields = aClass.getDeclaredFields();
-        List<Field> fields = new ArrayList<Field>(declaredFields.length + 5);
-        for (Field declaredField : declaredFields) {
-          declaredField.setAccessible(true);
-          Class<?> type = declaredField.getType();
-          if (isTrivial(type)) continue; // unable to hold references, skip
-          fields.add(declaredField);
-        }
-        Class superclass = aClass.getSuperclass();
-        if (superclass != null) {
-          for (Field sup : getAllFields(superclass)) {
-            if (!fields.contains(sup)) {
-              fields.add(sup);
-            }
-          }
-        }
-        cached = fields.isEmpty() ? EMPTY_FIELD_ARRAY : fields.toArray(new Field[fields.size()]);
-      }
-      catch (IncompatibleClassChangeError e) {
-        //this exception may be thrown because there are two different versions of org.objectweb.asm.tree.ClassNode from different plugins
-        //I don't see any sane way to fix it until we load all the plugins by the same classloader in tests
-        cached = EMPTY_FIELD_ARRAY;
-      }
-      catch (SecurityException e) {
-        cached = EMPTY_FIELD_ARRAY;
-      }
-      catch (NoClassDefFoundError e) {
-        cached = EMPTY_FIELD_ARRAY;
-      }
-
-      allFields.put(aClass, cached);
-    }
-    return cached;
-  }
-
-  private static boolean isTrivial(@NotNull Class<?> type) {
-    return type.isPrimitive() || type == String.class || type == Class.class || type.isArray() && isTrivial(type.getComponentType());
-  }
-
-  private static class BackLink {
-    private final Object value;
-    private final Field field;
-    private final BackLink backLink;
-
-    private BackLink(@NotNull Object value, Field field, BackLink backLink) {
-      this.value = value;
-      this.field = field;
-      this.backLink = backLink;
-    }
-  }
-
-  private static void walkObjects(@NotNull Class<?> lookFor,
-                                  @NotNull Collection<Object> startRoots,
-                                  @NotNull Processor<BackLink> leakProcessor) {
+  private static void walkObjects(@NotNull final Class<?> lookFor, @NotNull Collection<Object> startRoots, @NotNull final Processor<BackLink> leakProcessor) {
     TIntHashSet visited = new TIntHashSet();
-    Queue<BackLink> toVisit = new Queue<BackLink>(1000000);
+    final Queue<BackLink> toVisit = new Queue<BackLink>(1000000);
     for (Object startRoot : startRoots) {
       toVisit.addLast(new BackLink(startRoot, null, null));
     }
     while (true) {
       if (toVisit.isEmpty()) return;
-      BackLink backLink = toVisit.pullFirst();
+      final BackLink backLink = toVisit.pullFirst();
       Object root = backLink.value;
       if (!visited.add(System.identityHashCode(root))) continue;
-      Class rootClass = root.getClass();
-      for (Field field : getAllFields(rootClass)) {
-        String fieldName = field.getName();
-        if (root instanceof Reference && "referent".equals(fieldName)) continue; // do not follow weak/soft refs
-        Object value;
-        try {
-          value = field.get(root);
-        }
-        catch (IllegalArgumentException e) {
-          throw new RuntimeException(e);
-        }
-        catch (IllegalAccessException e) {
-          throw new RuntimeException(e);
-        }
-        if (value == null) continue;
-        Class<?> valueClass = value.getClass();
-        if (lookFor.isAssignableFrom(valueClass) && isReallyLeak(field, fieldName, value, valueClass)) {
-          BackLink newBackLink = new BackLink(value, field, backLink);
-          leakProcessor.process(newBackLink);
-        }
-        else {
-          BackLink newBackLink = new BackLink(value, field, backLink);
-          toVisit.addLast(newBackLink);
-        }
-      }
-      if (rootClass.isArray()) {
-        try {
-          for (Object o : (Object[])root) {
-            if (o == null) continue;
-            if (isTrivial(o.getClass())) continue;
-            toVisit.addLast(new BackLink(o, null, backLink));
+      DebugReflectionUtil.processStronglyReferencedValues(root, new PairProcessor<Object, Field>() {
+        @Override
+        public boolean process(Object value, Field field) {
+          Class<?> valueClass = value.getClass();
+          if (lookFor.isAssignableFrom(valueClass) && isReallyLeak(value)) {
+            leakProcessor.process(new BackLink(value, field, backLink));
           }
-        }
-        catch (ClassCastException ignored) {
-        }
-      }
-      // check for objects leaking via static fields. process classes which already were initialized only
-      if (root instanceof Class && isLoadedAlready((Class)root)) {
-        try {
-          for (Field field : getAllFields((Class)root)) {
-            if ((field.getModifiers() & Modifier.STATIC) == 0) continue;
-            Object value = field.get(null);
-            if (value == null) continue;
-            Class<?> valueClass = value.getClass();
-            if (lookFor.isAssignableFrom(valueClass) && isReallyLeak(field, field.getName(), value, valueClass)) {
-              BackLink newBackLink = new BackLink(value, field, backLink);
-              leakProcessor.process(newBackLink);
-            }
-            else {
-              BackLink newBackLink = new BackLink(value, field, backLink);
-              toVisit.addLast(newBackLink);
-            }
+          else {
+            toVisit.addLast(new BackLink(value, field, backLink));
           }
+          return true;
         }
-        catch (IllegalAccessException ignored) {
-        }
-      }
-    }
-  }
-
-  private static final Method Unsafe_shouldBeInitialized = ReflectionUtil.getDeclaredMethod(Unsafe.class, "shouldBeInitialized", Class.class);
-  private static boolean isLoadedAlready(Class root) {
-    if (Unsafe_shouldBeInitialized == null) return false;
-    boolean isLoadedAlready = false;
-    try {
-      isLoadedAlready = !(Boolean)Unsafe_shouldBeInitialized.invoke(AtomicFieldUpdater.getUnsafe(), root);
-    }
-    catch (Exception ignored) {
+      });
     }
-    //AtomicFieldUpdater.getUnsafe().shouldBeInitialized((Class<?>)root);
-    return isLoadedAlready;
   }
 
   private static final Key<Boolean> IS_NOT_A_LEAK = Key.create("IS_NOT_A_LEAK");
   public static void markAsNotALeak(@NotNull UserDataHolder object) {
     object.putUserData(IS_NOT_A_LEAK, Boolean.TRUE);
   }
-  private static boolean isReallyLeak(Field field, String fieldName, Object value, Class valueClass) {
+  private static boolean isReallyLeak(Object value) {
     return !(value instanceof UserDataHolder) || ((UserDataHolder)value).getUserData(IS_NOT_A_LEAK) == null;
   }
 
@@ -209,7 +90,7 @@ public class LeakHunter {
         return !project.isDefault() && !((ProjectImpl)project).isLight();
       }
     };
-    Collection<Object> roots = new ArrayList<Object>(Arrays.asList(ApplicationManager.getApplication(), Extensions.getRootArea()));
+    Collection<Object> roots = new ArrayList<Object>(allRoots());
     ClassLoader classLoader = LeakHunter.class.getClassLoader();
     Vector<Class> allLoadedClasses = ReflectionUtil.getField(classLoader.getClass(), classLoader, Vector.class, "classes");
     roots.addAll(allLoadedClasses); // inspect static fields of all loaded classes
@@ -243,17 +124,7 @@ public class LeakHunter {
           String place = leaked instanceof Project ? PlatformTestCase.getCreationPlace((Project)leaked) : "";
           System.out.println("Leaked object found:" + leaked +
                              "; hash: " + System.identityHashCode(leaked) + "; place: " + place);
-          while (backLink != null) {
-            String valueStr;
-            try {
-              valueStr = backLink.value instanceof FList ? "FList" : backLink.value instanceof Collection ? "Collection" : String.valueOf(backLink.value);
-            }
-            catch (Throwable e) {
-              valueStr = "(" + e.getMessage() + " while computing .toString())";
-            }
-            System.out.println("-->" + backLink.field + "; Value: " + valueStr + "; " + backLink.value.getClass());
-            backLink = backLink.backLink;
-          }
+          System.out.println(backLink);
           System.out.println(";-----");
 
           throw new AssertionError();
@@ -273,4 +144,9 @@ public class LeakHunter {
   public static <T> void checkLeak(@NotNull Object root, @NotNull Class<T> suspectClass, @Nullable final Processor<? super T> isReallyLeak) throws AssertionError {
     checkLeak(Collections.singletonList(root), suspectClass, isReallyLeak);
   }
+
+  @NotNull
+  public static List<Object> allRoots() {
+    return Arrays.asList(ApplicationManager.getApplication(), Disposer.getTree(), IdeEventQueue.getInstance(), LaterInvocator.getLaterInvocatorQueue());
+  }
 }
index 4a83a881fb605d9612ff6830f286bcb8e54600e1..11e128a69540fd0d549fc9200d520534b960d2f6 100644 (file)
@@ -47,7 +47,7 @@ public class MessageBusImpl implements MessageBus {
       return ContainerUtil.compareLexicographically(bus1.myOrderRef.get(), bus2.myOrderRef.get());
     }
   };
-  @SuppressWarnings("SSBasedInspection") private final ThreadLocal<Queue<DeliveryJob>> myMessageQueue = createThreadLocalQueue();
+  private final ThreadLocal<Queue<DeliveryJob>> myMessageQueue = createThreadLocalQueue();
 
   /**
    * Root's order is empty
@@ -75,13 +75,11 @@ public class MessageBusImpl implements MessageBus {
   private MessageBusImpl myParentBus;
 
   //is used for debugging purposes
-  private final String myOwner;
+  private final Object myOwner;
   private boolean myDisposed;
-  private final Disposable myConnectionDisposable;
 
   public MessageBusImpl(@NotNull Object owner, @NotNull MessageBus parentBus) {
     myOwner = owner.toString() + " of " + owner.getClass();
-    myConnectionDisposable = Disposer.newDisposable(myOwner);
     myParentBus = (MessageBusImpl)parentBus;
     myParentBus.onChildBusCreated(this);
     LOG.assertTrue(myParentBus.myChildBuses.contains(this));
@@ -90,7 +88,6 @@ public class MessageBusImpl implements MessageBus {
 
   private MessageBusImpl(Object owner) {
     myOwner = owner.toString() + " of " + owner.getClass();
-    myConnectionDisposable = Disposer.newDisposable(myOwner);
     myOrderRef.set(Collections.<Integer>emptyList());
   }
 
@@ -200,14 +197,14 @@ public class MessageBusImpl implements MessageBus {
   @Override
   @NotNull
   public MessageBusConnection connect() {
-    return connect(myConnectionDisposable);
+    checkNotDisposed();
+    return new MessageBusConnectionImpl(this);
   }
 
   @Override
   @NotNull
   public MessageBusConnection connect(@NotNull Disposable parentDisposable) {
-    checkNotDisposed();
-    final MessageBusConnection connection = new MessageBusConnectionImpl(this);
+    final MessageBusConnection connection = connect();
     Disposer.register(parentDisposable, connection);
     return connection;
   }
@@ -257,7 +254,6 @@ public class MessageBusImpl implements MessageBus {
   @Override
   public void dispose() {
     checkNotDisposed();
-    Disposer.dispose(myConnectionDisposable);
     Queue<DeliveryJob> jobs = myMessageQueue.get();
     if (!jobs.isEmpty()) {
       LOG.error("Not delivered events in the queue: " + jobs);
diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/template/toString/DefaultConcatMemberSuperGroovy.vm b/plugins/generate-tostring/src/org/jetbrains/java/generate/template/toString/DefaultConcatMemberSuperGroovy.vm
new file mode 100644 (file)
index 0000000..07d148e
--- /dev/null
@@ -0,0 +1,37 @@
+public java.lang.String toString() {
+#set($d = "$")
+#if ( $members.size() > 0 )
+#set ( $i = 0 )
+    return """\
+$classname{
+#foreach( $member in $members )
+#if( $i > 0 ),
+#end
+#if ( $member.objectArray )
+    $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
+#elseif ( $member.primitiveArray)
+    $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
+#elseif ( $member.string )
+    $member.name='$d$member.accessor'##
+#else
+    $member.name=$d${member.accessor}##
+#end
+#set( $i = $i + 1 )
+#end
+#if( $class.hasSuper )
+#if( $i > 0 ),
+#end
+    super=${d}{super.toString()}##
+#end
+
+}"""
+#else
+#if( $class.hasSuper )
+    return "$classname{##
+super=${d}{super.toString()}##
+}"
+#else
+    return "$classname{}"
+#end
+#end
+}
\ No newline at end of file
index 97413c8a7676275af862c7077ad94a62d95f5286..0b2b56482da0a5fabd65daa998466bad3a88c8f7 100644 (file)
@@ -36,6 +36,7 @@ public class ToStringTemplatesManager extends TemplatesManager {
   private static final String DEFAULT_CONCAT = "DefaultConcatMember.vm";
   private static final String DEFAULT_CONCAT_GROOVY = "/org/jetbrains/java/generate/template/toString/DefaultConcatMemberGroovy.vm";
   private static final String DEFAULT_CONCAT_SUPER = "/org/jetbrains/java/generate/template/toString/DefaultConcatMemberSuper.vm";
+  private static final String DEFAULT_CONCAT_SUPER_GROOVY = "/org/jetbrains/java/generate/template/toString/DefaultConcatMemberSuperGroovy.vm";
   private static final String DEFAULT_BUFFER = "/org/jetbrains/java/generate/template/toString/DefaultBuffer.vm";
   private static final String DEFAULT_BUILDER = "/org/jetbrains/java/generate/template/toString/DefaultBuilder.vm";
   private static final String DEFAULT_TOSTRINGBUILDER = "/org/jetbrains/java/generate/template/toString/DefaultToStringBuilder.vm";
@@ -60,6 +61,7 @@ public class ToStringTemplatesManager extends TemplatesManager {
         new TemplateResource("Objects.toStringHelper (Guava)", readFile(DEFAULT_GUAVA), true),
         new TemplateResource("MoreObjects.toStringHelper (Guava 18+)", readFile(DEFAULT_GUAVA_18), true),
         new TemplateResource("Groovy: String concat (+)", readFile(DEFAULT_CONCAT_GROOVY), true),
+        new TemplateResource("Groovy: String concat (+) and super.toString()", readFile(DEFAULT_CONCAT_SUPER_GROOVY), true),
       };
     }
     catch (IOException e) {
index 40b1b701a1ee3679244fb6779a377fe1b0f121ac..dbc08d772f5209defbda277caa851ebd923add72 100644 (file)
 
 
     <group id="GroovyGenerateGroup1">
+      <action id="org.jetbrains.plugins.groovy.actions.generate.tostring.GroovyGenerateToStringAction"
+              class="org.jetbrains.plugins.groovy.actions.generate.tostring.GroovyGenerateToStringAction"
+              text="to_String()" description="Generate toString() method"/>
       <action id="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
               class="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
               text="Constructor" description="Generates constructor"/>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/tostring/GroovyGenerateToStringAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/tostring/GroovyGenerateToStringAction.java
new file mode 100644 (file)
index 0000000..8df538d
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.actions.generate.tostring;
+
+import org.jetbrains.java.generate.GenerateToStringActionHandlerImpl;
+import org.jetbrains.plugins.groovy.actions.generate.GrBaseGenerateAction;
+
+public class GroovyGenerateToStringAction extends GrBaseGenerateAction {
+  public GroovyGenerateToStringAction() {
+    super(new GenerateToStringActionHandlerImpl());
+  }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateActionsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateActionsTest.groovy
new file mode 100644 (file)
index 0000000..d5daede
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.lang.actions.generate
+
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase
+import com.intellij.testFramework.TestActionEvent
+import org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterAction
+import org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction
+import org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateSetterAction
+import org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction
+import org.jetbrains.plugins.groovy.actions.generate.equals.GroovyGenerateEqualsAction
+import org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGenerateMethodMissingAction
+import org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGeneratePropertyMissingAction
+import org.jetbrains.plugins.groovy.actions.generate.tostring.GroovyGenerateToStringAction
+
+class GroovyGenerateActionsTest extends LightPlatformCodeInsightTestCase {
+
+  void 'test generate actions enabled for groovy files'() {
+    configureFromFileText 'a.groovy', '''\
+class Test {
+  def field
+  def anotherField
+
+  <caret>
+}
+'''
+    def actions = [
+      new GroovyGenerateEqualsAction(),
+      new GroovyGenerateGetterAction(),
+      new GroovyGenerateSetterAction(),
+      new GroovyGenerateGetterSetterAction(),
+      new GroovyGenerateConstructorAction(),
+      new GroovyGeneratePropertyMissingAction(),
+      new GroovyGenerateMethodMissingAction(),
+      new GroovyGenerateToStringAction()
+    ]
+    actions.each {
+      def event = new TestActionEvent(getCurrentEditorDataContext(), it)
+      it.update(event)
+      assert event.presentation.enabledAndVisible
+    }
+  }
+
+  void 'test generate actions disabled for non-groovy files'() {
+    configureFromFileText 'a.java', '''\
+class Test {
+  String field;
+  int anotherField;
+
+  <caret>
+}
+'''
+    def actions = [
+      new GroovyGenerateEqualsAction(),
+      new GroovyGenerateGetterAction(),
+      new GroovyGenerateSetterAction(),
+      new GroovyGenerateGetterSetterAction(),
+      new GroovyGenerateConstructorAction(),
+      new GroovyGeneratePropertyMissingAction(),
+      new GroovyGenerateMethodMissingAction(),
+      new GroovyGenerateToStringAction()
+    ]
+    actions.each {
+      def event = new TestActionEvent(getCurrentEditorDataContext(), it)
+      it.update(event)
+      assert !event.presentation.enabledAndVisible
+    }
+  }
+}
index 580d849bf7e9b1a8ff1ad4905a4c1a5ff59e6d2c..6003adc09cac14f1e1119675da2a887fa8f6ebfe 100644 (file)
@@ -86,6 +86,8 @@ public abstract class MavenIndicesStressTest extends MavenIndicesTestCase implem
     t2.join(100);
 
     indices.close();
+    t1.join();
+    t2.join();
   }
 
   public void test2() throws Exception {
@@ -130,6 +132,8 @@ public abstract class MavenIndicesStressTest extends MavenIndicesTestCase implem
 
     indices1.close();
     indices2.close();
+    t1.join();
+    t2.join();
   }
 
   private static Thread createThread(final MavenIndex index, final AtomicInteger finishedCount) {
index 4f9b1dfa46d0eeff46b1fd9a87375843cc4678aa..c99138a785da4435130bace006345866d4d0d6b8 100644 (file)
@@ -124,12 +124,9 @@ public class SvnBusyOnAddTest extends TestCase {
       final Semaphore semaphoreWokeUp = new Semaphore();
 
       final AtomicReference<Boolean> wasUp = new AtomicReference<Boolean>(false);
-      final ISVNStatusHandler handler = new ISVNStatusHandler() {
-        @Override
-        public void handleStatus(SVNStatus status) throws SVNException {
-          semaphore.waitFor();
-          wasUp.set(true);
-        }
+      final ISVNStatusHandler handler = status -> {
+        semaphore.waitFor();
+        wasUp.set(true);
       };
 
       semaphore.down();
@@ -137,19 +134,17 @@ public class SvnBusyOnAddTest extends TestCase {
       semaphoreWokeUp.down();
 
       final SVNException[] exception = new SVNException[1];
-      new Thread(new Runnable() {
-        @Override
-        public void run() {
-          try {
-            semaphoreMain.up();
-            readClient.doStatus(myWorkingCopyRoot, true, false, true, false, handler);
-            semaphoreWokeUp.up();
-          }
-          catch (SVNException e) {
-            exception[0] = e;
-          }
+      Thread thread = new Thread(() -> {
+        try {
+          semaphoreMain.up();
+          readClient.doStatus(myWorkingCopyRoot, true, false, true, false, handler);
+          semaphoreWokeUp.up();
         }
-      },"svn test").start();
+        catch (SVNException e) {
+          exception[0] = e;
+        }
+      }, "svn test");
+      thread.start();
 
       semaphoreMain.waitFor();
       TimeoutUtil.sleep(5);
@@ -162,7 +157,9 @@ public class SvnBusyOnAddTest extends TestCase {
       if (exception[0] != null) {
         throw exception[0];
       }
-    } finally {
+      thread.join();
+    }
+    finally {
       ioFile.delete();
     }
   }
index c9ca1afc96df489251476834f438c11dda856a2a..f97d3baf0348c74d73ac331c7fa2fc005dc98383 100644 (file)
@@ -32,6 +32,8 @@ import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.io.ISVNSession;
 import org.tmatesoft.svn.core.io.SVNRepository;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.Random;
 
@@ -127,6 +129,7 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest {
       }
     }
     Assert.assertTrue(!thread.isAlive());
+    thread.join();
     Assert.assertNotNull(exc[0]);
     //repository1.fireConnectionClosed(); // also test that used are also closed.. in dispose
 
@@ -151,7 +154,7 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest {
     Assert.assertEquals(0, group.getInactiveSize());
   }
 
-  private void testBigFlow(final SvnIdeaRepositoryPoolManager poolManager, boolean disposeAfter) throws SVNException {
+  private void testBigFlow(final SvnIdeaRepositoryPoolManager poolManager, boolean disposeAfter) throws SVNException, InterruptedException {
     poolManager.setCreator(new ThrowableConvertor<SVNURL, SVNRepository, SVNException>() {
       @Override
       public SVNRepository convert(SVNURL svnurl) throws SVNException {
@@ -163,6 +166,7 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest {
     final int[] cnt = new int[1];
     cnt[0] = 25;
     final SVNException[] exc = new SVNException[1];
+    List<Thread> threads = new ArrayList<>();
     for (int i = 0; i < 25; i++) {
       Runnable target = new Runnable() {
         @Override
@@ -186,6 +190,7 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest {
       };
       Thread thread = new Thread(target, "svn cache");
       thread.start();
+      threads.add(thread);
     }
 
     final long start = System.currentTimeMillis();
@@ -217,6 +222,10 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest {
       Assert.assertEquals(0, group.getUsedSize());
       Assert.assertEquals(0, group.getInactiveSize());
     }
+
+    for (Thread thread : threads) {
+      thread.join();
+    }
   }
 
   private boolean timeout(long start) {
index 7e4dc310d7e6c99481d4e27adff2e6f2829bdcae..b3402bed19808755ee4f27b2f6f3976950b9bafd 100644 (file)
@@ -108,6 +108,8 @@ public class SvnLockingTest extends TestCase {
 
       thread1.interrupt();
       thread2.interrupt();
+      thread1.join();
+      thread2.join();
     }
   }
 
@@ -138,6 +140,8 @@ public class SvnLockingTest extends TestCase {
 
       thread1.interrupt();
       thread2.interrupt();
+      thread1.join();
+      thread2.join();
     }
   }
 
@@ -225,6 +229,9 @@ public class SvnLockingTest extends TestCase {
       thread1.interrupt();
       thread2.interrupt();
       threadRead.interrupt();
+      thread1.join();
+      thread2.join();
+      threadRead.join();
     }
   }
 
index 9477478950cbcdc174b071238d35e3f7fb1e9327..7c95d06505f460f5e15169dedf6713502c6c20fc 100644 (file)
@@ -57,5 +57,6 @@ public class VcsWaitForUpdateForTest extends Svn17TestCase {
     }
 
     assert Boolean.TRUE.equals(done.get());
+    thread.join();
   }
 }
index 99d4a89be9585fd9d18797127187003f8bff3f9b..f65393ae91339f5e3c2db223c23c9fb4bb151633 100644 (file)
@@ -57,5 +57,6 @@ public class VcsWaitForUpdateForTest extends Svn16TestCase {
     }
 
     assert Boolean.TRUE.equals(done.get());
+    thread.join();
   }
 }
index da0f7a8333bac3246ab9a402b5871a21639bc94f..d555d4e913dc22b41c3847dca025f666860ba9e3 100644 (file)
@@ -29,7 +29,10 @@ try:
 except ImportError:
     # Versions of IPython [0.11,1.0) had an extra hierarchy level
     from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
-from IPython.utils.traitlets import CBool, Unicode
+try:
+    from traitlets import CBool, Unicode
+except ImportError:
+    from IPython.utils.traitlets import CBool, Unicode
 from IPython.core import release
 
 from pydev_imports import xmlrpclib
index ee81d63311f4e41d7727a3d80df551e3ff97eee2..97b0e74a0ff913c8e20d1fdb409a3bbe0047e33a 100644 (file)
@@ -324,9 +324,10 @@ public class PyConsoleTask extends PyExecutionFixtureTestTask {
       myLen = s.length();
     }
 
-    public void stop() {
+    public void stop() throws InterruptedException {
       printToConsole();
       myThread.interrupt();
+      myThread.join();
     }
   }
 
index 337a33dd75fcec2efdbf85058d6ebec5ee566af4..881e366306f1b322d790677ab965733e13a67145 100644 (file)
@@ -382,8 +382,9 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
       }
     }
 
-    public void stop() {
+    public void stop() throws InterruptedException {
       myThread.interrupt();
+      myThread.join();
     }
   }
 }
index 22bbc6f605204a647c9f6084fd44513e21511482..688f7bc95a9bddc3093d96759469dbccd745429e 100644 (file)
@@ -121427,6 +121427,8 @@ superstructures
 supertanker
 supertanker's
 supertankers
+supertype
+supertypes
 superuser
 superusers
 supervene
index 82f2f804c5c8f5e30471d2056d65f91afa364ab7..88faf95ea6566840c6d1e0af24f563c389d1a0a6 100644 (file)
@@ -28,7 +28,6 @@ import com.intellij.semantic.SemService;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.testFramework.Timings;
 import com.intellij.util.Function;
-import com.intellij.util.Processor;
 import com.intellij.util.TimeoutUtil;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.xml.impl.DomFileElementImpl;
@@ -121,33 +120,23 @@ public class DomConcurrencyStressTest extends DomTestCase {
 
       int N = 8;
       final CountDownLatch reads = new CountDownLatch(N);
-      List<Thread> threads = ContainerUtil.map(Collections.nCopies(N, ""), new Function<String, Thread>() {
+      List<Thread> threads = ContainerUtil.map(Collections.nCopies(N, ""), (Function<String, Thread>)s -> new Thread("dom concurrency") {
         @Override
-        public Thread fun(String s) {
-          return new Thread("dom concurrency") {
-            @Override
-            public void run() {
-              try {
-                runnable.run();
-              }
-              catch (Throwable e) {
-                exc.set(e);
-              }
-              finally {
-                reads.countDown();
-              }
-            }
-          };
-        }
-      });
-      ContainerUtil.process(threads, new Processor<Thread>() {
-        @Override
-        public boolean process(Thread thread) {
-          thread.start();
-          return true;
+        public void run() {
+          try {
+            runnable.run();
+          }
+          catch (Throwable e) {
+            exc.set(e);
+          }
+          finally {
+            reads.countDown();
+          }
         }
       });
 
+      threads.forEach(Thread::start);
+
       reads.await();
       if (!exc.isNull()) {
         throw exc.get();
@@ -207,26 +196,19 @@ public class DomConcurrencyStressTest extends DomTestCase {
     assert bigXml != null;
     final XmlFile file = (XmlFile)PsiManager.getInstance(ourProject).findFile(bigXml);
 
-    runThreads(42, new Runnable() {
-
-      @Override
-      public void run() {
-        final Random random = new Random();
-        for (int i = 0; i < ITERATIONS; i++) {
-          ApplicationManager.getApplication().runReadAction(new Runnable() {
-            @Override
-            public void run() {
-              int offset = random.nextInt(file.getTextLength() - 10);
-              XmlTag tag = PsiTreeUtil.findElementOfClassAtOffset(file, offset, XmlTag.class, false);
-              assert tag != null : offset;
-              DomElement element = DomUtil.getDomElement(tag);
-              assert element instanceof MyAllCustomElement : element;
-            }
-          });
-
-          if (random.nextInt(50) == 0) {
-            SemService.getSemService(getProject()).clearCache();
-          }
+    runThreads(42, () -> {
+      final Random random = new Random();
+      for (int i = 0; i < ITERATIONS; i++) {
+        ApplicationManager.getApplication().runReadAction(() -> {
+          int offset = random.nextInt(file.getTextLength() - 10);
+          XmlTag tag = PsiTreeUtil.findElementOfClassAtOffset(file, offset, XmlTag.class, false);
+          assert tag != null : offset;
+          DomElement element = DomUtil.getDomElement(tag);
+          assert element instanceof MyAllCustomElement : element;
+        });
+
+        if (random.nextInt(50) == 0) {
+          SemService.getSemService(getProject()).clearCache();
         }
       }
     });
index d9642c49acae1004f71085ea0c3594a12b9b2e6f..407b9b053533d44293d6b1aed070adde78304d55 100644 (file)
@@ -177,6 +177,7 @@ public class RngParser {
         public ParsedPattern parseInclude(String uri, SchemaBuilder schemaBuilder, IncludedGrammar g, String inheritedNs)
                 throws BuildException, IllegalSchemaException
         {
+          ProgressManager.checkCanceled();
           return super.parseInclude(resolveURI(virtualFile, uri), schemaBuilder, g, inheritedNs);
         }
       };