Merge remote-tracking branch 'origin/master' appcode/138.524 cppide/138.527 idea/138.526 idea/138.531 phpstorm/138.532 pycharm/138.525 rubymine/138.528 webstorm/138.529 webstorm/138.533
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Mon, 9 Jun 2014 18:19:15 +0000 (22:19 +0400)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Mon, 9 Jun 2014 18:19:15 +0000 (22:19 +0400)
73 files changed:
bin/mac/fsnotifier
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java
java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/SuspiciousMethodCallUtil.java
java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java
java/java-analysis-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java
java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsElementImpl.java
java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaVariableConflictResolver.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA61415.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA65473.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57338.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67600.java [new file with mode: 0644]
java/java-tests/testData/inspection/suspiciousCalls/SetList.java [new file with mode: 0644]
java/java-tests/testData/inspection/unusedLibrary/junit.jar [new file with mode: 0644]
java/java-tests/testData/inspection/unusedLibrary/simple/expected.xml [new file with mode: 0644]
java/java-tests/testData/inspection/unusedLibrary/simple/src/Test.java [new file with mode: 0644]
java/java-tests/testData/inspection/unusedLibrary/usedJunit/expected.xml [new file with mode: 0644]
java/java-tests/testData/inspection/unusedLibrary/usedJunit/src/MyTest.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java
java/java-tests/testSrc/com/intellij/codeInspection/SuspiciousCollectionMethodCallsTest.java
java/java-tests/testSrc/com/intellij/codeInspection/UnusedLibraryInspectionTest.java [new file with mode: 0644]
native/fsNotifier/mac/fsnotifier.c
platform/analysis-api/src/com/intellij/codeInspection/reference/RefGraphAnnotator.java
platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java
platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java
platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java
platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java
platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/platform-resources-en/src/messages/CommonBundle.properties
platform/platform-resources-en/src/messages/XmlBundle.properties
platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java [new file with mode: 0644]
platform/testRunner/src/com/intellij/execution/testframework/TestsUIUtil.java
platform/util/src/com/intellij/util/ArrayUtil.java
platform/util/src/com/intellij/util/io/URLUtil.java
plugins/git4idea/remote-servers-git/remote-servers-git.iml
plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
plugins/git4idea/src/git4idea/util/GitCommitCompareInfo.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java
plugins/hg4idea/src/META-INF/plugin.xml
plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateConfigurationSettings.java [new file with mode: 0644]
plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java
plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateType.java [new file with mode: 0644]
plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdater.java
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.java
plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgUpdateTest.java
plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetParser.java
xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java

index e2524e76d1bfcc1357127de6bcac59a23df7d030..d69157acdb19d6b7d460218ffb8a58b04c4235e8 100755 (executable)
Binary files a/bin/mac/fsnotifier and b/bin/mac/fsnotifier differ
index 3cd72560f13efce4bbbb252a13a7ce3a6efc5f73..06b11a3d364d249ede316186c9b03846ba5c6686 100644 (file)
@@ -49,6 +49,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.pom.PomNamedTarget;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -77,6 +78,7 @@ import java.util.*;
 public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
   private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
+  private final LanguageLevel myLanguageLevel;
   private RefCountHolder myRefCountHolder;
   private final PsiFile myFile;
   @Nullable private final Editor myEditor;
@@ -109,6 +111,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
     myEndOffset = file.getTextLength();
 
     myCurrentEntryIndex = -1;
+    myLanguageLevel = PsiUtil.getLanguageLevel(file);
   }
 
   static boolean isUpToDate(@NotNull PsiFile file) {
@@ -509,7 +512,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
       //parameter is defined by functional interface
       final PsiElement declarationScope = parameter.getDeclarationScope();
       if (declarationScope instanceof PsiMethod && 
-          myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope)) {
+          myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope, myLanguageLevel)) {
         return null;
       }
       String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
index 018fce54ddba9b16744c80cda09665138772ff5f..7bb318192ba984bb89cd27695213c013de4f6f20 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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,6 +20,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.UserDataHolderEx;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiMatcherImpl;
 import com.intellij.psi.util.PsiMatchers;
@@ -204,8 +205,8 @@ public class RefCountHolder {
     return usedStatus == Boolean.TRUE;
   }
 
