diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index fac35822aa13..99db3fdcd88d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -100,16 +100,19 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection final PsiElement lBrace = aClass.getLBrace(); LOG.assertTrue(lBrace != null); final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent()); - ProblemHighlightType problemHighlightType = ProblemHighlightType.LIKE_UNUSED_SYMBOL; + ProblemHighlightType type = ProblemHighlightType.LIKE_UNUSED_SYMBOL; if (isOnTheFly && !reportNotAnnotatedInterfaces) { final PsiClass baseClass = aClass.getBaseClassType().resolve(); LOG.assertTrue(baseClass != null); if (!AnnotationUtil.isAnnotated(baseClass, CommonClassNames.JAVA_LANG_FUNCTIONAL_INTERFACE, false, false)) { - problemHighlightType = ProblemHighlightType.INFORMATION; + type = ProblemHighlightType.INFORMATION; } } - holder.registerProblem(parent, "Anonymous #ref #loc can be replaced with lambda", - problemHighlightType, rangeInElement, new ReplaceWithLambdaFix()); + ProblemDescriptorBase descriptor = new ProblemDescriptorBase(parent, parent, "Anonymous #ref #loc can be replaced with lambda", + new LocalQuickFix[]{new ReplaceWithLambdaFix()}, + type, false, rangeInElement, + type != ProblemHighlightType.INFORMATION, true); + holder.registerProblem(descriptor); } } }; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java index 6c3a1a4600f1..5c14b72ded54 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -25,10 +25,10 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,8 +39,8 @@ import java.util.List; * @author max */ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { - @NonNls public static final String SHORT_NAME = DeprecationUtil.DEPRECATION_SHORT_NAME; - @NonNls public static final String ID = DeprecationUtil.DEPRECATION_ID; + public static final String SHORT_NAME = DeprecationUtil.DEPRECATION_SHORT_NAME; + public static final String ID = DeprecationUtil.DEPRECATION_ID; public static final String DISPLAY_NAME = DeprecationUtil.DEPRECATION_DISPLAY_NAME; public static final String IGNORE_METHODS_OF_DEPRECATED_NAME = "IGNORE_METHODS_OF_DEPRECATED"; @@ -51,8 +51,8 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { @Override @NotNull - public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { - return new DeprecationElementVisitor(holder, IGNORE_INSIDE_DEPRECATED, IGNORE_ABSTRACT_DEPRECATED_OVERRIDES, + public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { + return new DeprecationElementVisitor(holder, IGNORE_INSIDE_DEPRECATED, IGNORE_ABSTRACT_DEPRECATED_OVERRIDES, IGNORE_IMPORT_STATEMENTS, IGNORE_METHODS_OF_DEPRECATED); } @@ -76,7 +76,7 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { @Override @NotNull - @NonNls + @SuppressWarnings("PatternOverriddenByNonAnnotatedMethod") public String getID() { return ID; } @@ -94,7 +94,6 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { panel.addCheckbox("Ignore overrides of deprecated abstract methods from non-deprecated supers", "IGNORE_ABSTRACT_DEPRECATED_OVERRIDES"); panel.addCheckbox("Ignore members of deprecated classes", IGNORE_METHODS_OF_DEPRECATED_NAME); return panel; - } private static class DeprecationElementVisitor extends JavaElementVisitor { @@ -104,11 +103,11 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { private final boolean myIgnoreImportStatements; private final boolean myIgnoreMethodsOfDeprecated; - DeprecationElementVisitor(@NotNull ProblemsHolder holder, - boolean ignoreInsideDeprecated, - boolean ignoreAbstractDeprecatedOverrides, - boolean ignoreImportStatements, - boolean ignoreMethodsOfDeprecated) { + private DeprecationElementVisitor(ProblemsHolder holder, + boolean ignoreInsideDeprecated, + boolean ignoreAbstractDeprecatedOverrides, + boolean ignoreImportStatements, + boolean ignoreMethodsOfDeprecated) { myHolder = holder; myIgnoreInsideDeprecated = ignoreInsideDeprecated; myIgnoreAbstractDeprecatedOverrides = ignoreAbstractDeprecatedOverrides; @@ -118,59 +117,63 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { - JavaResolveResult result = reference.advancedResolve(true); - PsiElement resolved = result.getElement(); - checkDeprecated(resolved, reference.getReferenceNameElement(), null, myIgnoreInsideDeprecated, myIgnoreImportStatements, myIgnoreMethodsOfDeprecated, myHolder); + PsiElement resolved = reference.advancedResolve(true).getElement(); + PsiElement refName = reference.getReferenceNameElement(); + checkDeprecated(resolved, refName, null, myIgnoreInsideDeprecated, myIgnoreImportStatements, myIgnoreMethodsOfDeprecated, myHolder); } @Override public void visitImportStaticStatement(PsiImportStaticStatement statement) { - final PsiJavaCodeReferenceElement importReference = statement.getImportReference(); + PsiJavaCodeReferenceElement importReference = statement.getImportReference(); if (importReference != null) { - checkDeprecated(importReference.resolve(), importReference.getReferenceNameElement(), null, myIgnoreInsideDeprecated, false, true, myHolder); + PsiElement refName = importReference.getReferenceNameElement(); + checkDeprecated(importReference.resolve(), refName, null, myIgnoreInsideDeprecated, false, true, myHolder); } } - @Override public void visitReferenceExpression(PsiReferenceExpression expression) { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { visitReferenceElement(expression); } - @Override public void visitNewExpression(PsiNewExpression expression) { + @Override + public void visitNewExpression(PsiNewExpression expression) { + PsiClass aClass = null; PsiType type = expression.getType(); - PsiExpressionList list = expression.getArgumentList(); - if (!(type instanceof PsiClassType)) return; - PsiClassType.ClassResolveResult typeResult = ((PsiClassType)type).resolveGenerics(); - PsiClass aClass = typeResult.getElement(); - if (aClass == null) return; - if (aClass instanceof PsiAnonymousClass) { - type = ((PsiAnonymousClass)aClass).getBaseClassType(); - typeResult = ((PsiClassType)type).resolveGenerics(); - aClass = typeResult.getElement(); - if (aClass == null) return; + if (type instanceof PsiClassType) { + aClass = ((PsiClassType)type).resolveGenerics().getElement(); + if (aClass instanceof PsiAnonymousClass) { + type = ((PsiAnonymousClass)aClass).getBaseClassType(); + aClass = ((PsiClassType)type).resolveGenerics().getElement(); + } } - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper(); - final PsiMethod[] constructors = aClass.getConstructors(); - if (constructors.length > 0 && list != null) { + if (aClass == null) return; + PsiExpressionList list = expression.getArgumentList(); + PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper(); + if (list != null && aClass.getConstructors().length > 0) { JavaResolveResult[] results = resolveHelper.multiResolveConstructor((PsiClassType)type, list, list); MethodCandidateInfo result = null; if (results.length == 1) result = (MethodCandidateInfo)results[0]; PsiMethod constructor = result == null ? null : result.getElement(); - if (constructor != null && expression.getClassOrAnonymousClassReference() != null) { + PsiJavaCodeReferenceElement ref; + if (constructor != null && (ref = expression.getClassOrAnonymousClassReference()) != null) { if (expression.getClassReference() == null && constructor.getParameterList().getParametersCount() == 0) return; - checkDeprecated(constructor, expression.getClassOrAnonymousClassReference(), null, myIgnoreInsideDeprecated, myIgnoreImportStatements, true, myHolder); + checkDeprecated(constructor, ref, null, myIgnoreInsideDeprecated, myIgnoreImportStatements, true, myHolder); } } } - @Override public void visitMethod(PsiMethod method){ - MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY); - if (!method.isConstructor()) { - List superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true); - checkMethodOverridesDeprecated(methodSignature, superMethodSignatures, myIgnoreAbstractDeprecatedOverrides, myHolder); - } else { - checkImplicitCallToSuper(method); - } + @Override + public void visitMethod(PsiMethod method) { + MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY); + if (!method.isConstructor()) { + List superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true); + checkMethodOverridesDeprecated(methodSignature, superMethodSignatures, myIgnoreAbstractDeprecatedOverrides, myHolder); + } + else { + checkImplicitCallToSuper(method); + } } private void checkImplicitCallToSuper(PsiMethod method) { @@ -193,8 +196,8 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { } private void registerDefaultConstructorProblem(PsiClass superClass, PsiElement nameIdentifier, boolean asDeprecated) { - myHolder.registerProblem(nameIdentifier, "Default constructor in " + superClass.getQualifiedName() + " is deprecated", - asDeprecated ? ProblemHighlightType.LIKE_DEPRECATED : ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + ProblemHighlightType type = asDeprecated ? ProblemHighlightType.LIKE_DEPRECATED : ProblemHighlightType.GENERIC_ERROR_OR_WARNING; + myHolder.registerProblem(nameIdentifier, "Default constructor in " + superClass.getQualifiedName() + " is deprecated", type); } @Override @@ -209,7 +212,21 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { final PsiExpressionList argumentList = ((PsiAnonymousClass)aClass).getArgumentList(); if (argumentList != null && argumentList.getExpressions().length > 0) return; } - registerDefaultConstructorProblem(superClass, isAnonymous ? ((PsiAnonymousClass)aClass).getBaseClassReference() : aClass.getNameIdentifier(), isAnonymous); + PsiElement identifier = isAnonymous ? ((PsiAnonymousClass)aClass).getBaseClassReference() : aClass.getNameIdentifier(); + registerDefaultConstructorProblem(superClass, identifier, isAnonymous); + } + } + } + + @Override + public void visitRequiresStatement(PsiRequiresStatement statement) { + PsiJavaModuleReferenceElement refElement = statement.getReferenceElement(); + if (refElement != null) { + PsiPolyVariantReference ref = refElement.getReference(); + PsiElement target = ref != null ? ref.resolve() : null; + if (target instanceof PsiJavaModule && PsiImplUtil.isDeprecatedByAnnotation((PsiJavaModule)target)) { + String message = JavaErrorMessages.message("deprecated.symbol", HighlightMessageUtil.getSymbolName(target)); + myHolder.registerProblem(refElement, message, ProblemHighlightType.LIKE_DEPRECATED); } } } @@ -227,12 +244,13 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { return false; } - //@top - static void checkMethodOverridesDeprecated(MethodSignatureBackedByPsiMethod methodSignature, - List superMethodSignatures, - boolean ignoreAbstractDeprecatedOverrides, ProblemsHolder holder) { + private static void checkMethodOverridesDeprecated(MethodSignatureBackedByPsiMethod methodSignature, + List superMethodSignatures, + boolean ignoreAbstractDeprecatedOverrides, + ProblemsHolder holder) { PsiMethod method = methodSignature.getMethod(); PsiElement methodName = method.getNameIdentifier(); + if (methodName == null) return; for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) { PsiMethod superMethod = superMethodSignature.getMethod(); PsiClass aClass = superMethod.getContainingClass(); @@ -240,8 +258,7 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { // do not show deprecated warning for class implementing deprecated methods if (ignoreAbstractDeprecatedOverrides && !aClass.isDeprecated() && superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) continue; if (superMethod.isDeprecated()) { - String description = JavaErrorMessages.message("overrides.deprecated.method", - HighlightMessageUtil.getSymbolName(aClass, PsiSubstitutor.EMPTY)); + String description = JavaErrorMessages.message("overrides.deprecated.method", HighlightMessageUtil.getSymbolName(aClass)); holder.registerProblem(methodName, description, ProblemHighlightType.LIKE_DEPRECATED); } } @@ -254,17 +271,18 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { checkDeprecated(refElement, elementToHighlight, rangeInElement, false, false, true, holder); } - static void checkDeprecated(PsiElement refElement, - PsiElement elementToHighlight, - @Nullable TextRange rangeInElement, - boolean ignoreInsideDeprecated, - boolean ignoreImportStatements, - boolean ignoreMethodsOfDeprecated, - ProblemsHolder holder) { + private static void checkDeprecated(PsiElement refElement, + PsiElement elementToHighlight, + @Nullable TextRange rangeInElement, + boolean ignoreInsideDeprecated, + boolean ignoreImportStatements, + boolean ignoreMethodsOfDeprecated, + ProblemsHolder holder) { if (!(refElement instanceof PsiDocCommentOwner)) return; + if (!((PsiDocCommentOwner)refElement).isDeprecated()) { if (!ignoreMethodsOfDeprecated) { - checkDeprecated(((PsiDocCommentOwner)refElement).getContainingClass(), elementToHighlight, rangeInElement, + checkDeprecated(((PsiDocCommentOwner)refElement).getContainingClass(), elementToHighlight, rangeInElement, ignoreInsideDeprecated, ignoreImportStatements, false, holder); } return; @@ -281,9 +299,7 @@ public class DeprecationInspection extends BaseJavaBatchLocalInspectionTool { return; } - String description = JavaErrorMessages.message("deprecated.symbol", - HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY)); - + String description = JavaErrorMessages.message("deprecated.symbol", HighlightMessageUtil.getSymbolName(refElement)); holder.registerProblem(elementToHighlight, description, ProblemHighlightType.LIKE_DEPRECATED, rangeInElement); } -} +} \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/SuperClassHasFrequentlyUsedInheritorsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/SuperClassHasFrequentlyUsedInheritorsInspection.java index e7b9e3e353a4..d7c8e0aa4675 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/SuperClassHasFrequentlyUsedInheritorsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/SuperClassHasFrequentlyUsedInheritorsInspection.java @@ -75,10 +75,9 @@ public class SuperClassHasFrequentlyUsedInheritorsInspection extends BaseJavaBat break; } } - return new ProblemDescriptor[]{manager - .createProblemDescriptor(aClass, getDisplayName(), false, - topInheritorsQuickFix.toArray(new LocalQuickFix[topInheritorsQuickFix.size()]), - ProblemHighlightType.INFORMATION)}; + return new ProblemDescriptor[]{ + manager.createProblemDescriptor(aClass, getDisplayName(), false, ProblemHighlightType.INFORMATION, false, + topInheritorsQuickFix.toArray(new LocalQuickFix[topInheritorsQuickFix.size()]))}; } @Nullable diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java index 97335908d2d9..d37fbf3d8c74 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java @@ -84,7 +84,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { PsiExpression condition = (PsiExpression) ifStatement.getCondition().copy(); - setupBranches(ifStatement, controlFlow); + ifStatement = setupBranches(ifStatement, controlFlow); if (condition != null) { ifStatement.getCondition().replace(CodeInsightServicesUtil.invertCondition(condition)); } @@ -156,10 +156,6 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { return null; } - private static PsiElement findNearestCodeBlock(PsiIfStatement ifStatement) { - return PsiTreeUtil.getParentOfType(ifStatement, PsiCodeBlock.class); - } - private static ControlFlow buildControlFlow(PsiElement element) { try { return ControlFlowFactory.getInstance(element.getProject()).getControlFlow(element, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); @@ -169,7 +165,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { } } - private static void setupBranches(PsiIfStatement ifStatement, ControlFlow flow) throws IncorrectOperationException { + private static PsiIfStatement setupBranches(PsiIfStatement ifStatement, ControlFlow flow) throws IncorrectOperationException { PsiElementFactory factory = JavaPsiFacade.getInstance(ifStatement.getProject()).getElementFactory(); Project project = ifStatement.getProject(); @@ -180,7 +176,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { elseBranch = (PsiStatement) elseBranch.copy(); setElseBranch(ifStatement, thenBranch, flow); ifStatement.getThenBranch().replace(elseBranch); - return; + return ifStatement; } final CodeStyleManager codeStyle = CodeStyleManager.getInstance(project); @@ -190,7 +186,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { statement = (PsiStatement) codeStyle.reformat(statement); statement = (PsiStatement) ifStatement.getThenBranch().replace(statement); codeStyle.reformat(statement); - return; + return ifStatement; } int endOffset = calcEndOffset(flow, ifStatement); @@ -211,11 +207,11 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { } } else { if (!(thenBranch instanceof PsiReturnStatement)) { - addAfter(ifStatement, thenBranch); + ifStatement = addAfterWithinCodeBlock(ifStatement, thenBranch); } } ifStatement.getThenBranch().replace(statement); - return; + return ifStatement; } PsiElement element = flow.getElement(endOffset); while (element != null && !(element instanceof PsiStatement)) element = element.getParent(); @@ -225,27 +221,38 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { element instanceof PsiForeachStatement && flow.getStartOffset(element) + 1 == endOffset) { PsiStatement statement = factory.createStatementFromText("continue;", null); statement = (PsiStatement)codeStyle.reformat(statement); - addAfter(ifStatement, thenBranch); + ifStatement = addAfterWithinCodeBlock(ifStatement, thenBranch); ifStatement.getThenBranch().replace(statement); - return; + return ifStatement; } if (element instanceof PsiReturnStatement) { PsiReturnStatement returnStatement = (PsiReturnStatement) element; - addAfter(ifStatement, thenBranch); + ifStatement = addAfterWithinCodeBlock(ifStatement, thenBranch); ifStatement.getThenBranch().replace(returnStatement.copy()); ControlFlow flow2 = buildControlFlow(findCodeBlock(ifStatement)); if (!ControlFlowUtil.isInstructionReachable(flow2, flow2.getStartOffset(returnStatement), 0)) returnStatement.delete(); - return; + return ifStatement; } boolean nextUnreachable = flow.getEndOffset(ifStatement) == flow.getSize(); if (!nextUnreachable) { - PsiElement nearestCodeBlock = findNearestCodeBlock(ifStatement); - if (nearestCodeBlock != null) { - ControlFlow flow2 = buildControlFlow(nearestCodeBlock); - nextUnreachable = !ControlFlowUtil.isInstructionReachable(flow2, flow2.getEndOffset(ifStatement), getThenOffset(flow2, ifStatement)); + PsiElement parent = ifStatement.getParent(); + if (parent != null) { + if (!(parent instanceof PsiCodeBlock)) { + PsiCodeBlock codeBlock = factory.createCodeBlockFromText("{}", ifStatement); + codeBlock = (PsiCodeBlock)codeStyle.reformat(codeBlock); + codeBlock.add(ifStatement); + codeBlock = (PsiCodeBlock)ifStatement.replace(codeBlock); + ifStatement = (PsiIfStatement)codeBlock.getStatements()[0]; + parent = ifStatement.getParent(); + thenBranch = ifStatement.getThenBranch(); + } + ControlFlow localFlow = buildControlFlow(parent); + int startThenOffset = getThenOffset(localFlow, ifStatement); + int afterIfOffset = localFlow.getEndOffset(ifStatement); + nextUnreachable = !ControlFlowUtil.isInstructionReachable(localFlow, afterIfOffset, startThenOffset); } } if (nextUnreachable) { @@ -270,7 +277,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { ifStatement.getThenBranch().replace(codeBlock); } codeStyle.reformat(ifStatement); - return; + return ifStatement; } setElseBranch(ifStatement, thenBranch, flow); @@ -278,6 +285,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { statement = (PsiStatement) codeStyle.reformat(statement); statement = (PsiStatement) ifStatement.getThenBranch().replace(statement); codeStyle.reformat(statement); + return ifStatement; } private static void setElseBranch(PsiIfStatement ifStatement, PsiStatement thenBranch, ControlFlow flow) @@ -312,6 +320,26 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { ifStatement.setElseBranch(thenBranch); } + private static PsiIfStatement addAfterWithinCodeBlock(PsiIfStatement ifStatement, PsiStatement branch) { + final PsiElement parent = ifStatement.getParent(); + if (parent != null && !(parent instanceof PsiCodeBlock)) { + final Project project = ifStatement.getProject(); + final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + final CodeStyleManager codeStyle = CodeStyleManager.getInstance(project); + PsiCodeBlock codeBlock = factory.createCodeBlockFromText("{}", ifStatement); + codeBlock = (PsiCodeBlock)codeStyle.reformat(codeBlock); + final PsiIfStatement wrappedIfStatement = (PsiIfStatement)codeBlock.add(ifStatement); + + addAfter(wrappedIfStatement, branch); + codeBlock = (PsiCodeBlock)ifStatement.replace(codeBlock); + return (PsiIfStatement)codeBlock.getStatements()[0]; + } + else { + addAfter(ifStatement, branch); + return ifStatement; + } + } + static void addAfter(PsiIfStatement ifStatement, PsiStatement branch) throws IncorrectOperationException { if (branch instanceof PsiBlockStatement) { PsiBlockStatement blockStatement = (PsiBlockStatement) branch; diff --git a/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java index 473770741a3e..896a6b7fe4d9 100644 --- a/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java @@ -98,11 +98,14 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI final PsiElement lBrace = aClass.getLBrace(); LOG.assertTrue(lBrace != null); final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent()); - ProblemHighlightType highlightType = LambdaCanBeMethodReferenceInspection.checkQualifier(lambdaBodyCandidate) ? ProblemHighlightType.LIKE_UNUSED_SYMBOL + ProblemHighlightType type = LambdaCanBeMethodReferenceInspection.checkQualifier(lambdaBodyCandidate) ? ProblemHighlightType.LIKE_UNUSED_SYMBOL : ProblemHighlightType.INFORMATION; - holder.registerProblem(parent, - "Anonymous #ref #loc can be replaced with method reference", - highlightType, rangeInElement, new ReplaceWithMethodRefFix()); + ProblemDescriptorBase descriptor = new ProblemDescriptorBase(parent, parent, + "Anonymous #ref #loc can be replaced with method reference", + new LocalQuickFix[]{new ReplaceWithMethodRefFix()}, + type, false, rangeInElement, + type != ProblemHighlightType.INFORMATION, true); + holder.registerProblem(descriptor); } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/OptionalIsPresentInspection.java b/java/java-impl/src/com/intellij/codeInspection/OptionalIsPresentInspection.java index 6fb31afa813d..6f6a69c6c9b8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/OptionalIsPresentInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/OptionalIsPresentInspection.java @@ -57,9 +57,12 @@ public class OptionalIsPresentInspection extends BaseJavaBatchLocalInspectionToo void registerProblem(ProblemsHolder holder, PsiExpression condition, OptionalIsPresentCase scenario) { if(this != NONE) { - holder.registerProblem(condition, "Can be replaced with single expression in functional style", - this == INFO ? ProblemHighlightType.INFORMATION : ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new OptionalIsPresentFix(scenario)); + holder.registerProblem(holder.getManager().createProblemDescriptor(condition, + "Can be replaced with single expression in functional style", + this != INFO, + this == INFO ? ProblemHighlightType.INFORMATION : ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + true, + new OptionalIsPresentFix(scenario))); } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/java18api/Java8MapForEachInspection.java b/java/java-impl/src/com/intellij/codeInspection/java18api/Java8MapForEachInspection.java index 91b2e197f861..e48e2deacab2 100644 --- a/java/java-impl/src/com/intellij/codeInspection/java18api/Java8MapForEachInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/java18api/Java8MapForEachInspection.java @@ -107,14 +107,15 @@ public class Java8MapForEachInspection extends BaseJavaBatchLocalInspectionTool isOnTheFly && (DO_NOT_HIGHLIGHT_LOOP || InspectionProjectProfileManager.isInformationLevel(getShortName(), loop)); TextRange range; PsiJavaToken rParenth = loop.getRParenth(); + PsiElement firstChild = loop.getFirstChild(); if (wholeStatement && rParenth != null) { range = new TextRange(0, rParenth.getStartOffsetInParent() + 1); } else { - range = new TextRange(0, loop.getFirstChild().getTextLength()); + range = new TextRange(0, firstChild.getTextLength()); } - holder.registerProblem(loop.getFirstChild(), InspectionsBundle.message("inspection.map.foreach.message"), - type, range, new ReplaceWithMapForEachFix()); + holder.registerProblem(new ProblemDescriptorBase(firstChild, firstChild, InspectionsBundle.message("inspection.map.foreach.message"), + new LocalQuickFix[]{new ReplaceWithMapForEachFix()}, type, false, range, type != ProblemHighlightType.INFORMATION, holder.isOnTheFly())); } } }; diff --git a/java/java-psi-api/anno/com/intellij/patterns/annotations.xml b/java/java-psi-api/anno/com/intellij/patterns/annotations.xml deleted file mode 100644 index 32e2972fcf37..000000000000 --- a/java/java-psi-api/anno/com/intellij/patterns/annotations.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/java/java-psi-api/java-psi-api.iml b/java/java-psi-api/java-psi-api.iml index 2e92efedd035..9e771bf16372 100644 --- a/java/java-psi-api/java-psi-api.iml +++ b/java/java-psi-api/java-psi-api.iml @@ -2,9 +2,6 @@ - - - diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java index 6f48206a0c79..05b946491f42 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -45,6 +45,7 @@ public class AnnotationTargetUtil { private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE}; private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE}; private static final TargetType[] LOCAL_VARIABLE_TARGETS = {TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE}; + private static final TargetType[] MODULE_TARGETS = {TargetType.MODULE}; @NotNull public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { @@ -107,6 +108,9 @@ public class AnnotationTargetUtil { if (element instanceof PsiReceiverParameter) { return TYPE_USE_TARGETS; } + if (element instanceof PsiJavaModule) { + return MODULE_TARGETS; + } } return TargetType.EMPTY_ARRAY; diff --git a/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java b/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java index 0f521a5a91da..39d39e348af2 100644 --- a/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java +++ b/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java @@ -49,6 +49,7 @@ public class PsiJavaPatterns extends StandardPatterns{ return new PsiJavaElementPattern.Capture<>(aClass); } + @SafeVarargs public static PsiJavaElementPattern.Capture psiElement(final Class... classAlternatives) { return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition(PsiElement.class) { @Override @@ -73,19 +74,21 @@ public class PsiJavaPatterns extends StandardPatterns{ public static PsiJavaElementPattern.Capture psiLiteral(@Nullable final ElementPattern value) { return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus(PsiLiteral.class) { + @Override public boolean accepts(@Nullable final Object o, final ProcessingContext context) { return o instanceof PsiLiteral && (value == null || value.accepts(((PsiLiteral)o).getValue(), context)); } @Override public List> getPatterns() { - return Collections.>singletonList(value); + return Collections.singletonList(value); } }); } public static PsiJavaElementPattern.Capture psiNewExpression(@NotNull final String... fqns) { return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition(PsiNewExpression.class) { + @Override public boolean accepts(@Nullable final Object o, final ProcessingContext context) { if (o instanceof PsiNewExpression) { PsiJavaCodeReferenceElement reference = ((PsiNewExpression)o).getClassOrAnonymousClassReference(); @@ -102,13 +105,14 @@ public class PsiJavaPatterns extends StandardPatterns{ public static PsiJavaElementPattern.Capture literalExpression(@Nullable final ElementPattern value) { return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus(PsiLiteralExpression.class) { + @Override public boolean accepts(@Nullable final Object o, final ProcessingContext context) { return o instanceof PsiLiteralExpression && (value == null || value.accepts(((PsiLiteralExpression)o).getValue(), context)); } @Override public List> getPatterns() { - return Collections.>singletonList(value); + return Collections.singletonList(value); } }); } diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java index 078a49974ca5..5d2aec204db9 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java @@ -1,18 +1,18 @@ /* -* Copyright 2000-2009 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * 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.codeInsight.daemon.impl.analysis; import com.intellij.lang.LangBundle; @@ -26,12 +26,18 @@ public class HighlightMessageUtil { private HighlightMessageUtil() { } @Nullable - public static String getSymbolName(@NotNull PsiElement symbol, PsiSubstitutor substitutor) { - return getSymbolName(symbol, substitutor, PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES | PsiFormatUtilBase.USE_INTERNAL_CANONICAL_TEXT); + public static String getSymbolName(@NotNull PsiElement symbol) { + return getSymbolName(symbol, PsiSubstitutor.EMPTY); } @Nullable - public static String getSymbolName(@NotNull PsiElement symbol, PsiSubstitutor substitutor, final int parameterOptions) { + public static String getSymbolName(@NotNull PsiElement symbol, PsiSubstitutor substitutor) { + int options = PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES | PsiFormatUtilBase.USE_INTERNAL_CANONICAL_TEXT; + return getSymbolName(symbol, substitutor, options); + } + + @Nullable + public static String getSymbolName(@NotNull PsiElement symbol, PsiSubstitutor substitutor, int parameterOptions) { String symbolName = null; if (symbol instanceof PsiClass) { @@ -46,9 +52,8 @@ public class HighlightMessageUtil { } } else if (symbol instanceof PsiMethod) { - symbolName = PsiFormatUtil.formatMethod((PsiMethod)symbol, - substitutor, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, - parameterOptions); + int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS; + symbolName = PsiFormatUtil.formatMethod((PsiMethod)symbol, substitutor, options, parameterOptions); } else if (symbol instanceof PsiVariable) { symbolName = ((PsiVariable)symbol).getName(); @@ -64,7 +69,10 @@ public class HighlightMessageUtil { else if (symbol instanceof PsiDirectory) { symbolName = ((PsiDirectory)symbol).getName(); } + else if (symbol instanceof PsiJavaModule) { + symbolName = ((PsiJavaModule)symbol).getName(); + } return symbolName; } -} +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java index 2bedff69ed04..45665654b324 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -15,7 +15,6 @@ */ package com.intellij.psi.impl.source.resolve; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl; import com.intellij.psi.scope.util.PsiScopesUtil; @@ -24,56 +23,39 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ResolveClassUtil { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.ResolveClassUtil"); - @Nullable public static PsiClass resolveClass(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiFile containingFile) { if (ref instanceof PsiJavaCodeReferenceElementImpl && ((PsiJavaCodeReferenceElementImpl)ref).getKind(containingFile) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { PsiElement parent = ref.getParent(); - if (parent instanceof PsiAnonymousClass){ + if (parent instanceof PsiAnonymousClass) { parent = parent.getParent(); } - PsiExpression qualifier; - if (parent instanceof PsiNewExpression){ - qualifier = ((PsiNewExpression)parent).getQualifier(); - LOG.assertTrue(qualifier != null); + if (parent instanceof PsiNewExpression) { + PsiExpression qualifier = ((PsiNewExpression)parent).getQualifier(); + if (qualifier != null) { + PsiType qualifierType = qualifier.getType(); + if (qualifierType instanceof PsiClassType) { + PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType); + if (qualifierClass != null) { + return qualifierClass.findInnerClassByName(ref.getText(), true); + } + } + } } - else if (parent instanceof PsiJavaCodeReferenceElement){ - return null; + } + else { + PsiElement classNameElement = ref.getReferenceNameElement(); + if (classNameElement instanceof PsiIdentifier) { + String className = classNameElement.getText(); + ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, containingFile); + PsiScopesUtil.resolveAndWalk(processor, ref, null); + if (processor.getResult().length == 1) { + return (PsiClass)processor.getResult()[0].getElement(); + } } - else{ - LOG.assertTrue(false); - return null; - } - - PsiType qualifierType = qualifier.getType(); - if (qualifierType == null) return null; - if (!(qualifierType instanceof PsiClassType)) return null; - PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType); - if (qualifierClass == null) return null; - String name = ref.getText(); - return qualifierClass.findInnerClassByName(name, true); } - final PsiElement classNameElement = ref.getReferenceNameElement(); - if (!(classNameElement instanceof PsiIdentifier)) return null; - String className = classNameElement.getText(); - - /* - long time1 = System.currentTimeMillis(); - */ - - ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, containingFile); - PsiScopesUtil.resolveAndWalk(processor, ref, null); - - - /* - long time2 = System.currentTimeMillis(); - Statistics.resolveClassTime += (time2 - time1); - Statistics.resolveClassCount++; - */ - - return processor.getResult().length == 1 ? (PsiClass)processor.getResult()[0].getElement() : null; + return null; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/module-info.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/module-info.java new file mode 100644 index 000000000000..9da527c4bab6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/module-info.java @@ -0,0 +1 @@ +@Deprecated module M.M.M { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf1.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf1.java new file mode 100644 index 000000000000..c8bf8d0089d2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf1.java @@ -0,0 +1,12 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + if (a) { + if (b) { + return false; + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf2.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf2.java new file mode 100644 index 000000000000..045cc9dc04a6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf2.java @@ -0,0 +1,13 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + for (int i = 1; i < 10; i++) + if (a) { + if (b) /* comment 1 */ { + continue; + } + return true; /* comment 2 */ + } + return false; /* comment 3 */ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf3.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf3.java new file mode 100644 index 000000000000..4f7632c20a21 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf3.java @@ -0,0 +1,14 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + if (a) { + if (b) { + } + else { + return true; // comment + } + } + int x = 1; + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf4.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf4.java new file mode 100644 index 000000000000..66f3bcd0613f --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterNestedIf4.java @@ -0,0 +1,13 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + for (int i = 1; i < 10; i++) + { + if (b) { + continue; + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf1.java b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf1.java new file mode 100644 index 000000000000..1a224826a483 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf1.java @@ -0,0 +1,9 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + if (a) + if (!b) + return true; + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf2.java b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf2.java new file mode 100644 index 000000000000..ec41dd060885 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf2.java @@ -0,0 +1,10 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + for (int i = 1; i < 10; i++) + if (a) + if (!b) /* comment 1 */ + return true; /* comment 2 */ + return false; /* comment 3 */ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf3.java b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf3.java new file mode 100644 index 000000000000..24e2682371f6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf3.java @@ -0,0 +1,10 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + if (a) + if (!b) + return true; // comment + int x = 1; + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf4.java b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf4.java new file mode 100644 index 000000000000..56ee3f0bfdfd --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/beforeNestedIf4.java @@ -0,0 +1,9 @@ +// "Invert 'if' condition" "true" +class Main { + boolean method(boolean a, boolean b) { + for (int i = 1; i < 10; i++) + if (!b) + return true; + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java index 6cf7c1c6d20a..1af8334b0408 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -23,7 +23,7 @@ import com.intellij.pom.java.LanguageLevel; public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase { private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/annotations"; - public void testWrongPlace() { doTest(); } + public void testWrongPlace() { setLanguageLevel(LanguageLevel.JDK_1_7); doTest(); } public void testNotValueNameOmitted() { doTest(); } public void testCannotFindMethod() { doTest(); } public void testIncompatibleType1() { doTest(); } @@ -32,7 +32,7 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIncompatibleType4() { doTest(); } public void testIncompatibleType5() { doTest(); } public void testMissingAttribute() { doTest(); } - public void testDuplicateAnnotation() { doTest(); } + public void testDuplicateAnnotation() { setLanguageLevel(LanguageLevel.JDK_1_7); doTest(); } public void testNonConstantInitializer() { doTest(); } public void testInvalidType() { doTest(); } public void testInapplicable() { doTest(); } @@ -44,20 +44,13 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testPrivateInaccessibleConstant() { doTest(); } public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/package-info.java", false, false); } public void testPackageAnnotationNotInPackageInfo() { doTest(); } - - public void testTypeAnnotations() { doTest8(); } - public void testRepeatable() { doTest8(); } - public void testEnumValues() { doTest8(); } - public void testReceiverParameters() { doTest8(); } + public void testTypeAnnotations() { doTest(); } + public void testRepeatable() { doTest(); } + public void testEnumValues() { doTest(); } + public void testReceiverParameters() { doTest(); } public void testAnnotationOverIncompleteCode() { doTest(); } + public void testModuleAnnotation() { setLanguageLevel(LanguageLevel.JDK_1_9); doTest("module-info.java"); } - private void doTest() { - setLanguageLevel(LanguageLevel.JDK_1_7); - doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false); - } - - private void doTest8() { - setLanguageLevel(LanguageLevel.JDK_1_8); - doTest(BASE_PATH + "/" + getTestName(true) + ".java", false, false); - } -} + private void doTest() { doTest(getTestName(true) + ".java"); } + private void doTest(String name) { doTest(BASE_PATH + "/" + name, false, false); } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt index a49e65b8e69e..e309cf036003 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes +import com.intellij.codeInspection.deprecation.DeprecationInspection import com.intellij.openapi.util.TextRange import com.intellij.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase import com.intellij.testFramework.fixtures.MultiModuleJava9ProjectDescriptor.ModuleDescriptor.* @@ -215,6 +216,12 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { highlight("module M { requires M6; }") } + fun testDeprecations() { + myFixture.enableInspections(DeprecationInspection()) + addFile("module-info.java", "@Deprecated module M2 { }", M2) + highlight("""module M { requires M2; }""") + } + // private fun highlight(text: String) = highlight("module-info.java", text) diff --git a/java/mockJDK-1.8/jre/lib/rt.jar b/java/mockJDK-1.8/jre/lib/rt.jar index 405e80298239..13a2d8bd9b93 100644 Binary files a/java/mockJDK-1.8/jre/lib/rt.jar and b/java/mockJDK-1.8/jre/lib/rt.jar differ diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java index dbdce739369a..81deb2dc9dc8 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,6 +40,7 @@ public abstract class InspectionManager { public abstract Project getProject(); @NotNull + @Contract(pure = true) public abstract CommonProblemDescriptor createProblemDescriptor(@NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, QuickFix... fixes); /** @@ -49,6 +51,7 @@ public abstract class InspectionManager { * @param onTheFly for local tools on batch run */ @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, LocalQuickFix fix, @@ -56,6 +59,7 @@ public abstract class InspectionManager { boolean onTheFly); @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, boolean onTheFly, @@ -63,6 +67,7 @@ public abstract class InspectionManager { @NotNull ProblemHighlightType highlightType); @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, LocalQuickFix[] fixes, @@ -71,6 +76,7 @@ public abstract class InspectionManager { boolean isAfterEndOfLine); @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, @@ -79,6 +85,7 @@ public abstract class InspectionManager { LocalQuickFix... fixes); @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @Nullable("null means the text range of the element") TextRange rangeInElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, @@ -87,6 +94,7 @@ public abstract class InspectionManager { LocalQuickFix... fixes); @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, final boolean showTooltip, @@ -98,6 +106,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull String descriptionTemplate, LocalQuickFix fix, @@ -108,6 +117,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull String descriptionTemplate, LocalQuickFix[] fixes, @@ -118,6 +128,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, @NotNull String descriptionTemplate, LocalQuickFix[] fixes, @@ -129,6 +140,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String descriptionTemplate, @@ -141,6 +153,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, final TextRange rangeInElement, @NotNull final String descriptionTemplate, @@ -152,6 +165,7 @@ public abstract class InspectionManager { */ @Deprecated @NotNull + @Contract(pure = true) public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @NotNull final String descriptionTemplate, final boolean showTooltip, @@ -159,5 +173,6 @@ public abstract class InspectionManager { final LocalQuickFix... fixes); @NotNull + @Contract(pure = true) public abstract GlobalInspectionContext createNewGlobalContext(boolean reuse); } diff --git a/platform/core-api/anno/com/intellij/ide/annotations.xml b/platform/core-api/anno/com/intellij/ide/annotations.xml deleted file mode 100644 index 18250848f857..000000000000 --- a/platform/core-api/anno/com/intellij/ide/annotations.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/lang/annotations.xml b/platform/core-api/anno/com/intellij/lang/annotations.xml deleted file mode 100644 index b34f4ea410f7..000000000000 --- a/platform/core-api/anno/com/intellij/lang/annotations.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/openapi/progress/annotations.xml b/platform/core-api/anno/com/intellij/openapi/progress/annotations.xml deleted file mode 100644 index 67cd14dba2f9..000000000000 --- a/platform/core-api/anno/com/intellij/openapi/progress/annotations.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/openapi/project/annotations.xml b/platform/core-api/anno/com/intellij/openapi/project/annotations.xml deleted file mode 100644 index 95cfbb0d891c..000000000000 --- a/platform/core-api/anno/com/intellij/openapi/project/annotations.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/openapi/roots/annotations.xml b/platform/core-api/anno/com/intellij/openapi/roots/annotations.xml deleted file mode 100644 index d679dd1a9e6c..000000000000 --- a/platform/core-api/anno/com/intellij/openapi/roots/annotations.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/patterns/annotations.xml b/platform/core-api/anno/com/intellij/patterns/annotations.xml deleted file mode 100644 index d8c1fb0df7d7..000000000000 --- a/platform/core-api/anno/com/intellij/patterns/annotations.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/psi/search/annotations.xml b/platform/core-api/anno/com/intellij/psi/search/annotations.xml deleted file mode 100644 index 8dd390064e23..000000000000 --- a/platform/core-api/anno/com/intellij/psi/search/annotations.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/platform/core-api/anno/com/intellij/psi/util/annotations.xml b/platform/core-api/anno/com/intellij/psi/util/annotations.xml deleted file mode 100644 index f34c69802be4..000000000000 --- a/platform/core-api/anno/com/intellij/psi/util/annotations.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/platform/core-api/core-api.iml b/platform/core-api/core-api.iml index 9d5cfe79a52a..fedaceca9ba6 100644 --- a/platform/core-api/core-api.iml +++ b/platform/core-api/core-api.iml @@ -2,9 +2,6 @@ - - - diff --git a/platform/core-api/src/com/intellij/lang/ITokenTypeRemapper.java b/platform/core-api/src/com/intellij/lang/ITokenTypeRemapper.java index c5eca6676e08..b41795db91af 100644 --- a/platform/core-api/src/com/intellij/lang/ITokenTypeRemapper.java +++ b/platform/core-api/src/com/intellij/lang/ITokenTypeRemapper.java @@ -24,6 +24,7 @@ import com.intellij.psi.tree.IElementType; * Date: 06.04.2008 * Time: 23:41:56 */ +@FunctionalInterface public interface ITokenTypeRemapper { /** * An external hook to see and alter token types reported by lexer. diff --git a/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java b/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java index 7cc84c75d20d..6e9955e26d64 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java +++ b/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java @@ -21,6 +21,7 @@ package com.intellij.openapi.progress; import org.jetbrains.annotations.NotNull; +@FunctionalInterface public interface NonCancelableSection { void done(); diff --git a/platform/core-api/src/com/intellij/openapi/progress/Progressive.java b/platform/core-api/src/com/intellij/openapi/progress/Progressive.java index 710dc06daa77..9a0e185824c8 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/Progressive.java +++ b/platform/core-api/src/com/intellij/openapi/progress/Progressive.java @@ -17,6 +17,7 @@ package com.intellij.openapi.progress; import org.jetbrains.annotations.NotNull; +@FunctionalInterface public interface Progressive { void run(@NotNull ProgressIndicator indicator); diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbAwareRunnable.java b/platform/core-api/src/com/intellij/openapi/project/DumbAwareRunnable.java index 8c8b03de447f..685d37c601a8 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbAwareRunnable.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbAwareRunnable.java @@ -18,5 +18,6 @@ package com.intellij.openapi.project; /** * @author peter */ +@FunctionalInterface public interface DumbAwareRunnable extends Runnable, DumbAware { } diff --git a/platform/core-api/src/com/intellij/openapi/roots/ContentIterator.java b/platform/core-api/src/com/intellij/openapi/roots/ContentIterator.java index 78b781c4c2a4..91ceadc057aa 100644 --- a/platform/core-api/src/com/intellij/openapi/roots/ContentIterator.java +++ b/platform/core-api/src/com/intellij/openapi/roots/ContentIterator.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile; * * @see FileIndex#iterateContent(ContentIterator) */ +@FunctionalInterface public interface ContentIterator { /** * Processes the specified file or directory. diff --git a/platform/core-api/src/com/intellij/patterns/StandardPatterns.java b/platform/core-api/src/com/intellij/patterns/StandardPatterns.java index b3a818cd3e07..b6807a054185 100644 --- a/platform/core-api/src/com/intellij/patterns/StandardPatterns.java +++ b/platform/core-api/src/com/intellij/patterns/StandardPatterns.java @@ -17,7 +17,6 @@ package com.intellij.patterns; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; -import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; @@ -52,8 +51,9 @@ public class StandardPatterns { } @NotNull + @SafeVarargs public static ElementPattern instanceOf(@NotNull Class... classes) { - ElementPattern[] patterns = ContainerUtil.map(classes, aClass -> instanceOf(aClass), new ElementPattern[0]); + ElementPattern[] patterns = ContainerUtil.map(classes, StandardPatterns::instanceOf, new ElementPattern[0]); return or(patterns); } @@ -109,6 +109,7 @@ public class StandardPatterns { } @NotNull + @SafeVarargs public static ElementPattern or(@NotNull final ElementPattern... patterns) { return new ObjectPattern.Capture<>(new InitialPatternConditionPlus(Object.class) { @Override @@ -133,12 +134,13 @@ public class StandardPatterns { @Override public List> getPatterns() { - return Arrays.>asList(patterns); + return Arrays.asList(patterns); } }); } @NotNull + @SafeVarargs public static ElementPattern and(final ElementPattern... patterns) { final List initial = ContainerUtil.newSmartList(); for (ElementPattern pattern : patterns) { @@ -194,7 +196,7 @@ public class StandardPatterns { @Override public List> getPatterns() { - return Collections.>singletonList(pattern); + return Collections.singletonList(pattern); } }); } diff --git a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java index 4c29e06abf97..8a3c18fd2914 100644 --- a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java +++ b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java @@ -42,7 +42,8 @@ public abstract class TreeElementPattern... types) { + @SafeVarargs + public final Self withParents(@NotNull final Class... types) { return with(new PatternCondition("withParents") { @Override public boolean accepts(@NotNull T t, ProcessingContext context) { @@ -91,6 +92,7 @@ public abstract class TreeElementPattern pattern) { return with(new PatternCondition("isFirstAcceptedChild") { + @Override public boolean accepts(@NotNull final T t, final ProcessingContext context) { final ParentType parent = getParent(t); if (parent != null) { @@ -183,11 +185,12 @@ public abstract class TreeElementPattern... patterns) { + @SafeVarargs + public final Self insideSequence(final boolean strict, @NotNull final ElementPattern... patterns) { return with(new PatternCondition("insideSequence") { + @Override public boolean accepts(@NotNull final T t, final ProcessingContext context) { int i = 0; ParentType element = strict ? getParent(t) : t; diff --git a/platform/core-api/src/com/intellij/psi/search/PsiNonJavaFileReferenceProcessor.java b/platform/core-api/src/com/intellij/psi/search/PsiNonJavaFileReferenceProcessor.java index 406e95b74f8c..ccb662541491 100644 --- a/platform/core-api/src/com/intellij/psi/search/PsiNonJavaFileReferenceProcessor.java +++ b/platform/core-api/src/com/intellij/psi/search/PsiNonJavaFileReferenceProcessor.java @@ -17,6 +17,7 @@ package com.intellij.psi.search; import com.intellij.psi.PsiFile; +@FunctionalInterface public interface PsiNonJavaFileReferenceProcessor { boolean process(PsiFile file, int startOffset, int endOffset); } diff --git a/platform/core-api/src/com/intellij/psi/util/CachedValueProvider.java b/platform/core-api/src/com/intellij/psi/util/CachedValueProvider.java index 2fb23b95b953..e5bf7633f413 100644 --- a/platform/core-api/src/com/intellij/psi/util/CachedValueProvider.java +++ b/platform/core-api/src/com/intellij/psi/util/CachedValueProvider.java @@ -26,6 +26,7 @@ import java.util.Collection; * A computation (typically an anonymous class) to used in {@link CachedValue} to cache some computation result. * @param the type of the cached value */ +@FunctionalInterface public interface CachedValueProvider { /** diff --git a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java index a2ac93f96532..ed907a2b696d 100644 --- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -235,6 +235,7 @@ public class PsiTreeUtil { */ @Nullable @Contract("null, _ -> null") + @SafeVarargs public static T findChildOfAnyType(@Nullable final PsiElement element, @NotNull final Class... classes) { return findChildOfAnyType(element, true, classes); } @@ -248,6 +249,7 @@ public class PsiTreeUtil { * @param type to cast found element to. * @return first found element, or null if nothing found. */ + @SafeVarargs @Nullable @Contract("null, _, _ -> null") public static T findChildOfAnyType(@Nullable final PsiElement element, @@ -274,6 +276,7 @@ public class PsiTreeUtil { return findChildrenOfAnyType(element, aClass); } + @SafeVarargs @NotNull public static Collection findChildrenOfAnyType(@Nullable final PsiElement element, @NotNull final Class... classes) { @@ -372,6 +375,7 @@ public class PsiTreeUtil { return result == null ? null : ArrayUtil.toObjectArray(result, aClass); } + @SafeVarargs @NotNull public static List getChildrenOfAnyType(@Nullable PsiElement element, @NotNull Class... classes) { if (element == null) return ContainerUtil.emptyList(); @@ -457,6 +461,7 @@ public class PsiTreeUtil { * @return the element, or null if none was found. * @since 5.1 */ + @SafeVarargs @Nullable @Contract("null, _ -> null") public static T getChildOfAnyType(@Nullable PsiElement element, @NotNull Class... classes) { @@ -546,6 +551,7 @@ public class PsiTreeUtil { return getParentOfType(element, parentClass); } + @SafeVarargs @Nullable @Contract("null, _, _, _ -> null") public static T getContextOfType(@Nullable PsiElement element, @@ -574,11 +580,13 @@ public class PsiTreeUtil { return getContextOfType(element, strict, aClass); } + @SafeVarargs @Nullable public static T getContextOfType(@Nullable PsiElement element, @NotNull Class... classes) { return getContextOfType(element, true, classes); } + @SafeVarargs @Nullable @Contract("null, _, _ -> null") public static T getContextOfType(@Nullable PsiElement element, @@ -630,6 +638,7 @@ public class PsiTreeUtil { return null; } + @SafeVarargs @Nullable @Contract("null, _, _, _ -> null") public static T getParentOfType(@Nullable PsiElement element, @@ -688,6 +697,7 @@ public class PsiTreeUtil { return null; } + @SafeVarargs @Nullable @Contract("null, _ -> null") public static T getParentOfType(@Nullable final PsiElement element, @@ -698,6 +708,7 @@ public class PsiTreeUtil { return getNonStrictParentOfType(parent, classes); } + @SafeVarargs @Nullable @Contract("null, _ -> null") public static T getNonStrictParentOfType(@Nullable final PsiElement element, @@ -722,21 +733,18 @@ public class PsiTreeUtil { return processor.toArray(); } + @SafeVarargs @NotNull public static Collection collectElementsOfType(@Nullable final PsiElement element, @NotNull final Class... classes) { - CollectFilteredElements processor = new CollectFilteredElements<>(new PsiElementFilter() { - - @Override - public boolean isAccepted(PsiElement element) { - for (Class clazz : classes) { - if (clazz.isInstance(element)) { - return true; - } + CollectFilteredElements processor = new CollectFilteredElements<>(element1 -> { + for (Class clazz : classes) { + if (clazz.isInstance(element1)) { + return true; } - - return false; } + + return false; }); processElements(element, processor); return processor.getCollection(); @@ -873,6 +881,7 @@ public class PsiTreeUtil { return result; } + @SafeVarargs @Nullable public static T findElementOfClassAtOffsetWithStopSet(@NotNull PsiFile file, int offset, diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/FileTrees.java b/platform/core-impl/src/com/intellij/psi/impl/source/FileTrees.java index 1bebf4bf94a1..6c9c1cf68d97 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/FileTrees.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/FileTrees.java @@ -68,14 +68,12 @@ final class FileTrees { } FileTrees withExclusiveStub(@NotNull StubTree stub) { - assert derefTreeElement() == null; - assert !useStrongRefs; + assert derefTreeElement() == null && !useStrongRefs : this; return new FileTrees(new SoftReference<>(stub), null, false, false); } FileTrees withGreenStub(@NotNull StubTree stub) { - assert derefTreeElement() != null; - assert astLoaded; + assert derefTreeElement() != null && astLoaded : this; return new FileTrees(new SoftReference<>(stub), myTreeElementPointer, true, useStrongRefs); } @@ -86,8 +84,8 @@ final class FileTrees { @Override public String toString() { return "FileTrees{" + - "stub=" + derefStub() + - ", AST=" + derefTreeElement() + + "stub=" + (myStub == null ? "noRef" : derefStub()) + + ", AST=" + (myTreeElementPointer == null ? "noRef" : derefTreeElement()) + ", astLoaded=" + astLoaded + ", useStrongRefs=" + useStrongRefs + '}' ; 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 a044a58b4309..d3527709c708 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 @@ -682,7 +682,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (getElementTypeForStubBuilder() == null) return null; final VirtualFile vFile = getVirtualFile(); - if (!(vFile instanceof VirtualFileWithId)) return null; + if (!(vFile instanceof VirtualFileWithId) || !vFile.isValid()) return null; ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), vFile, this); if (!(tree instanceof StubTree)) return null; @@ -1059,6 +1059,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (tree != null) { return tree; } + assert myFileElementBeingLoaded.get() == null : "non-empty thread-local"; FileElement fileElement = calcTreeElement(); synchronized (myStubFromTreeLock) { tree = derefStub(); diff --git a/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java b/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java index 40a57a2f013a..bbad28c414cd 100644 --- a/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java +++ b/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java @@ -17,15 +17,23 @@ package com.intellij.ui.switcher; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.List; -@Deprecated public interface QuickActionProvider { - DataKey KEY = DataKey.create("QuickActionProvider"); - String getName(); + @NotNull List getActions(boolean originalProvider); + default boolean isCycleRoot() { return false; } + + @Nullable + JComponent getComponent(); + + @Nullable + String getName(); } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java index 74baf1ed3c0a..bb4905596537 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java @@ -22,13 +22,14 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; /** *

@@ -254,15 +255,15 @@ public abstract class AbstractSchemeActions { private AnAction createImportExportAction(@NotNull String groupName, @NotNull Collection actionNames, - @NotNull Function createActionByName) { + @NotNull BiFunction createActionByName) { if (actionNames.size() == 1) { - return createActionByName.apply(groupName); + return createActionByName.apply(ContainerUtil.getFirstItem(actionNames), groupName); } else { return new ActionGroupPopupAction(groupName, actionNames) { @NotNull @Override protected AnAction createAction(@NotNull String actionName) { - return createActionByName.apply(actionName); + return createActionByName.apply(actionName, actionName); } }; } @@ -300,8 +301,8 @@ public abstract class AbstractSchemeActions { private String myImporterName; - public ImportAction(@NotNull String importerName) { - super(importerName); + public ImportAction(@NotNull String importerName, @NotNull String importerText) { + super(importerText); myImporterName = importerName; } @@ -315,8 +316,8 @@ public abstract class AbstractSchemeActions { private class ExportAction extends DumbAwareAction { private String myExporterName; - public ExportAction(@NotNull String exporterName) { - super(exporterName); + public ExportAction(@NotNull String exporterName, @NotNull String exporterText) { + super(exporterText); myExporterName = exporterName; } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java index e96582e51f4d..4b8c882cb663 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java @@ -17,6 +17,7 @@ package com.intellij.application.options.schemes; import com.intellij.openapi.options.Scheme; import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; @@ -144,7 +145,8 @@ public class EditableSchemesCombo { public void cancelEdit() { mySchemesPanel.clearInfo(); myLayout.first(myRootPanel); - myRootPanel.requestFocus(); + final IdeFocusManager focusManager = IdeFocusManager.getGlobalInstance(); + focusManager.doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(myRootPanel, true)); } private void createCombo() { @@ -186,7 +188,8 @@ public class EditableSchemesCombo { showHint(); myNameEditorField.setText(scheme.getName()); myLayout.last(myRootPanel); - myNameEditorField.requestFocus(); + final IdeFocusManager focusManager = IdeFocusManager.getGlobalInstance(); + focusManager.doWhenFocusSettlesDown(() -> focusManager.requestFocus(myNameEditorField, true)); } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index a958238a676c..5dd012866127 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -47,11 +47,13 @@ import com.intellij.ui.docking.DockManager; import com.intellij.ui.docking.DockableContent; import com.intellij.ui.docking.DragSession; import com.intellij.ui.docking.impl.DockManagerImpl; +import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.ui.tabs.JBTabs; import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsListener; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.util.NotNullFunction; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AbstractLayoutManager; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.JBUI; @@ -75,7 +77,7 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors; public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Facade, ViewContextEx, PropertyChangeListener, - DockContainer.Dialog { + QuickActionProvider, DockContainer.Dialog { public static final DataKey KEY = DataKey.create("DebuggerContentUI"); public static final Key LIGHTWEIGHT_CONTENT_MARKER = Key.create("LightweightContent"); @@ -1351,7 +1353,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } - private class MyComponent extends NonOpaquePanel implements DataProvider { + private class MyComponent extends NonOpaquePanel implements DataProvider, QuickActionProvider { private boolean myWasEverAdded; public MyComponent(LayoutManager layout) { @@ -1364,7 +1366,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac @Override @Nullable public Object getData(@NonNls final String dataId) { - if (CloseAction.CloseTarget.KEY.is(dataId)) { + if (QuickActionProvider.KEY.is(dataId)) { + return RunnerContentUi.this; + } + else if (CloseAction.CloseTarget.KEY.is(dataId)) { Content content = getContentManager().getSelectedContent(); if (content != null && content.getManager().canCloseContents() && content.isCloseable()) { return new CloseAction.CloseTarget() { @@ -1384,6 +1389,28 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return null; } + @NotNull + @Override + public String getName() { + return RunnerContentUi.this.getName(); + } + + @NotNull + @Override + public List getActions(boolean originalProvider) { + return RunnerContentUi.this.getActions(originalProvider); + } + + @Override + public JComponent getComponent() { + return RunnerContentUi.this.getComponent(); + } + + @Override + public boolean isCycleRoot() { + return RunnerContentUi.this.isCycleRoot(); + } + @Override public void addNotify() { super.addNotify(); @@ -1671,6 +1698,23 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return myRunnerUi; } + @NotNull + @Override + public String getName() { + return mySessionName; + } + + @NotNull + @Override + public List getActions(boolean originalProvider) { + ArrayList result = new ArrayList<>(); + if (myLeftToolbarActions != null) { + AnAction[] kids = myLeftToolbarActions.getChildren(null); + ContainerUtil.addAll(result, kids); + } + return result; + } + private int findFreeWindow() { int i; for (i = 1; i < Integer.MAX_VALUE; i++) { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java index 707ad5344f60..c5f40a5bd1df 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java @@ -36,6 +36,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.ContentManagerListener; +import com.intellij.ui.switcher.QuickActionProvider; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -376,7 +377,7 @@ public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, La @Nullable @Override public Object getData(@NonNls String dataId) { - if (RunnerContentUi.KEY.is(dataId)) { + if (QuickActionProvider.KEY.is(dataId) || RunnerContentUi.KEY.is(dataId)) { return myContentUI; } return null; diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 2151736b31c5..493d9d2482fe 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -82,6 +82,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.ContentManagerAdapter; import com.intellij.ui.content.ContentManagerEvent; +import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.util.ArrayUtil; import com.intellij.util.IJSwingUtilities; import com.intellij.util.PlatformIcons; @@ -106,7 +107,7 @@ import java.util.*; import java.util.List; @State(name = "ProjectView", storages = @Storage(StoragePathMacros.WORKSPACE_FILE)) -public class ProjectViewImpl extends ProjectView implements PersistentStateComponent, Disposable, BusyObject { +public class ProjectViewImpl extends ProjectView implements PersistentStateComponent, Disposable, QuickActionProvider, BusyObject { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.projectView.impl.ProjectViewImpl"); private static final Key ID_KEY = Key.create("pane-id"); private static final Key SUB_ID_KEY = Key.create("pane-sub-id"); @@ -253,14 +254,84 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo private void constructUi() { myViewContentPanel = new JPanel(); - myPanel = new SimpleToolWindowPanel(true); + myPanel = new SimpleToolWindowPanel(true).setProvideQuickActions(false); myPanel.setContent(myViewContentPanel); } @NotNull - @Deprecated + @Override + public String getName() { + return "Project"; + } + + @NotNull + @Override public List getActions(boolean originalProvider) { - return Collections.emptyList(); + List result = new ArrayList<>(); + + DefaultActionGroup views = new DefaultActionGroup("Change View", true); + + ChangeViewAction lastHeader = null; + for (int i = 0; i < myContentManager.getContentCount(); i++) { + Content each = myContentManager.getContent(i); + if (each == null) continue; + + String id = each.getUserData(ID_KEY); + String subId = each.getUserData(SUB_ID_KEY); + ChangeViewAction newHeader = new ChangeViewAction(id, subId); + + if (lastHeader != null) { + boolean lastHasKids = lastHeader.mySubId != null; + boolean newHasKids = newHeader.mySubId != null; + if (lastHasKids != newHasKids || + lastHasKids && lastHeader.myId != newHeader.myId) { + views.add(Separator.getInstance()); + } + } + + views.add(newHeader); + lastHeader = newHeader; + } + result.add(views); + result.add(Separator.getInstance()); + + if (myActionGroup != null) { + List secondary = new ArrayList<>(); + for (AnAction each : myActionGroup.getChildren(null)) { + if (myActionGroup.isPrimary(each)) { + result.add(each); + } + else { + secondary.add(each); + } + } + + result.add(Separator.getInstance()); + result.addAll(secondary); + } + + return result; + } + + private class ChangeViewAction extends AnAction { + @NotNull private final String myId; + @Nullable private final String mySubId; + + private ChangeViewAction(@NotNull String id, @Nullable String subId) { + myId = id; + mySubId = subId; + } + + @Override + public void update(AnActionEvent e) { + AbstractProjectViewPane pane = getProjectViewPaneById(myId); + e.getPresentation().setText(pane.getTitle() + (mySubId != null ? (" - " + pane.getPresentableSubIdName(mySubId)) : "")); + } + + @Override + public void actionPerformed(AnActionEvent e) { + changeView(myId, mySubId); + } } @Override @@ -729,6 +800,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo myConnection.disconnect(); } + @Override public JComponent getComponent() { return myDataProvider; } @@ -1060,6 +1132,10 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo return selectedElements.isEmpty() ? null : selectedElements.toArray(new NamedLibraryElement[selectedElements.size()]); } + if (QuickActionProvider.KEY.is(dataId)) { + return ProjectViewImpl.this; + } + return null; } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java index 90171e905bd1..e2547cdd3b17 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -148,9 +148,11 @@ public class ContentEntryTreeEditor { final ContentEntry entry = contentEntryEditor.getContentEntry(); assert entry != null : contentEntryEditor; final VirtualFile file = entry.getFile(); - myDescriptor.setRoots(file); - if (file == null) { - final String path = VfsUtilCore.urlToPath(entry.getUrl()); + if (file != null) { + myDescriptor.setRoots(file); + } + else { + String path = VfsUtilCore.urlToPath(entry.getUrl()); myDescriptor.setTitle(FileUtil.toSystemDependentName(path)); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveDirectoryWithClassesProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveDirectoryWithClassesProcessor.java index caa2ecb8e391..18cdd6d2c077 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveDirectoryWithClassesProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveDirectoryWithClassesProcessor.java @@ -189,7 +189,7 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor myNonCodeUsages = CommonMoveUtil.retargetUsages(usages, oldToNewElementsMapping); for (MoveDirectoryWithClassesHelper helper : MoveDirectoryWithClassesHelper.findAll()) { - helper.postProcessUsages(usages, dir -> getResultDirectory(dir).getTargetDirectory()); + helper.postProcessUsages(usages, dir -> getResultDirectory(dir).findOrCreateTargetDirectory()); } for (PsiDirectory directory : myDirectories) { final TargetDirectoryWrapper wrapper = myNestedDirsToMove.get(directory); diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java index d7b1b6e0e32f..3ddbda756dad 100644 --- a/platform/platform-api/src/com/intellij/notification/Notification.java +++ b/platform/platform-api/src/com/intellij/notification/Notification.java @@ -104,7 +104,7 @@ public class Notification { LOG.assertTrue(hasTitle() || hasContent(), "Notification should have title: " + title + " and/or subtitle and/or content groupId: " + myGroupId); - id = calcId(this); + id = calculateId(this); } public Notification(@NotNull String groupDisplayId, @NotNull String title, @NotNull String content, @NotNull NotificationType type) { @@ -132,7 +132,7 @@ public class Notification { myTimestamp = System.currentTimeMillis(); LOG.assertTrue(hasContent(), "Notification should have content, title: " + title + ", groupId: " + myGroupId); - id = calcId(this); + id = calculateId(this); } /** @@ -348,7 +348,7 @@ public class Notification { } @NotNull - private static String calcId(@NotNull Notification notification) { + private static String calculateId(@NotNull Object notification) { return String.valueOf(System.currentTimeMillis()) + "." + String.valueOf(System.identityHashCode(notification)); } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 21e34be655dc..01e57bc5cf5e 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -31,7 +31,7 @@ import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.ui.popup.BalloonBuilder; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.*; @@ -52,7 +52,10 @@ import com.intellij.util.Alarm; import com.intellij.util.IconUtil; import com.intellij.util.TimeoutUtil; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.*; +import com.intellij.util.ui.DialogUtil; +import com.intellij.util.ui.GridBag; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; @@ -345,16 +348,8 @@ public abstract class DialogWrapper { private void reportProblem(@NotNull final ValidationInfo info) { installErrorPainter(); - myErrorPainter.setValidationInfo(info); - if (needRefresh(info.message)) { - SwingUtilities.invokeLater(() -> { - if (myDisposed) return; - setErrorText(info.message, info.component); - myPeer.getRootPane().getGlassPane().repaint(); - getOKAction().setEnabled(false); - }); - } + updateErrorMessage(info); } private void installErrorPainter() { @@ -365,21 +360,22 @@ public abstract class DialogWrapper { private void clearProblems() { myErrorPainter.setValidationInfo(null); - if (needRefresh(null)) { - SwingUtilities.invokeLater(() -> { - if (myDisposed) return; - setErrorText(null, null); - myPeer.getRootPane().getGlassPane().repaint(); - getOKAction().setEnabled(true); - }); - } + updateErrorMessage(null); } - private boolean needRefresh(String expectedText) { - if (Registry.is("ide.inplace.errors.balloon")) { - return !StringUtil.equals(expectedText, myLastErrorText); - } else { - return !myErrorText.isTextSet(expectedText); + protected void updateErrorMessage(@Nullable ValidationInfo info) { + String msg = (info == null) ? null : info.message; + JComponent errorComponent = (info == null) ? null : info.component; + boolean updateNeeded = Registry.is("ide.inplace.errors.balloon") ? + !StringUtil.equals(msg, myLastErrorText) : !myErrorText.isTextSet(msg); + + if (updateNeeded) { + SwingUtilities.invokeLater(() -> { + if (myDisposed) return; + setErrorText(msg, errorComponent); + myPeer.getRootPane().getGlassPane().repaint(); + getOKAction().setEnabled(msg == null); + }); } } @@ -1963,32 +1959,23 @@ public abstract class DialogWrapper { component.putClientProperty("JComponent.error.outline", outline); } - if (Registry.is("ide.inplace.errors.balloon") && outline) { + if (Registry.is("ide.inplace.errors.balloon") && component != null && outline) { JLabel label = new JLabel(); - Insets insets = UIUtil.getUIResource("Balloon.textInsets", Insets.class); + Insets insets = UIManager.getInsets("Balloon.error.textInsets"); int oneLineWidth = SwingUtilities2.stringWidth(label, label.getFontMetrics(label.getFont()), text); - int textWidth = component.getWidth() - JBUI.scale(30) - insets.right - insets.left; + int textWidth = component.getWidth() - JBUI.scale(30) - insets.left - insets.right; if (textWidth > oneLineWidth) textWidth = oneLineWidth; String htmlText = String.format("

%s
", textWidth, text); label.setText(htmlText); - label.setHorizontalAlignment(JLabel.LEADING); + label.setHorizontalAlignment(SwingConstants.LEADING); - Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(label) + BalloonBuilder bb = JBPopupFactory.getInstance().createBalloonBuilder(label) .setDisposable(getDisposable()) - .setBorderColor(UIUtil.getUIResource("Balloon.border.color", Color.class)) - .setFillColor(UIUtil.getUIResource("Balloon.background.color", Color.class)) - .setPointerSize(UIUtil.getUIResource("Balloon.pointerSize", Dimension.class)) - .setCornerToPointerDistance(JBUI.scale(30)) - .setBorderInsets(insets) - .setHideOnFrameResize(false) - .setRequestFocus(false) - .setAnimationCycle(300) - .setShadow(false) - .createBalloon(); + .setBorderInsets(insets); - component.putClientProperty("JComponent.error.balloon", balloon); + component.putClientProperty("JComponent.error.balloonBuilder", bb); } else { myErrorTextAlarm.addRequest(() -> { myErrorText.setError(myLastErrorText); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java index 90b3b6bb347f..bed652b0fe01 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java @@ -18,24 +18,28 @@ package com.intellij.openapi.ui; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.util.containers.JBIterable; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.ContainerAdapter; import java.awt.event.ContainerEvent; +import java.util.Collections; import java.util.List; -public class SimpleToolWindowPanel extends JPanel implements DataProvider { +public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider, DataProvider { private JComponent myToolbar; private JComponent myContent; private boolean myBorderless; protected boolean myVertical; + private boolean myProvideQuickActions; public SimpleToolWindowPanel(boolean vertical) { this(vertical, false); @@ -45,6 +49,7 @@ public class SimpleToolWindowPanel extends JPanel implements DataProvider { setLayout(new BorderLayout(vertical ? 0 : 1, vertical ? 1 : 0)); myBorderless = borderless; myVertical = vertical; + setProvideQuickActions(true); addContainerListener(new ContainerAdapter() { @Override @@ -94,18 +99,18 @@ public class SimpleToolWindowPanel extends JPanel implements DataProvider { @Nullable public Object getData(@NonNls String dataId) { - return null; + return QuickActionProvider.KEY.is(dataId) && myProvideQuickActions ? this : null; } - @Deprecated public SimpleToolWindowPanel setProvideQuickActions(boolean provide) { + myProvideQuickActions = provide; return this; } - public List getActions() { + @NotNull + public List getActions(boolean originalProvider) { JBIterable toolbars = UIUtil.uiTraverser(myToolbar).traverse().filter(ActionToolbar.class); - if (toolbars.size() == 0) - return null; + if (toolbars.size() == 0) return Collections.emptyList(); return toolbars.flatten(toolbar -> toolbar.getActions()).toList(); } diff --git a/platform/platform-api/src/com/intellij/ui/switcher/ShowQuickActionPopupAction.java b/platform/platform-api/src/com/intellij/ui/switcher/ShowQuickActionPopupAction.java new file mode 100644 index 000000000000..ab1c529d7949 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/switcher/ShowQuickActionPopupAction.java @@ -0,0 +1,82 @@ +/* + * 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.ui.switcher; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.Separator; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ObjectUtils; + +import javax.swing.*; +import java.awt.*; +import java.util.List; + +import static com.intellij.openapi.ui.popup.JBPopupFactory.ActionSelectionAid.ALPHA_NUMBERING; + +public class ShowQuickActionPopupAction extends AnAction { + @Override + public void update(AnActionEvent e) { + QuickActionProvider quickActionProvider = e.getData(QuickActionProvider.KEY); + if (quickActionProvider == null) { + e.getPresentation().setEnabled(false); + return; + } + + List actions = quickActionProvider.getActions(true); + e.getPresentation().setEnabled(!actions.isEmpty()); + } + + + @Override + public void actionPerformed(AnActionEvent e) { + QuickActionProvider provider = e.getRequiredData(QuickActionProvider.KEY); + List actions = provider.getActions(true); + + DefaultActionGroup group = new DefaultActionGroup(actions); + group.addSeparator(); + + JComponent component = provider.getComponent(); + if (component != null && !provider.isCycleRoot()) { + Component eachParent = component.getParent(); + while (eachParent != null) { + QuickActionProvider parentProvider = ObjectUtils.tryCast(eachParent, QuickActionProvider.class); + if (parentProvider != null) { + List parentActions = parentProvider.getActions(false); + if (!parentActions.isEmpty()) { + String name = StringUtil.notNullize(parentProvider.getName(), ""); + DefaultActionGroup parentGroup = new DefaultActionGroup(name, parentActions); + if (!StringUtil.isEmpty(name)) { + parentGroup.setPopup(true); + } + else { + group.add(Separator.getInstance()); + } + group.add(parentGroup); + } + if (parentProvider.isCycleRoot()) break; + } + eachParent = eachParent.getParent(); + } + } + + JBPopupFactory.getInstance() + .createActionGroupPopup(null, group, e.getDataContext(), ALPHA_NUMBERING, true) + .showInBestPositionFor(e.getDataContext()); + } +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 1d38e07d226c..f3ac1110488a 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.*; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.ui.tabs.*; import com.intellij.ui.tabs.impl.singleRow.ScrollableSingleRowLayout; import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout; @@ -60,7 +61,7 @@ import java.util.List; public class JBTabsImpl extends JComponent implements JBTabs, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, - UISettingsListener, Accessible { + UISettingsListener, QuickActionProvider, Accessible { public static final DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); @NonNls public static final Key SIDE_TABS_SIZE_LIMIT_KEY = Key.create("SIDE_TABS_SIZE_LIMIT_KEY"); @@ -3115,9 +3116,30 @@ public class JBTabsImpl extends JComponent if (value != null) return value; } + if (QuickActionProvider.KEY.getName().equals(dataId)) { + return this; + } + return NAVIGATION_ACTIONS_KEY.is(dataId) ? this : null; } + @NotNull + @Override + public List getActions(boolean originalProvider) { + ArrayList result = new ArrayList<>(); + + TabInfo selection = getSelectedInfo(); + if (selection != null) { + ActionGroup group = selection.getGroup(); + if (group != null) { + AnAction[] children = group.getChildren(null); + Collections.addAll(result, children); + } + } + + return result; + } + @Override public DataProvider getDataProvider() { return myDataProvider; diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 507877de3d5d..8228bd1b3d45 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -55,6 +55,7 @@ import com.intellij.util.IconUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jdom.Element; @@ -503,6 +504,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo initInputMapDefaults(uiDefaults); uiDefaults.put("Button.defaultButtonFollowsFocus", Boolean.FALSE); + uiDefaults.put("Balloon.error.textInsets", new JBInsets(3, 8, 3, 8).asUIResource()); patchFileChooserStrings(uiDefaults); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 5d7490f17ed0..0ecd0336b314 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -40,7 +40,10 @@ import org.jetbrains.annotations.NotNull; import sun.awt.AppContext; import javax.swing.*; -import javax.swing.plaf.*; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.IconUIResource; import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.plaf.metal.DefaultMetalTheme; import javax.swing.plaf.metal.MetalLookAndFeel; @@ -422,11 +425,10 @@ public class DarculaLaf extends BasicLookAndFeel { private static Insets parseInsets(String value) { final List numbers = StringUtil.split(value, ","); - JBInsets insets = new JBInsets(Integer.parseInt(numbers.get(0)), - Integer.parseInt(numbers.get(1)), - Integer.parseInt(numbers.get(2)), - Integer.parseInt(numbers.get(3))); - return insets.asUIResource(); + return new JBInsets(Integer.parseInt(numbers.get(0)), + Integer.parseInt(numbers.get(1)), + Integer.parseInt(numbers.get(2)), + Integer.parseInt(numbers.get(3))).asUIResource(); } @SuppressWarnings("UseJBColor") @@ -455,8 +457,7 @@ public class DarculaLaf extends BasicLookAndFeel { private static Dimension parseSize(String value) { final List numbers = StringUtil.split(value, ","); - JBDimension dimension = new JBDimension(Integer.parseInt(numbers.get(0)), Integer.parseInt(numbers.get(1))); - return dimension.asUIResource(); + return new JBDimension(Integer.parseInt(numbers.get(0)), Integer.parseInt(numbers.get(1))).asUIResource(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java index a099a4cc3cd4..cdd50485a703 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java @@ -41,6 +41,9 @@ import static javax.swing.SwingConstants.WEST; public class DarculaUIUtil { private static final Color GLOW_COLOR = new JBColor(new Color(31, 121, 212), new Color(96, 175, 255)); + private static final Color BALLOON_BORDER = new JBColor(new Color(0xe0a8a9), new Color(0x73454b)); + private static final Color BALLOON_BACKGROUND = new JBColor(new Color(0xf5e6e7), new Color(0x593d41)); + public static void paintFocusRing(Graphics g, Rectangle bounds) { MacUIUtil.paintFocusRing((Graphics2D)g, GLOW_COLOR, bounds); } @@ -121,9 +124,19 @@ public class DarculaUIUtil { } public static void showErrorTip(JComponent component) { - Balloon balloon = (Balloon)component.getClientProperty("JComponent.error.balloon"); - if (balloon != null) { - component.putClientProperty("JComponent.error.balloon", null); + BalloonBuilder bb = (BalloonBuilder)component.getClientProperty("JComponent.error.balloonBuilder"); + if (bb != null) { + component.putClientProperty("JComponent.error.balloonBuilder", null); + + Balloon balloon = bb.setPointerSize(new JBDimension(17, 6)) + .setCornerToPointerDistance(JBUI.scale(30)) + .setBorderColor(BALLOON_BORDER) + .setFillColor(BALLOON_BACKGROUND) + .setHideOnFrameResize(false) + .setRequestFocus(false) + .setAnimationCycle(300) + .setShadow(false) + .createBalloon(); JComponent root = component.getRootPane(); Point componentPos = SwingUtilities.convertPoint(component, 0, 0, root); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties index ae57de6b6217..ccd2a96ccd42 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties @@ -171,8 +171,3 @@ Tree.collapsedIcon=AllIcons.Mac.Tree_white_right_arrow Tree.expandedIcon=AllIcons.Mac.Tree_white_down_arrow FileView.fileIcon=AllIcons.FileTypes.Unknown - -Balloon.border.color=73454b -Balloon.background.color=593d41 -Balloon.textInsets=3,8,3,8 -Balloon.pointerSize=17,6 \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJTextBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJTextBorder.java index 059db41115e0..7495c6ee4d99 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJTextBorder.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJTextBorder.java @@ -55,6 +55,7 @@ public class MacIntelliJTextBorder extends DarculaTextBorder { try { g2.translate(x, y); DarculaUIUtil.paintErrorRing(g2, width, height, c.hasFocus()); + g2.translate(-x, -y); } finally { g2.dispose(); } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties index 3975c2a149ec..6b298b0b9079 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties @@ -175,8 +175,3 @@ Tree.collapsedIcon=AllIcons.Nodes.TreeRightArrow Tree.expandedIcon=AllIcons.Nodes.TreeDownArrow FileView.fileIcon=AllIcons.FileTypes.Unknown - -Balloon.border.color=e0a8a9 -Balloon.background.color=f5e6e7 -Balloon.textInsets=3,3,3,3 -Balloon.pointerSize=17,6 \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java index fc3c1ac16ecd..b2103ce43c42 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java @@ -38,6 +38,7 @@ import com.intellij.ui.Gray; import com.intellij.ui.JBColor; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.awt.RelativeRectangle; +import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.*; @@ -59,7 +60,7 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -public class ActionToolbarImpl extends JPanel implements ActionToolbar { +public class ActionToolbarImpl extends JPanel implements ActionToolbar, QuickActionProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionToolbarImpl"); private static final List ourToolbars = new LinkedList<>(); @@ -1237,6 +1238,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { mySecondaryActions.getTemplatePresentation().setDescription(secondaryActionsTooltip); } + @NotNull + @Override + public List getActions(boolean originalProvider) { + return getActions(); + } + @NotNull @Override public List getActions() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java index 9a1f17715770..70cca110ea70 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -17,10 +17,7 @@ package com.intellij.openapi.wm.impl.status; import com.intellij.ide.util.GotoLineNumberDialog; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.fileEditor.FileEditorManagerEvent; import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; @@ -36,7 +33,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; -public class PositionPanel extends EditorBasedWidget implements StatusBarWidget.Multiframe, StatusBarWidget.TextPresentation, CaretListener, SelectionListener { +public class PositionPanel extends EditorBasedWidget + implements StatusBarWidget.Multiframe, StatusBarWidget.TextPresentation, CaretListener, SelectionListener, DocumentListener { private static final int CHAR_COUNT_SYNC_LIMIT = 500_000; private static final String CHAR_COUNT_UNKNOWN = "..."; @@ -112,6 +110,7 @@ public class PositionPanel extends EditorBasedWidget implements StatusBarWidget. final EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster(); multicaster.addCaretListener(this, this); multicaster.addSelectionListener(this, this); + multicaster.addDocumentListener(this, this); } @Override @@ -135,6 +134,22 @@ public class PositionPanel extends EditorBasedWidget implements StatusBarWidget. updatePosition(e.getEditor()); } + @Override + public void beforeDocumentChange(DocumentEvent event) {} + + @Override + public void documentChanged(DocumentEvent event) { + Document document = event.getDocument(); + Editor[] editors = EditorFactory.getInstance().getEditors(document); + Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + for (Editor editor : editors) { + if (editor.getContentComponent() == focusOwner) { + updatePosition(editor); + break; + } + } + } + private void updatePosition(final Editor editor) { if (editor == null) { myText = ""; diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index 4c5b7664c7e0..6e02f908a4b7 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -66,4 +66,5 @@ org.jetbrains.memory.view 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8 0.0.9 0.0.10 com.jetbrains.intellij.api.watcher 5.0.0 5.1.0 5.2.0 5.3.0 5.4.0 com.jetbrains.performancePlugin 1.1 1.3 1.3.1 1.3.2 org.vuejs 1.1.0 1.0.1 1.0.0 -Vue.js 1.1.0 1.0.1 1.0.0 \ No newline at end of file +Vue.js 1.1.0 1.0.1 1.0.0 +com.intellij.resharper.unity 1.5.0.0 1.5.0.1 diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index b609625ace03..32f974feeb4e 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -15,6 +15,8 @@ --> + + @@ -574,6 +576,12 @@ + + + + + + @@ -700,7 +708,7 @@ - + diff --git a/platform/platform-resources/src/keymaps/$default.xml b/platform/platform-resources/src/keymaps/$default.xml index d3079c49d7e7..ca88b59a9742 100644 --- a/platform/platform-resources/src/keymaps/$default.xml +++ b/platform/platform-resources/src/keymaps/$default.xml @@ -1041,4 +1041,8 @@ + + + + \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java index 0a3a34b373f9..2c1bb57899fc 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java @@ -65,20 +65,13 @@ public abstract class SyntheticLibrary { * changed (use some caching in {@link AdditionalLibraryRootsProvider#getAdditionalProjectLibraries(Project)}). */ @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SyntheticLibrary library = (SyntheticLibrary)o; - return getSourceRoots().equals(library.getSourceRoots()); - } + public abstract boolean equals(Object o); /** * @see #equals(Object) javadoc */ @Override - public int hashCode() { - return getSourceRoots().hashCode(); - } + public abstract int hashCode(); @NotNull public static SyntheticLibrary newImmutableLibrary(@NotNull Collection sourceRoots) { @@ -88,6 +81,19 @@ public abstract class SyntheticLibrary { public Collection getSourceRoots() { return sourceRoots; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SyntheticLibrary library = (SyntheticLibrary)o; + return getSourceRoots().equals(library.getSourceRoots()); + } + + @Override + public int hashCode() { + return sourceRoots.hashCode(); + } }; } } diff --git a/platform/testFramework/extensions/src/com/intellij/keymap/KeymapsTestCase.java b/platform/testFramework/extensions/src/com/intellij/keymap/KeymapsTestCase.java index 5080c1ccae8f..a00dd7842a21 100644 --- a/platform/testFramework/extensions/src/com/intellij/keymap/KeymapsTestCase.java +++ b/platform/testFramework/extensions/src/com/intellij/keymap/KeymapsTestCase.java @@ -143,6 +143,7 @@ public abstract class KeymapsTestCase extends PlatformTestCase { { "control alt Z", "Vcs.RollbackChangedLines", "ChangesView.Revert"}, { "control TAB", "Switcher", "Diff.FocusOppositePane"}, { "shift control TAB", "Switcher", "Diff.FocusOppositePaneAndScroll"}, + { "ctrl alt ENTER", "EditorStartNewLineBefore", "QuickActionPopup"}, }); put("Mac OS X 10.5+", new String[][] { { "F5", "CopyElement", "Console.TableResult.Reload", "UML.ApplyCurrentLayout"}, diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 4f0f6b663bfd..4f3f67796613 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -1724,8 +1724,18 @@ public class UsageViewImpl implements UsageView { final JButton button = new JButton(UIUtil.replaceMnemonicAmpersand(text)); DialogUtil.registerMnemonic(button); - DumbService.getInstance(myProject).makeDumbAware(button, UsageViewImpl.this); - + getProject().getMessageBus().connect(UsageViewImpl.this).subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() { + @Override + public void enteredDumbMode() { + update(); + } + + @Override + public void exitDumbMode() { + update(); + } + }); + button.setFocusable(false); button.addActionListener(e -> runnable.run()); @@ -1742,7 +1752,7 @@ public class UsageViewImpl implements UsageView { Component component = getComponent(i); if (component instanceof JButton) { final JButton button = (JButton)component; - button.setEnabled(!isSearchInProgress()); + button.setEnabled(!isSearchInProgress() && !DumbService.isDumb(myProject)); } } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index fdec1029255a..dc2c3b25e0c8 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -3959,12 +3959,4 @@ public class UIUtil { } }); } - - /** - * @param key a key in UIDefaults table - * @return the property value from the specified component or {@code null} - */ - public static T getUIResource(@NotNull Object key, @NotNull Class type) { - return ObjectUtils.tryCast(UIManager.get(key), type); - } } diff --git a/plugins/InspectionGadgets/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/plugins/InspectionGadgets/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index adc7e76c69f4..fe7f1bdc5b57 100644 --- a/plugins/InspectionGadgets/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/plugins/InspectionGadgets/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -95,17 +95,20 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp ? ((PsiNewExpression)methodRefCandidate).getQualifier() : null; boolean safeQualifier = checkQualifier(qualifier); - ProblemHighlightType errorOrWarning; + ProblemHighlightType type; if (safeQualifier) { - errorOrWarning = ProblemHighlightType.GENERIC_ERROR_OR_WARNING; + type = ProblemHighlightType.GENERIC_ERROR_OR_WARNING; } else { if (!isOnTheFly) return; - errorOrWarning = ProblemHighlightType.INFORMATION; + type = ProblemHighlightType.INFORMATION; } - holder.registerProblem(InspectionProjectProfileManager.isInformationLevel(getShortName(), expression) ? expression : candidate, - "Can be replaced with method reference", - errorOrWarning, new ReplaceWithMethodRefFix(safeQualifier ? "" : " (may change semantics)")); + PsiElement element = InspectionProjectProfileManager.isInformationLevel(getShortName(), expression) ? expression : candidate; + holder.registerProblem(holder.getManager().createProblemDescriptor( + element, + "Can be replaced with method reference", + type != ProblemHighlightType.INFORMATION, + type, true, new ReplaceWithMethodRefFix(safeQualifier ? "" : " (may change semantics)"))); } } } diff --git a/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java b/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java index b26e8fae2209..88c4eefbb73a 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java +++ b/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java @@ -122,7 +122,7 @@ public class ShowCoveringTestsAction extends AnAction { }); } else { component = null; - final JPanel panel = new PanelWithText("Following test" + (testNames.length > 1 ? "s" : "") + " could not be found: " + StringUtil.join(testNames, ",").replace("_", ".")); + final JPanel panel = new PanelWithText("Following test" + (testNames.length > 1 ? "s" : "") + " could not be found: " + StringUtil.join(testNames, "
").replace("_", ".")); popupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, null); } final JBPopup popup = popupBuilder.setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE) diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 90afeef0b6c1..95ad637585cf 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -179,7 +179,6 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { } for (PsiClass aClass : classes) { - if (getClassCoverageInfo(aClass) == null) continue; topLevelNodes.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); } return topLevelNodes; diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java index 79d846ed3902..fc82b74c29ee 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java @@ -303,14 +303,14 @@ public class GitMergeProvider implements MergeProvider2 { return GitRevisionNumber.resolve(myProject, root, MERGE_HEAD); } catch (VcsException e) { - LOG.info("Couldn't resolve the MERGE_HEAD in " + root, e); // this may be not a bug, just cherry-pick + LOG.info("Couldn't resolve the MERGE_HEAD in " + root + ": " + e.getMessage()); // this may be not a bug, just cherry-pick } try { return GitRevisionNumber.resolve(myProject, root, CHERRY_PICK_HEAD); } catch (VcsException e) { - LOG.info("Couldn't resolve the CHERRY_PICK_HEAD in " + root, e); + LOG.info("Couldn't resolve the CHERRY_PICK_HEAD in " + root + ": " + e.getMessage()); } GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(root); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java index be59c6679fed..1c3b4680bf77 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java @@ -19,15 +19,15 @@ import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUt import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.xmlb.annotations.*; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.OptionTag; +import com.intellij.util.xmlb.annotations.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.data.BuildParticipant; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; /** * @author Denis Zhdanov @@ -41,38 +41,6 @@ public class GradleProjectSettings extends ExternalProjectSettings { private boolean disableWrapperSourceDistributionNotification; private boolean resolveModulePerSourceSet = true; @Nullable private CompositeBuild myCompositeBuild; - @Nullable private Set myNonCompositeModules = new HashSet<>(); - - @OptionTag("modules") - @Nullable - public Set getNonCompositeModules() { - Set modules = getModules(); - if (myCompositeBuild != null && !modules.isEmpty()) { - Set compositePaths = myCompositeBuild.getCompositeParticipants().stream() - .flatMap(participant -> participant.getProjects().stream()).collect(Collectors.toSet()); - return modules.stream().filter(m -> !compositePaths.contains(m)).collect(Collectors.toSet()); - } - else { - return myNonCompositeModules; - } - } - - public void setNonCompositeModules(@Nullable Set modules) { - myNonCompositeModules = modules; - } - - @Transient - @NotNull - @Override - public Set getModules() { - return super.getModules(); - } - - @Override - public void setModules(@Nullable Set modules) { - super.setModules(modules); - setNonCompositeModules(modules); - } @Nullable public String getGradleHome() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java index a9c06d017103..407ca581f356 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java @@ -21,7 +21,6 @@ import com.intellij.psi.*; import com.intellij.psi.impl.FakePsiElement; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FList; import groovy.lang.Closure; @@ -196,8 +195,8 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM PsiType[] argTypes = PsiUtil.getArgumentTypes(ref, false); if (argTypes == null) return; - String[] types = new String[argTypes.length]; - ContainerUtil.map(argTypes, (Function)type -> type.getCanonicalText(), types); + String[] types = + ContainerUtil.map(argTypes, PsiType::getCanonicalText, new String[argTypes.length]); generator.setDelegate(this); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java index 00dba6d4dbba..fe0ad8a746f9 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java @@ -20,7 +20,6 @@ import com.intellij.psi.impl.compiled.ClsMethodImpl; import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,8 +91,8 @@ public class ClosureDescriptor extends LightElement implements PsiElement { if (method instanceof ClsMethodImpl) method = ((ClsMethodImpl)method).getSourceMirrorMethod(); final PsiParameter[] parameters = method.getParameterList().getParameters(); - final PsiType[] typeArray = PsiType.createArray(parameters.length); - ContainerUtil.map(parameters, parameter -> parameter.getType(), typeArray); + final PsiType[] typeArray = + ContainerUtil.map(parameters, parameter -> parameter.getType(), PsiType.createArray(parameters.length)); return GrClosureSignatureUtil.isSignatureApplicable(closureSignature, typeArray, place); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java index 4c9bd920bfad..e421bf714c5d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java @@ -97,8 +97,7 @@ public class GrClosureSignatureUtil { public static GrClosureSignature createSignature(MethodSignature signature) { final PsiType[] types = signature.getParameterTypes(); - GrClosureParameter[] parameters = new GrClosureParameter[types.length]; - ContainerUtil.map(types, type -> new GrImmediateClosureParameterImpl(type, null, false, null), parameters); + GrClosureParameter[] parameters = ContainerUtil.map(types, type -> new GrImmediateClosureParameterImpl(type, null, false, null), new GrClosureParameter[types.length]); return new GrImmediateClosureSignatureImpl(parameters, null, false, false); } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java index 09cf96aca171..a3024f0d79ee 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -130,23 +130,18 @@ public class StudyProjectComponent implements ProjectComponent { private void registerShortcuts() { StudyToolWindow window = StudyUtils.getStudyToolWindow(myProject); if (window != null) { - List actionsOnToolbar = window.getActions(); - if (actionsOnToolbar != null) { - for (AnAction action : actionsOnToolbar) { - if (action instanceof StudyActionWithShortcut) { - String id = ((StudyActionWithShortcut)action).getActionId(); - String[] shortcuts = ((StudyActionWithShortcut)action).getShortcuts(); - if (shortcuts != null) { - addShortcut(id, shortcuts); - } + List actionsOnToolbar = window.getActions(true); + for (AnAction action : actionsOnToolbar) { + if (action instanceof StudyActionWithShortcut) { + String id = ((StudyActionWithShortcut)action).getActionId(); + String[] shortcuts = ((StudyActionWithShortcut)action).getShortcuts(); + if (shortcuts != null) { + addShortcut(id, shortcuts); } } - addShortcut(StudyNextWindowAction.ACTION_ID, new String[]{StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.SHORTCUT2}); - addShortcut(StudyPrevWindowAction.ACTION_ID, new String[]{StudyPrevWindowAction.SHORTCUT}); - } - else { - LOG.warn("Actions on toolbar are nulls"); } + addShortcut(StudyNextWindowAction.ACTION_ID, new String[]{StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.SHORTCUT2}); + addShortcut(StudyPrevWindowAction.ACTION_ID, new String[]{StudyPrevWindowAction.SHORTCUT}); } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java index 043bef13905e..b9e3debed96c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java @@ -501,7 +501,7 @@ public class StudyUtils { if (text == null) return null; text = convertToHtml(text); - if (course.isAdaptive() && !task.isChoiceTask()) text = wrapAdaptiveCourseText(text); + if (course.isAdaptive() && !task.isChoiceTask() && !task.isTheoryTask()) text = wrapAdaptiveCourseText(text); return wrapTextToDisplayLatex(text); } @@ -780,9 +780,9 @@ public class StudyUtils { return FileDocumentManager.getInstance().getDocument(taskFile); } - public static void showErrorPopupOnToolbar(@NotNull Project project) { + public static void showErrorPopupOnToolbar(@NotNull Project project, String content) { final Balloon balloon = - JBPopupFactory.getInstance().createHtmlTextBalloonBuilder("Couldn't post your reaction", MessageType.ERROR, null).createBalloon(); + JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(content, MessageType.ERROR, null).createBalloon(); showCheckPopUp(project, balloon); } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index b2ee1e17b4b3..e74bfdd19cd7 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -24,6 +24,7 @@ import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector; import com.jetbrains.edu.learning.stepic.EduStepicConnector; import com.jetbrains.edu.learning.stepic.StepicUpdateSettings; +import com.jetbrains.edu.learning.stepic.StepicUser; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -148,6 +149,23 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun final Pair result = EduAdaptiveStepicConnector.checkChoiceTask(myProject, myTask); processStepicCheckOutput(indicator, result); } + else if (myTask.isTheoryTask()) { + final int lessonId = myTask.getLesson().getId(); + final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final boolean reactionPosted = EduAdaptiveStepicConnector.postRecommendationReaction(String.valueOf(lessonId), + String.valueOf(user.getId()), + EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION); + if (reactionPosted) { + if (myStatusBeforeCheck != StudyStatus.Solved) { + myTask.setStatus(StudyStatus.Solved); + EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, indicator, EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION); + } + } + else { + ApplicationManager.getApplication().invokeLater(() -> + StudyUtils.showErrorPopupOnToolbar(myProject, "Unable to get next recommendation")); + } + } else { final StudyTestsOutputParser.TestsOutput testOutput = getTestOutput(indicator); if (testOutput != null) { @@ -169,7 +187,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun if (pair.getFirst()) { onTaskSolved("Congratulations! Remote tests passed."); if (myStatusBeforeCheck != StudyStatus.Solved) { - EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, indicator, 2); + EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, indicator, EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION); } } else { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/ChoiceParameters.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/AdaptiveTaskParameters.java similarity index 79% rename from python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/ChoiceParameters.java rename to python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/AdaptiveTaskParameters.java index 6f833e511278..cefcb18b1df9 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/ChoiceParameters.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/AdaptiveTaskParameters.java @@ -6,10 +6,11 @@ import com.google.gson.annotations.SerializedName; import java.util.ArrayList; import java.util.List; -public class ChoiceParameters { +public class AdaptiveTaskParameters { @Expose @SerializedName("choice_variants") private List myChoiceVariants = new ArrayList<>(); @Expose @SerializedName("is_multichoice") private boolean myIsMultipleChoice; @SerializedName("selected_variants") private List mySelectedVariants = new ArrayList<>(); + @Expose @SerializedName("is_theory_task") private boolean isTheoryTask = false; public List getSelectedVariants() { return mySelectedVariants; @@ -34,4 +35,12 @@ public class ChoiceParameters { public void setChoiceVariants(List choiceVariants) { myChoiceVariants = choiceVariants; } + + public boolean isTheoryTask() { + return isTheoryTask; + } + + public void setTheoryTask(boolean theoryTask) { + isTheoryTask = theoryTask; + } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Task.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Task.java index 6645209de07a..d2b794d743f0 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Task.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Task.java @@ -44,7 +44,7 @@ public class Task implements StudyItem { @Transient private Lesson myLesson; @Expose @SerializedName("update_date") private Date myUpdateDate; - @Expose @SerializedName("choice_parameters") private ChoiceParameters myChoiceParameters; + @Expose @SerializedName("choice_parameters") private AdaptiveTaskParameters myAdaptiveTaskParameters; private int myActiveSubtaskIndex = 0; @SerializedName("last_subtask_index") @Expose private int myLastSubtaskIndex = 0; @@ -57,7 +57,7 @@ public class Task implements StudyItem { public static Task createChoiceTask(@NotNull String name) { final Task task = new Task(name); - task.setChoiceParameters(new ChoiceParameters()); + task.setAdaptiveTaskParameters(new AdaptiveTaskParameters()); return task; } @@ -307,48 +307,59 @@ public class Task implements StudyItem { @Transient @NotNull public List getChoiceVariants() { - return myChoiceParameters.getChoiceVariants(); + return myAdaptiveTaskParameters.getChoiceVariants(); } @Transient public void setChoiceVariants(List choiceVariants) { - myChoiceParameters.setChoiceVariants(choiceVariants); + myAdaptiveTaskParameters.setChoiceVariants(choiceVariants); } @Transient public boolean isMultipleChoice() { - return myChoiceParameters.isMultipleChoice(); + return myAdaptiveTaskParameters.isMultipleChoice(); } @Transient public void setMultipleChoice(boolean multipleChoice) { - myChoiceParameters.setMultipleChoice(multipleChoice); + myAdaptiveTaskParameters.setMultipleChoice(multipleChoice); } @Transient public List getSelectedVariants() { - return myChoiceParameters.getSelectedVariants(); + return myAdaptiveTaskParameters.getSelectedVariants(); } @Transient public void setSelectedVariants(List selectedVariants) { - myChoiceParameters.setSelectedVariants(selectedVariants); + myAdaptiveTaskParameters.setSelectedVariants(selectedVariants); } public boolean isChoiceTask() { - return myChoiceParameters != null; + return myAdaptiveTaskParameters != null && !myAdaptiveTaskParameters.getChoiceVariants().isEmpty(); + } + + public boolean isTheoryTask() { + return myAdaptiveTaskParameters != null && myAdaptiveTaskParameters.isTheoryTask(); + } + + public void setTheoryTask(boolean isTheoryTask) { + if (myAdaptiveTaskParameters == null) { + myAdaptiveTaskParameters = new AdaptiveTaskParameters(); + } + myAdaptiveTaskParameters.setTheoryTask(isTheoryTask); } // used for serialization @SuppressWarnings("unused") - public ChoiceParameters getChoiceParameters() { - return myChoiceParameters; + public AdaptiveTaskParameters getAdaptiveTaskParameters() { + return myAdaptiveTaskParameters; } // used for serialization @SuppressWarnings("unused") - public void setChoiceParameters(ChoiceParameters choiceParameters) { - myChoiceParameters = choiceParameters; + public void setAdaptiveTaskParameters(AdaptiveTaskParameters adaptiveTaskParameters) { + myAdaptiveTaskParameters = adaptiveTaskParameters; } public void copyParametersOf(@NotNull Task task) { @@ -357,12 +368,14 @@ public class Task implements StudyItem { setText(task.getText()); getTestsText().clear(); setStatus(StudyStatus.Unchecked); - if (task.isChoiceTask()) { + setTheoryTask(task.isTheoryTask()); + if (task.isChoiceTask() || task.isTheoryTask()) { setChoiceVariants(task.getChoiceVariants()); setMultipleChoice(task.isMultipleChoice()); + setTheoryTask(task.isTheoryTask()); } else { - setChoiceParameters(null); + setAdaptiveTaskParameters(null); } final Map testsText = task.getTestsText(); for (String testName : testsText.keySet()) { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java index 0191176175be..649b5c7585ba 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java @@ -59,10 +59,14 @@ public class EduAdaptiveStepicConnector { public static final String PYTHON2 = "python2"; public static final String PYTHON3 = "python3"; public static final String PYCHARM_COMMENT = "# Posted from PyCharm Edu\n"; + public static final int NEXT_RECOMMENDATION_REACTION = 2; + public static final int TOO_HARD_RECOMMENDATION_REACTION = 0; + public static final int TOO_BORING_RECOMMENDATION_REACTION = -1; private static final Logger LOG = Logger.getInstance(EduAdaptiveStepicConnector.class); private static final int CONNECTION_TIMEOUT = 60 * 1000; private static final String CODE_TASK_TYPE = "code"; private static final String CHOICE_TYPE_TEXT = "choice"; + private static final String TEXT_STEP_TYPE = "text"; @Nullable public static Task getNextRecommendation(@NotNull Project project, @NotNull Course course) { @@ -104,7 +108,7 @@ public class EduAdaptiveStepicConnector { final StepicUser user = StepicUpdateSettings.getInstance().getUser(); postRecommendationReaction(lessonId, - String.valueOf(user.getId()), -1); + String.valueOf(user.getId()), TOO_BORING_RECOMMENDATION_REACTION); return getNextRecommendation(project, course); } else { @@ -151,9 +155,22 @@ public class EduAdaptiveStepicConnector { else if (stepType.startsWith(EduStepicConnector.PYCHARM_PREFIX)) { return EduStepicConnector.createTask(stepId); } + else if (stepType.equals(TEXT_STEP_TYPE)) { + return getTheoryTaskFromStep(name, step.block, stepId); + } return null; } + + private static Task getTheoryTaskFromStep(@NotNull String lessonName, @NotNull StepicWrappers.Step block, int stepId) { + final Task task = new Task(lessonName); + task.setStepId(stepId); + task.setText(block.text); + task.setTheoryTask(true); + + createMockTaskFile(task); + return task; + } private static Task getChoiceTaskFromStep(@NotNull String lessonName, @NotNull StepicWrappers.Step block, @@ -174,11 +191,11 @@ public class EduAdaptiveStepicConnector { } } - createMockTaskFileForChoiceProblem(task); + createMockTaskFile(task); return task; } - private static void createMockTaskFileForChoiceProblem(@NotNull Task task) { + private static void createMockTaskFile(@NotNull Task task) { final TaskFile taskFile = new TaskFile(); taskFile.text = "# you can experiment here, it won't be checked"; taskFile.name = "code"; @@ -289,7 +306,7 @@ public class EduAdaptiveStepicConnector { final Lesson adaptive = course.getLessons().get(0); final Task unsolvedTask = adaptive.getTaskList().get(adaptive.getTaskList().size() - 1); final String lessonName = EduNames.LESSON + String.valueOf(adaptive.getIndex()); - if (reaction == 0 || reaction == -1) { + if (reaction == TOO_HARD_RECOMMENDATION_REACTION || reaction == TOO_BORING_RECOMMENDATION_REACTION) { unsolvedTask.copyParametersOf(task); final Map taskFiles = task.getTaskFiles(); @@ -299,8 +316,7 @@ public class EduAdaptiveStepicConnector { ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().runWriteAction(() -> { final Document document = editor.getEditor().getDocument(); - final String taskFileText = taskFiles.get(EduStepicNames.DEFAULT_TASKFILE_NAME).text; - document.setText(taskFileText); + document.setText(taskFile.text); })); } else { @@ -315,7 +331,7 @@ public class EduAdaptiveStepicConnector { final VirtualFile lessonDir = project.getBaseDir().findChild(lessonName); if (lessonDir != null) { - createTestFiles(course, task, unsolvedTask, lessonDir); + createTestFiles(course, project, unsolvedTask, lessonDir); } final StudyToolWindow window = StudyUtils.getStudyToolWindow(project); if (window != null) { @@ -361,12 +377,12 @@ public class EduAdaptiveStepicConnector { } else { LOG.warn("Recommendation reactions weren't posted"); - ApplicationManager.getApplication().invokeLater(() -> StudyUtils.showErrorPopupOnToolbar(project)); + ApplicationManager.getApplication().invokeLater(() -> StudyUtils.showErrorPopupOnToolbar(project, "Couldn't post your reaction")); } } } - private static void createTestFiles(@NotNull Course course, @NotNull Task task, + private static void createTestFiles(@NotNull Course course, @NotNull Project project, @NotNull Task unsolvedTask, @NotNull VirtualFile lessonDir) { ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().runWriteAction(() -> { try { @@ -380,7 +396,7 @@ public class EduAdaptiveStepicConnector { if (filesInTask != null) { for (File file : filesInTask) { final String taskRelativePath = FileUtil.getRelativePath(taskDir.getPath(), file.getPath(), '/'); - if (taskRelativePath != null && !task.isTaskFile(taskRelativePath)) { + if (taskRelativePath != null && StudyUtils.isTestsFile(project, taskDir.getName())) { final File resourceFile = new File(newResourceRoot, taskRelativePath); final File fileInProject = new File(taskDir.getCanonicalPath(), taskRelativePath); FileUtil.copy(resourceFile, fileInProject); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java index f76bc589434b..ec6fde47a403 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java @@ -19,13 +19,14 @@ import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import static com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector.TOO_BORING_RECOMMENDATION_REACTION; +import static com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector.TOO_HARD_RECOMMENDATION_REACTION; + public class StepicAdaptiveReactionsPanel extends JPanel { private final ReactionButtonPanel myHardPanel; private final ReactionButtonPanel myBoringPanel; @NotNull private final Project myProject; - private static final int TOO_HARD_REACTION = 0; - private static final int TOO_BORING_REACTION = -1; private static final String HARD_REACTION = "Too Hard"; private static final String BORING_REACTION = "Too Boring"; private static final String SOLVED_TASK_TOOLTIP = "Reaction Disabled Due To Task Is Solved"; @@ -37,8 +38,8 @@ public class StepicAdaptiveReactionsPanel extends JPanel { setLayout(new GridBagLayout()); setBackground(UIUtil.getTextFieldBackground()); - myHardPanel = new ReactionButtonPanel(HARD_REACTION, HARD_LABEL_TOOLTIP, TOO_HARD_REACTION); - myBoringPanel = new ReactionButtonPanel(BORING_REACTION, BORING_LABEL_TOOLTIP, TOO_BORING_REACTION); + myHardPanel = new ReactionButtonPanel(HARD_REACTION, HARD_LABEL_TOOLTIP, TOO_HARD_RECOMMENDATION_REACTION); + myBoringPanel = new ReactionButtonPanel(BORING_REACTION, BORING_LABEL_TOOLTIP, TOO_BORING_RECOMMENDATION_REACTION); addFileListener(); final GridBagConstraints c = new GridBagConstraints(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java index 3cbc26a11b9b..dede22335891 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java @@ -149,8 +149,6 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D myCardLayout.swipe(myContentPanel, panelId, JBCardLayout.SwipeDirection.AUTO); } - //used in checkiO plugin. - @SuppressWarnings("unused") public void setBottomComponent(JComponent component) { mySplitPane.setSecondComponent(component); } diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInDocstringIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInDocstringIntention.java index 9ca526ef072e..fe40968f767b 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInDocstringIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInDocstringIntention.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.codeInsight.intentions; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -77,6 +78,17 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention { } } + @Override + public boolean startInWriteAction() { + return false; + } + + @Nullable + @Override + public PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) { + return currentFile; + } + private static void generateDocstring(@Nullable PyNamedParameter param, @NotNull PyFunction pyFunction) { if (!DocStringUtil.ensureNotPlainDocstringFormat(pyFunction)) { return; @@ -100,8 +112,10 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention { docstringGenerator.withReturnValue(type); } - docstringGenerator.addFirstEmptyLine().buildAndInsert(); - docstringGenerator.startTemplate(); + WriteAction.run(() -> { + docstringGenerator.addFirstEmptyLine().buildAndInsert(); + docstringGenerator.startTemplate(); + }); } @Override diff --git a/python/src/com/jetbrains/python/psi/impl/PyExpressionCodeFragmentImpl.java b/python/src/com/jetbrains/python/psi/impl/PyExpressionCodeFragmentImpl.java index 324fde700ddc..e0464cab6926 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyExpressionCodeFragmentImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyExpressionCodeFragmentImpl.java @@ -25,7 +25,6 @@ import com.intellij.psi.impl.file.impl.FileManager; import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.testFramework.LightVirtualFile; import com.jetbrains.python.psi.PyExpressionCodeFragment; -import com.jetbrains.python.psi.PyUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -66,12 +65,6 @@ public class PyExpressionCodeFragmentImpl extends PyFileImpl implements PyExpres return super.getViewProvider(); } - public boolean isValid() { - if (!super.isValid()) return false; - if (myContext != null && !myContext.isValid()) return false; - return true; - } - public boolean isPhysical() { return myPhysical; } diff --git a/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java b/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java index 01c6b653b0b3..82d07432841f 100644 --- a/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java +++ b/xml/impl/src/com/intellij/xml/config/ConfigFilesTreeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -108,7 +108,8 @@ public class ConfigFilesTreeBuilder { moduleNode.add(fileTypeNode); addChildrenFiles(psiFiles, fileTypeNode, new ArrayList<>(entry.getValue())); } - } else { + } + else { addChildrenFiles(psiFiles, moduleNode, moduleFiles); } } @@ -117,6 +118,7 @@ public class ConfigFilesTreeBuilder { List sortedJars = new ArrayList<>(jars.keySet()); Collections.sort(sortedJars, (o1, o2) -> StringUtil.naturalCompare(o1.getName(), o2.getName())); for (VirtualFile file : sortedJars) { + if (!file.isValid()) continue; final List list = new ArrayList<>(jars.get(file)); final PsiFile jar = list.get(0).getManager().findFile(file); if (jar != null) { @@ -133,7 +135,7 @@ public class ConfigFilesTreeBuilder { } private static String getFileTypeNodeName(FileType fileType) { - return fileType.getName() + " context files" ; + return fileType.getName() + " context files"; } private static boolean hasNonEmptyGroups(MultiMap filesByType) {