diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml index c72056508335..f37ae2c10a0e 100644 --- a/community-resources/src/idea/IdeaApplicationInfo.xml +++ b/community-resources/src/idea/IdeaApplicationInfo.xml @@ -4,7 +4,7 @@ - + diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png index d70f9e0bb45e..3d15b0a762f9 100644 Binary files a/community-resources/src/idea_community_about.png and b/community-resources/src/idea_community_about.png differ diff --git a/community-resources/src/idea_community_about@2x.png b/community-resources/src/idea_community_about@2x.png index 6d33c8779f35..cb3a2035f09a 100644 Binary files a/community-resources/src/idea_community_about@2x.png and b/community-resources/src/idea_community_about@2x.png differ diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png index 4802436fdf5b..ce56a20d19e1 100644 Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png index 623e731b8506..73eb6056501c 100644 Binary files a/community-resources/src/idea_community_logo@2x.png and b/community-resources/src/idea_community_logo@2x.png differ diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 69de5260feb6..cfa3e6624735 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.inliner.*; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.dataFlow.value.*; import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType; +import com.intellij.lang.jvm.JvmModifier; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; @@ -77,11 +78,31 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { myAssertionError = createClassType(scope, JAVA_LANG_ASSERTION_ERROR); } + private void buildClassInitializerFlow(PsiClass psiClass, boolean isStatic) { + pushUnknown(); + ConditionalGotoInstruction conditionalGoto = new ConditionalGotoInstruction(null, false, null); + addInstruction(conditionalGoto); + for (PsiElement element : psiClass.getChildren()) { + if ((element instanceof PsiField || element instanceof PsiClassInitializer) && + ((PsiModifierListOwner)element).hasModifier(JvmModifier.STATIC) == isStatic) { + element.accept(this); + } + } + addInstruction(new FlushVariableInstruction(null)); + conditionalGoto.setOffset(getInstructionCount()); + } + @Nullable public ControlFlow buildControlFlow() { myCurrentFlow = new ControlFlow(myFactory); try { - myCodeFragment.accept(this); + if(myCodeFragment instanceof PsiClass) { + // if(unknown) { staticInitializer(); } if(unknown) { instanceInitializer(); } + buildClassInitializerFlow((PsiClass)myCodeFragment, true); + buildClassInitializerFlow((PsiClass)myCodeFragment, false); + } else { + myCodeFragment.accept(this); + } } catch (CannotAnalyzeException e) { return null; @@ -271,6 +292,20 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (initializer != null) { initializeVariable(field, initializer); } + else if (!field.hasModifier(JvmModifier.FINAL)) { + // initialize with default value + DfaVariableValue dfaVariable = myFactory.getVarFactory().createVariableValue(field, false); + addInstruction(new PushInstruction(dfaVariable, null, true)); + addInstruction(new PushInstruction( + myFactory.getConstFactory().createFromValue(PsiTypesUtil.getDefaultValue(field.getType()), field.getType(), null), null)); + addInstruction(new AssignInstruction(null, dfaVariable)); + addInstruction(new PopInstruction()); + } + } + + @Override + public void visitClassInitializer(PsiClassInitializer initializer) { + visitCodeBlock(initializer.getBody()); } private void initializeVariable(PsiVariable variable, PsiExpression initializer) { @@ -1029,7 +1064,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (componentType != null) { generateBoxingUnboxingInstructionFor(initializer, componentType); if (componentNullability == Nullness.NOT_NULL) { - addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.assigningToNotNull)); + addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.storingToNotNullArray)); } } addInstruction(new PopInstruction()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 6db91af441a6..42583ee11214 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -108,8 +108,8 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) { return new JavaElementVisitor() { @Override - public void visitField(PsiField field) { - analyzeCodeBlock(field, holder, isOnTheFly); + public void visitClass(PsiClass aClass) { + analyzeCodeBlock(aClass, holder, isOnTheFly); } @Override @@ -118,11 +118,6 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { analyzeNullLiteralMethodArguments(method, holder, isOnTheFly); } - @Override - public void visitClassInitializer(PsiClassInitializer initializer) { - analyzeCodeBlock(initializer.getBody(), holder, isOnTheFly); - } - @Override public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { super.visitMethodReferenceExpression(expression); @@ -190,7 +185,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { private void analyzeCodeBlock(@Nullable final PsiElement scope, ProblemsHolder holder, final boolean onTheFly) { if (scope == null) return; - PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class); + PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class, false); if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass) && !(containingClass instanceof PsiEnumConstantInitializer)) return; final StandardDataFlowRunner dfaRunner = @@ -200,6 +195,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { private static boolean isInsideConstructorOrInitializer(PsiElement element) { while (element != null) { + if (element instanceof PsiClass) return true; element = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClassInitializer.class); if (element instanceof PsiClassInitializer) return true; if (element instanceof PsiMethod) { @@ -249,12 +245,17 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { } } else if (rc == RunnerResult.TOO_COMPLEX) { - if (scope.getParent() instanceof PsiMethod) { - PsiMethod method = (PsiMethod)scope.getParent(); - final PsiIdentifier name = method.getNameIdentifier(); - if (name != null) { // Might be null for synthetic methods like JSP page. - holder.registerProblem(name, InspectionsBundle.message("dataflow.too.complex"), ProblemHighlightType.WEAK_WARNING); - } + PsiIdentifier name = null; + String message = null; + if(scope.getParent() instanceof PsiMethod) { + name = ((PsiMethod)scope.getParent()).getNameIdentifier(); + message = InspectionsBundle.message("dataflow.too.complex"); + } else if(scope instanceof PsiClass) { + name = ((PsiClass)scope).getNameIdentifier(); + message = InspectionsBundle.message("dataflow.too.complex.class"); + } + if (name != null) { // Might be null for synthetic methods like JSP page. + holder.registerProblem(name, message, ProblemHighlightType.WEAK_WARNING); } } } @@ -324,7 +325,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { reportNullableFunctions(visitor, holder, reportedAnchors); reportNullableArguments(visitor, holder, reportedAnchors); - reportNullableAssignments(visitor, holder, reportedAnchors); + reportNullableAssignments(visitor, holder, reportedAnchors, onTheFly); reportUnboxedNullables(visitor, holder, reportedAnchors); reportNullableReturns(visitor, holder, reportedAnchors, scope); if (SUGGEST_NULLABLE_ANNOTATIONS) { @@ -681,14 +682,29 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { } } - private static void reportNullableAssignments(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set reportedAnchors) { + private void reportNullableAssignments(DataFlowInstructionVisitor visitor, + ProblemsHolder holder, + Set reportedAnchors, + boolean onTheFly) { for (PsiElement expr : visitor.getProblems(NullabilityProblem.assigningToNotNull)) { if (!reportedAnchors.add(expr)) continue; + assert expr instanceof PsiExpression; final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message("dataflow.message.assigning.null") : InspectionsBundle.message("dataflow.message.assigning.nullable"); - holder.registerProblem(expr, text); + holder.registerProblem(expr, text, + createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY)); + } + for (PsiElement expr : visitor.getProblems(NullabilityProblem.storingToNotNullArray)) { + if (!reportedAnchors.add(expr)) continue; + assert expr instanceof PsiExpression; + + final String text = isNullLiteralExpression(expr) + ? InspectionsBundle.message("dataflow.message.storing.array.null") + : InspectionsBundle.message("dataflow.message.storing.array.nullable"); + holder.registerProblem(expr, text, + createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY)); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java index bc16cb37b09b..dfb0a88628d7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java @@ -26,7 +26,10 @@ import com.intellij.psi.*; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.*; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FList; @@ -195,24 +198,16 @@ public class DfaUtil { } static DfaValue getPossiblyNonInitializedValue(@NotNull DfaValueFactory factory, @NotNull PsiField target, @NotNull PsiElement context) { - PsiMember placeMember = PsiTreeUtil.getParentOfType(context, PsiMember.class, false, PsiClass.class, PsiLambdaExpression.class); - PsiType type = target.getType(); - if (placeMember == null || type instanceof PsiPrimitiveType && !(placeMember instanceof PsiField)) return null; + if (target.getType() instanceof PsiPrimitiveType) return null; + PsiMethod placeMethod = PsiTreeUtil.getParentOfType(context, PsiMethod.class, false, PsiClass.class, PsiLambdaExpression.class); + if (placeMethod == null) return null; - PsiClass placeClass = placeMember.getContainingClass(); - if (placeClass != null && placeClass == target.getContainingClass()) { - if (!placeMember.hasModifier(JvmModifier.STATIC) && target.hasModifier(JvmModifier.STATIC)) { - return null; - } + PsiClass placeClass = placeMethod.getContainingClass(); + if (placeClass == null || placeClass != target.getContainingClass()) return null; + if (!placeMethod.hasModifier(JvmModifier.STATIC) && target.hasModifier(JvmModifier.STATIC)) return null; + if (getAccessOffset(placeMethod) >= getWriteOffset(target)) return null; - if(getAccessOffset(placeMember) >= getWriteOffset(target)) { - return null; - } - return placeMember instanceof PsiField - ? factory.getConstFactory().createFromValue(PsiTypesUtil.getDefaultValue(type), type, null) - : factory.createTypeValue(type, Nullness.NULLABLE); - } - return null; + return factory.createTypeValue(target.getType(), Nullness.NULLABLE); } private static int getWriteOffset(PsiField target) { @@ -256,26 +251,21 @@ public class DfaUtil { return offset; } - private static int getAccessOffset(PsiMember referrer) { - if (referrer instanceof PsiField) { - return referrer.getTextRange().getStartOffset(); - } + private static int getAccessOffset(PsiMethod referrer) { PsiClass aClass = Objects.requireNonNull(referrer.getContainingClass()); - if (referrer instanceof PsiMethod) { - boolean isStatic = referrer.hasModifier(JvmModifier.STATIC); - for (PsiField field : aClass.getFields()) { - if (field.hasModifier(JvmModifier.STATIC) != isStatic) continue; - PsiExpression initializer = field.getInitializer(); - Predicate callToMethod = (PsiExpression e) -> { - if (!(e instanceof PsiMethodCallExpression)) return false; - PsiMethodCallExpression call = (PsiMethodCallExpression)e; - return call.getMethodExpression().isReferenceTo(referrer) && - (isStatic || DfaValueFactory.isEffectivelyUnqualified(call.getMethodExpression())); - }; - if (ExpressionUtils.isMatchingChildAlwaysExecuted(initializer, callToMethod)) { - // current method is definitely called from some field initialization - return field.getTextRange().getStartOffset(); - } + boolean isStatic = referrer.hasModifier(JvmModifier.STATIC); + for (PsiField field : aClass.getFields()) { + if (field.hasModifier(JvmModifier.STATIC) != isStatic) continue; + PsiExpression initializer = field.getInitializer(); + Predicate callToMethod = (PsiExpression e) -> { + if (!(e instanceof PsiMethodCallExpression)) return false; + PsiMethodCallExpression call = (PsiMethodCallExpression)e; + return call.getMethodExpression().isReferenceTo(referrer) && + (isStatic || DfaValueFactory.isEffectivelyUnqualified(call.getMethodExpression())); + }; + if (ExpressionUtils.isMatchingChildAlwaysExecuted(initializer, callToMethod)) { + // current method is definitely called from some field initialization + return field.getTextRange().getStartOffset(); } } return Integer.MAX_VALUE; // accessed after initialization or at unknown moment diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java index b5c62a649954..36e738d67e8d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java @@ -8,6 +8,7 @@ public enum NullabilityProblem { fieldAccessNPE, unboxingNullable, assigningToNotNull, + storingToNotNullArray, nullableReturn, nullableFunctionReturn, passingNullableToNotNullParameter, diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 9ee4c874c25b..bf5a01b4ffce 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -72,13 +72,16 @@ public class StandardInstructionVisitor extends InstructionVisitor { dfaDest = instruction.getAssignedValue(); } + NullabilityProblem problem = PsiUtil.skipParenthesizedExprDown(instruction.getLExpression()) instanceof PsiArrayAccessExpression ? + NullabilityProblem.storingToNotNullArray : NullabilityProblem.assigningToNotNull; + if (dfaDest instanceof DfaVariableValue) { DfaVariableValue var = (DfaVariableValue) dfaDest; final PsiModifierListOwner psi = var.getPsiVariable(); boolean forceDeclaredNullity = !(psi instanceof PsiParameter && psi.getParent() instanceof PsiParameterList); if (forceDeclaredNullity && var.getInherentNullability() == Nullness.NOT_NULL) { - checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression()); + checkNotNullable(memState, dfaSource, problem, instruction.getRExpression()); } if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) { memState.setVarValue(var, dfaSource); @@ -89,7 +92,7 @@ public class StandardInstructionVisitor extends InstructionVisitor { } } else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue)dfaDest).isNotNull()) { - checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression()); + checkNotNullable(memState, dfaSource, problem, instruction.getRExpression()); } memState.push(dfaDest); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java index 38b7b98edf10..d6260c15d9a2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java @@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.DfaInstructionState; import com.intellij.codeInspection.dataFlow.DfaMemoryState; import com.intellij.codeInspection.dataFlow.InstructionVisitor; import com.intellij.codeInspection.dataFlow.value.DfaValue; +import com.intellij.psi.PsiAssignmentExpression; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiVariable; import org.jetbrains.annotations.Nullable; @@ -44,6 +45,15 @@ public class AssignInstruction extends Instruction { return myRExpression; } + @Nullable + public PsiExpression getLExpression() { + if(myRExpression == null) return null; + if(myRExpression.getParent() instanceof PsiAssignmentExpression) { + return ((PsiAssignmentExpression)myRExpression.getParent()).getLExpression(); + } + return null; + } + public boolean isVariableInitializer() { return myRExpression != null && myRExpression.getParent() instanceof PsiVariable; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java index bc301e221951..c83ae090624c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java @@ -80,6 +80,8 @@ public class GuessTypeParameters { return; } + typeElement = (PsiTypeElement)typeElement.replace(JavaPsiFacade.getElementFactory(myProject).createTypeElement(info.getType())); + PsiSubstitutor rawingSubstitutor = getRawingSubstitutor(myProject, context, targetClass); int substitionResult = hasNullSubstitutions(mySubstitutor) ? SUBSTITUTED_NONE diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java index 29219d6aa559..4ddd17376bc3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java @@ -58,8 +58,10 @@ public class JavaCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper { builder.replaceElement(field.getInitializer(), new EmptyExpression()); PsiIdentifier identifier = field.getNameIdentifier(); builder.setEndVariableAfter(identifier); - field = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(field); } + + field = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(field); + editor.getCaretModel().moveToOffset(field.getTextRange().getStartOffset()); Template template = builder.buildInlineTemplate(); if (ExpectedTypesProvider.processExpectedTypes((ExpectedTypeInfo[])expectedTypes, new PsiTypeVisitor() { diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index f28fe9c2c6ea..96e1c27f8c61 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -84,6 +84,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { final PsiFile containingFile = navigationElement.getContainingFile(); if (!(containingFile instanceof PsiClassOwner && JavaProjectRootsUtil.isOutsideJavaSourceRoot(containingFile))) { + if (PsiPackage.PACKAGE_INFO_CLS_FILE.equals(containingFile.getName())) continue; PsiClass[] topLevelClasses = getTopLevelClasses(element); if (topLevelClasses == null) { if (element instanceof PsiDirectory) { diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java index 770f67bff837..3174948bfdfd 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java @@ -44,7 +44,7 @@ public class OverrideImplementExploreUtil { Map finals = new LinkedHashMap<>(); Map concretes = new LinkedHashMap<>(); - if (aClass.isAnnotationType()) return Collections.emptyMap(); + if (aClass.isAnnotationType() || aClass instanceof PsiTypeParameter) return Collections.emptyMap(); PsiUtilCore.ensureValid(aClass); Collection allMethodSigs = aClass.getVisibleSignatures(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java index 4681764c4ff0..6a04c16d6ce0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java @@ -153,9 +153,8 @@ public class PsiDiamondTypeUtil { typeElement = ((PsiVariable)gParent).getTypeElement(); } else if (gParent instanceof PsiReturnStatement) { - PsiMethod method = PsiTreeUtil.getParentOfType(gParent, PsiMethod.class); - LOG.assertTrue(method != null); - typeElement = method.getReturnTypeElement(); + PsiElement method = PsiTreeUtil.getParentOfType(gParent, PsiMethod.class, PsiLambdaExpression.class); + typeElement = method instanceof PsiMethod ? ((PsiMethod)method).getReturnTypeElement() : null; } return typeElement != null && PsiAugmentProvider.getInferredType(typeElement) != null; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java new file mode 100644 index 000000000000..3ecab1b9f6fa --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java @@ -0,0 +1,10 @@ +// "Make 'T' implement 'b'" "true" +class a> { + void f(b r, T t) { + r.g(t); + } +} +interface b { + void g(b t); +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java new file mode 100644 index 000000000000..f84b4c1ef641 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java @@ -0,0 +1,10 @@ +// "Make 'T' implement 'b'" "true" +class a { + void f(b r, T t) { + r.g(t); + } +} +interface b { + void g(b t); +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java new file mode 100644 index 000000000000..d92d3daeafda --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java @@ -0,0 +1,12 @@ +// "Create field 'foo'" "true" +class Usage { + + void usage(Generic g, List p) { + g.foo = p; + } +} + +class Generic { + + public List foo; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java new file mode 100644 index 000000000000..7f974cd5c2e5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java @@ -0,0 +1,12 @@ +// "Create field 'foo'" "true" +class Usage { + + void usage(Generic g, List[] p) { + g.foo = p; + } +} + +class Generic { + + public List[] foo; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java new file mode 100644 index 000000000000..5bc4ca00a7c6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java @@ -0,0 +1,11 @@ +// "Create field 'foo'" "true" +class Usage { + + void usage(Generic g, List p) { + g.foo = p; + } +} + +class Generic { + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java new file mode 100644 index 000000000000..ccb038f44716 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java @@ -0,0 +1,11 @@ +// "Create field 'foo'" "true" +class Usage { + + void usage(Generic g, List[] p) { + g.foo = p; + } +} + +class Generic { + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java new file mode 100644 index 000000000000..883b188ee1e7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java @@ -0,0 +1,11 @@ +// "Create method 'foo'" "true" +interface Generic { + List> foo(); +} + +class Usage { + + List> usage(Generic g) { + return g.foo(); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java new file mode 100644 index 000000000000..265fafb3fbae --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java @@ -0,0 +1,10 @@ +// "Create method 'foo'" "true" +interface Generic { +} + +class Usage { + + List> usage(Generic g) { + return g.foo(); + } +} diff --git a/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java b/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java index c31d7cff7cc9..a672e8ac0f47 100644 --- a/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java +++ b/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java @@ -6,7 +6,7 @@ class TestGenericsInstanceof { I member; - { + void test() { boolean test = member instanceof Impl; } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java index b1874526dad1..2b58f950ec77 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java @@ -19,10 +19,17 @@ class FooImpl implements Foo { return null; } else if (Math.random() > 0.5) { - @NotNull Object @Nullable [] arr1 = new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null}; - @NotNull Object @Nullable [] arr2 = {null, new Object(), Math.random() > 0.5 ? new Object() : null}; - return new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null}; + @NotNull Object @Nullable [] arr1 = new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null}; + @NotNull Object @Nullable [] arr2 = {null, new Object(), Math.random() > 0.5 ? new Object() : null}; + return new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null}; } - return new @NotNull Object @Nullable []{null, new Object(), Math.random() > 0.5 ? new Object() : null}; + return new @NotNull Object @Nullable []{null, new Object(), Math.random() > 0.5 ? new Object() : null}; + } + + void test() { + @NotNull Object @Nullable [] array = getNullableArrayOfNotNullObjects(); + assert array != null; + array[0] = null; + array[1] = Math.random() > 0.5 ? null : "foo"; } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java b/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java new file mode 100644 index 000000000000..952fbfbab8e9 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java @@ -0,0 +1,87 @@ +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class InitializerTest { + int x = Math.random() > 0.5 ? 0 : 1; + int y = x < 2 ? 5 : 6; + String z; + + { + if(y == 6) { + System.out.println("oops"); + } + z = "foo"; + } + + boolean b = z.startsWith("bar"); + + static final String ABC; + static { + if(Math.random() > 0.5) { + ABC = null; + } else { + ABC = "foo"; + } + } + + static final String XYZ = ABC.toLowerCase(); + + static { + new InitializerTest(); // INITIALIZED is not initialized yet here + } + + static final String INITIALIZED = "xyz".trim(); + + { + if(INITIALIZED == null) { + System.out.println("Class is not initialized yet"); + } + } + + static { + if(INITIALIZED == null) { + System.out.println("Class is not initialized yet"); + } + } +} + +class Constants { + static final Object C1 = get(); + static final Object C2 = get(); + static final Object C3 = get(); + static final Object C4 = get(); + static final Object C5 = get(); + static final Object C6 = get(); + static final Object C7 = get(); + static final Object C8 = get(); + static final Object C9 = get(); + static final Object C10 = get(); + static final Object C11 = get(); + + static Object get() {return new Object();} +} + +class TooComplexInitializer { + // This test just checks that "too complex" warning is placed correctly on class name, + // not that this particular code always must be considered as "too complex". + // If in future this code will become not too complex, that's fine, just update test to make it even more complex + static { + int i = 1; + for(Object obj = Constants.get(); obj != Constants.C5; obj = Constants.get()) { + if (obj == Constants.C1) i = 2; + if (obj == Constants.C2) i = 3; + if (obj == Constants.C3) i = 4; + if (obj == Constants.C4) i = 5; + if (obj == Constants.C5) i = 6; + if (obj == Constants.C6) i = 7; + if (obj == Constants.C7) i = 8; + if (obj == Constants.C8) i = 9; + if (obj == Constants.C9) i = 10; + if (obj == Constants.C10) i = 11; + if (obj == Constants.C11) i = 12; + if (i > 5 && obj == Constants.C3) { + System.out.println("Never?"); + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java b/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java index f9ddb5c1a88b..bb5539b072d0 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java @@ -87,8 +87,7 @@ class NonFinalInitialized { class NonFinalAssignedInside { String x; - // Should warn on the first trim - String y = x.trim()+(x = " foo ").trim(); + String y = x.trim()+(x = " foo ").trim(); String z = x.trim(); } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java index 0b3d76b5f59c..255f598d504f 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java @@ -3,7 +3,7 @@ import org.jetbrains.annotations.Nullable; class Goo { Permission permission; - { + void test() { Object category = permission.getCategory(); System.out.println(category.hashCode()); } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java index b6d38eb8cd40..7d6d8d04fb55 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java @@ -84,6 +84,10 @@ public class CreateFieldFromUsageTest extends LightQuickFixTestCase { doSingleTest(); } + public void testInnerGeneric() { doSingleTest(); } + + public void testInnerGenericArray() { doSingleTest(); } + protected void doSingleTest() { doSingleTest(getTestName(false) + ".java"); } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy index f7c920d98418..de6082e4915e 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy @@ -50,7 +50,7 @@ class DataFlowInspectionHeavyTest extends JavaCodeInsightFixtureTestCase { def testFile = myFixture.addFileToProject 'test.java', ''' class Zoo { @annos.Nullable String a = null; - @annos.NotNull String f = foo.ObjectUtils.notNull(a); + @annos.NotNull String f = foo.ObjectUtils.notNull(a); void bar(@annos.NotNull String param) { } void goo(@annos.Nullable String param) { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index 622faa144912..bc00b4e7b5ba 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -536,4 +536,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testEmptySingletonMap() {doTest();} public void testStaticFieldsWithNewObjects() { doTest(); } + public void testComplexInitializer() { doTest(); } } diff --git a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java index 44e09b559978..32bc8e76c8ff 100644 --- a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java @@ -16,15 +16,11 @@ package com.intellij.psi; import com.intellij.lang.Language; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.SharedPsiElementImplUtil; import com.intellij.psi.impl.source.DummyHolder; -import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.psi.impl.source.tree.LeafElement; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.LocalTimeCounter; @@ -35,41 +31,21 @@ import java.util.Collections; import java.util.List; import java.util.Set; -public class DummyHolderViewProvider extends UserDataHolderBase implements FileViewProvider{ +public class DummyHolderViewProvider extends AbstractFileViewProvider { private DummyHolder myHolder; - private final PsiManager myManager; private final long myModificationStamp; - private final LightVirtualFile myLightVirtualFile = new LightVirtualFile("DummyHolder"); public DummyHolderViewProvider(@NotNull PsiManager manager) { - myManager = manager; + super(manager, new LightVirtualFile("DummyHolder"), false, UnknownFileType.INSTANCE); myModificationStamp = LocalTimeCounter.currentTime(); } - @Override - @NotNull - public PsiManager getManager() { - return myManager; - } - - @Override - @Nullable - public Document getDocument() { - return FileDocumentManager.getInstance().getDocument(getVirtualFile()); - } - @Override @NotNull public CharSequence getContents() { return myHolder != null ? myHolder.getNode().getText() : ""; } - @Override - @NotNull - public VirtualFile getVirtualFile() { - return myLightVirtualFile; - } - @Override @NotNull public Language getBaseLanguage() { @@ -82,32 +58,33 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV return Collections.singleton(getBaseLanguage()); } + @Nullable @Override - public PsiFile getPsi(@NotNull Language target) { - ((PsiManagerEx)myManager).getFileManager().setViewProvider(getVirtualFile(), this); + protected PsiFile getPsiInner(Language target) { + return getCachedPsi(target); + } + + @Override + public PsiFile getCachedPsi(@NotNull Language target) { + getManager().getFileManager().setViewProvider(getVirtualFile(), this); return target == getBaseLanguage() ? myHolder : null; } + @Override + public List getCachedPsiFiles() { + return Collections.singletonList(myHolder); + } + + @NotNull + @Override + public List getKnownTreeRoots() { + return Collections.singletonList(myHolder.getTreeElement()); + } + @Override @NotNull public List getAllFiles() { - return Collections.singletonList(getPsi(getBaseLanguage())); - } - - @Override - public void beforeContentsSynchronized() {} - - @Override - public void contentsSynchronized() {} - - @Override - public boolean isEventSystemEnabled() { - return false; - } - - @Override - public boolean isPhysical() { - return false; + return getCachedPsiFiles(); } @Override @@ -115,23 +92,9 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV return myModificationStamp; } - @Override - public boolean supportsIncrementalReparse(@NotNull final Language rootLanguage) { - return true; - } - - @Override - public void rootChanged(@NotNull PsiFile psiFile) { - } - public void setDummyHolder(@NotNull DummyHolder dummyHolder) { myHolder = dummyHolder; - myLightVirtualFile.setFileType(dummyHolder.getFileType()); - } - - @Override - public FileViewProvider clone(){ - throw new RuntimeException("Clone is not supported for DummyHolderProviders. Use DummyHolder clone directly."); + ((LightVirtualFile)getVirtualFile()).setFileType(dummyHolder.getFileType()); } @Override @@ -139,45 +102,21 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV return SharedPsiElementImplUtil.findReferenceAt(getPsi(getBaseLanguage()), offset); } - @Override - @Nullable - public PsiElement findElementAt(final int offset, @NotNull final Language language) { - return language == getBaseLanguage() ? findElementAt(offset) : null; - } - - @Override public PsiElement findElementAt(int offset, @NotNull Class lang) { if (!lang.isAssignableFrom(getBaseLanguage().getClass())) return null; return findElementAt(offset); } - @Override - public PsiReference findReferenceAt(final int offsetInElement, @NotNull final Language language) { - return language == getBaseLanguage() ? findReferenceAt(offsetInElement) : null; - } - @NotNull @Override public FileViewProvider createCopy(@NotNull final VirtualFile copy) { throw new RuntimeException("Clone is not supported for DummyHolderProviders. Use DummyHolder clone directly."); } - @NotNull - @Override - public PsiFile getStubBindingRoot() { - return getPsi(getBaseLanguage()); - } - - @NotNull - @Override - public FileType getFileType() { - return myLightVirtualFile.getFileType(); - } - @Override public PsiElement findElementAt(final int offset) { - final LeafElement element = ((PsiFileImpl)getPsi(getBaseLanguage())).calcTreeElement().findLeafElementAt(offset); + final LeafElement element = myHolder.calcTreeElement().findLeafElementAt(offset); return element != null ? element.getPsi() : null; } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index ca070a4cd889..f025b73abd88 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -427,7 +427,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen } void forceReload(VirtualFile virtualFile, @Nullable FileViewProvider viewProvider) { - if (viewProvider instanceof AbstractFileViewProvider) { + if (viewProvider != null) { ((AbstractFileViewProvider)viewProvider).markInvalidated(); } if (virtualFile != null) { @@ -900,12 +900,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() { @Override public void run() { - FileViewProvider viewProvider = psiFile.getViewProvider(); - if (viewProvider instanceof AbstractFileViewProvider) { - ((AbstractFileViewProvider)viewProvider).onContentReload(); - } else { - LOG.error("Invalid view provider: " + viewProvider + " of " + viewProvider.getClass()); - } + ((AbstractFileViewProvider)psiFile.getViewProvider()).onContentReload(); } }); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java index 414522e8bae9..67b2938d42c6 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java @@ -366,7 +366,7 @@ public class PsiManagerImpl extends PsiManagerEx { for (PsiTreeChangePreprocessor preprocessor : myTreeChangePreprocessors) { preprocessor.treeChanged(event); } - boolean enableOutOfCodeBlockTracking = myModificationTracker.getOutOfCodeBlockModificationTracker() != myModificationTracker; + boolean enableOutOfCodeBlockTracking = ((PsiModificationTrackerImpl)myModificationTracker).isEnableCodeBlockTracker(); for (PsiTreeChangePreprocessor preprocessor : Extensions.getExtensions(PsiTreeChangePreprocessor.EP_NAME, myProject)) { if (!enableOutOfCodeBlockTracking && preprocessor instanceof PsiTreeChangePreprocessorBase) continue; preprocessor.treeChanged(event); diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java index b9653843f218..021edf8be5f4 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.SimpleModificationTracker; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiModificationTracker; @@ -36,7 +37,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED; import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.PROPERTY_CHANGED; @@ -46,16 +46,15 @@ import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.PROPERTY * Date: Jul 18, 2002 */ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTreeChangePreprocessor { - private final boolean myEnableCodeBlockTracker = Registry.is("psi.modification.tracker.code-block"); - private final boolean myEnableJavaStructureTracker = Registry.is("psi.modification.tracker.java-structure"); - private final boolean myEnableLanguageTracker = Registry.is("psi.modification.tracker.per-language"); + private static final RegistryValue ourEnableCodeBlockTracker = Registry.get("psi.modification.tracker.code-block"); + private static final RegistryValue ourEnableJavaStructureTracker = Registry.get("psi.modification.tracker.java-structure"); + private static final RegistryValue ourEnableLanguageTracker = Registry.get("psi.modification.tracker.per-language"); - private final AtomicLong myModificationCount = new AtomicLong(0); - private final AtomicLong myOutOfCodeBlockModificationCount = myEnableCodeBlockTracker ? new AtomicLong(0) : myModificationCount; - private final AtomicLong myJavaStructureModificationCount = myEnableJavaStructureTracker ? new AtomicLong(0) : myModificationCount; + private final boolean myTestMode = ApplicationManager.getApplication().isUnitTestMode(); - private final ModificationTracker myOutOfCodeBlockModificationTracker = myEnableCodeBlockTracker ? () -> getOutOfCodeBlockModificationCount() : this; - private final ModificationTracker myJavaStructureModificationTracker = myEnableJavaStructureTracker ? () -> getJavaStructureModificationCount() : this; + private final SimpleModificationTracker myModificationCount = new SimpleModificationTracker(); + private final SimpleModificationTracker myOutOfCodeBlockModificationTracker = wrapped(ourEnableCodeBlockTracker, myModificationCount, myTestMode); + private final SimpleModificationTracker myJavaStructureModificationTracker = wrapped(ourEnableJavaStructureTracker, myModificationCount, myTestMode); private final Map myLanguageTrackers = ConcurrentFactoryMap.createMap(language -> new SimpleModificationTracker()); @@ -63,7 +62,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr private final Listener myPublisher; public PsiModificationTrackerImpl(Project project) { - final MessageBus bus = project.getMessageBus(); + MessageBus bus = project.getMessageBus(); myPublisher = bus.syncPublisher(TOPIC); bus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() { private void doIncCounter() { @@ -83,10 +82,11 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr } public void incCounter() { - myModificationCount.getAndIncrement(); - myJavaStructureModificationCount.getAndIncrement(); - myOutOfCodeBlockModificationCount.getAndIncrement(); - fireEvent(); + incCountersInner(7); + } + + public void incOutOfCodeBlockModificationCounter() { + incCountersInner(3); } private void fireEvent() { @@ -94,9 +94,10 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr myPublisher.modificationCountChanged(); } - public void incOutOfCodeBlockModificationCounter() { - myModificationCount.getAndIncrement(); - myOutOfCodeBlockModificationCount.getAndIncrement(); + private void incCountersInner(int bits) { + if ((bits & 0x1) != 0) myModificationCount.incModificationCount(); + if ((bits & 0x2) != 0) myOutOfCodeBlockModificationTracker.incModificationCount(); + if ((bits & 0x4) != 0) myJavaStructureModificationTracker.incModificationCount(); fireEvent(); } @@ -114,12 +115,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr code == CHILD_MOVED ? event.getOldParent() instanceof PsiDirectory || event.getNewParent() instanceof PsiDirectory : event.getParent() instanceof PsiDirectory; - myModificationCount.getAndIncrement(); - if (outOfCodeBlock) { - myJavaStructureModificationCount.getAndIncrement(); - myOutOfCodeBlockModificationCount.getAndIncrement(); - } - fireEvent(); + incCountersInner(outOfCodeBlock ? 7 : 1); } public static boolean canAffectPsi(@NotNull PsiTreeChangeEventImpl event) { @@ -127,7 +123,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr } protected void incLanguageTrackers(@NotNull PsiTreeChangeEventImpl event) { - if (!myEnableLanguageTracker) return; + if (!ourEnableLanguageTracker.asBoolean()) return; incLanguageModificationCount(Language.ANY); for (PsiElement o : new PsiElement[]{ event.getFile(), event.getParent(), event.getOldParent(), event.getNewParent(), @@ -154,12 +150,17 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr @Override public long getModificationCount() { - return myModificationCount.get(); + return myModificationCount.getModificationCount(); } @Override public long getOutOfCodeBlockModificationCount() { - return myOutOfCodeBlockModificationCount.get(); + return myOutOfCodeBlockModificationTracker.getModificationCount(); + } + + @Override + public long getJavaStructureModificationCount() { + return myJavaStructureModificationTracker.getModificationCount(); } @NotNull @@ -168,17 +169,24 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr return myOutOfCodeBlockModificationTracker; } - @Override - public long getJavaStructureModificationCount() { - return myJavaStructureModificationCount.get(); - } - @NotNull @Override public ModificationTracker getJavaStructureModificationTracker() { return myJavaStructureModificationTracker; } + + @ApiStatus.Experimental + public boolean isEnableCodeBlockTracker() { + if (myTestMode) return true; + return ourEnableCodeBlockTracker.asBoolean(); + } + + @ApiStatus.Experimental + public boolean isEnableLanguageTracker() { + return ourEnableLanguageTracker.asBoolean(); + } + @ApiStatus.Experimental public void incLanguageModificationCount(@Nullable Language language) { if (language == null) return; @@ -188,14 +196,14 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr @ApiStatus.Experimental @NotNull public ModificationTracker forLanguage(@NotNull Language language) { - if (!myEnableLanguageTracker) return this; + if (!ourEnableLanguageTracker.asBoolean()) return this; return myLanguageTrackers.get(language); } @ApiStatus.Experimental @NotNull public ModificationTracker forLanguages(@NotNull Condition condition) { - if (!myEnableLanguageTracker) return this; + if (!ourEnableLanguageTracker.asBoolean()) return this; return () -> { long result = 0; for (Language l : myLanguageTrackers.keySet()) { @@ -205,4 +213,24 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr return result; }; } + + @NotNull + private static SimpleModificationTracker wrapped(RegistryValue value, SimpleModificationTracker fallback, boolean testMode) { + if (testMode) { + return new SimpleModificationTracker(); + } + return new SimpleModificationTracker() { + @Override + public long getModificationCount() { + return value.asBoolean() ? super.getModificationCount() : + fallback.getModificationCount(); + } + + @Override + public void incModificationCount() { + if (value.asBoolean()) super.incModificationCount(); + //else fallback.incModificationCount(); + } + }; + } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java index ca615bf74b62..c5c495daad3d 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -91,9 +91,7 @@ public class FileManagerImpl implements FileManager { } public static void clearPsiCaches(@NotNull FileViewProvider provider) { - List psiFiles = provider instanceof AbstractFileViewProvider? ((AbstractFileViewProvider)provider).getCachedPsiFiles() - : provider.getAllFiles(); - psiFiles.forEach(PsiFile::clearCaches); + ((AbstractFileViewProvider)provider).getCachedPsiFiles().forEach(PsiFile::clearCaches); } public void forceReload(@NotNull VirtualFile vFile) { @@ -438,9 +436,7 @@ public class FileManagerImpl implements FileManager { } private void markInvalidated(@NotNull FileViewProvider viewProvider) { - if (viewProvider instanceof AbstractFileViewProvider) { - ((AbstractFileViewProvider)viewProvider).markInvalidated(); - } + ((AbstractFileViewProvider)viewProvider).markInvalidated(); VirtualFile virtualFile = viewProvider.getVirtualFile(); Document document = FileDocumentManager.getInstance().getCachedDocument(virtualFile); if (document != null) { @@ -453,8 +449,7 @@ public class FileManagerImpl implements FileManager { PsiFile getCachedPsiFileInner(@NotNull VirtualFile file) { FileViewProvider fileViewProvider = myVFileToViewProviderMap.get(file); if (fileViewProvider == null) fileViewProvider = file.getUserData(myPsiHardRefKey); - return fileViewProvider instanceof AbstractFileViewProvider - ? ((AbstractFileViewProvider)fileViewProvider).getCachedPsi(fileViewProvider.getBaseLanguage()) : null; + return fileViewProvider != null ? ((AbstractFileViewProvider)fileViewProvider).getCachedPsi(fileViewProvider.getBaseLanguage()) : null; } @NotNull @@ -462,9 +457,7 @@ public class FileManagerImpl implements FileManager { public List getAllCachedFiles() { List files = new ArrayList<>(); for (FileViewProvider provider : myVFileToViewProviderMap.values()) { - if (provider instanceof AbstractFileViewProvider) { - ContainerUtil.addIfNotNull(files, ((AbstractFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage())); - } + ContainerUtil.addIfNotNull(files, ((AbstractFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage())); } return files; } @@ -588,11 +581,6 @@ public class FileManagerImpl implements FileManager { return; } - FileViewProvider viewProvider = file.getViewProvider(); - if (viewProvider instanceof AbstractFileViewProvider) { - ((AbstractFileViewProvider)viewProvider).onContentReload(); - } else { - LOG.error("Invalid view provider: " + viewProvider + " of " + viewProvider.getClass()); - } + ((AbstractFileViewProvider)file.getViewProvider()).onContentReload(); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index d8e3cda6163b..cdb0f5218fcf 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -545,9 +545,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF myOriginalFile = originalFile.getOriginalFile(); FileViewProvider original = myOriginalFile.getViewProvider(); - if (myViewProvider instanceof AbstractFileViewProvider && original instanceof AbstractFileViewProvider) { - ((AbstractFileViewProvider)original).registerAsCopy((AbstractFileViewProvider)myViewProvider); - } + ((AbstractFileViewProvider)original).registerAsCopy((AbstractFileViewProvider)myViewProvider); } @Override diff --git a/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java b/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java index 64fb30582fe4..4f494be7f13b 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java +++ b/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java @@ -16,6 +16,7 @@ package com.intellij.execution.console; import com.intellij.icons.AllIcons; +import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -36,7 +37,7 @@ import javax.swing.*; */ public class IdeConsoleRootType extends ConsoleRootType { IdeConsoleRootType() { - super("ide", "IDE Scripting"); + super("ide", ApplicationNamesInfo.getInstance().getProductName() + " Consoles"); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java b/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java index a2ebac4e0066..a8ec4122a8e4 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java @@ -18,6 +18,7 @@ package com.intellij.internal.psiView.stubtree; import com.intellij.ide.util.treeView.TreeVisitor; import com.intellij.internal.psiView.ViewerPsiBasedTree; import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; @@ -25,6 +26,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.StubBuilder; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; import com.intellij.psi.stubs.*; @@ -53,11 +55,12 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import static com.intellij.internal.psiView.PsiViewerDialog.LOG; import static com.intellij.internal.psiView.PsiViewerDialog.initTree; public class StubViewerPsiBasedTree implements ViewerPsiBasedTree { + public static final Logger LOG = Logger.getInstance("#com.intellij.internal.psiView.PsiViewerDialog"); + private static final Key PSI_ELEMENT_SELECTION_REQUESTOR = Key.create("SelectionRequester"); @Nullable @@ -167,8 +170,8 @@ public class StubViewerPsiBasedTree implements ViewerPsiBasedTree { stub = tree.getRoot(); } else if (rootElement instanceof PsiFileImpl) { - IStubFileElementType builder = ((PsiFileImpl)rootElement).getElementTypeForStubBuilder(); - stub = builder == null ? null : builder.getBuilder().buildStubTree((PsiFile)rootElement); + StubBuilder stubBuilder = getStubBuilder((PsiFileImpl)rootElement); + stub = stubBuilder == null ? null : stubBuilder.buildStubTree((PsiFile)rootElement); } if (stub == null) { LightVirtualFile file = new LightVirtualFile("stub", rootElement.getLanguage(), textToParse); @@ -185,6 +188,12 @@ public class StubViewerPsiBasedTree implements ViewerPsiBasedTree { return stub; } + @Nullable + private static StubBuilder getStubBuilder(@NotNull PsiFileImpl rootElement) { + IStubFileElementType builder = rootElement.getElementTypeForStubBuilder(); + return builder == null ? null : builder.getBuilder(); + } + public void selectNodeFromPsi(@Nullable PsiElement element) { if (myStubTreeBuilder == null || element == null) return; final PsiFile file = element.getContainingFile(); @@ -268,24 +277,37 @@ public class StubViewerPsiBasedTree implements ViewerPsiBasedTree { public void fillTreeForStub(@NotNull PsiFileWithStubSupport file, @NotNull StubTree tree) { + StubBuilder builder = file instanceof PsiFileImpl ? getStubBuilder(((PsiFileImpl)file)) : null; + if (builder == null) return; + final Iterator> stubs = tree.getPlainList().iterator(); final StubElement root = stubs.next(); final ASTNode ast = file.getNode(); myNodeToStubs.put(ast, root); - findTreeForStub(ast, stubs); + findTreeForStub(builder, ast, stubs); + + if (stubs.hasNext()) { + LOG.error("Stub mismatch, unprocessed stubs " + stubs.next()); + } } - private void findTreeForStub(ASTNode tree, final Iterator> stubs) { + private void findTreeForStub(StubBuilder builder, ASTNode tree, final Iterator> stubs) { final IElementType type = tree.getElementType(); if (type instanceof IStubElementType && ((IStubElementType)type).shouldCreateStub(tree)) { + if (!stubs.hasNext()) { + LOG.error("Stub mismatch, " + type); + } final StubElement curStub = stubs.next(); myNodeToStubs.put(tree, curStub); } + for (ASTNode node : tree.getChildren(null)) { - findTreeForStub(node, stubs); + if (!builder.skipChildProcessingWhenBuildingStubs(tree, node)) { + findTreeForStub(builder, node, stubs); + } } } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index 4c56c16ce754..d5806ef782dc 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java @@ -375,14 +375,8 @@ public class PsiVFSListener implements VirtualFileListener { final String propertyName = event.getPropertyName(); final VirtualFile vFile = event.getFile(); - final FileViewProvider oldFileViewProvider = myFileManager.findCachedViewProvider(vFile); - final PsiFile oldPsiFile; - if (oldFileViewProvider instanceof AbstractFileViewProvider) { - oldPsiFile = ((AbstractFileViewProvider)oldFileViewProvider).getCachedPsi(oldFileViewProvider.getBaseLanguage()); - } - else { - oldPsiFile = null; - } + FileViewProvider oldFileViewProvider = myFileManager.findCachedViewProvider(vFile); + PsiFile oldPsiFile = myFileManager.getCachedPsiFile(vFile); VirtualFile parent = vFile.getParent(); final PsiDirectory parentDir = oldPsiFile != null && parent != null ? myFileManager.findDirectory(parent) : getCachedDirectory(parent); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 7efe4564eb36..e2bbb18e2fa0 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -470,7 +470,7 @@ public class InjectedLanguageUtil { if (!delegate.isValid()) return; FileViewProvider viewProvider = psiManagerEx.getFileManager().findCachedViewProvider(delegate); - if (!(viewProvider instanceof AbstractFileViewProvider)) return; + if (viewProvider == null) return; for (PsiFile hostFile : ((AbstractFileViewProvider)viewProvider).getCachedPsiFiles()) { // modification of cachedInjectedDocuments must be under PsiLock diff --git a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java index d892c7fd5a5d..33c954ce8451 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java @@ -228,7 +228,7 @@ public class CopyFilesOrDirectoriesHandler extends CopyHandlerDelegateBase { } final Project project = targetDirectory.getProject(); - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, Collections.singleton(targetDirectory), false)) { + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, Collections.singleton(targetDirectory), true)) { return; } diff --git a/platform/platform-impl/src/com/intellij/internal/ui/ShowMainMenuAction.java b/platform/platform-impl/src/com/intellij/internal/ui/ShowMainMenuAction.java new file mode 100644 index 000000000000..e58192bf69b2 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/ui/ShowMainMenuAction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2017 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.internal.ui; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.ui.popup.JBPopupFactory; + +/** + * @author Konstantin Bulenkov + */ +public class ShowMainMenuAction extends DumbAwareAction { + @Override + public void actionPerformed(AnActionEvent e) { + ActionGroup mainMenu = (ActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_MAIN_MENU); + JBPopupFactory.getInstance() + .createActionGroupPopup("Main Menu", mainMenu, + e.getDataContext(), + false, true, false, null, 30, null) + .showInBestPositionFor(e.getDataContext()); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/ActionButtonLook.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/ActionButtonLook.java index 1a593e14ddf2..ea8c986c1ee4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/ActionButtonLook.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/ActionButtonLook.java @@ -25,10 +25,31 @@ import javax.swing.*; import java.awt.*; public abstract class ActionButtonLook { - @SuppressWarnings("StaticInitializerReferencesSubClass") - public static final ActionButtonLook DEFAULT_LOOK = UIUtil.isUnderWin10LookAndFeel() ? - new Win10ActionButtonLook() : - new IdeaActionButtonLook(); + public static final ActionButtonLook SYSTEM_LOOK = new ActionButtonLook() { + private ActionButtonLook currentLook; + private void validateLook() { + if (currentLook == null || !currentLook.isValid()) { + currentLook = UIUtil.isUnderWin10LookAndFeel() ? + new Win10ActionButtonLook() : + new IdeaActionButtonLook(); + } + } + + @Override public void paintBackground(Graphics g, JComponent component, int state) { + validateLook(); + currentLook.paintBackground(g, component, state); + } + + @Override public void paintBorder(Graphics g, JComponent component, int state) { + validateLook(); + currentLook.paintBorder(g, component, state); + } + + @Override public Insets getInsets() { + validateLook(); + return currentLook.getInsets(); + } + }; public static final ActionButtonLook INPLACE_LOOK = new ActionButtonLook() { @Override public void paintBackground(Graphics g, JComponent component, int state) {} @@ -47,6 +68,10 @@ public abstract class ActionButtonLook { public abstract void paintBorder(Graphics g, JComponent component, @ActionButtonComponent.ButtonState int state); + public boolean isValid() { + return true; + } + @SuppressWarnings("MethodMayBeStatic") @ActionButtonComponent.ButtonState protected int getState(ActionButtonComponent button) { @@ -59,10 +84,10 @@ public abstract class ActionButtonLook { int height = icon.getIconHeight(); int x = (actionButton.getWidth() - width) / 2; int y = (actionButton.getHeight() - height) / 2; - paintIconAt(g, actionButton, icon, x, y); + paintIconAt(g, icon, x, y); } - public void paintIconAt(Graphics g, ActionButtonComponent button, Icon icon, int x, int y) { + public void paintIconAt(Graphics g, Icon icon, int x, int y) { icon.paintIcon(null, g, x, y); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java index cc280b4a118f..c7dba9d3047e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java @@ -50,7 +50,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A protected final Presentation myPresentation; protected final AnAction myAction; protected final String myPlace; - private ActionButtonLook myLook = ActionButtonLook.DEFAULT_LOOK; + private ActionButtonLook myLook = ActionButtonLook.SYSTEM_LOOK; private boolean myMouseDown; private boolean myRollover; private static boolean ourGlobalMouseDown = false; @@ -238,7 +238,6 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A } } - public void setIconInsets(@Nullable Insets insets) { myInsets = insets != null ? JBUI.insets(insets) : JBUI.emptyInsets(); } @@ -308,7 +307,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A myLook = look; } else { - myLook = ActionButtonLook.DEFAULT_LOOK; + myLook = ActionButtonLook.SYSTEM_LOOK; } repaint(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButtonWithText.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButtonWithText.java index d6a5deb82354..6fe4a96530dd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButtonWithText.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButtonWithText.java @@ -140,9 +140,9 @@ public class ActionButtonWithText extends ActionButton { SwingConstants.CENTER, horizontalTextAlignment(), SwingConstants.CENTER, horizontalTextPosition(), viewRect, iconRect, textRect, iconTextSpace()); - ActionButtonLook look = ActionButtonLook.DEFAULT_LOOK; + ActionButtonLook look = ActionButtonLook.SYSTEM_LOOK; look.paintBackground(g, this); - look.paintIconAt(g, this, icon, iconRect.x, iconRect.y); + look.paintIconAt(g, icon, iconRect.x, iconRect.y); look.paintBorder(g, this); UISettings.setupAntialiasing(g); @@ -165,10 +165,12 @@ public class ActionButtonWithText extends ActionButton { return UIUtil.getInactiveTextColor(); } + @SuppressWarnings("unused") public void setHorizontalTextPosition(@MagicConstant(valuesFromClass = SwingConstants.class) int position) { myHorizontalTextPosition = position; } + @SuppressWarnings("unused") public void setHorizontalTextAlignment(@MagicConstant(flagsFromClass = SwingConstants.class) int alignment) { myHorizontalTextAlignment = alignment; } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/IdeaActionButtonLook.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/IdeaActionButtonLook.java index 17321a765eec..69e49973622d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/IdeaActionButtonLook.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/IdeaActionButtonLook.java @@ -118,6 +118,10 @@ public class IdeaActionButtonLook extends ActionButtonLook { } } + @Override public boolean isValid() { + return !UIUtil.isUnderWin10LookAndFeel(); + } + private static Shape getShape(Dimension size) { return new RoundRectangle2D.Double(1, 1, size.width - 3, size.height - 3, 4, 4); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Win10ActionButtonLook.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Win10ActionButtonLook.java index c94b453f2f63..a4cce9197ec9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Win10ActionButtonLook.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Win10ActionButtonLook.java @@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.ex.ActionButtonLook; import com.intellij.ui.Gray; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.*; @@ -87,4 +88,8 @@ public class Win10ActionButtonLook extends ActionButtonLook { return UIManager.getColor("Button.intellij.native.borderColor"); } } + + @Override public boolean isValid() { + return UIUtil.isUnderWin10LookAndFeel(); + } } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index b271d9454055..91cb018c8a88 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -858,6 +858,7 @@ group.MemoryManagement.text=Memory Management action.DumpPsiMemoryCaches.text=Dump what is cached in PSI action.DecodeBytesAction.text=Decode Bytes... action.ReloadProjectAction.text=Reload Project +action.ShowMainMenu.text=Show Main Menu action.LocalVcs.ShowStatistics.text=Show Local VCS Statistics... action.LocalVcs.ShowStatistics.description=Show Local VCS statistics action.LocalVcs.ShowRepHistory.text=Repository History diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 671e2984f93d..f9e9b5a4f378 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -85,6 +85,8 @@ dataflow.message.passing.nullable.argument=Argument #ref #loc might dataflow.message.passing.nullable.argument.methodref=Method reference argument might be null dataflow.message.assigning.null=null is assigned to a variable that is annotated with @NotNull dataflow.message.assigning.nullable=Expression #ref might evaluate to null but is assigned to a variable that is annotated with @NotNull +dataflow.message.storing.array.null=null is stored to an array which elements are @NotNull +dataflow.message.storing.array.nullable=Expression #ref might evaluate to null but is stored to an array of @NotNull elements dataflow.message.return.null.from.notnull=null is returned by the method declared as @{0} dataflow.message.return.nullable.from.notnull=Expression #ref might evaluate to null but is returned by the method declared as @{0} dataflow.message.return.null.from.notnullable=null is returned by the method which is not declared as @{0} @@ -93,6 +95,7 @@ dataflow.message.return.nullable.from.notnull.function=Function may return null, dataflow.message.unboxing=Unboxing of #ref #loc may produce java.lang.NullPointerException dataflow.message.unboxing.method.reference=Use of #ref #loc would need unboxing which may produce java.lang.NullPointerException dataflow.too.complex=Method #ref is too complex to analyze by data flow algorithm +dataflow.too.complex.class=Class initializer is too complex to analyze by data flow algorithm dataflow.method.fails.with.null.argument=Method will throw an exception when parameter is null dataflow.message.optional.get.without.is.present={0}.#ref() without ''isPresent()'' check dataflow.message.constant.method.reference=Method reference result is always ''{0}'' diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 162cea1234d5..7b8b6c0cb5c5 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -519,7 +519,7 @@ - + @@ -734,6 +734,7 @@ + diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 9fbda5bafbd6..ac7b4811001c 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -389,11 +389,11 @@ psi.element.list.cell.renderer.focus.border.enabled=false psi.element.list.cell.renderer.focus.border.enabled.description=Enables default focus border in a list of PSI elements. psi.modification.tracker.code-block=true -psi.modification.tracker.code-block.description=Controls out-of-code-block PSI modification tracker optimization (requires project reopening) +psi.modification.tracker.code-block.description=Controls out-of-code-block PSI modification tracker optimization psi.modification.tracker.java-structure=true -psi.modification.tracker.java-structure.description=Controls java-structure PSI modification tracker optimization (requires project reopening) +psi.modification.tracker.java-structure.description=Controls java-structure PSI modification tracker optimization psi.modification.tracker.per-language=false -psi.modification.tracker.per-language.description=Controls per-language PSI modification tracker optimization (requires project reopening) +psi.modification.tracker.per-language.description=Controls per-language PSI modification tracker optimization ide.suggest.file.when.creating.filename.like.directory=true ide.suggest.file.when.creating.filename.like.directory.description=When creating a directory named foo.txt, suggest to create a file with such a name instead diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/table/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/table/VcsLogGraphTable.java index 4f130b3b5f58..b8990f6a398e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/table/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/table/VcsLogGraphTable.java @@ -93,6 +93,11 @@ public class VcsLogGraphTable extends TableWithProgress implements DataProvider, private static final int MAX_DEFAULT_AUTHOR_COLUMN_WIDTH = 300; private static final int MAX_ROWS_TO_CALC_WIDTH = 1000; + public static final String LOADING_COMMITS_TEXT = "Loading commits..."; + public static final String CHANGES_LOG_TEXT = "Changes log"; + public static final String NO_CHANGES_COMMITTED_TEXT = "No changes committed"; + public static final String NO_COMMITS_MATCHING_TEXT = "No commits matching filters"; + @NotNull private final AbstractVcsLogUi myUi; @NotNull private final VcsLogData myLogData; @NotNull private final MyDummyTableCellEditor myDummyEditor = new MyDummyTableCellEditor(); @@ -121,7 +126,7 @@ public class VcsLogGraphTable extends TableWithProgress implements DataProvider, myGraphCommitCellRenderer = new GraphCommitCellRenderer(logData, graphCellPainter, this, true, false); myStringCellRenderer = new StringCellRenderer(); - getEmptyText().setText("Changes Log"); + getEmptyText().setText(CHANGES_LOG_TEXT); myLogData.getProgress().addProgressIndicatorListener(new MyProgressListener(), ui); initColumns(); @@ -166,6 +171,22 @@ public class VcsLogGraphTable extends TableWithProgress implements DataProvider, return Registry.is("vcs.log.speedsearch"); } + @NotNull + private String getEmptyTextString() { + VisiblePack visiblePack = getModel().getVisiblePack(); + + if (visiblePack.getVisibleGraph().getVisibleCommitCount() == 0) { + if (visiblePack.getFilters().isEmpty()) { + return NO_CHANGES_COMMITTED_TEXT; + } + else { + return NO_COMMITS_MATCHING_TEXT; + } + } + + return CHANGES_LOG_TEXT; + } + public void updateDataPack(@NotNull VisiblePack visiblePack, boolean permGraphChanged) { Selection previousSelection = getSelection(); boolean filtersChanged = !getModel().getVisiblePack().getFilters().equals(visiblePack.getFilters()); @@ -176,6 +197,10 @@ public class VcsLogGraphTable extends TableWithProgress implements DataProvider, highlighter.update(visiblePack, permGraphChanged); } + if (!getEmptyText().getText().equals(LOADING_COMMITS_TEXT)) { + getEmptyText().setText(getEmptyTextString()); + } + setPaintBusy(false); myAuthorColumnInitialized = myAuthorColumnInitialized && !filtersChanged; reLayout(); @@ -880,17 +905,14 @@ public class VcsLogGraphTable extends TableWithProgress implements DataProvider, } private class MyProgressListener implements VcsLogProgress.ProgressListener { - @NotNull private String myText = ""; - @Override public void progressStarted() { - myText = getEmptyText().getText(); - getEmptyText().setText("Loading History..."); + getEmptyText().setText(LOADING_COMMITS_TEXT); } @Override public void progressStopped() { - getEmptyText().setText(myText); + getEmptyText().setText(getEmptyTextString()); } } diff --git a/python/gen/icons/PythonIcons.java b/python/gen/icons/PythonIcons.java index 96603fa94042..a5948cb713df 100644 --- a/python/gen/icons/PythonIcons.java +++ b/python/gen/icons/PythonIcons.java @@ -42,6 +42,7 @@ public class PythonIcons { public static final Icon Buildout = load("/icons/com/jetbrains/python/buildout/buildout.png"); // 16x16 } + public static final Icon Condaenv = load("/icons/com/jetbrains/python/condaenv.png"); // 16x16 public static final Icon DataView = load("/icons/com/jetbrains/python/DataView.png"); // 13x13 public static class Debug { diff --git a/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java b/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java index a3a221f96020..b57a729c9198 100644 --- a/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java +++ b/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java @@ -26,6 +26,7 @@ import com.jetbrains.python.sdk.PyDetectedSdk; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkAdditionalData; import com.jetbrains.python.sdk.PythonSdkType; +import com.jetbrains.python.sdk.flavors.CondaEnvSdkFlavor; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor; import org.jetbrains.annotations.NotNull; @@ -79,8 +80,9 @@ public class PyConfigurableInterpreterList { private void addDetectedSdks(@NotNull final List result) { final List sdkHomes = new ArrayList<>(); sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths()); + sdkHomes.addAll(CondaEnvSdkFlavor.INSTANCE.suggestHomePaths()); for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) { - if (flavor instanceof VirtualEnvSdkFlavor) continue; + if (flavor instanceof VirtualEnvSdkFlavor || flavor instanceof CondaEnvSdkFlavor) continue; sdkHomes.addAll(flavor.suggestHomePaths()); } Collections.sort(sdkHomes); diff --git a/python/resources/icons/com/jetbrains/python/condaenv.png b/python/resources/icons/com/jetbrains/python/condaenv.png new file mode 100644 index 000000000000..8681282f0d52 Binary files /dev/null and b/python/resources/icons/com/jetbrains/python/condaenv.png differ diff --git a/python/resources/icons/com/jetbrains/python/condaenv@2x.png b/python/resources/icons/com/jetbrains/python/condaenv@2x.png new file mode 100644 index 000000000000..d3d752947012 Binary files /dev/null and b/python/resources/icons/com/jetbrains/python/condaenv@2x.png differ diff --git a/python/resources/icons/com/jetbrains/python/condaenv_dark.png b/python/resources/icons/com/jetbrains/python/condaenv_dark.png new file mode 100644 index 000000000000..7e983a1f419e Binary files /dev/null and b/python/resources/icons/com/jetbrains/python/condaenv_dark.png differ diff --git a/python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png b/python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png new file mode 100644 index 000000000000..5ed486884ef0 Binary files /dev/null and b/python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png differ diff --git a/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java b/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java index 29f3e5a70cdd..a6f8be202e3d 100644 --- a/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java +++ b/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java @@ -30,7 +30,7 @@ import com.intellij.util.xmlb.XmlSerializerUtil; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; -import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor; +import com.jetbrains.python.sdk.flavors.CondaEnvSdkFlavor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -132,7 +132,7 @@ public class PyCondaPackageService implements PersistentStateComponent locations = VirtualEnvSdkFlavor.getCondaDefaultLocations(); + final List locations = CondaEnvSdkFlavor.getCondaDefaultLocations(); if (!locations.isEmpty()) { myInitialPath = locations.get(0).getPath(); return; diff --git a/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java new file mode 100644 index 000000000000..1f9baad43ac0 --- /dev/null +++ b/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2017 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.jetbrains.python.sdk.flavors; + +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.SystemProperties; +import com.jetbrains.python.sdk.PythonSdkType; +import icons.PythonIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor.findInDirectory; + +public class CondaEnvSdkFlavor extends CPythonSdkFlavor { + private CondaEnvSdkFlavor() { + } + + public final static String[] CONDA_DEFAULT_ROOTS = new String[]{"anaconda", "anaconda2", "anaconda3", "miniconda", "miniconda2", + "miniconda3", "Anaconda", "Anaconda2", "Anaconda3", "Miniconda", "Miniconda2", "Miniconda3"}; + + public static CondaEnvSdkFlavor INSTANCE = new CondaEnvSdkFlavor(); + + @Override + public Collection suggestHomePaths() { + List candidates = new ArrayList<>(); + + for (VirtualFile file : getCondaDefaultLocations()) { + candidates.addAll(findInDirectory(file)); + } + + return candidates; + } + + public static List getCondaDefaultLocations() { + List roots = new ArrayList<>(); + final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/')); + if (userHome != null) { + final VirtualFile condaHidden = userHome.findChild(".conda"); + if (condaHidden != null) { + addEnvsFolder(roots, condaHidden); + } + for (String root : CONDA_DEFAULT_ROOTS) { + VirtualFile condaFolder = userHome.findChild(root); + addEnvsFolder(roots, condaFolder); + if (SystemInfo.isWindows) { + final VirtualFile appData = userHome.findFileByRelativePath("AppData\\Local\\Continuum\\" + root); + addEnvsFolder(roots, appData); + condaFolder = LocalFileSystem.getInstance().findFileByPath("C:\\" + root); + addEnvsFolder(roots, condaFolder); + } + else { + final String systemWidePath = "/opt/anaconda"; + condaFolder = LocalFileSystem.getInstance().findFileByPath(systemWidePath); + addEnvsFolder(roots, condaFolder); + } + } + } + return roots; + } + + private static void addEnvsFolder(@NotNull final List roots, @Nullable final VirtualFile condaFolder) { + if (condaFolder != null) { + final VirtualFile envs = condaFolder.findChild("envs"); + if (envs != null) { + roots.add(envs); + } + } + } + + @Override + public boolean isValidSdkPath(@NotNull File file) { + if (!super.isValidSdkPath(file)) return false; + final File bin = file.getParentFile(); + String condaName = "conda"; + if (SystemInfo.isWindows) { + condaName = new File(bin, "envs").exists() ? "conda.exe" : "conda.bat"; + } + if (bin != null) { + final File conda = new File(bin, condaName); + if (conda.exists()) { + return true; + } + final File condaFolder = bin.getParentFile(); + final File condaExecutable = PythonSdkType.findExecutableFile(condaFolder, condaName); + if (condaExecutable != null) return true; + } + return false; + } + + @Override + public Icon getIcon() { + return PythonIcons.Python.Condaenv; + } +} diff --git a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java index 5181beb33af4..414d3646c0bb 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java @@ -117,6 +117,7 @@ public abstract class PythonSdkFlavor { result.add(IronPythonSdkFlavor.INSTANCE); result.add(PyPySdkFlavor.INSTANCE); result.add(VirtualEnvSdkFlavor.INSTANCE); + result.add(CondaEnvSdkFlavor.INSTANCE); result.add(PyRemoteSdkFlavor.INSTANCE); return result; diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java index c931f54c9648..3034a11072b1 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java @@ -42,8 +42,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { private VirtualEnvSdkFlavor() { } private final static String[] NAMES = new String[]{"jython", "pypy", "python.exe", "jython.bat", "pypy.exe"}; - public final static String[] CONDA_DEFAULT_ROOTS = new String[]{"anaconda", "anaconda2", "anaconda3", "miniconda", "miniconda2", - "miniconda3", "Anaconda", "Anaconda2", "Anaconda3", "Miniconda", "Miniconda2", "Miniconda3"}; public static VirtualEnvSdkFlavor INSTANCE = new VirtualEnvSdkFlavor(); @@ -61,10 +59,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { if (path != null) candidates.addAll(findInDirectory(path)); - for (VirtualFile file : getCondaDefaultLocations()) { - candidates.addAll(findInDirectory(file)); - } - final VirtualFile pyEnvLocation = getPyEnvDefaultLocations(); if (pyEnvLocation != null) { candidates.addAll(findInDirectory(pyEnvLocation)); @@ -88,42 +82,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { return null; } - public static List getCondaDefaultLocations() { - List roots = new ArrayList<>(); - final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/')); - if (userHome != null) { - final VirtualFile condaHidden = userHome.findChild(".conda"); - if (condaHidden != null) { - addEnvsFolder(roots, condaHidden); - } - for (String root : CONDA_DEFAULT_ROOTS) { - VirtualFile condaFolder = userHome.findChild(root); - addEnvsFolder(roots, condaFolder); - if (SystemInfo.isWindows) { - final VirtualFile appData = userHome.findFileByRelativePath("AppData\\Local\\Continuum\\" + root); - addEnvsFolder(roots, appData); - condaFolder = LocalFileSystem.getInstance().findFileByPath("C:\\" + root); - addEnvsFolder(roots, condaFolder); - } - else { - final String systemWidePath = "/opt/anaconda"; - condaFolder = LocalFileSystem.getInstance().findFileByPath(systemWidePath); - addEnvsFolder(roots, condaFolder); - } - } - } - return roots; - } - - private static void addEnvsFolder(@NotNull final List roots, @Nullable final VirtualFile condaFolder) { - if (condaFolder != null) { - final VirtualFile envs = condaFolder.findChild("envs"); - if (envs != null) { - roots.add(envs); - } - } - } - public static VirtualFile getDefaultLocation() { final String path = System.getenv().get("WORKON_HOME"); if (!StringUtil.isEmpty(path)) {