-  public boolean isReferencedByMethodReference(@NotNull PsiMethod method) {
-    if (!PsiUtil.isLanguageLevel8OrHigher(method)) return false;
+  public boolean isReferencedByMethodReference(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel) {
+    if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return false;
 
     List<PsiReference> array;
     synchronized (myLocalRefsMap) {
@@ -253,11 +254,10 @@ public class RefCountHolder {
     return true;
   }
 
-  public boolean isReferencedForRead(@NotNull PsiElement element) {
-    LOG.assertTrue(element instanceof PsiVariable);
+  public boolean isReferencedForRead(@NotNull PsiVariable variable) {
     List<PsiReference> array;
     synchronized (myLocalRefsMap) {
-      array = myLocalRefsMap.getKeysByValue(element);
+      array = myLocalRefsMap.getKeysByValue(variable);
     }
     if (array == null) return false;
     for (PsiReference ref : array) {
@@ -277,11 +277,10 @@ public class RefCountHolder {
     return false;
   }
 
-  public boolean isReferencedForWrite(@NotNull PsiElement element) {
-    LOG.assertTrue(element instanceof PsiVariable);
+  public boolean isReferencedForWrite(@NotNull PsiVariable variable) {
     List<PsiReference> array;
     synchronized (myLocalRefsMap) {
-      array = myLocalRefsMap.getKeysByValue(element);
+      array = myLocalRefsMap.getKeysByValue(variable);
     }
     if (array == null) return false;
     for (PsiReference ref : array) {
index ad17594a8c1f60fed4aa03351a82eac1ff6b41f5..10b933018455113e9598a4b4b5045978f0316316 100644 (file)
@@ -163,7 +163,7 @@ public class AnnotationsHighlightUtil {
     return null;
   }
 
-  static HighlightInfo checkDuplicateAnnotations(@NotNull PsiAnnotation annotationToCheck) {
+  static HighlightInfo checkDuplicateAnnotations(@NotNull PsiAnnotation annotationToCheck, @NotNull LanguageLevel languageLevel) {
     PsiAnnotationOwner owner = annotationToCheck.getOwner();
     if (owner == null) return null;
 
@@ -186,7 +186,7 @@ public class AnnotationsHighlightUtil {
       }
     }
     else if (isAnnotationRepeatedTwice(owner, annotationType.getQualifiedName())) {
-      if (!PsiUtil.isLanguageLevel8OrHigher(annotationToCheck)) {
+      if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
         String description = JavaErrorMessages.message("annotation.duplicate.annotation");
         return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
       }
index 659bd14aaec55c7060da14334dd11aa22fffb896..7f8d01382b0952a1042bc6d15dc6515e076cde2b 100644 (file)
@@ -137,7 +137,7 @@ public class GenericsHighlightUtil {
       if (targetParametersNum == 0) {
         if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
             typeParameterListOwner instanceof PsiMethod &&
-            javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) {
+            (javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7) || hasSuperMethodsWithTypeParams((PsiMethod)typeParameterListOwner))) {
           description = null;
         }
         else {
@@ -196,6 +196,13 @@ public class GenericsHighlightUtil {
     return null;
   }
 
+  private static boolean hasSuperMethodsWithTypeParams(PsiMethod method) {
+    for (PsiMethod superMethod : method.findDeepestSuperMethods()) {
+      if (superMethod.hasTypeParameters()) return true;
+    }
+    return false;
+  }
+
   private static PsiType detectExpectedType(PsiReferenceParameterList referenceParameterList) {
     final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(referenceParameterList, PsiNewExpression.class);
     LOG.assertTrue(newExpression != null);
index 1d7e8b4011fa75e7d91843a2a131779a17078104..410be64ee7384a81bb867e1a1cc2d78d468f31f8 100644 (file)
@@ -506,36 +506,29 @@ public class HighlightMethodUtil {
     if (methodCandidate2 != null) {
       return null;
     }
+    if (element != null && !resolveResult.isAccessible()) {
+      description = HighlightUtil.buildProblemWithAccessDescription(referenceToMethod, resolveResult);
+      elementToHighlight = referenceToMethod.getReferenceNameElement();
+    }
+    else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
+      description = HighlightUtil.buildProblemWithStaticDescription(element);
+      elementToHighlight = referenceToMethod.getReferenceNameElement();
+    }
     else {
-      if (element != null && !resolveResult.isAccessible()) {
-        description = HighlightUtil.buildProblemWithAccessDescription(referenceToMethod, resolveResult);
-        elementToHighlight = referenceToMethod.getReferenceNameElement();
-      }
-      else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
-        description = HighlightUtil.buildProblemWithStaticDescription(element);
+      String methodName = referenceToMethod.getReferenceName() + buildArgTypesList(list);
+      description = JavaErrorMessages.message("cannot.resolve.method", methodName);
+      if (candidates.length == 0) {
         elementToHighlight = referenceToMethod.getReferenceNameElement();
+        highlightInfoType = HighlightInfoType.WRONG_REF;
       }
       else {
-        String methodName = referenceToMethod.getReferenceName() + buildArgTypesList(list);
-        description = JavaErrorMessages.message("cannot.resolve.method", methodName);
-        if (candidates.length == 0) {
-          elementToHighlight = referenceToMethod.getReferenceNameElement();
-          highlightInfoType = HighlightInfoType.WRONG_REF;
-        }
-        else {
-          return null;
-        }
+        return null;
       }
-      toolTip = XmlStringUtil.escapeString(description);
     }
+    toolTip = XmlStringUtil.escapeString(description);
     HighlightInfo info =
       HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description).escapedToolTip(toolTip).create();
-    if (methodCandidate2 == null) {
-      registerMethodCallIntentions(info, methodCall, list, resolveHelper);
-    }
-    if (!resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect() && methodCandidate2 != null) {
-      HighlightUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, info, resolveResult.getCurrentFileResolveScope());
-    }
+    registerMethodCallIntentions(info, methodCall, list, resolveHelper);
     if (element != null && !resolveResult.isStaticsScopeCorrect()) {
       HighlightUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
     }
@@ -1014,7 +1007,7 @@ public class HighlightMethodUtil {
   }
 
   @Nullable
-  static HighlightInfo checkMethodCanHaveBody(PsiMethod method, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+  static HighlightInfo checkMethodCanHaveBody(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel) {
     PsiClass aClass = method.getContainingClass();
     boolean hasNoBody = method.getBody() == null;
     boolean isInterface = aClass != null && aClass.isInterface();
@@ -1035,7 +1028,7 @@ public class HighlightMethodUtil {
     else if (isInterface) {
       if (!isExtension && !isStatic) {
         description = JavaErrorMessages.message("interface.methods.cannot.have.body");
-        if (PsiUtil.isLanguageLevel8OrHigher(method)) {
+        if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
           additionalFixes.add(QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.DEFAULT, true, false));
           additionalFixes.add(QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.STATIC, true, false));
         }
@@ -1242,7 +1235,7 @@ public class HighlightMethodUtil {
       }
       return createIncompatibleReturnTypeMessage(currentMethod, otherSuperMethod, otherSuperReturnType,
                                                  currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"),
-                                                 false ? currentMethod.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE);
+                                                 TextRange.EMPTY_RANGE);
     }
     return null;
   }
@@ -1262,7 +1255,7 @@ public class HighlightMethodUtil {
       if (aClass.equals(containingClass)) continue; //to be checked at method level
 
       if (aClass.isInterface() && !containingClass.isInterface()) continue;
-      HighlightInfo highlightInfo = null;
+      HighlightInfo highlightInfo;
       if (allAbstracts) {
         superSignatures = new ArrayList<HierarchicalMethodSignature>(superSignatures);
         superSignatures.add(signature);
index ba0e0fd4765984fbb5d69f0c4d6e3c9f5bc25805..0dc8e3df8fec5db0f07fae2168c95f18576b99a8 100644 (file)
@@ -299,12 +299,12 @@ public class HighlightUtil extends HighlightUtilBase {
 
 
   @Nullable
-  static HighlightInfo checkIntersectionInTypeCast(@NotNull PsiTypeCastExpression expression) {
+  static HighlightInfo checkIntersectionInTypeCast(@NotNull PsiTypeCastExpression expression, @NotNull LanguageLevel languageLevel) {
     final PsiTypeElement castTypeElement = expression.getCastType();
     if (castTypeElement == null) return null;
     PsiType castType = castTypeElement.getType();
     if (isIntersection(castTypeElement, castType)) {
-      if (PsiUtil.isLanguageLevel8OrHigher(expression)) {
+      if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
         final PsiTypeElement[] conjuncts = PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class);
         if (conjuncts != null) {
           final List<PsiTypeElement> conjList = new ArrayList<PsiTypeElement>(Arrays.asList(conjuncts));
@@ -680,8 +680,8 @@ public class HighlightUtil extends HighlightUtilBase {
   }
 
   @Nullable
-  public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable) {
-    if ("_".equals(variable.getName()) && PsiUtil.isLanguageLevel8OrHigher(variable)) {
+  public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable, @NotNull LanguageLevel languageLevel) {
+    if ("_".equals(variable.getName()) && languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
       if (variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) {
         String message = JavaErrorMessages.message("underscore.lambda.identifier");
         return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create();
@@ -1416,7 +1416,8 @@ public class HighlightUtil extends HighlightUtilBase {
 
   @Nullable
   static HighlightInfo checkThisOrSuperExpressionInIllegalContext(@NotNull PsiExpression expr,
-                                                                  @Nullable PsiJavaCodeReferenceElement qualifier) {
+                                                                  @Nullable PsiJavaCodeReferenceElement qualifier,
+                                                                  @NotNull LanguageLevel languageLevel) {
     if (expr instanceof PsiSuperExpression) {
       final PsiElement parent = expr.getParent();
       if (!(parent instanceof PsiReferenceExpression)) {
@@ -1442,7 +1443,7 @@ public class HighlightUtil extends HighlightUtilBase {
     if (aClass == null) return null;
 
     if (!InheritanceUtil.hasEnclosingInstanceInScope(aClass, expr, false, false) &&
-        !resolvesToImmediateSuperInterface(expr, qualifier, aClass)) {
+        !resolvesToImmediateSuperInterface(expr, qualifier, aClass, languageLevel)) {
       return HighlightClassUtil.reportIllegalEnclosingUsage(expr, null, aClass, expr);
     }
 
@@ -1492,8 +1493,9 @@ public class HighlightUtil extends HighlightUtilBase {
 
   private static boolean resolvesToImmediateSuperInterface(@NotNull PsiExpression expr,
                                                            @Nullable PsiJavaCodeReferenceElement qualifier,
-                                                           @NotNull PsiClass aClass) {
-    if (!(expr instanceof PsiSuperExpression) || qualifier == null || !PsiUtil.isLanguageLevel8OrHigher(expr)) return false;
+                                                           @NotNull PsiClass aClass,
+                                                           @NotNull LanguageLevel languageLevel) {
+    if (!(expr instanceof PsiSuperExpression) || qualifier == null || !languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return false;
     final PsiType superType = expr.getType();
     if (!(superType instanceof PsiClassType)) return false;
     final PsiClass superClass = ((PsiClassType)superType).resolve();
index 7056319c5883736dbd40fb41ec34785f17811a46..cbfb5f4f5d6553f90ec848bca3ac44caf5b5a95e 100644 (file)
@@ -220,7 +220,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
-    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation));
+    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation, myLanguageLevel));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation, myLanguageLevel));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkRepeatableAnnotation(annotation));
@@ -590,7 +590,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
         }
       }
 
-      myHolder.add(HighlightUtil.checkUnderscore(identifier, variable));
+      myHolder.add(HighlightUtil.checkUnderscore(identifier, variable, myLanguageLevel));
     }
     else if (parent instanceof PsiClass) {
       PsiClass aClass = (PsiClass)parent;
@@ -833,7 +833,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
     PsiElement parent = list.getParent();
     if (parent instanceof PsiMethod) {
       PsiMethod method = (PsiMethod)parent;
-      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method, myLanguageLevel,myFile));
+      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method, myLanguageLevel));
       MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
       if (!method.isConstructor()) {
         try {
@@ -1378,7 +1378,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
 
   @Override
   public void visitSuperExpression(PsiSuperExpression expr) {
-    myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
+    myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
     if (!myHolder.hasErrorResults()) visitExpression(expr);
   }
 
@@ -1396,7 +1396,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
 
   @Override
   public void visitThisExpression(PsiThisExpression expr) {
-    myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
+    myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
     if (!myHolder.hasErrorResults()) {
       myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
     }
@@ -1452,7 +1452,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
   public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
     super.visitTypeCastExpression(typeCast);
     try {
-      if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast));
+      if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast, myLanguageLevel));
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
     }
     catch (IndexNotReadyException ignore) {
@@ -1498,7 +1498,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
   @Override
   public void visitConditionalExpression(PsiConditionalExpression expression) {
     super.visitConditionalExpression(expression);
-    if (PsiUtil.isLanguageLevel8OrHigher(expression) && PsiPolyExpressionUtil.isPolyExpression(expression)) {
+    if (myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) && PsiPolyExpressionUtil.isPolyExpression(expression)) {
       final PsiExpression thenExpression = expression.getThenExpression();
       final PsiExpression elseExpression = expression.getElseExpression();
       if (thenExpression != null && elseExpression != null) {
index 3b427e8297713cdb3e096ea1d72fc1a2ca10bd7e..c5bba7888154266b9d50fb978c9edf29cd483be8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.*;
 import com.intellij.psi.infos.CandidateInfo;
@@ -35,7 +31,6 @@ import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.util.RefactoringChangeUtil;
-import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.HashSet;
@@ -81,7 +76,6 @@ public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{
         for (CandidateInfo candidate : candidates) {
           PsiMethod method = (PsiMethod)candidate.getElement();
           PsiSubstitutor substitutor = candidate.getSubstitutor();
-          assert method != null;
           PsiParameter[] parameters = method.getParameterList().getParameters();
           if (expressions.length != parameters.length) {
             continue;
index 41111cba76fe52f4bcb17967983161dda23bd19a..ecf21db51d47d3b6d7c85b88cca26fbba9e4dbe2 100644 (file)
@@ -158,11 +158,14 @@ public class SuspiciousMethodCallUtil {
         PsiType paramType = parameters[0].getType();
         if (InheritanceUtil.isInheritor(paramType, CommonClassNames.JAVA_UTIL_COLLECTION)) {
           PsiType qualifierType = qualifier.getType();
-          if (qualifierType != null && !qualifierType.isAssignableFrom(argType)) {
+          if (qualifierType != null) {
             final PsiType itemType = JavaGenericsUtil.getCollectionItemType(argType, calleeMethod.getResolveScope());
-            return InspectionsBundle.message("inspection.suspicious.collections.method.calls.problem.descriptor",
-                                                PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY),
-                                                PsiFormatUtil.formatType(itemType, 0, PsiSubstitutor.EMPTY));
+            final PsiType qualifierItemType = JavaGenericsUtil.getCollectionItemType(qualifierType, calleeMethod.getResolveScope());
+            if (qualifierItemType != null && itemType != null && !qualifierItemType.isAssignableFrom(itemType)) {
+              return InspectionsBundle.message("inspection.suspicious.collections.method.calls.problem.descriptor",
+                                                  PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY),
+                                                  PsiFormatUtil.formatType(itemType, 0, PsiSubstitutor.EMPTY));
+            }
           }
           return null;
         }
index 359c9c962463822f125681cebd1e6cd625beeb7c..e1057c734fcd9c4825754aa760bf1bb3e6ebce0b 100644 (file)
@@ -249,6 +249,7 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa
           }
         }
       }
+      getRefManager().fireNodeMarkedReferenced(psiWhat, psiFrom, false);
     }
   }
 
index 0b72b716fd7a191e56f6c533eb6dcd870ecb9a6b..5a419dfa9647e7e0b800864a94898eed73b149f2 100644 (file)
@@ -23,35 +23,22 @@ package com.intellij.codeInspection.unusedLibraries;
 import com.intellij.analysis.AnalysisScope;
 import com.intellij.codeInsight.daemon.GroupNames;
 import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.JobDescriptor;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
+import com.intellij.codeInspection.reference.*;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleUtilCore;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.impl.DirectoryIndex;
+import com.intellij.openapi.roots.impl.DirectoryInfo;
 import com.intellij.openapi.roots.libraries.Library;
-import com.intellij.openapi.roots.libraries.LibraryUtil;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.packageDependencies.BackwardDependenciesBuilder;
-import com.intellij.psi.PsiCompiledElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiRecursiveElementVisitor;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.GlobalSearchScopesCore;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.PackageSetFactory;
-import com.intellij.psi.search.scope.packageSet.ParsingException;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -60,140 +47,63 @@ import org.jetbrains.annotations.Nullable;
 import java.util.*;
 
 public class UnusedLibrariesInspection extends GlobalInspectionTool {
-  private static final Logger LOG = Logger.getInstance("#" + UnusedLibrariesInspection.class.getName());
-  private final JobDescriptor BACKWARD_ANALYSIS = new JobDescriptor(InspectionsBundle.message("unused.library.backward.analysis.job.description"));
+
+  @Override
+  public boolean isGraphNeeded() {
+    return true;
+  }
 
   @Nullable
   @Override
-  public JobDescriptor[] getAdditionalJobs() {
-    return new JobDescriptor[]{BACKWARD_ANALYSIS};
+  public RefGraphAnnotator getAnnotator(@NotNull RefManager refManager) {
+    return new UnusedLibraryGraphAnnotator(refManager);
   }
 
+  @Nullable
   @Override
-  public void runInspection(@NotNull AnalysisScope scope,
-                            @NotNull InspectionManager manager,
-                            @NotNull final GlobalInspectionContext globalContext,
-                            @NotNull ProblemDescriptionsProcessor problemProcessor) {
-    final Project project = manager.getProject();
-    final ArrayList<VirtualFile> libraryRoots = new ArrayList<VirtualFile>();
-    if (scope.getScopeType() == AnalysisScope.PROJECT) {
-      ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(project, false, false));
-    }
-    else {
-      final Set<Module> modules = new HashSet<Module>();
-      scope.accept(new PsiRecursiveElementVisitor() {
-        @Override
-        public void visitFile(PsiFile file) {
-          if (!(file instanceof PsiCompiledElement)) {
-            final VirtualFile virtualFile = file.getVirtualFile();
-            if (virtualFile != null) {
-              final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
-              if (module != null) {
-                modules.add(module);
-              }
+  public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
+                                                @NotNull AnalysisScope scope,
+                                                @NotNull InspectionManager manager,
+                                                @NotNull GlobalInspectionContext globalContext,
+                                                @NotNull ProblemDescriptionsProcessor processor) {
+    if (refEntity instanceof RefModule) {
+      final RefModule refModule = (RefModule)refEntity;
+      final Module module = refModule.getModule();
+      if (module.isDisposed()) return CommonProblemDescriptor.EMPTY_ARRAY;
+      final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+      final Set<VirtualFile> usedRoots = refModule.getUserData(UnusedLibraryGraphAnnotator.USED_LIBRARY_ROOTS);
+
+      final List<CommonProblemDescriptor> result = new ArrayList<CommonProblemDescriptor>();
+      for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
+        if (entry instanceof LibraryOrderEntry && !((LibraryOrderEntry)entry).isExported()) {
+          if (usedRoots == null) {
+            String message = InspectionsBundle.message("unused.library.problem.descriptor", entry.getPresentableName());
+            result.add(manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, entry, null)));
+          } else {
+            final Set<VirtualFile> files = new HashSet<VirtualFile>(Arrays.asList(((LibraryOrderEntry)entry).getRootFiles(OrderRootType.CLASSES)));
+            files.removeAll(usedRoots);
+            if (!files.isEmpty()) {
+              final String unusedLibraryRoots = StringUtil.join(files, new Function<VirtualFile, String>() {
+                @Override
+                public String fun(final VirtualFile file) {
+                  return file.getPresentableName();
+                }
+              }, ",");
+              String message =
+                InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, entry.getPresentableName());
+              processor.addProblemElement(refModule,
+                                          manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, entry, files)));
             }
           }
         }
-      });
-      ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(modules.toArray(new Module[modules.size()]), false, false));
-    }
-    if (libraryRoots.isEmpty()) {
-      return;
-    }
-
-    GlobalSearchScope searchScope;
-    try {
-      @NonNls final String libsName = "libs";
-      NamedScope libScope = new NamedScope(libsName, PackageSetFactory.getInstance().compile("lib:*..*"));
-      searchScope = GlobalSearchScopesCore.filterScope(project, libScope);
-    }
-    catch (ParsingException e) {
-      //can't be
-      LOG.error(e);
-      return;
-    }
-    final AnalysisScope analysisScope = new AnalysisScope(searchScope, project);
-    analysisScope.setSearchInLibraries(true);
-    final BackwardDependenciesBuilder builder = new BackwardDependenciesBuilder(project, analysisScope);
-
-    final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
-
-    BACKWARD_ANALYSIS.setTotalAmount(builder.getTotalFileCount());
-    ProgressIndicator progress = new AbstractProgressIndicatorBase() {
-      @Override
-      public void setFraction(final double fraction) {
-        super.setFraction(fraction);
-        int nextAmount = (int)(fraction * BACKWARD_ANALYSIS.getTotalAmount());
-        if (nextAmount > BACKWARD_ANALYSIS.getDoneAmount() && nextAmount < BACKWARD_ANALYSIS.getTotalAmount()) {
-          BACKWARD_ANALYSIS.setDoneAmount(nextAmount);
-          globalContext.incrementJobDoneAmount(BACKWARD_ANALYSIS, getText2());
-        }
       }
 
-      @Override
-      public boolean isCanceled() {
-        return progressIndicator != null && progressIndicator.isCanceled() || super.isCanceled();
-      }
-    };
-    ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
-      @Override
-      public void run() {
-        builder.analyze();
-      }
-    }, progress);
-    BACKWARD_ANALYSIS.setDoneAmount(BACKWARD_ANALYSIS.getTotalAmount());
-    final Map<PsiFile, Set<PsiFile>> dependencies = builder.getDependencies();
-    for (PsiFile file : dependencies.keySet()) {
-      final VirtualFile virtualFile = file.getVirtualFile();
-      LOG.assertTrue(virtualFile != null);
-      for (Iterator<VirtualFile> i = libraryRoots.iterator(); i.hasNext();) {
-        if (VfsUtilCore.isAncestor(i.next(), virtualFile, false)) {
-          i.remove();
-        }
-      }
-    }
-    if (libraryRoots.isEmpty()) {
-      return;
-    }
-    ProjectFileIndex projectIndex = ProjectRootManager.getInstance(project).getFileIndex();
-    Map<OrderEntry, Set<VirtualFile>> unusedLibs = new HashMap<OrderEntry, Set<VirtualFile>>();
-    for (VirtualFile libraryRoot : libraryRoots) {
-      final List<OrderEntry> orderEntries = projectIndex.getOrderEntriesForFile(libraryRoot);
-      for (OrderEntry orderEntry : orderEntries) {
-        Set<VirtualFile> files = unusedLibs.get(orderEntry);
-        if (files == null) {
-          files = new HashSet<VirtualFile>();
-          unusedLibs.put(orderEntry, files);
-        }
-        files.add(libraryRoot);
-      }
-    }
-    final RefManager refManager = globalContext.getRefManager();
-    for (OrderEntry orderEntry : unusedLibs.keySet()) {
-      if (!(orderEntry instanceof LibraryOrderEntry)) continue;
-      final RefModule refModule = refManager.getRefModule(orderEntry.getOwnerModule());
-      final Set<VirtualFile> files = unusedLibs.get(orderEntry);
-      final VirtualFile[] roots = ((LibraryOrderEntry)orderEntry).getRootFiles(OrderRootType.CLASSES);
-      if (files.size() < roots.length) {
-        final String unusedLibraryRoots = StringUtil.join(files, new Function<VirtualFile, String>() {
-            @Override
-            public String fun(final VirtualFile file) {
-              return file.getPresentableName();
-            }
-          }, ",");
-        String message =
-          InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, orderEntry.getPresentableName());
-        problemProcessor.addProblemElement(refModule,
-                                           manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, files)));
-      }
-      else {
-        String message = InspectionsBundle.message("unused.library.problem.descriptor", orderEntry.getPresentableName());
-        problemProcessor.addProblemElement(refModule,
-                                           manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, null)));
-      }
+      return result.isEmpty() ? null : result.toArray(new CommonProblemDescriptor[result.size()]);
     }
+    return null;
   }
 
+
   @Override
   public boolean isEnabledByDefault() {
     return false;
@@ -272,4 +182,41 @@ public class UnusedLibrariesInspection extends GlobalInspectionTool {
       });
     }
   }
+
+  private static class UnusedLibraryGraphAnnotator extends RefGraphAnnotator {
+    public static final Key<Set<VirtualFile>> USED_LIBRARY_ROOTS = Key.create("inspection.dependencies");
+    private final DirectoryIndex myDirectoryIndex;
+    private RefManager myManager;
+
+    public UnusedLibraryGraphAnnotator(RefManager manager) {
+      myManager = manager;
+      myDirectoryIndex = DirectoryIndex.getInstance(manager.getProject());
+    }
+
+    @Override
+    public void onMarkReferenced(PsiElement what, PsiElement from, boolean referencedFromClassInitializer) {
+      if (what != null && from != null){
+        final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(what);
+        final VirtualFile containingDir = virtualFile != null ? virtualFile.getParent() : null;
+        if (containingDir != null) {
+          final DirectoryInfo infoForDirectory = myDirectoryIndex.getInfoForDirectory(containingDir);
+          final VirtualFile libraryClassRoot = infoForDirectory != null ? infoForDirectory.getLibraryClassRoot() : null;
+          if (libraryClassRoot != null) {
+            final Module fromModule = ModuleUtilCore.findModuleForPsiElement(from);
+            if (fromModule != null){
+              final RefModule refModule = myManager.getRefModule(fromModule);
+              if (refModule != null) {
+                Set<VirtualFile> modules = refModule.getUserData(USED_LIBRARY_ROOTS);
+                if (modules == null){
+                  modules = new HashSet<VirtualFile>();
+                  refModule.putUserData(USED_LIBRARY_ROOTS, modules);
+                }
+                modules.add(libraryClassRoot);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }
index 7ff2d6f9e4bc5b5b572dc941f5b156801da79844..08a071231410eb28485008f83d370911550e9df4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -938,7 +938,6 @@ public class ExpectedTypesProvider {
         for (CandidateInfo candidate : methodCandidates) {
           PsiMethod method = (PsiMethod)candidate.getElement();
           PsiSubstitutor substitutor = candidate.getSubstitutor();
-          assert method != null;
           PsiParameter[] params = method.getParameterList().getParameters();
           if (params.length <= index) continue;
           PsiParameter param = params[index];
index 144be8a5dc5248dd5d595a9c2928a2a4adaaf1e9..7015004b734019088f02a755ccbfd16c524a85f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -97,7 +97,6 @@ public class JavaGenerateMemberCompletionContributor {
   private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result, Set<MethodSignature> addedSignatures) {
     for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
       PsiMethod baseMethod = (PsiMethod)candidate.getElement();
-      assert baseMethod != null;
       PsiClass baseClass = baseMethod.getContainingClass();
       PsiSubstitutor substitutor = candidate.getSubstitutor();
       if (!baseMethod.isConstructor() && baseClass != null && addedSignatures.add(baseMethod.getSignature(substitutor))) {
index ea34686ec8af8eb4e242526b0a856579ff7bbb92..e2065ce3d46cdd1634e6c3ece042da78a7d000fb 100644 (file)
@@ -371,7 +371,12 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
               !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(TypeConversionUtil.erasure(originalBound)) &&
               !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(originalBound)) { //erasure is essential to avoid infinite recursion
             if (wildcardType.isExtends()) {
-              final PsiType glb = GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType);
+              final PsiType bound = wildcardType.getBound();
+              if (bound instanceof PsiArrayType && substitutedBoundType instanceof PsiArrayType &&
+                  !bound.isAssignableFrom(substitutedBoundType) && !substitutedBoundType.isAssignableFrom(bound)) {
+                continue;
+              }
+              final PsiType glb = GenericsUtil.getGreatestLowerBound(bound, substitutedBoundType);
               if (glb != null) {
                 substituted = PsiWildcardType.createExtends(manager, glb);
               }
index 8808cc7cde1067acf080433b3600481c51cb8311..a2ce5b36c589ee334dc22e7d0044897cb47b1909 100644 (file)
@@ -228,7 +228,7 @@ public abstract class ClsElementImpl extends PsiElementBase implements PsiCompil
 
     StringBuilder buffer = new StringBuilder();
     appendMirrorText(0, buffer);
-    LOG.error("Mirror wasn't set for " + this + " in " + getContainingFile() + ", expected text '" + buffer + "'");
+    LOG.warn("Mirror wasn't set for " + this + " in " + getContainingFile() + ", expected text '" + buffer + "'");
     return buffer.toString();
   }
 
index 9cdca6d1b79ec6871dddefe27945f9f44014020f..403465efab0392c97aeced4d4c6f712f421f0873 100644 (file)
@@ -275,10 +275,8 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
                                      @NotNull PsiElement place) {
     assert isValid();
 
-    // TODO den remove
-    boolean allowCaching = true;
-
-    if (allowCaching && processor instanceof ClassResolverProcessor && isPhysical() &&
+    if (processor instanceof ClassResolverProcessor &&
+        isPhysical() &&
         (getUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING) == Boolean.TRUE || myResolveCache.hasUpToDateValue())) {
       final ClassResolverProcessor hint = (ClassResolverProcessor)processor;
       String name = hint.getName(state);
index f3257f91ac3e71599b8839ba7ffbd4e3aa41fa3a..aa18e6e6b8a4d669da87fc28c1c1a5defe87608a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -148,18 +148,16 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
       ProgressManager.checkCanceled();
       final CandidateInfo conflict = iterator.next();
       final PsiMethod method = (PsiMethod)conflict.getElement();
-      if (method != null) {
-        final PsiParameter[] methodParameters = method.getParameterList().getParameters();
-        if (methodParameters.length == 0) continue;
-        final PsiParameter param = i < methodParameters.length ? methodParameters[i] : methodParameters[methodParameters.length - 1];
-        final PsiType paramType = param.getType();
-        // http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1
-        // A lambda expression or a method reference expression is potentially compatible with a type variable if the type variable is a type parameter of the candidate method.
-        final PsiClass paramClass = PsiUtil.resolveClassInType(paramType);
-        if (paramClass instanceof PsiTypeParameter && ((PsiTypeParameter)paramClass).getOwner() == method) continue;
-        if (!lambdaExpression.isAcceptable(((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType), lambdaExpression.hasFormalParameterTypes())) {
-          iterator.remove();
-        }
+      final PsiParameter[] methodParameters = method.getParameterList().getParameters();
+      if (methodParameters.length == 0) continue;
+      final PsiParameter param = i < methodParameters.length ? methodParameters[i] : methodParameters[methodParameters.length - 1];
+      final PsiType paramType = param.getType();
+      // http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1
+      // A lambda expression or a method reference expression is potentially compatible with a type variable if the type variable is a type parameter of the candidate method.
+      final PsiClass paramClass = PsiUtil.resolveClassInType(paramType);
+      if (paramClass instanceof PsiTypeParameter && ((PsiTypeParameter)paramClass).getOwner() == method) continue;
+      if (!lambdaExpression.isAcceptable(((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType), lambdaExpression.hasFormalParameterTypes())) {
+        iterator.remove();
       }
     }
   }
@@ -240,7 +238,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
       ProgressManager.checkCanceled();
       CandidateInfo info = conflicts.get(i);
       PsiMethod method = (PsiMethod)info.getElement();
-      assert method != null;
 
       if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) {
         conflicts.remove(i);
@@ -258,7 +255,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
         continue;
       }
       PsiMethod existingMethod = (PsiMethod)existing.getElement();
-      assert existingMethod != null;
       PsiClass existingClass = existingMethod.getContainingClass();
       if (class1 != null && existingClass != null && 
           class1.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(existingClass.getQualifiedName())) { //prefer interface methods to methods from Object
@@ -768,7 +764,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
       for (CandidateInfo conflict : conflicts) {
         ProgressManager.checkCanceled();
         PsiMethod method = (PsiMethod)conflict.getElement();
-        if (method != objectVararg && method != null && method.isVarArgs()) {
+        if (method != objectVararg && method.isVarArgs()) {
           final int paramsCount = method.getParameterList().getParametersCount();
           final PsiType type = method.getParameterList().getParameters()[paramsCount - 1].getType();
           final PsiType componentType = ((PsiArrayType)type).getComponentType();
@@ -784,7 +780,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
   @Nullable
   private static PsiType getFunctionalType(int functionalTypeIdx, CandidateInfo candidateInfo) {
     final PsiMethod psiMethod = (PsiMethod)candidateInfo.getElement();
-    LOG.assertTrue(psiMethod != null);
+    LOG.assertTrue(true);
     final PsiParameter[] methodParameters = psiMethod.getParameterList().getParameters();
     if (methodParameters.length == 0) return null;
     final PsiParameter param = functionalTypeIdx < methodParameters.length ? methodParameters[functionalTypeIdx] : methodParameters[methodParameters.length - 1];
index f5e13840d5e8be9553d1bdcea6f31ad3a3a0907f..3a34be7a731b88472ff6493f1ffddb27934611c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -50,7 +50,6 @@ public class JavaVariableConflictResolver implements PsiConflictResolver{
       for (int i = 1; i < uncheckedResult.length; i++) {
         final CandidateInfo candidate = uncheckedResult[i];
         final PsiElement otherElement = candidate.getElement();
-        if (otherElement == null) continue;
 
         if (!(otherElement instanceof PsiField)) {
           if (otherElement instanceof PsiLocalVariable) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA61415.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA61415.java
new file mode 100644 (file)
index 0000000..8f86c8e
--- /dev/null
@@ -0,0 +1,10 @@
+class Test {
+  Runnable r = new Runnable() {
+    <error descr="Modifier 'private' not allowed here">private</error> class Foo {}
+    @Override
+    public void run() {
+
+    }
+  };
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA65473.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/IDEA65473.java
new file mode 100644 (file)
index 0000000..13e19fe
--- /dev/null
@@ -0,0 +1,13 @@
+
+class FirstClass {
+  public FirstClass(int i) {
+  }
+
+  public FirstClass() {
+    this(Point.FOO);
+  }
+
+  public class Point {
+    public static final int FOO = 0;
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57338.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57338.java
new file mode 100644 (file)
index 0000000..06e25b1
--- /dev/null
@@ -0,0 +1,17 @@
+abstract class A {
+  abstract <T> void foo();
+}
+
+abstract class B extends A {
+  void foo()
+  {
+    this.<Integer>foo();
+  }
+}
+
+abstract class C {
+  void foo()
+  {
+    this.<error descr="Method 'foo()' does not have type parameters"><Integer></error>foo();
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67600.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67600.java
new file mode 100644 (file)
index 0000000..6f0e625
--- /dev/null
@@ -0,0 +1,24 @@
+abstract class A<T, S extends T>
+{
+  abstract S bar();
+  void foo(A<Runnable[], ? extends Cloneable[]> a){
+    <error descr="Incompatible types. Found: 'java.lang.Cloneable[]', required: 'java.lang.Runnable[]'">Runnable[] x = a.bar();</error>
+  }
+}
+
+abstract class AB<T, S extends T>
+{
+  abstract S bar();
+  void foo(AB<Runnable, ? extends Cloneable> a){
+    Runnable x = a.bar();
+  }
+}
+
+abstract class AC<T, S>
+{
+  abstract S bar();
+  void foo(AC<Runnable[], ? extends Cloneable[]> a){
+    <error descr="Incompatible types. Found: 'java.lang.Cloneable[]', required: 'java.lang.Runnable[]'">Runnable[] x = a.bar();</error>
+  }
+}
+
diff --git a/java/java-tests/testData/inspection/suspiciousCalls/SetList.java b/java/java-tests/testData/inspection/suspiciousCalls/SetList.java
new file mode 100644 (file)
index 0000000..19f0b0f
--- /dev/null
@@ -0,0 +1,8 @@
+import java.util.List;
+import java.util.Set;
+
+class Clazz {
+    void foo(List<String> l, Set<String> s) {
+      l.removeAll(s);
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/unusedLibrary/junit.jar b/java/java-tests/testData/inspection/unusedLibrary/junit.jar
new file mode 100644 (file)
index 0000000..bfb318b
Binary files /dev/null and b/java/java-tests/testData/inspection/unusedLibrary/junit.jar differ
diff --git a/java/java-tests/testData/inspection/unusedLibrary/simple/expected.xml b/java/java-tests/testData/inspection/unusedLibrary/simple/expected.xml
new file mode 100644 (file)
index 0000000..8184735
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+  <problem>
+    <file>testSimple_0.iml</file>
+    <problem_class>Unused library</problem_class>
+    <description>Unused library 'JUnit'</description>
+  </problem>
+
+</problems>
+
diff --git a/java/java-tests/testData/inspection/unusedLibrary/simple/src/Test.java b/java/java-tests/testData/inspection/unusedLibrary/simple/src/Test.java
new file mode 100644 (file)
index 0000000..96d83e0
--- /dev/null
@@ -0,0 +1,2 @@
+class Test {
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/unusedLibrary/usedJunit/expected.xml b/java/java-tests/testData/inspection/unusedLibrary/usedJunit/expected.xml
new file mode 100644 (file)
index 0000000..ec272ab
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems/>
+
diff --git a/java/java-tests/testData/inspection/unusedLibrary/usedJunit/src/MyTest.java b/java/java-tests/testData/inspection/unusedLibrary/usedJunit/src/MyTest.java
new file mode 100644 (file)
index 0000000..dceefa7
--- /dev/null
@@ -0,0 +1,2 @@
+import junit.framework.TestCase;
+public class MyTest extends TestCase {}
index e347b4c192b16f3495060ae1872ee32899809dca..74d2465f43a53de8750fbde564ab3d925f4c3628 100644 (file)
@@ -366,6 +366,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
   public void testIDEA57388() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
   public void testIDEA125800() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
   public void testIDEA125816() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
+  public void testIDEA57338() { doTest(LanguageLevel.JDK_1_6, JavaSdkVersion.JDK_1_6, false); }
+  public void testIDEA67600() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
   //jdk should propagate LL 1.4 but actually it provides LL 1.7?!
   public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); }
 
index 671d151179fe53bcbe9fbd196467ce1c47953194..fa4334a591ee5068354230521bc2315dac6c89af 100644 (file)
@@ -64,6 +64,8 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase {
   public void testEnumInitializers() { doTest(false, false); }
   public void testEnumSynthetics() { doTest(false, false); }
   public void testIDEA79251() { doTest(false, false); }
+  public void testIDEA65473() { doTest(false, false); }
+  public void testIDEA61415() { doTest(false, false); }
   public void testAgentPremain() {
     doTest(false, false); 
   }
index 404219c5d067bab58cb922824807498d5d384ddb..4d3ef19d9828044c5a119786fff73383773a6648 100644 (file)
@@ -21,6 +21,7 @@ public class SuspiciousCollectionMethodCallsTest extends LightCodeInsightFixture
 
   public void testConcurrentHashMap() throws Exception { doTest(); }
   public void testRemoveAllCall() throws Exception { doTest(); }
+  public void testSetList() throws Exception { doTest(); }
   public void testUseDfa() throws Exception { doTest(); }
   public void testWildcard() throws Exception { doTest(); }
   public void testIgnoreConvertible() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/UnusedLibraryInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/UnusedLibraryInspectionTest.java
new file mode 100644 (file)
index 0000000..bb6195a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 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.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: max
+ * Date: Apr 11, 2002
+ * Time: 6:50:50 PM
+ * To change template for new class use 
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.codeInspection;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.magicConstant.MagicConstantInspection;
+import com.intellij.codeInspection.unusedLibraries.UnusedLibrariesInspection;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.SdkModificator;
+import com.intellij.openapi.roots.AnnotationOrderRootType;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.InspectionTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
+import com.intellij.testFramework.PsiTestUtil;
+
+public class UnusedLibraryInspectionTest extends InspectionTestCase {
+  @Override
+  protected String getTestDataPath() {
+    return JavaTestUtil.getJavaTestDataPath() + "/inspection/unusedLibrary";
+  }
+
+  @Override
+  protected void setupRootModel(String testDir, VirtualFile[] sourceDir, String sdkName) {
+    super.setupRootModel(testDir, sourceDir, sdkName);
+    PsiTestUtil.addLibrary(getModule(), "JUnit", getTestDataPath() + "/junit.jar");
+  }
+
+  private void doTest() throws Exception {
+    doTest("/" + getTestName(true), new UnusedLibrariesInspection());
+  }
+
+  public void testSimple() throws Exception { doTest(); }
+}
index 0a4a6c8e18463022b3dc36a916d5eef8714fb086..1f774c40c48960d27b28674a01348ca152b8d367 100644 (file)
 #include <pthread.h>
 #include <sys/mount.h>
 
+#define PRIVATE_DIR "/private/"
+#define PRIVATE_LEN 9
+
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static bool report_private = true;
 
 static void reportEvent(char *event, char *path) {
     int len = 0;
@@ -32,15 +36,15 @@ static void reportEvent(char *event, char *path) {
     }
 
     pthread_mutex_lock(&lock);
-
-    fputs(event, stdout);
-    fputc('\n', stdout);
-    if (path != NULL) {
-        fwrite(path, len, 1, stdout);
+    if (report_private || strncasecmp(path, PRIVATE_DIR, PRIVATE_LEN) != 0) {
+        fputs(event, stdout);
         fputc('\n', stdout);
+        if (path != NULL) {
+            fwrite(path, len, 1, stdout);
+            fputc('\n', stdout);
+        }
+        fflush(stdout);
     }
-
-    fflush(stdout);
     pthread_mutex_unlock(&lock);
 }
 
@@ -128,14 +132,22 @@ static char command[2048];
 
 static void ParseRoots() {
     CFMutableArrayRef roots = CFArrayCreateMutable(NULL, 0, NULL);
+    bool has_private_root = false;
 
     while (TRUE) {
         fscanf(stdin, "%s", command);
         if (strcmp(command, "#") == 0 || feof(stdin)) break;
         char* path = command[0] == '|' ? command + 1 : command;
         CFArrayAppendValue(roots, strdup(path));
+        if (strcmp(path, "/") == 0 || strncasecmp(path, PRIVATE_DIR, PRIVATE_LEN) == 0) {
+            has_private_root = true;
+        }
     }
 
+    pthread_mutex_lock(&lock);
+    report_private = has_private_root;
+    pthread_mutex_unlock(&lock);
+
     PrintMountedFileSystems(roots);
 
     for (int i = 0; i < CFArrayGetCount(roots); i++) {
index fd7313c06e94caba4880c8963215560341795401..e1f139c07ff40be8ac7c382e9fda03aefdd486ee 100644 (file)
@@ -15,6 +15,8 @@
  */
 package com.intellij.codeInspection.reference;
 
+import com.intellij.psi.PsiElement;
+
 /**
  * Callback which gets called while a reference graph is being built during a global
  * inspection run.
@@ -71,4 +73,16 @@ public abstract class RefGraphAnnotator {
     onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer);
   }
 
+
+  /**
+   * Called when 'what' element doesn't belong to the selected scope. 
+   * @param what                            the referenced element
+   * @param from                            the referencing element
+   * @param referencedFromClassInitializer if true, <code>refFrom</code> is a class and the reference
+   *                                       has been found in its initializer block.
+   */
+  public void onMarkReferenced(PsiElement what,
+                               PsiElement from,
+                               boolean referencedFromClassInitializer) {}
+
 }
index ffea51b3e79ba093e9ce96c8982afa26d7293995..072e12114bc65382f9df46d467e2967afb0562f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -26,8 +26,14 @@ import com.intellij.psi.PsiDirectory;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiManager;
 import com.intellij.psi.search.scope.packageSet.*;
+import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.List;
+
 public class GlobalSearchScopesCore {
   @NotNull
   public static GlobalSearchScope projectProductionScope(@NotNull Project project) {
@@ -216,5 +222,131 @@ public class GlobalSearchScopesCore {
       //noinspection HardCodedStringLiteral
       return "directory scope: " + myDirectory + "; withSubdirs:"+myWithSubdirectories;
     }
+
+    @Override
+    public int hashCode() {
+      return myDirectory.hashCode() *31 + (myWithSubdirectories?1:0);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return obj instanceof DirectoryScope &&
+             myDirectory.equals(((DirectoryScope)obj).myDirectory) &&
+             myWithSubdirectories == ((DirectoryScope)obj).myWithSubdirectories;
+    }
+
+    @NotNull
+    @Override
+    public GlobalSearchScope uniteWith(@NotNull GlobalSearchScope scope) {
+      if (equals(scope)) return this;
+      if (scope instanceof DirectoryScope) {
+        DirectoryScope other = (DirectoryScope)scope;
+        VirtualFile otherDirectory = other.myDirectory;
+        if (myWithSubdirectories && VfsUtilCore.isAncestor(myDirectory, otherDirectory, false)) return this;
+        if (other.myWithSubdirectories && VfsUtilCore.isAncestor(otherDirectory, myDirectory, false)) return other;
+        BitSet newWithSubdirectories = new BitSet();
+        newWithSubdirectories.set(0, myWithSubdirectories);
+        newWithSubdirectories.set(1, other.myWithSubdirectories);
+        return new DirectoriesScope(getProject(), new VirtualFile[]{myDirectory,otherDirectory}, newWithSubdirectories);
+      }
+      return super.uniteWith(scope);
+    }
+  }
+
+  static class DirectoriesScope extends GlobalSearchScope {
+    private final VirtualFile[] myDirectories;
+    private final BitSet myWithSubdirectories;
+
+    private DirectoriesScope(@NotNull Project project, @NotNull VirtualFile[] directories, @NotNull BitSet withSubdirectories) {
+      super(project);
+      myWithSubdirectories = withSubdirectories;
+      myDirectories = directories;
+    }
+
+    @Override
+    public boolean contains(@NotNull VirtualFile file) {
+      VirtualFile parent = file.getParent();
+      return parent != null && in(parent);
+    }
+
+    private boolean in(@NotNull VirtualFile parent) {
+      for (int i = 0; i < myDirectories.length; i++) {
+        VirtualFile directory = myDirectories[i];
+        boolean withSubdirectories = myWithSubdirectories.get(i);
+        if (withSubdirectories ? VfsUtilCore.isAncestor(directory, parent, false) : directory.equals(parent)) return true;
+      }
+      return false;
+    }
+
+    @Override
+    public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
+      return 0;
+    }
+
+    @Override
+    public boolean isSearchInModuleContent(@NotNull Module aModule) {
+      return true;
+    }
+
+    @Override
+    public boolean isSearchInLibraries() {
+      return false;
+    }
+
+    public String toString() {
+      //noinspection HardCodedStringLiteral
+      return "Directories scope: " + Arrays.asList(myDirectories);
+    }
+
+    @Override
+    public int hashCode() {
+      int result = 1;
+      for (int i = 0; i < myDirectories.length; i++) {
+        VirtualFile directory = myDirectories[i];
+        boolean withSubdirectories = myWithSubdirectories.get(i);
+        result = result*31 + directory.hashCode() *31 + (withSubdirectories?1:0);
+      }
+      return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return obj instanceof DirectoriesScope &&
+             Arrays.equals(myDirectories, ((DirectoriesScope)obj).myDirectories) &&
+             myWithSubdirectories.equals(((DirectoriesScope)obj).myWithSubdirectories);
+    }
+
+    @NotNull
+    @Override
+    public GlobalSearchScope uniteWith(@NotNull GlobalSearchScope scope) {
+      if (equals(scope)) {
+        return this;
+      }
+      if (scope instanceof DirectoryScope) {
+        if (in(((DirectoryScope)scope).myDirectory)) {
+          return this;
+        }
+        VirtualFile[] newDirectories = ArrayUtil.append(myDirectories, ((DirectoryScope)scope).myDirectory, VirtualFile.class);
+        BitSet newWithSubdirectories = (BitSet)myWithSubdirectories.clone();
+        newWithSubdirectories.set(myDirectories.length, ((DirectoryScope)scope).myWithSubdirectories);
+        return new DirectoriesScope(getProject(), newDirectories, newWithSubdirectories);
+      }
+      if (scope instanceof DirectoriesScope) {
+        DirectoriesScope other = (DirectoriesScope)scope;
+        List<VirtualFile> newDirectories = new ArrayList<VirtualFile>(myDirectories.length + other.myDirectories.length);
+        newDirectories.addAll(Arrays.asList(other.myDirectories));
+        BitSet newWithSubdirectories = (BitSet)myWithSubdirectories.clone();
+        VirtualFile[] directories = other.myDirectories;
+        for (int i = 0; i < directories.length; i++) {
+          VirtualFile otherDirectory = directories[i];
+          if (!in(otherDirectory)) {
+            newWithSubdirectories.set(newDirectories.size(), other.myWithSubdirectories.get(i));
+            newDirectories.add(otherDirectory);
+          }
+        }
+        return new DirectoriesScope(getProject(), newDirectories.toArray(new VirtualFile[newDirectories.size()]), newWithSubdirectories);
+      }
+      return super.uniteWith(scope);
+    }
   }
 }
index 529db4430573ec6f52a9784531c6fc6c189dfdd9..c417f72e5b34527c2b061451da2650df16b01b36 100644 (file)
@@ -162,6 +162,14 @@ public class RefManagerImpl extends RefManager {
     }
   }
 
+  public void fireNodeMarkedReferenced(PsiElement what,
+                                       PsiElement from,
+                                       boolean referencedFromClassInitializer) {
+    for (RefGraphAnnotator annotator : myGraphAnnotators) {
+      annotator.onMarkReferenced(what, from, referencedFromClassInitializer);
+    }
+  }
+
   public void fireBuildReferences(RefElement refElement) {
     for (RefGraphAnnotator annotator : myGraphAnnotators) {
       annotator.onReferencesBuild(refElement);
index 92d74cfef60f16bb1b9445d7602b5a20d6384116..b28fa487379743a8030fcc854b93d09fce878de4 100644 (file)
@@ -97,22 +97,22 @@ public class BraceHighlightingHandler {
 
     myPsiFile = psiFile;
     myCodeInsightSettings = CodeInsightSettings.getInstance();
-    // myFileType = myPsiFile == null ? null : myPsiFile.getFileType();
   }
 
   static void lookForInjectedAndMatchBracesInOtherThread(@NotNull final Editor editor,
                                                          @NotNull final Alarm alarm,
                                                          @NotNull final Processor<BraceHighlightingHandler> processor) {
     ApplicationManagerEx.getApplicationEx().assertIsDispatchThread();
-    final Project project = editor.getProject();
-    if (project == null || project.isDisposed()) return;
+    if (!isValidEditor(editor)) return;
     if (!PROCESSED_EDITORS.add(editor)) {
       // Skip processing if that is not really necessary.
       // Assuming to be in EDT here.
       return;
     }
     final int offset = editor.getCaretModel().getOffset();
+    final Project project = editor.getProject();
     final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
+    if (!isValidFile(psiFile)) return;
     ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
       @Override
       public void run() {
@@ -124,7 +124,8 @@ public class BraceHighlightingHandler {
               injected = psiFile == null ||
                          psiFile instanceof PsiCompiledElement ||
                          psiFile instanceof PsiBinaryFile ||
-                         isReallyDisposed(editor, project)
+                         !isValidEditor(editor) ||
+                         !isValidFile(psiFile)
                          ? null : getInjectedFileIfAny(editor, project, offset, psiFile, alarm);
             }
             catch (RuntimeException e) {
@@ -141,7 +142,7 @@ public class BraceHighlightingHandler {
               @Override
               public void run() {
                 try {
-                  if (!isReallyDisposed(editor, project)) {
+                  if (isValidEditor(editor) && isValidFile(injected)) {
                     Editor newEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injected);
                     BraceHighlightingHandler handler = new BraceHighlightingHandler(project, newEditor, alarm, injected);
                     processor.process(handler);
@@ -167,10 +168,13 @@ public class BraceHighlightingHandler {
     });
   }
 
-  private static boolean isReallyDisposed(@NotNull Editor editor, @NotNull Project project) {
+  private static boolean isValidFile(PsiFile file) {
+    return file != null && file.isValid() && !file.getProject().isDisposed();
+  }
+
+  private static boolean isValidEditor(@NotNull Editor editor) {
     Project editorProject = editor.getProject();
-    return editorProject == null ||
-           editorProject.isDisposed() || project.isDisposed() || !editor.getComponent().isShowing() || editor.isViewer();
+    return editorProject != null && !editorProject.isDisposed() && !editor.isDisposed() && editor.getComponent().isShowing() && !editor.isViewer();
   }
 
   @NotNull
index 16ecdb0984c052b39b134736290bcf0a8e142fcb..6a829c5dc08a144ec581aee0afb1bef360c1e531 100644 (file)
@@ -1808,6 +1808,16 @@ public class FileBasedIndexImpl extends FileBasedIndex {
     return !myNotRequiringContentIndices.contains(indexId);
   }
 
+  private @Nullable IndexableFileSet getIndexableSetForFile(VirtualFile file) {
+    for (IndexableFileSet set : myIndexableSets) {
+      if (set.isInSet(file)) {
+        return set;
+      }
+    }
+    return null;
+  }
+
+
   private abstract static class InvalidationTask implements Runnable {
     private final VirtualFile mySubj;
 
@@ -2051,8 +2061,8 @@ public class FileBasedIndexImpl extends FileBasedIndex {
               }
             }
           });
-          // the file is for sure not a dir and it was previously indexed by at least one index
-          if (!isTooLarge(file)) scheduleForUpdate(file);
+          // the file is for sure not a dir and it was previously indexed by at least one index AND it belongs to some update set
+          if (!isTooLarge(file) && getIndexableSetForFile(file) != null) scheduleForUpdate(file);
         }
       }
       else if (!fileIndexedStatesToUpdate.isEmpty()) { // file was removed, its data should be (lazily) wiped for every index
@@ -2143,12 +2153,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
         }
       }
       else {
-        for (IndexableFileSet set : myIndexableSets) {
-          if (set.isInSet(file)) {
-            processor.process(file);
-            break;
-          }
-        }
+        if (getIndexableSetForFile(file) != null) processor.process(file);
       }
     }
 
index c1f0c8bc5c75e19a2df7c590c18d28c2716848be..0c34152861d1fdb45a685bad24deaa6fddea64a2 100644 (file)
@@ -31,7 +31,7 @@ import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
@@ -198,7 +198,7 @@ public class BrowserLauncherAppless extends BrowserLauncher {
         url = url.substring(0, sharpPos);
       }
 
-      Couple<String> pair = URLUtil.splitJarUrl(url);
+      Pair<String, String> pair = URLUtil.splitJarUrl(url);
       if (pair == null) return null;
 
       File jarFile = new File(FileUtil.toSystemDependentName(pair.first));
index 562afc37ea159a4a457d31f3fb6d3639cc18cecd..e909ea060af6c0e31689e1c4d9b4732f2b13d34f 100644 (file)
@@ -20,11 +20,11 @@ import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.ApplicationComponent;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.ui.mac.foundation.Foundation;
 import com.intellij.ui.mac.foundation.ID;
+import com.intellij.util.concurrency.FutureResult;
 import com.sun.jna.IntegerType;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -38,6 +38,7 @@ import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
  * <p>This class is used to workaround the problem with getting clipboard contents (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4818143).
@@ -251,7 +252,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
 
     @Nullable
     private static Transferable getContentsSafe() {
-      final Ref<Transferable> result = new Ref<Transferable>();
+      final FutureResult<Transferable> result = new FutureResult<Transferable>();
 
       Foundation.executeOnMainThread(new Runnable() {
         @Override
@@ -261,9 +262,14 @@ public class ClipboardSynchronizer implements ApplicationComponent {
             result.set(transferable);
           }
         }
-      }, true, true);
+      }, true, false);
 
-      return result.get();
+      try {
+        return result.get(10, TimeUnit.MILLISECONDS);
+      }
+      catch (Exception ignored) {
+        return null;
+      }
     }
 
     @Nullable
index e7a3f23febd2ef5148ab09a7fd38fb8742b4ca44..59fdfc24ab30499f81031f69c76f76cb4f927a2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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,8 @@ import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.util.ExecUtil;
 import com.intellij.ide.DataManager;
 import com.intellij.ide.IdeBundle;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationListener;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -50,6 +52,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
 import javax.swing.filechooser.FileSystemView;
 import java.awt.*;
 import java.awt.event.MouseEvent;
@@ -57,6 +60,7 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -64,6 +68,15 @@ import java.util.regex.Pattern;
 public class ShowFilePathAction extends AnAction {
   private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowFilePathAction");
 
+  public static final NotificationListener FILE_SELECTING_LISTENER = new NotificationListener.Adapter() {
+    @Override
+    protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+      URL url = e.getURL();
+      if (url != null) openFile(new File(url.getPath()));
+      notification.expire();
+    }
+  };
+
   private static NotNullLazyValue<Boolean> canUseNautilus = new NotNullLazyValue<Boolean>() {
     @NotNull
     @Override
index 4fa04fe0398be74d3250ebfc58c6011d24c8ab90..d2c3df51609a07108e887f9dae61d627644fb6ca 100644 (file)
@@ -31,6 +31,7 @@ import com.intellij.openapi.editor.actionSystem.EditorAction;
 import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
 import com.intellij.openapi.editor.ex.util.EditorUtil;
 import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Pair;
 import org.jetbrains.annotations.Nullable;
 
 public class DuplicateAction extends EditorAction {
@@ -75,7 +76,7 @@ public class DuplicateAction extends EditorAction {
 
   @Nullable
   static Couple<Integer> duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) {
-    Couple<LogicalPosition> lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd);
+    Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd);
     int offset = editor.getCaretModel().getOffset();
 
     LogicalPosition lineStart = lines.first;
index 8809d3d3bc99be38188b0a7540d5697e6f09afd4..caadfc8ae7443b846fa5ac6d8778f44750c5eeb0 100644 (file)
@@ -29,7 +29,6 @@ import com.intellij.openapi.editor.impl.FontInfo;
 import com.intellij.openapi.editor.impl.IterationState;
 import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl;
 import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
-import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.TextRange;
@@ -719,9 +718,9 @@ public final class EditorUtil {
    * @see #getNotFoldedLineEndOffset(com.intellij.openapi.editor.Editor, int)
    */
   @SuppressWarnings("AssignmentToForLoopParameter")
-  public static Couple<LogicalPosition> calcSurroundingRange(@NotNull Editor editor,
-                                                             @NotNull VisualPosition start,
-                                                             @NotNull VisualPosition end) {
+  public static Pair<LogicalPosition, LogicalPosition> calcSurroundingRange(@NotNull Editor editor,
+                                                                            @NotNull VisualPosition start,
+                                                                            @NotNull VisualPosition end) {
     final Document document = editor.getDocument();
     final FoldingModel foldingModel = editor.getFoldingModel();
 
@@ -729,8 +728,7 @@ public final class EditorUtil {
     for (
       int line = first.line, offset = document.getLineStartOffset(line);
       offset >= 0;
-      offset = document.getLineStartOffset(line))
-    {
+      offset = document.getLineStartOffset(line)) {
       final FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(offset);
       if (foldRegion == null) {
         first = new LogicalPosition(line, 0);
@@ -749,8 +747,7 @@ public final class EditorUtil {
     for (
       int line = second.line, offset = document.getLineEndOffset(line);
       offset <= document.getTextLength();
-      offset = document.getLineEndOffset(line))
-    {
+      offset = document.getLineEndOffset(line)) {
       final FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(offset);
       if (foldRegion == null) {
         second = new LogicalPosition(line + 1, 0);
@@ -767,7 +764,7 @@ public final class EditorUtil {
     if (second.line >= document.getLineCount()) {
       second = editor.offsetToLogicalPosition(document.getTextLength());
     }
-    return Couple.of(first, second);
+    return Pair.create(first, second);
   }
 
   /**
index 893000b7d47dfce07ea562e42c3cd52675ef3a89..a3c1d37ae726eddae334c717fa4134b3808a05b0 100644 (file)
@@ -261,10 +261,11 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
       }
     });
   }
-  private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("file type re-detect", Condition.FALSE, -1, new Processor<Collection<VirtualFile>>() {
+
+  private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("File type re-detect", Condition.FALSE, -1, new Processor<Collection<VirtualFile>>() {
     @Override
     public boolean process(Collection<VirtualFile> files) {
-      ((FileTypeManagerImpl)getInstance()).reDetect(files);
+      reDetect(files);
       return true;
     }
   });
@@ -317,8 +318,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
 
   private boolean shouldBeSavedToFile(final FileType fileType) {
     if (!(fileType instanceof JDOMExternalizable) || !shouldSave(fileType)) return false;
-    if (myDefaultTypes.contains(fileType) && !isDefaultModified(fileType)) return false;
-    return true;
+    return !myDefaultTypes.contains(fileType) || isDefaultModified(fileType);
   }
 
   @Override
index d955c496deb39cd5c0c15ce852c1ec4dd3e239dc..f7346548124af89241fb42fa2c3d85cbc102d225 100644 (file)
@@ -217,7 +217,7 @@ public class FileWatcher {
 
   private static boolean isUpToDate(File executable) {
     long length = SystemInfo.isWindows ? 71208 :
-                  SystemInfo.isMac ? 13924 :
+                  SystemInfo.isMac ? 13984 :
                   SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29155 : 22791 :
                   -1;
     return length < 0 || length == executable.length();
index e5a5de80c9aa629845595aa47594ec30a2644fd7..59e89750f30bd254fb35119fd25d6addb92a57a8 100644 (file)
@@ -6,8 +6,10 @@ action.CaptureMemorySnapShot.text=Capture Memory Snapshot
 action.CaptureMemorySnapShot.description=Capture memory snapshot
 action.CaptureCPUUsageData.text=Start CPU Usage Profiling
 action.CaptureCPUUsageData.description=Capture CPU usage data
+stop.capture.cpu.usage.data.action.name=Stop CPU Usage Profiling
 action.CaptureAllocations.text=Capture Allocations
 action.CaptureAllocations.description=Capture memory allocations data
+stop.capture.allocations.data.action.name=Stop Capturing Allocations
 action.ContextHelp.text=Conte_xt Help
 action.ContextHelp.description=Show context help
 action.RunConfiguration.text=Select Run/Debug Configuration
@@ -1030,11 +1032,6 @@ action.UsageView.ShowRecentFindUsages.description=Choose and re-run recent find
 group.ShowRecentFindUsagesGroup.text=Recent Find Usages
 group.ShowRecentFindUsagesGroup.description=Choose and re-run recent find usages
 
-stop.capture.cpu.usage.data.action.name=Stop CPU Usage Profiling
-stop.capture.cpu.usage.data.action.description=Stop capturing CPU usage data
-stop.capture.allocations.usage.data.action.name=Capture allocations data, now capturing
-stop.capture.allocations.usage.data.action.description=Stop capturing allocations data
-
 action.IntegrateFiles.text=Integrate
 action.IntegrateFiles.description=Integrate selected files or directories
 action.Vcs.IntegrateProject.text=Inte_grate Project
index 7820960979a71823a18edc4ffeca5d715b4e8f5f..46750d536a0639817dd0b62f41307aea62531eb8 100644 (file)
@@ -124,10 +124,8 @@ format.file.size.bytes={0}b
 format.file.size.kbytes={0}Kb
 format.file.size.mbytes={0}Mb
 
-profiling.captured.cpu.snapshot.message.text=Captured CPU snapshot: ''{0}'' is placed in user home directory.
-profiling.captured.allocations.snapshot.message.text=Captured allocations snapshot: ''{0}'' is placed in user home directory.
-information.dialog.title=Information
-captured.memory.snapshot.placed.in.user.home.directory.message.text=Captured memory snapshot: ''{0}'' is placed in user home directory.
+profiling.capture.snapshot.success=Captured snapshot ''{0}'' is placed in user home directory. <a href="{1}">Show in {2}</a>.
+profiling.capture.snapshot.error=Failed to capture snapshot: {0}
 
 cannot.undo.dialog.title=Cannot Undo
 cannot.undo.error.other.affected.files.changed.message=Following files affected by this action have been already changed:
index e761b3c9a92bec1f6da41cd6197efeec9423d846..1ef6ef385adbed53a946a4acda40b27c2152877d 100644 (file)
@@ -215,13 +215,11 @@ cant.delete.file=Can't delete file {0}
 select.xsd.schema.dialog.title=Select XSD Schema
 
 emmet.title=Emmet
-emmet.configuration.title=Emmet (Zen Coding)
+emmet.configuration.title=Emmet
 emmet.enable.label=&Enable XML Emmet
 emmet.enable.bem.filter=Enable &BEM filter by default
 emmet.enable.preview=Enable &abbreviation preview
 emmet.expand.abbreviation.with=Expand &abbreviation with
-zen.coding.enter.abbreviation.dialog.label=Please enter an abbreviation
-zen.coding.incorrect.abbreviation.error=Incorrect abbreviation
 
 title.cannot.create.html.file=Cannot create HTML file
 new.html.file.action=HTML File
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java b/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java
new file mode 100644 (file)
index 0000000..418190f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.search;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.PlatformTestCase;
+
+public class GlobalSearchScopeTest extends PlatformTestCase {
+  public void testUniteDirectorySearchScopeDoesNotSOE() throws Exception {
+    VirtualFile genRoot = getVirtualFile(createTempDir("genSrcRoot"));
+    VirtualFile srcRoot = getVirtualFile(createTempDir("srcRoot"));
+    VirtualFile child = srcRoot.createChildDirectory(this, "child");
+    GlobalSearchScope childScope = GlobalSearchScopesCore.directoryScope(getProject(), child, true);
+
+    GlobalSearchScope directoryScope = GlobalSearchScopesCore.directoryScope(getProject(), srcRoot, true);
+    GlobalSearchScope scope = GlobalSearchScope.EMPTY_SCOPE.uniteWith(directoryScope);
+    assertSame(scope, directoryScope);
+    scope = scope.uniteWith(directoryScope);
+    assertSame(scope, directoryScope);
+
+    scope = scope.uniteWith(childScope);
+    assertSame(scope, directoryScope);
+
+    GlobalSearchScope s = childScope;
+    int N = 1000;
+    VirtualFile[] d = new VirtualFile[N];
+    for (int i=0; i< N;i++) {
+      d[i] = srcRoot.createChildDirectory(this, "d"+i);
+      GlobalSearchScope united = s.uniteWith(GlobalSearchScopesCore.directoryScope(getProject(), d[i], true));
+      assertNotSame(s, united);
+      s = united;
+      assertTrue(s instanceof GlobalSearchScopesCore.DirectoriesScope);
+    }
+    for (VirtualFile file : d) {
+      VirtualFile f = createChildData(file, "f");
+      assertTrue(s.contains(f));
+    }
+    assertFalse(s.contains(genRoot));
+
+    assertSame(s.uniteWith(childScope), s);
+    assertSame(s.uniteWith(s), s);
+  }
+}
\ No newline at end of file
index 72df63470354733fb97efd75d924fadebdc7cdbf..01a6921a89492a404810802e756d0b92e4a2ec98 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.execution.Location;
 import com.intellij.execution.configurations.RunConfiguration;
 import com.intellij.notification.NotificationGroup;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -36,6 +37,8 @@ import com.intellij.ui.SystemNotifications;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
+import javax.swing.tree.TreePath;
 import java.awt.*;
 import java.util.List;
 
@@ -74,6 +77,17 @@ public class TestsUIUtil {
     return null;
   }
 
+  public static boolean isMultipleSelectionImpossible(DataContext dataContext) {
+    final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
+    if (component instanceof JTree) {
+      final TreePath[] selectionPaths = ((JTree)component).getSelectionPaths();
+      if (selectionPaths == null || selectionPaths.length <= 1) {
+        return true;
+      }
+    }
+    return false;
+  }
+  
   public static Navigatable getOpenFileDescriptor(final AbstractTestProxy testProxy, final TestFrameworkRunningModel model) {
     final TestConsoleProperties testConsoleProperties = model.getProperties();
     return getOpenFileDescriptor(testProxy, testConsoleProperties,
index 1e47adf8fcf1be39450820d9bdf7265197544e8c..5de68c11799bc821f6efa23051dc75df664ae785 100644 (file)
@@ -78,6 +78,21 @@ public class ArrayUtil extends ArrayUtilRt {
     System.arraycopy(array, 0, result, 0, Math.min(oldSize, newSize));
     return result;
   }
+  @NotNull
+  public static boolean[] realloc(@NotNull boolean[] array, final int newSize) {
+    if (newSize == 0) {
+      return EMPTY_BOOLEAN_ARRAY;
+    }
+
+    final int oldSize = array.length;
+    if (oldSize == newSize) {
+      return array;
+    }
+
+    boolean[] result = new boolean[newSize];
+    System.arraycopy(array, 0, result, 0, Math.min(oldSize, newSize));
+    return result;
+  }
 
   @NotNull
   public static int[] realloc(@NotNull int[] array, final int newSize) {
@@ -131,6 +146,12 @@ public class ArrayUtil extends ArrayUtilRt {
     array[array.length - 1] = value;
     return array;
   }
+  @NotNull
+  public static boolean[] append(@NotNull boolean[] array, boolean value) {
+    array = realloc(array, array.length + 1);
+    array[array.length - 1] = value;
+    return array;
+  }
 
   @NotNull
   public static char[] realloc(@NotNull char[] array, final int newSize) {
index 2c6496f9693f7297e6c29ff501181b1d46242958..1a6e633a32665beab8e0d543c8ddca381acbb746 100644 (file)
@@ -15,7 +15,7 @@
  */
 package com.intellij.util.io;
 
-import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.CharsetToolkit;
@@ -88,7 +88,7 @@ public class URLUtil {
 
   @NotNull
   private static InputStream openJarStream(@NotNull URL url) throws IOException {
-    Couple<String> paths = splitJarUrl(url.getFile());
+    Pair<String, String> paths = splitJarUrl(url.getFile());
     if (paths == null) {
       throw new MalformedURLException(url.getFile());
     }
@@ -116,7 +116,7 @@ public class URLUtil {
    * E.g. "jar:file:///path/to/jar.jar!/resource.xml" is converted into ["/path/to/jar.jar", "resource.xml"].
    */
   @Nullable
-  public static Couple<String> splitJarUrl(@NotNull String url) {
+  public static Pair<String, String> splitJarUrl(@NotNull String url) {
     int pivot = url.indexOf(JAR_SEPARATOR);
     if (pivot < 0) return null;
 
@@ -137,7 +137,7 @@ public class URLUtil {
       }
     }
 
-    return Couple.of(jarPath, resourcePath);
+    return Pair.create(jarPath, resourcePath);
   }
 
   @NotNull
index 154f59125497649593f5fd4c19d0dd68a0002064..a2ae7940093c8e719ec79c725ed9ac61f768e1a1 100644 (file)
@@ -17,6 +17,7 @@
     <orderEntry type="module" module-name="lang-impl" />
     <orderEntry type="module" module-name="idea-ui" />
     <orderEntry type="module" module-name="openapi" />
+    <orderEntry type="module" module-name="vcs-impl" />
   </component>
 </module>
 
index 74c023241847722a10fc834d44516860940529ef..43a1c6cbe349a5712307a23e66494ba221133e04 100644 (file)
@@ -1,14 +1,20 @@
 package com.intellij.remoteServer.util;
 
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.AbstractVcsHelper;
 import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.remoteServer.agent.util.CloudGitApplication;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
@@ -16,6 +22,7 @@ import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
 import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.concurrency.Semaphore;
+import git4idea.GitPlatformFacade;
 import git4idea.GitUtil;
 import git4idea.actions.GitInit;
 import git4idea.commands.*;
@@ -29,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -38,13 +46,17 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
 
   private static final Logger LOG = Logger.getInstance("#" + CloudGitDeploymentRuntime.class.getName());
 
+  private static final String COMMIT_MESSAGE = "Deploy";
+
   private final GitRepositoryManager myGitRepositoryManager;
   private final Git myGit;
+  private final AbstractVcsHelper myVcsHelper;
 
   private final VirtualFile myContentRoot;
   private final File myRepositoryRootFile;
 
   private final String myDefaultRemoteName;
+  private final ChangeListManagerEx myChangeListManager;
   private String myRemoteName;
   private final String myCloudName;
 
@@ -68,23 +80,135 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
     LOG.assertTrue(contentRoot != null, "Repository root is not found");
     myContentRoot = contentRoot;
 
-    myGitRepositoryManager = GitUtil.getRepositoryManager(getProject());
+    Project project = getProject();
+    myGitRepositoryManager = GitUtil.getRepositoryManager(project);
     myGit = ServiceManager.getService(Git.class);
     if (myGit == null) {
       throw new ServerRuntimeException("Can't initialize GIT");
     }
+    GitPlatformFacade gitPlatformFacade = ServiceManager.getService(GitPlatformFacade.class);
+    myVcsHelper = gitPlatformFacade.getVcsHelper(project);
+    myChangeListManager = gitPlatformFacade.getChangeListManager(project);
   }
 
   @Override
   public CloudGitApplication deploy() throws ServerRuntimeException {
     CloudGitApplication application = findOrCreateApplication();
+    deployApplication(application);
+    return application;
+  }
+
+  private void deployApplication(CloudGitApplication application) throws ServerRuntimeException {
+    boolean firstDeploy = findRepository() == null;
+
     GitRepository repository = findOrCreateRepository();
     addOrResetGitRemote(application, repository);
-    add();
-    commit();
+
+    if (firstDeploy) {
+      add();
+      commit();
+      return;
+    }
+
+    final LocalChangeList activeChangeList = myChangeListManager.getDefaultChangeList();
+    if (activeChangeList == null) {
+      add();
+      commit();
+      return;
+    }
+
+    Collection<Change> changes = activeChangeList.getChanges();
+    final List<Change> relevantChanges = new ArrayList<Change>();
+    for (Change change : changes) {
+      if (isRelevant(change.getBeforeRevision()) || isRelevant(change.getAfterRevision())) {
+        relevantChanges.add(change);
+      }
+    }
+    if (relevantChanges.isEmpty()) {
+      Integer showCommitDialogChoice = runOnEdt(new Computable<Integer>() {
+
+        @Override
+        public Integer compute() {
+          return Messages.showYesNoCancelDialog(getProject(),
+                                                "Active changelist does not contain a relevant change.\n"
+                                                + "Do you want to show commit dialog anyway?\n\n"
+                                                + "Yes - show commit dialog\n"
+                                                + "No - push immediately\n"
+                                                + "Cancel - interrupt deploy",
+                                                "Deploy",
+                                                Messages.getWarningIcon());
+        }
+      });
+      if (showCommitDialogChoice == Messages.YES) {
+        relevantChanges.addAll(changes);
+      }
+      else if (showCommitDialogChoice == Messages.NO) {
+        pushApplication(application);
+        return;
+      }
+      else {
+        throw new ServerRuntimeException("Deploy interrupted");
+      }
+    }
+
+    final Semaphore commitSemaphore = new Semaphore();
+    commitSemaphore.down();
+
+    final Ref<Boolean> commitSucceeded = new Ref<Boolean>(false);
+    Boolean commitStarted = runOnEdt(new Computable<Boolean>() {
+
+      @Override
+      public Boolean compute() {
+        return myVcsHelper.commitChanges(relevantChanges, activeChangeList, COMMIT_MESSAGE,
+                                         new CommitResultHandler() {
+
+                                           @Override
+                                           public void onSuccess(@NotNull String commitMessage) {
+                                             commitSucceeded.set(true);
+                                             commitSemaphore.up();
+                                           }
+
+                                           @Override
+                                           public void onFailure() {
+                                             commitSemaphore.up();
+                                           }
+                                         });
+      }
+    });
+    if (commitStarted != null && commitStarted) {
+      commitSemaphore.waitFor();
+      if (!commitSucceeded.get()) {
+        repository.update();
+        throw new ServerRuntimeException("Commit failed");
+      }
+    }
+    else {
+      getLoggingHandler().println("Commit canceled");
+    }
+
     repository.update();
     pushApplication(application);
-    return application;
+  }
+
+  private boolean isRelevant(ContentRevision contentRevision) throws ServerRuntimeException {
+    if (contentRevision == null) {
+      return false;
+    }
+    GitRepository repository = getRepository();
+    VirtualFile affectedFile = contentRevision.getFile().getVirtualFile();
+    return affectedFile != null && VfsUtilCore.isAncestor(repository.getRoot(), affectedFile, false);
+  }
+
+  private static <T> T runOnEdt(final Computable<T> computable) {
+    final Ref<T> result = new Ref<T>();
+    ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+
+      @Override
+      public void run() {
+        result.set(computable.compute());
+      }
+    }, ModalityState.any());
+    return result.get();
   }
 
   public void undeploy() throws ServerRuntimeException {
@@ -273,7 +397,7 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
         GitSimpleHandler handler = new GitSimpleHandler(getProject(), myContentRoot, GitCommand.COMMIT);
         handler.setSilent(false);
         handler.setStdoutSuppressed(false);
-        handler.addParameters("-m", "Deploy");
+        handler.addParameters("-m", COMMIT_MESSAGE);
         handler.endOptions();
         handler.run();
       }
index c04077b817f4efb97696cccc3623f77e904811c5..2986fb79adda1391511fbe62a51fe15f03eb71c8 100644 (file)
@@ -16,7 +16,7 @@
 package git4idea.util;
 
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vcs.changes.Change;
 import git4idea.GitCommit;
 import git4idea.repo.GitRepository;
@@ -31,7 +31,7 @@ public class GitCommitCompareInfo {
   
   private static final Logger LOG = Logger.getInstance(GitCommitCompareInfo.class);
   
-  private final Map<GitRepository, Couple<List<GitCommit>>> myInfo = new HashMap<GitRepository, Couple<List<GitCommit>>>();
+  private final Map<GitRepository, Pair<List<GitCommit>, List<GitCommit>>> myInfo = new HashMap<GitRepository, Pair<List<GitCommit>, List<GitCommit>>>();
   private final Map<GitRepository, Collection<Change>> myTotalDiff = new HashMap<GitRepository, Collection<Change>>();
   private final InfoType myInfoType;
 
@@ -43,7 +43,7 @@ public class GitCommitCompareInfo {
     myInfoType = infoType;
   }
 
-  public void put(@NotNull GitRepository repository, @NotNull Couple<List<GitCommit>> commits) {
+  public void put(@NotNull GitRepository repository, @NotNull Pair<List<GitCommit>, List<GitCommit>> commits) {
     myInfo.put(repository, commits);
   }
 
@@ -62,11 +62,11 @@ public class GitCommitCompareInfo {
   }
 
   @NotNull
-  private Couple<List<GitCommit>> getCompareInfo(@NotNull GitRepository repo) {
-    Couple<List<GitCommit>> pair = myInfo.get(repo);
+  private Pair<List<GitCommit>, List<GitCommit>> getCompareInfo(@NotNull GitRepository repo) {
+    Pair<List<GitCommit>, List<GitCommit>> pair = myInfo.get(repo);
     if (pair == null) {
       LOG.error("Compare info not found for repository " + repo);
-      return Couple.of(Collections.<GitCommit>emptyList(), Collections.<GitCommit>emptyList());
+      return Pair.create(Collections.<GitCommit>emptyList(), Collections.<GitCommit>emptyList());
     }
     return pair;
   }
index 2c51b29b1564dfbfdc1d3afc212f81c8de71599a..946b00b1f12630abc71957015fd3a9f72e54f936 100644 (file)
@@ -137,6 +137,12 @@ public abstract class AbstractProjectResolverExtension implements GradleProjectR
     return Collections.emptyList();
   }
 
+  @NotNull
+  @Override
+  public List<String> getExtraCommandLineArgs() {
+    return Collections.emptyList();
+  }
+
   @NotNull
   @Override
   public ExternalSystemException getUserFriendlyError(@NotNull Throwable error,
index be3df4b1c824b3998ff6807b35928800ea91560b..8873f25c41575e2211087468f91de74a9ffe7983 100644 (file)
@@ -342,6 +342,12 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
     return Collections.emptyList();
   }
 
+  @NotNull
+  @Override
+  public List<String> getExtraCommandLineArgs() {
+    return Collections.emptyList();
+  }
+
   @NotNull
   @Override
   public ExternalSystemException getUserFriendlyError(@NotNull Throwable error,
index 01e1c2295facbb147ecb3776100fa5f2e92491da..1df5e1e2ef9ef1b3ec107c7a9de0c83840369373 100644 (file)
@@ -144,6 +144,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
     final ProjectImportAction projectImportAction = new ProjectImportAction(resolverCtx.isPreviewMode());
 
     final List<KeyValue<String, String>> extraJvmArgs = new ArrayList<KeyValue<String, String>>();
+    final List<String> commandLineArgs = ContainerUtil.newArrayList();
+
     for (GradleProjectResolverExtension resolverExtension = projectResolverChain;
          resolverExtension != null;
          resolverExtension = resolverExtension.getNext()) {
@@ -155,6 +157,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
       projectImportAction.addExtraProjectModelClasses(resolverExtension.getExtraProjectModelClasses());
       // collect extra JVM arguments provided by gradle project resolver extensions
       extraJvmArgs.addAll(resolverExtension.getExtraJvmArgs());
+      // collect extra command-line arguments
+      commandLineArgs.addAll(resolverExtension.getExtraCommandLineArgs());
     }
 
     final ParametersList parametersList = new ParametersList();
@@ -165,7 +169,6 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
 
     BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = resolverCtx.getConnection().action(projectImportAction);
 
-    final List<String> commandLineArgs = ContainerUtil.newArrayList();
     // TODO [vlad] remove the check
     if (!GradleEnvironment.DISABLE_ENHANCED_TOOLING_API) {
       File initScript = GradleExecutionHelper.generateInitScript(isBuildSrcProject);
index 1b0af6841869569e90f61dda0f2a3b9f9a41b8fb..145225ce45d490515709c6b11086cb87977f0955 100644 (file)
@@ -101,6 +101,9 @@ public interface GradleProjectResolverExtension extends ParametersEnhancer {
   @NotNull
   List<KeyValue<String, String>> getExtraJvmArgs();
 
+  @NotNull
+  List<String> getExtraCommandLineArgs();
+
   @NotNull
   ExternalSystemException getUserFriendlyError(@NotNull Throwable error, @NotNull String projectPath, @Nullable String buildFilePath);
 
index 7c9b6b0f54536f1ce01f23d1107400bf22a8c126..07eba1828b5876742173a2e781de77f0eec2b55a 100644 (file)
@@ -154,10 +154,6 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
                                   @Nullable final PsiType classToDelegate) {
     if (classToDelegate == null) return true;
 
-    if (state.get(ClassHint.RESOLVE_CONTEXT) == null) {
-      state = state.put(ClassHint.RESOLVE_CONTEXT, this);
-    }
-
     return ResolveUtil.processAllDeclarationsSeparately(classToDelegate, processor, nonCodeProcessor,
                                             state.put(ClassHint.RESOLVE_CONTEXT, this), place);
   }
index 99f325857fb3b0618168a7d1e472bc512f3dfc0a..9ccc175803f57f369b570b36d20de8eca5e8b9e4 100644 (file)
@@ -31,6 +31,8 @@
                         serviceImplementation="org.zmlx.hg4idea.HgRememberedInputs"/>
     <projectService serviceInterface="org.zmlx.hg4idea.HgProjectSettings"
                     serviceImplementation="org.zmlx.hg4idea.HgProjectSettings"/>
+    <projectService serviceInterface="org.zmlx.hg4idea.provider.update.HgUpdateConfigurationSettings"
+                    serviceImplementation="org.zmlx.hg4idea.provider.update.HgUpdateConfigurationSettings"/>
     <projectService serviceInterface="org.zmlx.hg4idea.HgRootsHandler"
                     serviceImplementation="org.zmlx.hg4idea.HgRootsHandler" />
   </extensions>
index e88b1947f4a85edc4d549d539b2fda169e479019..c9630038df949abe9ab6f42b49fa729490d8e720 100644 (file)
@@ -35,27 +35,21 @@ import java.util.List;
 import java.util.Set;
 
 import static org.zmlx.hg4idea.HgErrorHandler.ensureSuccess;
+import static org.zmlx.hg4idea.provider.update.HgUpdateType.MERGE;
+import static org.zmlx.hg4idea.provider.update.HgUpdateType.ONLY_UPDATE;
 
 public class HgRegularUpdater implements HgUpdater {
 
   @NotNull private final Project project;
   @NotNull private final VirtualFile repoRoot;
-  @NotNull private final UpdateConfiguration updateConfiguration;
+  @NotNull private final HgUpdateConfigurationSettings updateConfiguration;
 
-  public HgRegularUpdater(@NotNull Project project, @NotNull VirtualFile repository, @NotNull UpdateConfiguration configuration) {
+  public HgRegularUpdater(@NotNull Project project, @NotNull VirtualFile repository, @NotNull HgUpdateConfigurationSettings configuration) {
     this.project = project;
     this.repoRoot = repository;
     this.updateConfiguration = configuration;
   }
 
-  private boolean shouldMerge() {
-    return updateConfiguration.shouldMerge();
-  }
-
-  private boolean shouldCommitAfterMerge() {
-    return updateConfiguration.shouldCommitAfterMerge();
-  }
-
   public boolean update(final UpdatedFiles updatedFiles, ProgressIndicator indicator, List<VcsException> warnings)
     throws VcsException {
     indicator.setText(HgVcsMessages.message("hg4idea.progress.updating", repoRoot.getPath()));
@@ -81,9 +75,11 @@ public class HgRegularUpdater implements HgUpdater {
 //      throw new VcsException("working dir not at branch tip (use \"Update to...\" to check out branch tip)");
 //    }
 
-    HgCommandExitCode pullResult = pull(repoRoot, indicator);
-    if (pullResult == HgCommandExitCode.ERROR) {
-      return false;
+    if (updateConfiguration.shouldPull()) {
+      HgCommandExitCode pullResult = pull(repoRoot, indicator);
+      if (pullResult == HgCommandExitCode.ERROR) {
+        return false;
+      }
     }
 
     List<HgRevisionNumber> parentsBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).parents(repoRoot);
@@ -97,17 +93,18 @@ public class HgRegularUpdater implements HgUpdater {
     List<HgRevisionNumber> pulledBranchHeads = determinePulledBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull);
     List<HgRevisionNumber> remainingOriginalBranchHeads =
       determingRemainingOriginalBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull);
+    HgUpdateType updateType = updateConfiguration.getUpdateType();
 
-    if (branchHeadsAfterPull.size() > 1) {
+    if (branchHeadsAfterPull.size() > 1 && updateType != ONLY_UPDATE) {
       // merge strategy
-      if (shouldMerge()) {
+      if (updateType == MERGE) {
         abortOnLocalChanges();
         abortOnMultiplePulledHeads(pulledBranchHeads);
         abortOnMultipleLocalHeads(remainingOriginalBranchHeads);
 
         HgCommandResult mergeResult = doMerge(indicator);
 
-        if (shouldCommitAfterMerge()) {
+        if (updateConfiguration.shouldCommitAfterMerge()) {
           commitOrWarnAboutConflicts(warnings, mergeResult);
         }
       }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateConfigurationSettings.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateConfigurationSettings.java
new file mode 100644 (file)
index 0000000..e0b6d4e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2014 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.zmlx.hg4idea.provider.update;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.components.StoragePathMacros;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@State(
+  name = "HgUpdateConfigurationSettings",
+  storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE)
+)
+public class HgUpdateConfigurationSettings implements PersistentStateComponent<HgUpdateConfigurationSettings.State> {
+
+
+  private State myState = new State();
+
+  public static class State {
+    public boolean shouldPull = true;
+    @NotNull public HgUpdateType updateType = HgUpdateType.ONLY_UPDATE;
+    public boolean shouldCommitAfterMerge = false;
+  }
+
+  public void setShouldPull(boolean shouldPull) {
+    myState.shouldPull = shouldPull;
+  }
+
+  public void setUpdateType(@NotNull HgUpdateType updateType) {
+    myState.updateType = updateType;
+  }
+
+  public void setShouldCommitAfterMerge(boolean shouldCommitAfterMerge) {
+    myState.shouldCommitAfterMerge = shouldCommitAfterMerge;
+  }
+
+  public boolean shouldPull() {
+    return myState.shouldPull;
+  }
+
+  public HgUpdateType getUpdateType() {
+    return myState.updateType;
+  }
+
+  public boolean shouldCommitAfterMerge() {
+    return myState.updateType == HgUpdateType.MERGE && myState.shouldCommitAfterMerge;
+  }
+
+  @Nullable
+  @Override
+  public HgUpdateConfigurationSettings.State getState() {
+    return myState;
+  }
+
+  @Override
+  public void loadState(HgUpdateConfigurationSettings.State state) {
+    myState = state;
+  }
+}
\ No newline at end of file
index cbb35eae761f89972c94bbc597b2f6ea84f0cd30..75387b221b024a12b8253b9f56e33f33a2b9acc4 100644 (file)
@@ -12,6 +12,7 @@
 // limitations under the License.
 package org.zmlx.hg4idea.provider.update;
 
+import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.progress.ProgressIndicator;
@@ -34,10 +35,11 @@ import java.util.List;
 public class HgUpdateEnvironment implements UpdateEnvironment {
 
   private final Project project;
-  private final HgUpdater.UpdateConfiguration updateConfiguration = new HgUpdater.UpdateConfiguration();
+  private final HgUpdateConfigurationSettings updateConfiguration;
 
   public HgUpdateEnvironment(Project project) {
     this.project = project;
+    updateConfiguration = ServiceManager.getService(project, HgUpdateConfigurationSettings.class);
   }
 
   public void fillGroups(UpdatedFiles updatedFiles) {
@@ -84,10 +86,10 @@ public class HgUpdateEnvironment implements UpdateEnvironment {
   }
   
   public static class UpdateConfigurable implements Configurable {
-    private final HgUpdater.UpdateConfiguration updateConfiguration;
+    private final HgUpdateConfigurationSettings updateConfiguration;
     protected HgUpdateDialog updateDialog;
 
-    public UpdateConfigurable(HgUpdater.UpdateConfiguration updateConfiguration) {
+    public UpdateConfigurable(HgUpdateConfigurationSettings updateConfiguration) {
       this.updateConfiguration = updateConfiguration;
     }
 
@@ -101,8 +103,8 @@ public class HgUpdateEnvironment implements UpdateEnvironment {
     }
 
     public JComponent createComponent() {
-      updateDialog = new HgUpdateDialog();
-      return updateDialog.createCenterPanel();
+      updateDialog = new HgUpdateDialog(updateConfiguration);
+      return updateDialog.getContentPanel();
     }
 
     public boolean isModified() {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateType.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateType.java
new file mode 100644 (file)
index 0000000..3ffccb6
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 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.zmlx.hg4idea.provider.update;
+
+/**
+ * The type of update to perform
+ */
+public enum HgUpdateType {
+
+
+  /**
+   * Try to update without merge, fails if conflicts
+   */
+  ONLY_UPDATE,
+  /**
+   * Merge commits with pulled
+   */
+  MERGE,
+  /**
+   * Rebase local commits
+   */
+  REBASE
+}
\ No newline at end of file
index e8f3d59d7871d51fdb126b7ae0c4c47a81b8051d..ce304dfaa4c72fca34f01b6ca0a4ff14eacc7884 100644 (file)
@@ -22,35 +22,4 @@ public interface HgUpdater {
 
   boolean update(UpdatedFiles updatedFiles, ProgressIndicator indicator, List<VcsException> exceptions)
     throws VcsException;
-
-  class UpdateConfiguration{
-    private boolean shouldMerge = true;
-    private boolean shouldCommitAfterMerge = true;
-    private boolean shouldRebase = false;
-
-
-    public void setShouldMerge(boolean shouldMerge) {
-      this.shouldMerge = shouldMerge;
-    }
-
-    public void setShouldCommitAfterMerge(boolean shouldCommitAfterMerge) {
-      this.shouldCommitAfterMerge = shouldCommitAfterMerge;
-    }
-
-    public void setShouldRebase(boolean shouldRebase) {
-      this.shouldRebase = shouldRebase;
-    }
-
-  public boolean shouldRebase() {
-    return shouldRebase;
-  }
-  
-  public boolean shouldMerge() {
-    return shouldMerge;
-  }
-  
-  public boolean shouldCommitAfterMerge() {
-    return shouldMerge() && shouldCommitAfterMerge;
-  }
-  }
 }
index de4b865e5ca7079f1d2ff4aa2d39e12d141ec18e..16fb9b4ddeecd49de3101dc8ccc74f2b15a3643d 100644 (file)
 package org.zmlx.hg4idea.ui;
 
 import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.components.JBCheckBox;
 import net.miginfocom.swing.MigLayout;
-import org.zmlx.hg4idea.provider.update.HgUpdater;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.provider.update.HgUpdateConfigurationSettings;
+import org.zmlx.hg4idea.provider.update.HgUpdateType;
 
 import javax.swing.*;
 import java.awt.event.ItemEvent;
@@ -24,62 +27,106 @@ import java.awt.event.ItemListener;
  * Configuration dialog for the update process.
  */
 public class HgUpdateDialog {
+
+  private JComponent myContentPanel;
+  private JCheckBox myPullCheckBox;
   private JCheckBox myCommitAfterMergeCheckBox;
+  private JRadioButton myOnlyUpdateButton;
   private JRadioButton myMergeRadioButton;
   private JRadioButton myRebaseRadioButton;
 
 
-  public HgUpdateDialog() {
-    createCenterPanel();
+  public HgUpdateDialog(@NotNull HgUpdateConfigurationSettings updateSettings) {
+    myContentPanel = createCenterPanel(updateSettings);
+  }
+
+  public JComponent getContentPanel() {
+    return myContentPanel;
   }
 
   private void updateEnabledStates() {
     myCommitAfterMergeCheckBox.setEnabled(myMergeRadioButton.isSelected());
   }
 
-  public void applyTo(HgUpdater.UpdateConfiguration updateConfiguration) {
-    updateConfiguration.setShouldMerge(myMergeRadioButton.isSelected());
+  public void applyTo(HgUpdateConfigurationSettings updateConfiguration) {
+    updateConfiguration.setShouldPull(myPullCheckBox.isSelected());
+    if (myOnlyUpdateButton.isSelected()) {
+      updateConfiguration.setUpdateType(HgUpdateType.ONLY_UPDATE);
+    }
+    if (myMergeRadioButton.isSelected()) {
+      updateConfiguration.setUpdateType(HgUpdateType.MERGE);
+    }
+    if (myRebaseRadioButton.isSelected()) {
+      updateConfiguration.setUpdateType(HgUpdateType.REBASE);
+    }
     updateConfiguration.setShouldCommitAfterMerge(myCommitAfterMergeCheckBox.isSelected());
-    updateConfiguration.setShouldRebase(myRebaseRadioButton.isSelected());
   }
 
-  public JComponent createCenterPanel() {
+  public JComponent createCenterPanel(HgUpdateConfigurationSettings updateSettings) {
     MigLayout migLayout = new MigLayout("flowy,ins 0, fill");
     JPanel contentPane = new JPanel(migLayout);
 
+    myPullCheckBox = new JBCheckBox("Pull", true);
+    myPullCheckBox.setMnemonic('p');
+    myPullCheckBox.setToolTipText("Pull from the default remote repository");
+    myPullCheckBox.setSelected(updateSettings.shouldPull());
 
+    myOnlyUpdateButton = new JRadioButton("Only Update", true);
+    myOnlyUpdateButton.setMnemonic('u');
+    myOnlyUpdateButton.setToolTipText("Update to the head of the current branch");
 
-    contentPane.setBorder(IdeBorderFactory.createTitledBorder("Update Type"));
-
-    myMergeRadioButton = new JRadioButton("Merge", true);
+    myMergeRadioButton = new JRadioButton("Merge", false);
     myMergeRadioButton.setMnemonic('m');
     myMergeRadioButton.setToolTipText("Merge if pulling resulted in extra heads");
+    myMergeRadioButton.addItemListener(new ItemListener() {
+      @Override
+      public void itemStateChanged(ItemEvent e) {
+        updateEnabledStates();
+      }
+    });
+
     myCommitAfterMergeCheckBox = new JCheckBox("Commit after merge without conflicts", false);
     myCommitAfterMergeCheckBox.setMnemonic('c');
     myCommitAfterMergeCheckBox.setToolTipText("Commit automatically after the merge");
+    myCommitAfterMergeCheckBox.setSelected(updateSettings.shouldCommitAfterMerge());
+
     myRebaseRadioButton = new JRadioButton("Rebase", false);
     myRebaseRadioButton.setToolTipText("Rebase changesets to a branch tip as destination");
     myRebaseRadioButton.setMnemonic('r');
-    final ButtonGroup radioButtonGroup = new ButtonGroup();
-    radioButtonGroup.add(myMergeRadioButton);
-    radioButtonGroup.add(myRebaseRadioButton);
 
-    contentPane.add(myMergeRadioButton, "left");
-    contentPane.add(myCommitAfterMergeCheckBox, "gapx 5%");
-    contentPane.add(myRebaseRadioButton, "left");
-    myMergeRadioButton.addItemListener(new ItemListener() {
-      public void itemStateChanged(ItemEvent e) {
-        updateEnabledStates();
-      }
-    });
 
+    contentPane.add(myPullCheckBox, "left");
+    JPanel strategyPanel = new JPanel(migLayout);
+    strategyPanel.setBorder(IdeBorderFactory.createTitledBorder("Update Strategy"));
+    strategyPanel.add(myOnlyUpdateButton, "left");
+    strategyPanel.add(myMergeRadioButton, "left");
+    strategyPanel.add(myCommitAfterMergeCheckBox, "gapx 5%");
+    strategyPanel.add(myRebaseRadioButton, "left");
+    contentPane.add(strategyPanel);
+    ButtonGroup group = new ButtonGroup();
+    group.add(myOnlyUpdateButton);
+    group.add(myRebaseRadioButton);
+    group.add(myMergeRadioButton);
     updateEnabledStates();
     return contentPane;
   }
 
-  public void updateFrom(HgUpdater.UpdateConfiguration updateConfiguration) {
-    myMergeRadioButton.setSelected(updateConfiguration.shouldMerge());
+  public void updateFrom(@NotNull HgUpdateConfigurationSettings updateConfiguration) {
+    myPullCheckBox.setSelected(updateConfiguration.shouldPull());
+    HgUpdateType updateType = updateConfiguration.getUpdateType();
+    switch (updateType) {
+      case ONLY_UPDATE:
+        myOnlyUpdateButton.setSelected(true);
+        break;
+      case MERGE:
+        myMergeRadioButton.setSelected(true);
+        break;
+      case REBASE:
+        myRebaseRadioButton.setSelected(true);
+        break;
+      default:
+        assert false : "Unknown value of update type: " + updateType;
+    }
     myCommitAfterMergeCheckBox.setSelected(updateConfiguration.shouldCommitAfterMerge());
-    myRebaseRadioButton.setSelected(updateConfiguration.shouldRebase());
   }
 }
index c0c424102b4b57112d184548d646d3224c510069..6a8b50bbc3c8848b360c76e704f6150c04d9aaf5 100644 (file)
@@ -26,6 +26,7 @@ import org.zmlx.hg4idea.HgFileStatusEnum;
 import org.zmlx.hg4idea.HgRevisionNumber;
 import org.zmlx.hg4idea.command.*;
 import org.zmlx.hg4idea.provider.update.HgRegularUpdater;
+import org.zmlx.hg4idea.provider.update.HgUpdateConfigurationSettings;
 import org.zmlx.hg4idea.util.HgUtil;
 
 import java.io.File;
@@ -257,7 +258,7 @@ public class HgUpdateTest extends HgCollaborativeTest {
   }
 
   private List<VcsException> updateThroughPlugin() throws VcsException {
-    HgRegularUpdater updater = new HgRegularUpdater(myProject, projectRepoVirtualFile, new org.zmlx.hg4idea.provider.update.HgUpdater.UpdateConfiguration());
+    HgRegularUpdater updater = new HgRegularUpdater(myProject, projectRepoVirtualFile, new HgUpdateConfigurationSettings());
     UpdatedFiles updatedFiles = UpdatedFiles.create();
     EmptyProgressIndicator indicator = new EmptyProgressIndicator();
     ArrayList<VcsException> nonFatalWarnings = new ArrayList<VcsException>();
index ef81f5281cdd3829129bc39470f074bbfb6df9d8..b0f8424316ce68206eb3d24c36cab34793cc58dd 100644 (file)
@@ -22,16 +22,23 @@ import com.intellij.execution.actions.ConfigurationContext;
 import com.intellij.execution.configurations.ModuleBasedConfiguration;
 import com.intellij.execution.junit2.info.MethodLocation;
 import com.intellij.execution.testframework.AbstractTestProxy;
+import com.intellij.execution.testframework.TestTreeView;
+import com.intellij.execution.testframework.TestsUIUtil;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
+import com.intellij.util.ui.Tree;
 
+import javax.swing.*;
+import javax.swing.tree.TreePath;
+import java.awt.*;
 import java.util.ArrayList;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -98,7 +105,7 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer {
   }
 
   public static boolean isMultipleElementsSelected(ConfigurationContext context) {
-    if (AbstractTestProxy.DATA_KEY.getData(context.getDataContext()) != null) return false;
+    if (TestsUIUtil.isMultipleSelectionImpossible(context.getDataContext())) return false;
     final LinkedHashSet<String> classes = new LinkedHashSet<String>();
     final PsiElement[] elements = collectPatternElements(context, classes);
     if (elements != null && collectTestMembers(elements, false).size() > 1) {
index 9869e9ccf52e638608e37e50c4fc801063e30436..67f3eb17db8f1efe2db2e9acf688bd0be03cd048 100644 (file)
@@ -27,6 +27,7 @@ import com.intellij.execution.configurations.ModuleBasedConfiguration;
 import com.intellij.execution.junit.JUnitUtil;
 import com.intellij.execution.junit2.info.MethodLocation;
 import com.intellij.execution.testframework.AbstractTestProxy;
+import com.intellij.execution.testframework.TestsUIUtil;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.LangDataKeys;
@@ -86,7 +87,7 @@ public class TestNGPatternConfigurationProducer extends TestNGConfigurationProdu
   }
 
   public static boolean isMultipleElementsSelected(ConfigurationContext context) {
-    if (AbstractTestProxy.DATA_KEY.getData(context.getDataContext()) != null) return false;
+    if (TestsUIUtil.isMultipleSelectionImpossible(context.getDataContext())) return false;
     final LinkedHashSet<String> classes = new LinkedHashSet<String>();
     final PsiElement[] elements = collectPatternElements(context, classes);
     if (elements != null && collectTestMembers(elements).size() > 1) {
index b9fb54d3b31a1453479bb09380c98a762661c74d..6bc71f9f8549ba5a3ad6070ef6744dfa99dbb4ac 100644 (file)
@@ -67,12 +67,11 @@ public abstract class EmmetParser {
       }
 
       final String filterSuffix = ((IdentifierToken)token).getText();
-      if (!ZenCodingUtil.checkFilterSuffix(filterSuffix)) {
-        return null;
+      if (ZenCodingUtil.checkFilterSuffix(filterSuffix)) {
+        result = new FilterNode(result, filterSuffix);
       }
 
       advance();
-      result = new FilterNode(result, filterSuffix);
     }
   }
 
index bbd5a3a10cd6dc7b42c3bf7cd1db993866a5907d..46d5a5640f5375f3491128448f2fa892c61a346c 100644 (file)
@@ -323,7 +323,7 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
     });
     field.addKeyboardListener(new KeyAdapter() {
       @Override
-      public void keyPressed(KeyEvent e) {
+      public void keyPressed(@NotNull KeyEvent e) {
         if (!field.isPopupVisible()) {
           switch (e.getKeyCode()) {
             case KeyEvent.VK_ENTER:
@@ -509,6 +509,8 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
           }
         }).isEmpty();
         
+        CompletionResultSet resultSet = result.withPrefixMatcher(result.getPrefixMatcher().cloneWithPrefix(templatePrefix));
+        resultSet.restartCompletionOnPrefixChange(StandardPatterns.string().startsWith(templatePrefix));
         if (!regularTemplateWithSamePrefixExists) {
           // exclude perfect matches with existing templates because LiveTemplateCompletionContributor handles it
           final Collection<SingleLineEmmetFilter> extraFilters = ContainerUtil.newLinkedList(new SingleLineEmmetFilter());
@@ -518,9 +520,8 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
             template.setKey(templatePrefix);
             template.setDescription(template.getTemplateText());
 
-            CompletionResultSet resultSet = result.withPrefixMatcher(result.getPrefixMatcher().cloneWithPrefix(templatePrefix));
-            resultSet.restartCompletionOnPrefixChange(StandardPatterns.string().startsWith(templatePrefix));
-            resultSet.addElement(new CustomLiveTemplateLookupElement(this, template.getKey(), template.getKey(), template.getDescription(), true, true));
+            resultSet.addElement(new CustomLiveTemplateLookupElement(this, template.getKey(), template.getKey(), template.getDescription(), 
+              !LiveTemplateCompletionContributor.shouldShowAllTemplates(), true));
           }
         }
       }