diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 7fd9dd0b191d..69d838f90ec5 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -8,9 +8,7 @@ message() { TITLE="Cannot start @@product_full@@" - if [ -t 1 ]; then - echo "ERROR: $TITLE\n$1" - elif [ -n `which zenity` ]; then + if [ -n `which zenity` ]; then zenity --error --title="$TITLE" --text="$1" elif [ -n `which kdialog` ]; then kdialog --error --title "$TITLE" "$1" @@ -35,13 +33,6 @@ RM=`which rm` CAT=`which cat` TR=`which tr` -#Disbale Jayatana on linux - -if [ -n "$JAVA_TOOL_OPTIONS" -a "$JAVA_TOOL_OPTIONS" != "${JAVA_TOOL_OPTIONS%-javaagent*jayatanaag.jar*"}" ] ; then - JAVA_TOOL_OPTIONS=${JAVA_TOOL_OPTIONS%-javaagent*jayatanaag.jar*}${JAVA_TOOL_OPTIONS#*jayatanaag.jar}; - message "Jayatana global menu integration is disabled."; -fi - if [ -z "$UNAME" -o -z "$GREP" -o -z "$CUT" -o -z "$MKTEMP" -o -z "$RM" -o -z "$CAT" -o -z "$TR" ]; then message "Required tools are missing - check beginning of \"$0\" file for details." exit 1 @@ -125,7 +116,7 @@ if [ -z "$JDK" ] || [ ! -x "$JAVA_BIN" ]; then fi VERSION_LOG=`"$MKTEMP" -t java.version.log.XXXXXX` -"$JAVA_BIN" -version 2> "$VERSION_LOG" +JAVA_TOOL_OPTIONS= "$JAVA_BIN" -version 2> "$VERSION_LOG" "$GREP" "64-Bit|x86_64|amd64" "$VERSION_LOG" > /dev/null BITS=$? "$RM" -f "$VERSION_LOG" @@ -162,8 +153,8 @@ fi VM_OPTIONS="" if [ -r "$vm_options_file" ]; then - VM_OPTIONS_DATA=`"$CAT" "$vm_options_file" | "$GREP" -v "^#.*" | "$TR" '\n' ' '` - VM_OPTIONS="$VM_OPTIONS $VM_OPTIONS_DATA" + VM_OPTIONS_DATA=`"$CAT" "$vm_options_file" | "$GREP" -v "^#.*" | "$TR" '\n' ' '` + VM_OPTIONS="$VM_OPTIONS $VM_OPTIONS_DATA" else message "Cannot find VM options file." fi @@ -184,6 +175,11 @@ if [ -n "$@@product_uc@@_CLASSPATH" ]; then CLASSPATH="$CLASSPATH:$@@product_uc@@_CLASSPATH" fi +if [ -n "$JAVA_TOOL_OPTIONS" -a "$JAVA_TOOL_OPTIONS" != "${JAVA_TOOL_OPTIONS%-javaagent*jayatanaag.jar*}" ] ; then + export _ORIGINAL_JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS" + JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS%-javaagent*jayatanaag.jar*}${JAVA_TOOL_OPTIONS#*jayatanaag.jar}" +fi + # --------------------------------------------------------------------- # Run the IDE. # --------------------------------------------------------------------- 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 4ce89c1e92ca..4c676204b47e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -286,7 +286,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project); if (forceIgnoreTypeCast) { - return (PsiExpression)javaCodeStyleManager.shortenClassReferences(elementFactory.createExpressionFromText(withoutTypesDeclared, lambdaExpression)); + return (PsiExpression)javaCodeStyleManager.shortenClassReferences(lambdaExpression); } PsiTypeCastExpression typeCast = (PsiTypeCastExpression)elementFactory diff --git a/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java b/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java index 82ca2917e069..7617bf72cde2 100644 --- a/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection; +import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -177,6 +178,8 @@ public class CollectionAddAllCanBeReplacedWithConstructorInspection extends Base public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiMethodCallExpression methodCallExpression = myMethodCallExpression.getElement(); LOG.assertTrue(methodCallExpression != null); + if (!CodeInsightUtil.preparePsiElementsForWrite(methodCallExpression.getContainingFile())) return; + final PsiElement parameter = methodCallExpression.getArgumentList().getExpressions()[0].copy(); final PsiNewExpression element = myAssignmentExpression.getElement(); LOG.assertTrue(element != null); diff --git a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java index 44796a744891..8c02aead1495 100644 --- a/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java +++ b/java/java-impl/src/com/intellij/codeInspection/java18StreamApi/PseudoLambdaReplaceTemplate.java @@ -33,7 +33,7 @@ import java.util.*; /** * @author Dmitry Batkovich */ -class PseudoLambdaReplaceTemplate { +public class PseudoLambdaReplaceTemplate { private final static Logger LOG = Logger.getInstance(PseudoLambdaReplaceTemplate.class); public enum LambdaRole { @@ -512,7 +512,7 @@ class PseudoLambdaReplaceTemplate { return expression; } - private static String createPipelineHeadText(PsiExpression collectionExpression, boolean force) { + public static PsiExpression replaceTypeParameters(PsiExpression collectionExpression) { if (collectionExpression instanceof PsiNewExpression) { final PsiDiamondType.DiamondInferenceResult diamondResolveResult = PsiDiamondTypeImpl.resolveInferredTypesNoCheck((PsiNewExpression)collectionExpression, collectionExpression); @@ -528,12 +528,16 @@ class PseudoLambdaReplaceTemplate { final PsiExpression copiedExpression = (PsiExpression) collectionExpression.copy(); final PsiType newType = copiedExpression.getType(); if (!currentType.equals(newType)) { - collectionExpression = AddTypeArgumentsFix.addTypeArguments(copiedExpression, currentType); - if (collectionExpression == null) { - return null; - } + final PsiExpression newExpression = AddTypeArgumentsFix.addTypeArguments(copiedExpression, currentType); + return newExpression == null ? collectionExpression : newExpression; } } + return collectionExpression; + } + + private static String createPipelineHeadText(PsiExpression collectionExpression, boolean force) { + collectionExpression = replaceTypeParameters(collectionExpression); + if (collectionExpression == null) return null; final PsiType type = collectionExpression.getType(); if (type instanceof PsiClassType) { final PsiClass resolved = ((PsiClassType)type).resolve(); diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java index 8bfaedcf6723..4379ef30114a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java @@ -31,8 +31,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class JavaSourceFilterScope extends DelegatingGlobalSearchScope { - private static final Logger LOG = Logger.getInstance(JavaSourceFilterScope.class); - @Nullable private final ProjectFileIndex myIndex; @@ -45,7 +43,6 @@ public class JavaSourceFilterScope extends DelegatingGlobalSearchScope { } else { myIndex = null; - LOG.error("delegate.getProject() == null, delegate.getClass() == " + delegate.getClass()); } } diff --git a/java/java-runtime/src/com/intellij/rt/execution/application/AppMain.java b/java/java-runtime/src/com/intellij/rt/execution/application/AppMain.java index ec26d7c5ae1e..5dbd883bc029 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/application/AppMain.java +++ b/java/java-runtime/src/com/intellij/rt/execution/application/AppMain.java @@ -135,6 +135,10 @@ public class AppMain { System.err.println("main method should be static"); return; } + if (!Void.class.isInstance(m.getReturnType())) { + System.err.println("main method must return a value of type void"); + return; + } try { ensureAccess(m); m.invoke(null, new Object[]{parms}); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllAnnotatorQuickfixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllAnnotatorQuickfixTest.java index baf6e8799462..f26f45f59104 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllAnnotatorQuickfixTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllAnnotatorQuickfixTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ */ package com.intellij.codeInsight.daemon.quickFix; +import com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitorBasedInspection; import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.DefaultHighlightVisitorBasedInspection; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.ide.highlighter.JavaHighlightingColors; @@ -31,7 +31,6 @@ import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java index 742b1d131b88..32fed469fecd 100644 --- a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java @@ -21,7 +21,6 @@ package com.intellij.psi; import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase; import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator; -import com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor; import com.intellij.codeInsight.daemon.impl.HighlightVisitor; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; import com.intellij.openapi.application.ApplicationManager; @@ -29,6 +28,7 @@ import com.intellij.openapi.application.Result; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; @@ -163,8 +163,10 @@ public class PsiConcurrencyStressTest extends DaemonAnalyzerTestCase { super.visitElement(element); final HighlightInfoHolder infoHolder = new HighlightInfoHolder(myFile); - final HighlightVisitor visitor = new DefaultHighlightVisitor(getProject()); - visitor.analyze(myFile, true, infoHolder, () -> visitor.visit(element)); + for (HighlightVisitor visitor : Extensions.getExtensions(HighlightVisitor.EP_HIGHLIGHT_VISITOR, getProject())) { + HighlightVisitor v = visitor.clone(); // to avoid race for com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.myAnnotationHolder + v.analyze(myFile, true, infoHolder, () -> v.visit(element)); + } } }); break; diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java index 914a17cb6bf0..ba4f9ec787bb 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java @@ -110,6 +110,14 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool { final PsiMethodCallExpression chain = findGuavaMethodChain(expression); + final PsiElement maybeLocalVariable = chain.getParent(); + if (maybeLocalVariable instanceof PsiLocalVariable) { + final PsiClass aClass = PsiUtil.resolveClassInType(chain.getType()); + if (aClass != null && GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(aClass.getQualifiedName())) { + return; + } + } + PsiClassType initialType = (PsiClassType)expression.getType(); LOG.assertTrue(initialType != null); PsiClass resolvedClass = initialType.resolve(); diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java index 8984ccc0f4a4..0db92643aaba 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java @@ -26,6 +26,8 @@ import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collection; import java.util.Map; /** @@ -93,12 +95,6 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule { } private boolean canConvert(PsiType from, PsiType to) { - if (from instanceof PsiEllipsisType) { - from = ((PsiEllipsisType)from).getComponentType(); - } - if (to instanceof PsiEllipsisType) { - to = ((PsiEllipsisType)to).getComponentType(); - } if (!(from instanceof PsiClassType)) { return false; } diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java new file mode 100644 index 000000000000..9566d0a997ad --- /dev/null +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java @@ -0,0 +1,161 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.typeMigration.rules.guava; + +import com.intellij.codeInspection.AnonymousCanBeLambdaInspection; +import com.intellij.codeInspection.java18StreamApi.StreamApiConstants; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.typeMigration.TypeConversionDescriptor; +import com.intellij.util.SmartList; +import com.siyeh.ipp.types.ReplaceMethodRefWithLambdaIntention; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Dmitry Batkovich + */ +public class FluentIterableConversionUtil { + private final static Logger LOG = Logger.getInstance(FluentIterableConversionUtil.class); + + @Nullable + static TypeConversionDescriptor getFilterDescriptor(PsiMethod method) { + LOG.assertTrue("filter".equals(method.getName())); + + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length != 1) return null; + final PsiParameter parameter = parameters[0]; + final PsiType type = parameter.getType(); + if (!(type instanceof PsiClassType)) return null; + final PsiClass resolvedClass = ((PsiClassType)type).resolve(); + if (resolvedClass == null) return null; + if (CommonClassNames.JAVA_LANG_CLASS.equals(resolvedClass.getQualifiedName())) { + return new GuavaFilterInstanceOfConversionDescriptor(); + } + else if (GuavaPredicateConversionRule.GUAVA_PREDICATE.equals(resolvedClass.getQualifiedName())) { + return new LambdaParametersTypeConversionDescriptor("$it$.filter($p$)", "$it$." + StreamApiConstants.FILTER + "($p$)"); + } + return null; + } + + static class TransformAndConcatConversionRule extends LambdaParametersTypeConversionDescriptor { + public TransformAndConcatConversionRule() { + super("$q$.transformAndConcat($params$)", "$q$.flatMap($params$)"); + } + + @Override + public PsiExpression replace(PsiExpression expression) { + PsiExpression argument = ((PsiMethodCallExpression)expression).getArgumentList().getExpressions()[0]; + + PsiAnonymousClass anonymousClass; + if (argument instanceof PsiNewExpression && + (anonymousClass = ((PsiNewExpression)argument).getAnonymousClass()) != null) { + if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, true)) { + argument = AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(argument, true, true); + }; + } + final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(expression.getProject()); + if (argument != null && !(argument instanceof PsiFunctionalExpression)) { + argument = + (PsiExpression)argument.replace(javaPsiFacade.getElementFactory().createExpressionFromText("(" + argument.getText() + ")::apply", null)); + } + + if (argument instanceof PsiMethodReferenceExpression) { + argument = ReplaceMethodRefWithLambdaIntention.convertMethodReferenceToLambda((PsiMethodReferenceExpression)argument); + } + if (argument instanceof PsiLambdaExpression) { + List> iterableReturnValues = new SmartList>(); + + final PsiElement body = ((PsiLambdaExpression)argument).getBody(); + final PsiClass collection = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_COLLECTION, expression.getResolveScope()); + if (collection == null) return expression; + final PsiClass iterable = javaPsiFacade.findClass(CommonClassNames.JAVA_LANG_ITERABLE, expression.getResolveScope()); + if (iterable == null) return expression; + + if (body instanceof PsiCodeBlock) { + for (PsiReturnStatement statement : PsiTreeUtil + .findChildrenOfType(body, PsiReturnStatement.class)) { + final PsiExpression retValue = statement.getReturnValue(); + if (!determineType(retValue, iterableReturnValues, iterable, collection)) { + return expression; + } + } + } else if (!(body instanceof PsiExpression) || !determineType((PsiExpression)body, iterableReturnValues, iterable, collection)) { + return expression; + } + + for (Pair returnValueAndIsCollection : iterableReturnValues) { + convertToStream(returnValueAndIsCollection.getFirst(), returnValueAndIsCollection.getSecond()); + } + + } else { + return expression; + } + + return super.replace(expression); + } + + private static boolean determineType(PsiExpression retValue, + List> iterableReturnValues, + PsiClass iterable, + PsiClass collection) { + if (retValue == null) return false; + final PsiType type = retValue.getType(); + if (PsiType.NULL.equals(type)) { + return true; + } + if (type instanceof PsiClassType) { + final PsiClass resolvedClass = ((PsiClassType)type).resolve(); + + if (InheritanceUtil.isInheritorOrSelf(resolvedClass, iterable, true)) { + final boolean isCollection = InheritanceUtil.isInheritorOrSelf(resolvedClass, collection, true); + iterableReturnValues.add(Pair.create(retValue, isCollection)); + return true; + } + } + return false; + } + + private static void convertToStream(@NotNull PsiExpression returnValue, boolean isCollection) { + String expressionAsText = isCollection + ? "(" + returnValue.getText() + ").stream()" + : "java.util.stream.StreamSupport.stream((" + returnValue.getText() + ").spliterator(), false)"; + returnValue.replace(JavaPsiFacade.getElementFactory(returnValue.getProject()).createExpressionFromText(expressionAsText, returnValue)); + } + } + + private static class GuavaFilterInstanceOfConversionDescriptor extends TypeConversionDescriptor { + public GuavaFilterInstanceOfConversionDescriptor() { + super("$it$.filter($p$)", "$it$." + StreamApiConstants.FILTER + "($p$)"); + } + + @Override + public PsiExpression replace(PsiExpression expression) { + final PsiExpression argument = ((PsiMethodCallExpression)expression).getArgumentList().getExpressions()[0]; + final PsiExpression newArgument = + JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText("(" + argument.getText() + ")::isInstance", argument); + argument.replace(newArgument); + return super.replace(expression); + } + } + + +} diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java index 386c6ebcfe6b..e644e9c834b4 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.typeMigration.rules.guava; +import com.intellij.codeInspection.java18StreamApi.PseudoLambdaReplaceTemplate; import com.intellij.codeInspection.java18StreamApi.StreamApiConstants; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.psi.*; @@ -62,7 +63,7 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu } public TypeConversionDescriptor create() { - return myWithLambdaParameter ? new LambdaParametersTypeConversionDescription(myStringToReplace, myReplaceByString) + return myWithLambdaParameter ? new LambdaParametersTypeConversionDescriptor(myStringToReplace, myReplaceByString) : new TypeConversionDescriptor(myStringToReplace, myReplaceByString); } @@ -74,20 +75,15 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu static { DESCRIPTORS_MAP.put("contains", new TypeConversionDescriptorFactory("$it$.contains($o$)", "$it$.anyMatch(e -> e != null && e.equals($o$))", false)); - DESCRIPTORS_MAP.put("from", new TypeConversionDescriptorFactory("FluentIterable.from($it$)", "$it$.stream()", false, true)); DESCRIPTORS_MAP.put("isEmpty", new TypeConversionDescriptorFactory("$q$.isEmpty()", "$q$.findAny().isPresent()", false)); DESCRIPTORS_MAP.put("skip", new TypeConversionDescriptorFactory("$q$.skip($p$)", "$q$.skip($p$)", false, true)); DESCRIPTORS_MAP.put("limit", new TypeConversionDescriptorFactory("$q$.limit($p$)", "$q$.limit($p$)", false, true)); DESCRIPTORS_MAP.put("first", new TypeConversionDescriptorFactory("$q$.first()", "$q$.findFirst()", false)); DESCRIPTORS_MAP.put("transform", new TypeConversionDescriptorFactory("$q$.transform($params$)", "$q$.map($params$)", true, true)); - //TODO support - //DESCRIPTORS_MAP.put("transformAndConcat", new TransformAndConcatDescriptorBase("$q$.transformAndConcat($params$)", "$q$.flatMap($params$)")); DESCRIPTORS_MAP.put("allMatch", new TypeConversionDescriptorFactory("$it$.allMatch($c$)", "$it$." + StreamApiConstants.ALL_MATCH + "($c$)", true)); DESCRIPTORS_MAP.put("anyMatch", new TypeConversionDescriptorFactory("$it$.anyMatch($c$)", "$it$." + StreamApiConstants.ANY_MATCH + "($c$)", true)); - //TODO add another filter processor - DESCRIPTORS_MAP.put("filter", new TypeConversionDescriptorFactory("$it$.filter($p$)", "$it$." + StreamApiConstants.FILTER + "($p$)", true, true)); DESCRIPTORS_MAP.put("first", new TypeConversionDescriptorFactory("$it$.first()", "$it$." + StreamApiConstants.FIND_FIRST + "()", false)); DESCRIPTORS_MAP.put("firstMatch", new TypeConversionDescriptorFactory("$it$.firstMatch($p$)", "$it$.filter($p$).findFirst()", true)); DESCRIPTORS_MAP.put("get", new TypeConversionDescriptorFactory("$it$.get($p$)", "$it$.collect(java.util.stream.Collectors.toList()).get($p$)", false)); @@ -113,21 +109,52 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu if (context instanceof PsiMethodCallExpression) { return buildCompoundDescriptor((PsiMethodCallExpression)context, to, labeler); } - final TypeConversionDescriptorFactory base = DESCRIPTORS_MAP.get(methodName); - if (base != null) { - final TypeConversionDescriptor descriptor = base.create(); - if (base.isChainedMethod()) { - descriptor.withConversionType(to); - } - return descriptor; - } - else { - return null; - } + + return getOneMethodDescriptor(methodName, method, to, context); } @Nullable - private static GuavaChainedConversionDescriptor buildCompoundDescriptor(PsiMethodCallExpression expression, + private TypeConversionDescriptorBase getOneMethodDescriptor(@NotNull String methodName, + @NotNull PsiMethod method, + @Nullable PsiType to, + @Nullable PsiExpression context) { + TypeConversionDescriptor descriptorBase = null; + boolean needSpecifyType = true; + if (methodName.equals("from")) { + descriptorBase = new TypeConversionDescriptor("FluentIterable.from($it$)", "$it$.stream()") { + @Override + public PsiExpression replace(PsiExpression expression) { + PseudoLambdaReplaceTemplate.replaceTypeParameters(((PsiMethodCallExpression) expression).getArgumentList().getExpressions()[0]); + return super.replace(expression); + } + }; + } else if (methodName.equals("filter")) { + descriptorBase = FluentIterableConversionUtil.getFilterDescriptor(method); + } + else if (methodName.equals("transformAndConcat")) { + descriptorBase = new FluentIterableConversionUtil.TransformAndConcatConversionRule(); + } + else { + final TypeConversionDescriptorFactory base = DESCRIPTORS_MAP.get(methodName); + if (base != null) { + final TypeConversionDescriptor descriptor = base.create(); + needSpecifyType = base.isChainedMethod(); + descriptorBase = descriptor; + } + } + if (descriptorBase != null) { + if (needSpecifyType && to != null) { + descriptorBase.withConversionType(to); + } + return descriptorBase; + } + return null; + } + + + + @Nullable + private GuavaChainedConversionDescriptor buildCompoundDescriptor(PsiMethodCallExpression expression, PsiType to, TypeMigrationLabeler labeler) { List methodDescriptors = new SmartList(); @@ -156,21 +183,15 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu if (containingClass == null) { break; } - TypeConversionDescriptorBase descriptor; + TypeConversionDescriptorBase descriptor = null; if (FLUENT_ITERABLE.equals(containingClass.getQualifiedName())) { - final TypeConversionDescriptorFactory descriptorFactory = DESCRIPTORS_MAP.get(methodName); - if (descriptorFactory == null) { - return null; - } - descriptor = descriptorFactory.create(); + descriptor = getOneMethodDescriptor(methodName, method, null, current); } else if (GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(containingClass.getQualifiedName())) { descriptor = optionalDescriptor.getValue().findConversion(null, null, method, current.getMethodExpression(), labeler); - if (descriptor == null) { - return null; - } - } else { - break; + } + if (descriptor == null) { + return null; } methodDescriptors.add(descriptor); final PsiExpression qualifier = current.getMethodExpression().getQualifierExpression(); diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java index 9363797e757d..3f5ae3013a95 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java @@ -45,11 +45,7 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { if ("or".equals(methodName)) { PsiMethodCallExpression methodCallExpression = null; if (context instanceof PsiMethodCallExpression) { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - if (parameters.length != 1) { - return null; - } - final PsiClass aClass = PsiTypesUtil.getPsiClass(parameters[0].getType()); + final PsiClass aClass = getParameterClass(method); if (aClass != null) { final String qName = aClass.getQualifiedName(); String pattern = @@ -63,11 +59,7 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { if (methodCallExpression == null) { return null; } - final PsiParameter[] parameters = method.getParameterList().getParameters(); - if (parameters.length != 1) { - return null; - } - final PsiClass aClass = PsiTypesUtil.getPsiClass(parameters[0].getType()); + final PsiClass aClass = getParameterClass(method); if (aClass != null) { final String qName = aClass.getQualifiedName(); if (GUAVA_OPTIONAL.equals(qName)) { @@ -79,13 +71,21 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { return descriptor; } String pattern = GuavaSupplierConversionRule.GUAVA_SUPPLIER.equals(qName) ? "$val$.orElseGet($other$)" : "$val$.orElse($other$)"; - return new LambdaParametersTypeConversionDescription("$val$.or($other$)", pattern); + return new LambdaParametersTypeConversionDescriptor("$val$.or($other$)", pattern); } return null; } return null; } + private PsiClass getParameterClass(PsiMethod method) { + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length != 1) { + return null; + } + return PsiTypesUtil.getPsiClass(parameters[0].getType()); + } + @Override protected void fillSimpleDescriptors(Map descriptorsMap) { descriptorsMap.put("absent", new TypeConversionDescriptor("Optional.absent()", "java.util.Optional.empty()") { diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java index 2b1c4a4032ca..f47ac3a4b38c 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java @@ -33,6 +33,8 @@ import java.util.Map; * @author Dmitry Batkovich */ public class GuavaPredicateConversionRule extends BaseGuavaTypeConversionRule { + public static final String GUAVA_PREDICATE = "com.google.common.base.Predicate"; + @Override protected void fillSimpleDescriptors(Map descriptorsMap) { descriptorsMap.put("apply", new TypeConversionDescriptor("$q$.apply($o$)", "$q$.test($o$)")); @@ -41,7 +43,7 @@ public class GuavaPredicateConversionRule extends BaseGuavaTypeConversionRule { @NotNull @Override public String ruleFromClass() { - return "com.google.common.base.Predicate"; + return GUAVA_PREDICATE; } @NotNull diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescriptor.java similarity index 90% rename from java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java rename to java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescriptor.java index c64472df85a3..586be0b84ea2 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescriptor.java @@ -24,15 +24,15 @@ import org.jetbrains.annotations.NonNls; /** * @author Dmitry Batkovich */ -public class LambdaParametersTypeConversionDescription extends TypeConversionDescriptor { - private static final Logger LOG = Logger.getInstance(LambdaParametersTypeConversionDescription.class); +public class LambdaParametersTypeConversionDescriptor extends TypeConversionDescriptor { + private static final Logger LOG = Logger.getInstance(LambdaParametersTypeConversionDescriptor.class); - public LambdaParametersTypeConversionDescription(@NonNls String stringToReplace, @NonNls String replaceByString) { + public LambdaParametersTypeConversionDescriptor(@NonNls String stringToReplace, @NonNls String replaceByString) { super(stringToReplace, replaceByString); } @Override - public final PsiExpression replace(PsiExpression expression) { + public PsiExpression replace(PsiExpression expression) { LOG.assertTrue(expression instanceof PsiMethodCallExpression); PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression; final PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); diff --git a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java index 886a3c356356..27b211eef5bf 100644 --- a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java +++ b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.impl.quickfix.VariableTypeFix; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.PathManager; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.typeMigration.inspections.GuavaInspection; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.PlatformTestUtil; @@ -26,6 +27,7 @@ import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import java.io.File; +import java.util.Arrays; /** * @author Dmitry Batkovich @@ -75,6 +77,45 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase { doTest(); } + public void testTransformAndConcat1() { + doTest(); + } + + public void testTransformAndConcat2() { + doTest(); + } + + public void testTransformAndConcat3() { + doTest(); + } + + public void testTransformAndConcat4() { + doTest(); + } + + public void testFilterIsInstance() { + doTest(); + } + + public void testInsertTypeParameter() { + doTest(); + } + + public void testDontShowFluentIterableChainQuickFix() { + doTestNoQuickFixes(GuavaInspection.MigrateFluentIterableChainQuickFix.class); + } + + private void doTestNoQuickFixes(final Class... quickFixesClasses) { + myFixture.configureByFile(getTestName(true) + ".java"); + myFixture.enableInspections(new GuavaInspection()); + myFixture.doHighlighting(); + for (IntentionAction action : myFixture.getAvailableIntentions()) { + if (PsiTreeUtil.instanceOf(action, quickFixesClasses)) { + fail("Quick fix is found for types " + Arrays.toString(quickFixesClasses)); + } + } + } + private void doTest() { myFixture.configureByFile(getTestName(true) + ".java"); myFixture.enableInspections(new GuavaInspection()); diff --git a/java/typeMigration/testData/inspections/guava/dontShowFluentIterableChainQuickFix.java b/java/typeMigration/testData/inspections/guava/dontShowFluentIterableChainQuickFix.java new file mode 100644 index 000000000000..fddfb23bf894 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/dontShowFluentIterableChainQuickFix.java @@ -0,0 +1,10 @@ +import com.google.common.collect.FluentIterable; +import java.util.ArrayList; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings).transform(String::trim); + System.out.println(it.size()); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/filterIsInstance.java b/java/typeMigration/testData/inspections/guava/filterIsInstance.java new file mode 100644 index 000000000000..f08d09fd2398 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/filterIsInstance.java @@ -0,0 +1,12 @@ +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings); + + int i = it.filter(String::isEmpty).filter(String.class).size(); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/filterIsInstance_after.java b/java/typeMigration/testData/inspections/guava/filterIsInstance_after.java new file mode 100644 index 000000000000..92ef7eed019e --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/filterIsInstance_after.java @@ -0,0 +1,12 @@ +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class A { + void c() { + ArrayList strings = new ArrayList(); + Stream it = strings.stream(); + + int i = it.filter(String::isEmpty).filter((String.class)::isInstance).collect(Collectors.toList()).size(); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/insertTypeParameter.java b/java/typeMigration/testData/inspections/guava/insertTypeParameter.java new file mode 100644 index 000000000000..97ac2c9dae48 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/insertTypeParameter.java @@ -0,0 +1,11 @@ +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; +import java.util.Collections; + +class A { + void c() { + FluentIterable it = FluentIterable.from(new ArrayList<>()); + int i = it.transformAndConcat(input -> Collections.emptyList()).size(); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/insertTypeParameter_after.java b/java/typeMigration/testData/inspections/guava/insertTypeParameter_after.java new file mode 100644 index 000000000000..4097e63b6df7 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/insertTypeParameter_after.java @@ -0,0 +1,11 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class A { + void c() { + Stream it = new ArrayList().stream(); + int i = it.flatMap(input -> (Collections.emptyList()).stream()).collect(Collectors.toList()).size(); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat1.java b/java/typeMigration/testData/inspections/guava/transformAndConcat1.java new file mode 100644 index 000000000000..3d56b52b163c --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat1.java @@ -0,0 +1,14 @@ +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; +import java.util.Collections; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings); + + int i = it.transformAndConcat(input -> Collections.emptyList()).size(); + + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat1_after.java b/java/typeMigration/testData/inspections/guava/transformAndConcat1_after.java new file mode 100644 index 000000000000..8b29d3f78355 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat1_after.java @@ -0,0 +1,14 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class A { + void c() { + ArrayList strings = new ArrayList(); + Stream it = strings.stream(); + + int i = it.flatMap(input -> (Collections.emptyList()).stream()).collect(Collectors.toList()).size(); + + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat2.java b/java/typeMigration/testData/inspections/guava/transformAndConcat2.java new file mode 100644 index 000000000000..4a575c5dacab --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat2.java @@ -0,0 +1,14 @@ +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; +import java.util.Collections; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings); + + int i = it.transformAndConcat(Collections::singletonList).size(); + + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat2_after.java b/java/typeMigration/testData/inspections/guava/transformAndConcat2_after.java new file mode 100644 index 000000000000..411f43ed2352 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat2_after.java @@ -0,0 +1,14 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class A { + void c() { + ArrayList strings = new ArrayList(); + Stream it = strings.stream(); + + int i = it.flatMap((t) -> (Collections.singletonList(t)).stream()).collect(Collectors.toList()).size(); + + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat3.java b/java/typeMigration/testData/inspections/guava/transformAndConcat3.java new file mode 100644 index 000000000000..ce7c23edbfd8 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat3.java @@ -0,0 +1,30 @@ +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings); + + int i = it.transformAndConcat(new Function>() { + @Override + public Iterable apply(String o) { + if ('a' > 2) { + return getIterable(); + } else if ('c' < 123) { + ArrayList strings1 = new ArrayList<>(); + strings1.add(o); + return strings1; + } + return null; + } + }).size(); + + } + + Iterable getIterable() { + return null; + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat3_after.java b/java/typeMigration/testData/inspections/guava/transformAndConcat3_after.java new file mode 100644 index 000000000000..f568b60c63a8 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat3_after.java @@ -0,0 +1,27 @@ +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +class A { + void c() { + ArrayList strings = new ArrayList(); + Stream it = strings.stream(); + + int i = it.flatMap(o -> { + if ('a' > 2) { + return StreamSupport.stream((getIterable()).spliterator(), false); + } else if ('c' < 123) { + ArrayList strings1 = new ArrayList<>(); + strings1.add(o); + return (strings1).stream(); + } + return null; + }).collect(Collectors.toList()).size(); + + } + + Iterable getIterable() { + return null; + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat4.java b/java/typeMigration/testData/inspections/guava/transformAndConcat4.java new file mode 100644 index 000000000000..d5ca2c3fda4c --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat4.java @@ -0,0 +1,19 @@ +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; + +import java.util.ArrayList; +import java.util.List; + +class A { + void c() { + ArrayList strings = new ArrayList(); + FluentIterable it = FluentIterable.from(strings); + + int i = it.transformAndConcat(getFunction()).size(); + } + + Function> getFunction() { + return null; + } + +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/transformAndConcat4_after.java b/java/typeMigration/testData/inspections/guava/transformAndConcat4_after.java new file mode 100644 index 000000000000..9b6926d69c8d --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/transformAndConcat4_after.java @@ -0,0 +1,20 @@ +import com.google.common.base.Function; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class A { + void c() { + ArrayList strings = new ArrayList(); + Stream it = strings.stream(); + + int i = it.flatMap((f) -> ((getFunction()).apply(f)).stream()).collect(Collectors.toList()).size(); + } + + Function> getFunction() { + return null; + } + +} \ No newline at end of file diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CachedAnnotators.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CachedAnnotators.java new file mode 100644 index 000000000000..e293eb1e7a8c --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CachedAnnotators.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.daemon.impl; + +import com.intellij.lang.Language; +import com.intellij.lang.LanguageAnnotators; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.extensions.ExtensionPointListener; +import com.intellij.openapi.extensions.PluginDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +public class CachedAnnotators { + private final ThreadLocalAnnotatorMap cachedAnnotators = new ThreadLocalAnnotatorMap() { + @NotNull + @Override + public Collection initialValue(@NotNull String languageId) { + Language language = Language.findLanguageByID(languageId); + return language == null ? ContainerUtil.emptyList() : LanguageAnnotators.INSTANCE.allForLanguage(language); + } + }; + + public CachedAnnotators(Project project) { + ExtensionPointListener listener = new ExtensionPointListener() { + @Override + public void extensionAdded(@NotNull Annotator extension, @Nullable PluginDescriptor pluginDescriptor) { + cachedAnnotators.clear(); + } + + @Override + public void extensionRemoved(@NotNull Annotator extension, @Nullable PluginDescriptor pluginDescriptor) { + cachedAnnotators.clear(); + } + }; + LanguageAnnotators.INSTANCE.addListener(listener, project); + } + + @NotNull + List get(@NotNull String languageId) { + return cachedAnnotators.get(languageId); + } +} diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java index a595477698ee..8bb3fa173c79 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java @@ -19,14 +19,10 @@ package com.intellij.codeInsight.daemon.impl; import com.intellij.codeInsight.daemon.impl.analysis.ErrorQuickFixProvider; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; import com.intellij.codeInsight.highlighting.HighlightErrorFilter; -import com.intellij.lang.Language; -import com.intellij.lang.LanguageAnnotators; import com.intellij.lang.LanguageUtil; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.Annotator; -import com.intellij.openapi.extensions.ExtensionPointListener; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; @@ -37,17 +33,14 @@ import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.List; /** * @author yole */ -public class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { +class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { private AnnotationHolderImpl myAnnotationHolder; private final HighlightErrorFilter[] myErrorFilters; @@ -57,15 +50,18 @@ public class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { private final DumbService myDumbService; private HighlightInfoHolder myHolder; private final boolean myBatchMode; + private final CachedAnnotators cachedAnnotators; @SuppressWarnings("UnusedDeclaration") - public DefaultHighlightVisitor(@NotNull Project project) { - this(project, true, true, false); + DefaultHighlightVisitor(@NotNull Project project, @NotNull CachedAnnotators cachedAnnotators) { + this(project, true, true, false, cachedAnnotators); } - public DefaultHighlightVisitor(@NotNull Project project, boolean highlightErrorElements, boolean runAnnotators, boolean batchMode) { + + DefaultHighlightVisitor(@NotNull Project project, boolean highlightErrorElements, boolean runAnnotators, boolean batchMode, @NotNull CachedAnnotators cachedAnnotators) { myProject = project; myHighlightErrorElements = highlightErrorElements; myRunAnnotators = runAnnotators; + this.cachedAnnotators = cachedAnnotators; myErrorFilters = Extensions.getExtensions(HighlightErrorFilter.EP_NAME, project); myDumbService = DumbService.getInstance(project); myBatchMode = batchMode; @@ -114,7 +110,7 @@ public class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { @Override @NotNull public HighlightVisitor clone() { - return new DefaultHighlightVisitor(myProject, myHighlightErrorElements, myRunAnnotators, myBatchMode); + return new DefaultHighlightVisitor(myProject, myHighlightErrorElements, myRunAnnotators, myBatchMode,cachedAnnotators); } @Override @@ -122,29 +118,6 @@ public class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { return 2; } - private static final ThreadLocalAnnotatorMap cachedAnnotators = new ThreadLocalAnnotatorMap() { - @NotNull - @Override - public Collection initialValue(@NotNull String languageId) { - Language language = Language.findLanguageByID(languageId); - return language == null ? ContainerUtil.emptyList() : LanguageAnnotators.INSTANCE.allForLanguage(language); - } - }; - - static { - LanguageAnnotators.INSTANCE.addListener(new ExtensionPointListener() { - @Override - public void extensionAdded(@NotNull Annotator extension, @Nullable PluginDescriptor pluginDescriptor) { - cachedAnnotators.clear(); - } - - @Override - public void extensionRemoved(@NotNull Annotator extension, @Nullable PluginDescriptor pluginDescriptor) { - cachedAnnotators.clear(); - } - }); - } - private void runAnnotators(PsiElement element) { List annotators = cachedAnnotators.get(element.getLanguage().getID()); if (annotators.isEmpty()) return; diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/DefaultHighlightVisitorBasedInspection.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitorBasedInspection.java similarity index 93% rename from platform/analysis-impl/src/com/intellij/codeInspection/DefaultHighlightVisitorBasedInspection.java rename to platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitorBasedInspection.java index 39c59a853474..117fedbb3e54 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/DefaultHighlightVisitorBasedInspection.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitorBasedInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.intellij.codeInspection; +package com.intellij.codeInsight.daemon.impl; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeHighlighting.TextEditorHighlightingPass; -import com.intellij.codeInsight.daemon.impl.*; +import com.intellij.codeInspection.*; import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; @@ -174,7 +175,10 @@ public abstract class DefaultHighlightVisitorBasedInspection extends GlobalSimpl @Override public HighlightVisitor[] produce() { gpass.incVisitorUsageCount(1); - return new HighlightVisitor[]{new DefaultHighlightVisitor(project, highlightErrorElements, runAnnotators, true)}; + + HighlightVisitor visitor = new DefaultHighlightVisitor(project, highlightErrorElements, runAnnotators, true, + ServiceManager.getService(project, CachedAnnotators.class)); + return new HighlightVisitor[]{visitor}; } }); } diff --git a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java index ac908d25aa64..bb7294a96182 100644 --- a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java +++ b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ package com.intellij.openapi.util; import com.intellij.diagnostic.PluginException; +import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.*; import com.intellij.openapi.progress.ProcessCanceledException; @@ -230,6 +231,15 @@ public class KeyedExtensionCollector { public void addListener(@NotNull ExtensionPointListener listener) { myListeners.add(listener); } + public void addListener(@NotNull final ExtensionPointListener listener, @NotNull Disposable parent) { + myListeners.add(listener); + Disposer.register(parent, new Disposable() { + @Override + public void dispose() { + myListeners.remove(listener); + } + }); + } public void removeListener(@NotNull ExtensionPointListener listener) { myListeners.remove(listener); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java index d6f17ad5e02d..34219d86f959 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java @@ -66,10 +66,12 @@ public class NaturalLanguageTextSelectioner extends ExtendWordSelectionHandlerBa return new TextRange(prev, next + 1); } + @Nullable private static TextRange findSentenceRange(String editorText, int start, int end) { int sentenceStart = start; while (sentenceStart > 0) { + if (start - sentenceStart > 1000) return null; if (isSentenceEnd(editorText, sentenceStart - 1) || !isNatural(editorText.charAt(sentenceStart - 1))) { break; } @@ -83,6 +85,7 @@ public class NaturalLanguageTextSelectioner extends ExtendWordSelectionHandlerBa while (sentenceEnd < editorText.length()) { sentenceEnd++; + if (sentenceEnd - end > 1000) return null; if (isSentenceEnd(editorText, sentenceEnd - 1)) { break; } @@ -145,6 +148,8 @@ public class NaturalLanguageTextSelectioner extends ExtendWordSelectionHandlerBa int end = selEnd - shift; TextRange best = findSentenceRange(elementText, start, end); + if (best == null) return null; + best = narrowRange(best, findCustomRange(elementText, start, end, '\"', '\"')); best = narrowRange(best, findCustomRange(elementText, start, end, '(', ')')); best = narrowRange(best, findCustomRange(elementText, start, end, '<', '>')); diff --git a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/WebProjectSettingsStepWrapper.java b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/WebProjectSettingsStepWrapper.java index ee4c81d824fd..460507dde64a 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/WebProjectSettingsStepWrapper.java +++ b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/WebProjectSettingsStepWrapper.java @@ -15,15 +15,12 @@ */ package com.intellij.ide.util.projectWizard; -import com.intellij.ide.util.projectWizard.SettingsStep; -import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.util.Pair; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import sun.reflect.generics.reflectiveObjects.NotImplementedException; import javax.swing.*; import java.util.List; @@ -66,12 +63,12 @@ public class WebProjectSettingsStepWrapper implements SettingsStep { @Override public void addExpertPanel(@NotNull JComponent panel) { - throw new NotImplementedException(); + throw new UnsupportedOperationException(); } @Override public void addExpertField(@NotNull String label, @NotNull JComponent field) { - throw new NotImplementedException(); + throw new UnsupportedOperationException(); } @Override diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/FileTypeUsagesCollector.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/FileTypeUsagesCollector.java index b2eac02b3541..731134a66cba 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/FileTypeUsagesCollector.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/FileTypeUsagesCollector.java @@ -21,14 +21,19 @@ import com.intellij.internal.statistic.beans.GroupDescriptor; import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.FileTypeIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.NotNullFunction; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileBasedIndex; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.io.File; +import java.io.FilenameFilter; import java.util.HashSet; import java.util.Set; @@ -58,8 +63,7 @@ public class FileTypeUsagesCollector extends AbstractApplicationUsagesCollector if (project.isDisposed()) { throw new CollectUsagesException("Project is disposed"); } - VirtualFile ideaDir = project.getBaseDir().findChild(Project.DIRECTORY_STORE_FOLDER); - final String ideaDirPath = ideaDir == null ? null : ideaDir.getPath(); + final String ideaDirPath = getIdeaDirPath(project.getBasePath()); ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { @@ -71,7 +75,7 @@ public class FileTypeUsagesCollector extends AbstractApplicationUsagesCollector @Override public boolean process(VirtualFile file, Void value) { //skip files from .idea directory otherwise 99% of projects would have XML and PLAIN_TEXT file types - if (ideaDirPath == null || !file.getPath().startsWith(ideaDirPath)) { + if (ideaDirPath == null || FileUtil.isAncestorThreeState(ideaDirPath, file.getPath(), true) == ThreeState.NO) { usedFileTypes.add(fileType); return false; } @@ -89,4 +93,21 @@ public class FileTypeUsagesCollector extends AbstractApplicationUsagesCollector } }); } + + @Nullable + private static String getIdeaDirPath(@Nullable String projectPath) { + if (projectPath != null) { + File projectDir = new File(projectPath); + File[] ideaDirs = projectDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return Project.DIRECTORY_STORE_FOLDER.equals(name); + } + }); + if (ideaDirs.length == 1) { + return ideaDirs[0].getPath(); + } + } + return null; + } } diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java index 8ef1392c5c95..4d2bf48e62b5 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.EnvironmentUtil; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -79,7 +80,7 @@ public class PathEnvironmentVariableUtil { @Nullable private static File findInPath(@NotNull String fileBaseName, boolean logDetails, @Nullable FileFilter filter) { List exeFiles = findExeFilesInPath(fileBaseName, true, logDetails, filter); - return exeFiles.size() > 0 ? exeFiles.get(0) : null; + return ContainerUtil.getFirstItem(exeFiles); } /** @@ -91,15 +92,9 @@ public class PathEnvironmentVariableUtil { * @return {@link File} instance or null if not found */ private static File findInOriginalPath(@NotNull String fileBaseName) { - String originalPath; - if (SystemInfo.isMac) { - originalPath = System.getenv(PATH_ENV_VAR_NAME); - } - else { - originalPath = EnvironmentUtil.getValue(PATH_ENV_VAR_NAME); - } + String originalPath = System.getenv(PATH_ENV_VAR_NAME); List exeFiles = doFindExeFilesInPath(originalPath, fileBaseName, true, false, null); - return exeFiles.size() > 0 ? exeFiles.get(0) : null; + return ContainerUtil.getFirstItem(exeFiles); } /** @@ -165,17 +160,34 @@ public class PathEnvironmentVariableUtil { } /** - * Finds the absolute path of an executable file in PATH by the given relative path. - * This method makes sense for Mac only, because other OSs pass correct environment variables to IDE process - * letting {@link ProcessBuilder#start} sees correct PATH environment variable. + * Alters the passed in exe path to increase probability of exe file success finding when + * spawning an external process. Modifications are performed iff the passed in exe path is + * a basename (i.e. it doesn't contain slashes). E.g. "java", "git" or "node". + *

+ * The motivation behind this modification is as follows. When exe path is a basename, + * {@link ProcessBuilder#start} searches for the executable file in the original PATH + * environment variable (i.e. {@code System.getenv("PATH")}). + * The problem is that on MacOSX original PATH value can be different than the PATH + * value in Terminal (see {@link EnvironmentUtil#getEnvironmentMap()}. * - * @param exePath String relative path (or just a base name) - * @return the absolute path if the executable file found, and the given {@code exePath} otherwise + * @param exePath String path to exe file (basename, relative path or absolute path) + * @return if an exe file can be found in {@code EnvironmentUtil.getValue("PATH")} and + * nothing found in original PATH (i.e. {@code System.getenv("PATH")}), + * return the found exe file absolute path. + * Otherwise, return the passed in exe path. */ @NotNull + public static String toLocatableExePath(@NotNull String exePath) { + //noinspection deprecation + return findAbsolutePathOnMac(exePath); + } + + /** + * @deprecated use {@link #toLocatableExePath(String)} instead + */ public static String findAbsolutePathOnMac(@NotNull String exePath) { if (SystemInfo.isMac) { - if (!exePath.contains(File.separator)) { + if (!StringUtil.containsChar(exePath, '/') && !StringUtil.containsChar(exePath, '\\')) { File originalResolvedExeFile = findInOriginalPath(exePath); // don't modify exePath if the absolute path can be found in the original PATH if (originalResolvedExeFile == null) { diff --git a/platform/platform-api/src/com/intellij/ui/ScrollingUtil.java b/platform/platform-api/src/com/intellij/ui/ScrollingUtil.java index 93cf6554ac7f..ad44f8b77e1d 100644 --- a/platform/platform-api/src/com/intellij/ui/ScrollingUtil.java +++ b/platform/platform-api/src/com/intellij/ui/ScrollingUtil.java @@ -16,7 +16,10 @@ package com.intellij.ui; import com.intellij.ide.ui.UISettings; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonShortcuts; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.actionSystem.ShortcutSet; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.util.Couple; @@ -354,7 +357,7 @@ public class ScrollingUtil { UIUtil.maybeInstall(map, MOVE_END_ID, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)); } - public static abstract class ListScrollAction extends AnAction { + public static abstract class ListScrollAction extends DumbAwareAction { protected ListScrollAction(final ShortcutSet shortcutSet, final JComponent component) { registerCustomShortcutSet(shortcutSet, component); } diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java index 91fa29177d8c..9c23f46a9b0d 100644 --- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java +++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java @@ -69,6 +69,7 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter { public void initComponent() { checkJvm(); checkIBus(); + checkJAyatana(); startDiskSpaceMonitoring(); } @@ -99,6 +100,16 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter { } } + @SuppressWarnings("SpellCheckingInspection") + private void checkJAyatana() { + if (SystemInfo.isXWindow) { + String originalOpts = System.getenv("_ORIGINAL_JAVA_TOOL_OPTIONS"); + if (originalOpts != null && originalOpts.contains("jayatanaag.jar")) { + showNotification("ayatana.menu.warn.message"); + } + } + } + private void showNotification(@PropertyKey(resourceBundle = "messages.IdeBundle") String key) { final String ignoreKey = "ignore." + key; if (myProperties.isValueSet(ignoreKey)) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessPanel.java b/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessPanel.java index 1b590106a31b..8f71bb62b018 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessPanel.java @@ -30,6 +30,7 @@ import javax.swing.event.ChangeListener; final class ColorBlindnessPanel extends JPanel implements ChangeListener { private final JCheckBox myCheckBox = new JCheckBox(); private final JComboBox myComboBox = new ComboBox(); + private ColorBlindness myBlindness; public ColorBlindnessPanel() { super(new HorizontalLayout(JBUI.scale(10))); @@ -58,6 +59,9 @@ final class ColorBlindnessPanel extends JPanel implements ChangeListener { public ColorBlindness getColorBlindness() { if (myCheckBox.isSelected()) { + if (myBlindness != null) { + return myBlindness; + } Object object = myComboBox.getSelectedItem(); if (object instanceof Item) { Item item = (Item)object; @@ -68,8 +72,10 @@ final class ColorBlindnessPanel extends JPanel implements ChangeListener { } public void setColorBlindness(ColorBlindness blindness) { + // invisible combobox should not be used to store values + myBlindness = myComboBox.isVisible() ? null : blindness; Item item = null; - if (blindness != null) { + if (myBlindness == null && blindness != null) { int count = myComboBox.getItemCount(); for (int i = 0; i < count && item == null; i++) { Object object = myComboBox.getItemAt(i); @@ -81,7 +87,7 @@ final class ColorBlindnessPanel extends JPanel implements ChangeListener { } } } - myCheckBox.setSelected(item != null); + myCheckBox.setSelected(myBlindness != null || item != null); if (item != null) { myComboBox.setSelectedItem(item); } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java index cebbc42aa245..70b879b14233 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java @@ -342,22 +342,16 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border { if (hasFocus) { g.clipRect(JBUI.scale(2), JBUI.scale(2), comboBox.getWidth()- JBUI.scale(4), comboBox.getHeight() - JBUI.scale(4)); } - if (editor != null && comboBox.isEditable()) { - ((JComponent)editor).setBorder(null); - g.setColor(editor.getBackground()); - g.fillRoundRect(x + JBUI.scale(1), y + JBUI.scale(1), W, H, R, R); - g.setColor(getArrowButtonFillColor(arrowButton.getBackground())); - g.fillRoundRect(xxx, y + JBUI.scale(1), width - xxx, H, R, R); - g.setColor(editor.getBackground()); - g.fillRect(xxx, y + JBUI.scale(1), JBUI.scale(5), H); - } else { - g.setColor(UIUtil.getPanelBackground()); - g.fillRoundRect(x + JBUI.scale(1), y + JBUI.scale(1), W, H, R, R); - g.setColor(getArrowButtonFillColor(arrowButton.getBackground())); - g.fillRoundRect(xxx, y + JBUI.scale(1), width - xxx, H, R, R); - g.setColor(UIUtil.getPanelBackground()); - g.fillRect(xxx, y + JBUI.scale(1), JBUI.scale(5), H); - } + final Color background = editor != null && comboBox.isEditable() + ? editor.getBackground() + : UIUtil.getPanelBackground(); + g.setColor(background); + g.fillRoundRect(x + JBUI.scale(1), y + JBUI.scale(1), W, H, R, R); + g.setColor(getArrowButtonFillColor(arrowButton.getBackground())); + g.fillRoundRect(xxx, y + JBUI.scale(1), width - xxx, H, R, R); + g.setColor(background); + g.fillRect(xxx, y + JBUI.scale(1), JBUI.scale(5), H); + final Color borderColor = getBorderColor();//ColorUtil.shift(UIUtil.getBorderColor(), 4); g.setColor(getArrowButtonFillColor(borderColor)); int off = hasFocus ? 1 : 0; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index 7e5f99c602c9..2a68653c0711 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -22,6 +22,7 @@ import com.intellij.ide.ui.UISettingsListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; import gnu.trove.TIntHashSet; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NonNls; @@ -51,6 +52,16 @@ public class ComplementaryFontsRegistry { private static final String[] BOLD_ITALIC_NAMES = {"bolditalic", "bold-italic", "bold italic", "boldoblique", "bold-oblique", "bold oblique", "demibold italic", "negreta cursiva","demi oblique"}; + // Explicit mapping fontName->style for cases where generic rules (given above) don't work. + private static final Map FONT_NAME_TO_STYLE = new HashMap(); + static { + FONT_NAME_TO_STYLE.put("AnkaCoder-b", Font.BOLD); + FONT_NAME_TO_STYLE.put("AnkaCoder-i", Font.ITALIC); + FONT_NAME_TO_STYLE.put("AnkaCoder-bi", Font.BOLD | Font.ITALIC); + FONT_NAME_TO_STYLE.put("SourceCodePro-It", Font.ITALIC); + FONT_NAME_TO_STYLE.put("SourceCodePro-BoldIt", Font.BOLD | Font.ITALIC); + } + static { final UISettings settings = UISettings.getInstance(); ourOldUseAntialiasing = !AntialiasingType.OFF.equals(settings.EDITOR_AA_TYPE); @@ -111,7 +122,7 @@ public class ComplementaryFontsRegistry { if (ApplicationManager.getApplication().isUnitTestMode()) { ourFontNames.add("Monospaced"); } else { - if (Patches.JDK_MAC_FONT_STYLE_BUG) { + if (Patches.JDK_MAC_FONT_STYLE_DETECTION_WORKAROUND) { fillStyledFontMap(); } String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); @@ -128,7 +139,14 @@ public class ComplementaryFontsRegistry { Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for (Font font : allFonts) { String name = font.getName(); - int style = getFontStyle(name); + Integer style = null; + if (!SystemInfo.isAppleJvm) { + style = FONT_NAME_TO_STYLE.get(name); // workaround with explicit fontName->style mapping doesn't work on Apple JVM + } + if (style == null) { + if (!Patches.JDK_MAC_FONT_STYLE_BUG) continue; + style = getFontStyle(name); + } if (style != Font.PLAIN) { String familyName = font.getFamily(); Pair[] entry = ourStyledFontMap.get(familyName); @@ -199,7 +217,7 @@ public class ComplementaryFontsRegistry { @Nullable private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) { synchronized (lock) { - if (Patches.JDK_MAC_FONT_STYLE_BUG && style > 0 && style < 4) { + if (Patches.JDK_MAC_FONT_STYLE_DETECTION_WORKAROUND && style > 0 && style < 4) { Pair[] replacement = ourStyledFontMap.get(defaultFontFamily); if (replacement != null) { defaultFontFamily = replacement[style].first; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java index d5ed2640367a..337ecfd223ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java @@ -203,7 +203,7 @@ public class ActionsTree { reset(myKeymap, currentQuickListIds, filter, null); } - private void reset(@NotNull Keymap keymap, @NotNull QuickList[] allQuickLists, String filter, @Nullable KeyboardShortcut shortcut) { + private void reset(@NotNull Keymap keymap, @NotNull QuickList[] allQuickLists, String filter, @Nullable Shortcut shortcut) { myKeymap = keymap; final PathsKeeper pathsKeeper = new PathsKeeper(); @@ -228,8 +228,8 @@ public class ActionsTree { pathsKeeper.restorePaths(); } - public void filterTree(final KeyboardShortcut keyboardShortcut, final QuickList [] currentQuickListIds) { - reset(myKeymap, currentQuickListIds, myFilter, keyboardShortcut); + public void filterTree(Shortcut shortcut, QuickList[] currentQuickListIds) { + reset(myKeymap, currentQuickListIds, myFilter, shortcut); } private class MyModel extends DefaultTreeModel implements TreeTableModel { diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java index 476043d3b2f8..0b077e9cd560 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java @@ -34,7 +34,6 @@ import com.intellij.openapi.keymap.ex.KeymapManagerEx; import com.intellij.openapi.keymap.impl.ActionShortcutRestrictions; import com.intellij.openapi.keymap.impl.KeymapImpl; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -528,19 +527,16 @@ public class ActionsTreeUtil { public static Condition isActionFiltered(final ActionManager actionManager, final Keymap keymap, - final KeyboardShortcut keyboardShortcut) { + final Shortcut shortcut) { return new Condition() { public boolean value(final AnAction action) { - if (keyboardShortcut == null) return true; + if (shortcut == null) return true; if (action == null) return false; final Shortcut[] actionShortcuts = keymap.getShortcuts(action instanceof ActionStub ? ((ActionStub)action).getId() : actionManager.getId(action)); - for (Shortcut shortcut : actionShortcuts) { - if (shortcut instanceof KeyboardShortcut) { - final KeyboardShortcut keyboardActionShortcut = (KeyboardShortcut)shortcut; - if (Comparing.equal(keyboardActionShortcut, keyboardShortcut)) { - return true; - } + for (Shortcut actionShortcut : actionShortcuts) { + if (shortcut.equals(actionShortcut)) { + return true; } } return false; @@ -550,7 +546,7 @@ public class ActionsTreeUtil { public static Condition isActionFiltered(final ActionManager actionManager, final Keymap keymap, - final KeyboardShortcut shortcut, + final Shortcut shortcut, final String filter, final boolean force) { return filter != null && filter.length() > 0 ? isActionFiltered(filter, force) : diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index 37b33485ff18..4a354efdcbe1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -513,9 +513,14 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi final ShortcutTextField secondShortcut) { final KeyStroke keyStroke = firstShortcut.getKeyStroke(); if (keyStroke != null) { + filterTreeByShortcut(new KeyboardShortcut(keyStroke, enable2Shortcut.isSelected() ? secondShortcut.getKeyStroke() : null)); + } + } + + private void filterTreeByShortcut(Shortcut shortcut) { + if (shortcut != null) { myTreeExpansionMonitor.freeze(); - myActionsTree.filterTree(new KeyboardShortcut(keyStroke, enable2Shortcut.isSelected() ? secondShortcut.getKeyStroke() : null), - myQuickLists); + myActionsTree.filterTree(shortcut, myQuickLists); final JTree tree = myActionsTree.getTree(); TreeUtil.expandAll(tree); myTreeExpansionMonitor.restore(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutConsumer.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutConsumer.java new file mode 100644 index 000000000000..f89c597ba009 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutConsumer.java @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.keymap.impl.ui; + +import com.intellij.openapi.actionSystem.MouseShortcut; +import com.intellij.util.Consumer; +import com.intellij.util.ui.UIUtil; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.SwingUtilities; + +/** + * @author Sergey.Malenkov + */ +abstract class MouseShortcutConsumer implements HierarchyListener, Consumer { + private Window myWindow; + private Component myComponent; + private MouseShortcut myShortcut; + private final MouseAdapter myListener = new MouseAdapter() { + @Override + public void mouseWheelMoved(MouseWheelEvent event) { + setShortcutFrom(event); + } + + @Override + public void mouseReleased(MouseEvent event) { + setShortcutFrom(event); + } + }; + + MouseShortcutConsumer(MouseShortcut shortcut) { + if (shortcut != null) { + setShortcut(shortcut); + } + } + + MouseShortcut getShortcut() { + return myShortcut; + } + + private void setShortcut(MouseShortcut shortcut) { + myShortcut = shortcut; + consume(shortcut); + } + + private void setShortcutFrom(MouseEvent event) { + if (myComponent != null) { + Point point = SwingUtilities.convertPoint(event.getComponent(), event.getX(), event.getY(), myComponent); + if (0 <= point.x && point.x < myComponent.getWidth() && 0 <= point.y && point.y < myComponent.getHeight()) { + event.consume(); + + int button = MouseShortcut.getButton(event); + if (button >= 0) { + int modifiers = event.getModifiersEx(); + int clickCount = event instanceof MouseWheelEvent ? 1 : event.getClickCount(); + if (myShortcut == null + || button != myShortcut.getButton() + || modifiers != myShortcut.getModifiers() + || clickCount != myShortcut.getClickCount()) { + setShortcut(new MouseShortcut(button, modifiers, clickCount)); + } + } + } + } + } + + @Override + public void hierarchyChanged(HierarchyEvent event) { + Component component = event.getComponent(); + if (component != null) { + if (myComponent == null) { + myComponent = component; + } + if (HierarchyEvent.SHOWING_CHANGED == (HierarchyEvent.SHOWING_CHANGED & event.getChangeFlags())) { + if (myComponent == component) { + Window window = !component.isShowing() ? null : UIUtil.getWindow(component); + if (myWindow != window) { + // It's very important that MouseListener is added to the Window. + // If you add the same listener, for example, to the component + // you will get fake Alt and Meta modifiers. + // Pressing of a middle button causes Alt+Button2 event: + // http://bugs.openjdk.java.net/browse/JDK-4109826 + if (myWindow != null) { + myWindow.removeMouseListener(myListener); + myWindow.removeMouseWheelListener(myListener); + } + myWindow = window; + if (myWindow != null) { + myWindow.addMouseListener(myListener); + myWindow.addMouseWheelListener(myListener); + } + } + } + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java index ef1516f833af..2de4bdf5f3eb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java @@ -46,9 +46,11 @@ class MouseShortcutDialog extends DialogWrapper{ private final JRadioButton myRbSingleClick; private final JRadioButton myRbDoubleClick; private final JLabel myLblPreview; - private final MyClickPad myClickPad; + private final JLabel myClickPad; private final JTextArea myTarConflicts; + private final MouseShortcutConsumer myShortcutConsumer; + private int myButton; @JdkConstants.InputEventMask private int myModifiers; @@ -79,8 +81,6 @@ class MouseShortcutDialog extends DialogWrapper{ myLblPreview=new JLabel(" "); - myClickPad=new MyClickPad(); - myTarConflicts=new JTextArea(); myTarConflicts.setFocusable(false); myTarConflicts.setEditable(false); @@ -106,6 +106,20 @@ class MouseShortcutDialog extends DialogWrapper{ updatePreviewAndConflicts(); + myClickPad = new JLabel( + KeyMapBundle.message("mouse.shortcut.label"), + AllIcons.General.Mouse, SwingConstants.LEADING + ); + myShortcutConsumer = new MouseShortcutConsumer(shortcut) { + @Override + public void consume(MouseShortcut shortcut) { + myButton = shortcut.getButton(); + myModifiers = shortcut.getModifiers(); + updatePreviewAndConflicts(); + } + }; + myClickPad.addHierarchyListener(myShortcutConsumer); + init(); } @@ -160,15 +174,13 @@ class MouseShortcutDialog extends DialogWrapper{ // Click pad - JPanel clickPadPanel=new JPanel(new BorderLayout()); panel.add( - clickPadPanel, + myClickPad, new GridBagConstraints(0,1,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,4,0),0,0) ); - clickPadPanel.setBorder(IdeBorderFactory.createTitledBorder( - KeyMapBundle.message("mouse.shortcut.dialog.click.pad.border"), true)); - myClickPad.setPreferredSize(JBUI.size(260, 60)); - clickPadPanel.add(myClickPad,BorderLayout.CENTER); + myClickPad.setBorder(BorderFactory.createCompoundBorder( + IdeBorderFactory.createTitledBorder(KeyMapBundle.message("mouse.shortcut.dialog.click.pad.border"), true), + JBUI.Borders.empty(20, 0, 20, 20))); // Shortcut preview @@ -276,38 +288,4 @@ class MouseShortcutDialog extends DialogWrapper{ myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.assigned.to.area", buffer.toString())); } } - - private class MyClickPad extends JLabel{ - public MyClickPad(){ - super( - KeyMapBundle.message("mouse.shortcut.label"), - AllIcons.General.Mouse, SwingConstants.CENTER - ); - // It's very imporatant that MouseListener is added to the Dialog. If you add - // the same listener, for example, into the MyClickPad component you get fake - // Alt and Meta modifiers. I means that pressing of middle button causes - // Alt+Button2 event. - // See bug ID 4109826 on Sun's bug parade. - //cast is needed in order to compile with mustang - MouseAdapter adapter = new MouseAdapter() { - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - mouseReleased(e); - } - - public void mouseReleased(MouseEvent e){ - Component component= SwingUtilities.getDeepestComponentAt(e.getComponent(),e.getX(),e.getY()); - if(component== MyClickPad.this){ - e.consume(); - myButton = MouseShortcut.getButton(e); - myModifiers=e.getModifiersEx(); - updatePreviewAndConflicts(); - } - } - }; - Window window = MouseShortcutDialog.this.getPeer().getWindow(); - window.addMouseListener(adapter); - window.addMouseWheelListener(adapter); - } - } } diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java index 66d8189afbef..126bfca35c03 100644 --- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java @@ -131,6 +131,8 @@ public class AppUIUtil { registerFont("/fonts/Inconsolata.ttf"); registerFont("/fonts/SourceCodePro-Regular.ttf"); registerFont("/fonts/SourceCodePro-Bold.ttf"); + registerFont("/fonts/SourceCodePro-It.ttf"); + registerFont("/fonts/SourceCodePro-BoldIt.ttf"); } } diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 896ca5611fff..a518dacd5e99 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1120,7 +1120,9 @@ updates.check.period.on.exit=On every exit unsupported.jvm.openjdk.message=OpenJDK 6 is not supported. Please use Oracle Java or newer OpenJDK. unsupported.jvm.ea.message=Early Access Java versions may cause compatibility issues. Please use stable release. -ibus.blocking.warn.message=IBus prior to 1.5.11 may cause input problem. See IDEA-78860 for details. +ibus.blocking.warn.message=IBus prior to 1.5.11 may cause input problems. See IDEA-78860 for details. + +ayatana.menu.warn.message=JAyatana may cause menus not working. See IDEA-141725 for details. sys.health.acknowledge.link=
Do not show again. diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 7dc527d1a97d..1f2d70977edb 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -451,6 +451,7 @@ + @@ -778,9 +779,9 @@ serviceImplementation="com.intellij.ui.debugger.extensions.PlaybackDebugger$PlaybackDebuggerState"/> + implementationClass="com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitorBasedInspection$AnnotatorBasedInspection"/> + implementationClass="com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitorBasedInspection$SyntaxErrorInspection"/> diff --git a/platform/platform-resources/src/fonts/SourceCodePro-Bold.ttf b/platform/platform-resources/src/fonts/SourceCodePro-Bold.ttf index a56f1fa5ddf4..e0c576f1b023 100644 Binary files a/platform/platform-resources/src/fonts/SourceCodePro-Bold.ttf and b/platform/platform-resources/src/fonts/SourceCodePro-Bold.ttf differ diff --git a/platform/platform-resources/src/fonts/SourceCodePro-BoldIt.ttf b/platform/platform-resources/src/fonts/SourceCodePro-BoldIt.ttf new file mode 100644 index 000000000000..9a4010d8bfaf Binary files /dev/null and b/platform/platform-resources/src/fonts/SourceCodePro-BoldIt.ttf differ diff --git a/platform/platform-resources/src/fonts/SourceCodePro-It.ttf b/platform/platform-resources/src/fonts/SourceCodePro-It.ttf new file mode 100644 index 000000000000..e7f1541e7eb0 Binary files /dev/null and b/platform/platform-resources/src/fonts/SourceCodePro-It.ttf differ diff --git a/platform/platform-resources/src/fonts/SourceCodePro-Regular.ttf b/platform/platform-resources/src/fonts/SourceCodePro-Regular.ttf index b2cff928e42a..437f47280b4f 100644 Binary files a/platform/platform-resources/src/fonts/SourceCodePro-Regular.ttf and b/platform/platform-resources/src/fonts/SourceCodePro-Regular.ttf differ diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapPerformanceTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapPerformanceTest.java index 27fc29deb15f..72c6f45c4d37 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapPerformanceTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapPerformanceTest.java @@ -206,6 +206,7 @@ public class PersistentMapPerformanceTest extends PersistentMapTestBase { final int finalJ = j; map.appendData("abc" + i, out -> IOUtil.writeString(StringUtil.repeat("0123456789", 10000 + finalJ - 3), out)); } + map.force(); } map.close(); diff --git a/platform/util/src/com/intellij/Patches.java b/platform/util/src/com/intellij/Patches.java index dfbbce137097..1ce3f94ade10 100644 --- a/platform/util/src/com/intellij/Patches.java +++ b/platform/util/src/com/intellij/Patches.java @@ -130,6 +130,12 @@ public class Patches { */ public static final boolean JDK_BUG_ID_8042123 = !SystemInfo.isJavaVersionAtLeast("1.8.0_40"); + /** + * JDK on Mac detects font style for system fonts based only on their name (PostScript name). + * This doesn't work for some fonts which don't use recognizable style suffixes in their names. + */ + public static final boolean JDK_MAC_FONT_STYLE_DETECTION_WORKAROUND = SystemInfo.isMac; + /** * Older JDK versions could mistakenly use derived italics font, when genuine italics font was available in the system. * The issue was fixed in JDK 1.8.0_60 as part of JDK-8064833. diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java index d7b8a4cc1337..9a77708d4bd8 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java @@ -19,10 +19,10 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.TestUtils; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -137,11 +137,7 @@ public class TestMethodWithoutAssertionInspectionBase extends BaseInspection { } private boolean lastStatementIsCallToMethodWithAssertion(PsiMethod method) { - final PsiCodeBlock body = method.getBody(); - if (body == null) { - return false; - } - final PsiStatement lastStatement = PsiTreeUtil.getPrevSiblingOfType(body.getLastChild(), PsiStatement.class); + final PsiStatement lastStatement = ControlFlowUtils.getLastStatementInBlock(method.getBody()); if (!(lastStatement instanceof PsiExpressionStatement)) { return false; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/BooleanMethodNameMustStartWithQuestionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/BooleanMethodNameMustStartWithQuestionInspectionBase.java index 6bd74419d834..221a28ec5e29 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/BooleanMethodNameMustStartWithQuestionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/BooleanMethodNameMustStartWithQuestionInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,17 +34,19 @@ import java.util.ArrayList; import java.util.List; public class BooleanMethodNameMustStartWithQuestionInspectionBase extends BaseInspection { - @SuppressWarnings({"PublicField"}) - public boolean ignoreBooleanMethods = false; - @SuppressWarnings({"PublicField"}) - public boolean ignoreInAnnotationInterface = true; - @SuppressWarnings({"PublicField"}) - public boolean onlyWarnOnBaseMethods = true; - /** - * @noinspection PublicField - */ - @NonNls public String questionString = + + public static final String DEFAULT_QUESTION_WORDS = "add,are,can,check,contains,could,endsWith,equals,has,is,matches,must,put,remove,shall,should,startsWith,was,were,will,would"; + + @SuppressWarnings("PublicField") + public boolean ignoreBooleanMethods = false; + @SuppressWarnings("PublicField") + public boolean ignoreInAnnotationInterface = true; + @SuppressWarnings("PublicField") + public boolean onlyWarnOnBaseMethods = true; + + @SuppressWarnings("PublicField") + @NonNls public String questionString = DEFAULT_QUESTION_WORDS; List questionList = new ArrayList(32); public BooleanMethodNameMustStartWithQuestionInspectionBase() { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/NonBooleanMethodNameMayNotStartWithQuestionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/NonBooleanMethodNameMayNotStartWithQuestionInspectionBase.java index 2eefa678699d..aa7bb226f642 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/NonBooleanMethodNameMayNotStartWithQuestionInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/NonBooleanMethodNameMayNotStartWithQuestionInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,20 +33,20 @@ import java.util.ArrayList; import java.util.List; public class NonBooleanMethodNameMayNotStartWithQuestionInspectionBase extends BaseInspection { + + @SuppressWarnings("PublicField") + @NonNls public String questionString = BooleanMethodNameMustStartWithQuestionInspectionBase.DEFAULT_QUESTION_WORDS; + @SuppressWarnings("PublicField") + public boolean ignoreBooleanMethods = false; + @SuppressWarnings("PublicField") + public boolean onlyWarnOnBaseMethods = true; + + List questionList = new ArrayList(32); + public NonBooleanMethodNameMayNotStartWithQuestionInspectionBase() { parseString(questionString, questionList); } - /** - * @noinspection PublicField - */ - @NonNls public String questionString = - "add,are,can,check,contains,could,endsWith,equals,has,is,matches,must,put,remove,shall,should,startsWith,was,were,will,would"; - @SuppressWarnings({"PublicField"}) - public boolean ignoreBooleanMethods = false; - @SuppressWarnings({"PublicField"}) - public boolean onlyWarnOnBaseMethods = true;List questionList = new ArrayList(32); - @Override @NotNull public String getDisplayName() { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java index cd9cf1dfaaf9..eba4c0b99b88 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java @@ -471,6 +471,21 @@ public class ControlFlowUtils { return false; } + public static PsiStatement getLastStatementInBlock(@Nullable PsiCodeBlock codeBlock) { + return getLastChildOfType(codeBlock, PsiStatement.class); + } + + private static T getLastChildOfType(@Nullable PsiElement element, @NotNull Class aClass) { + if (element == null) return null; + for (PsiElement child = element.getLastChild(); child != null; child = child.getPrevSibling()) { + if (aClass.isInstance(child)) { + //noinspection unchecked + return (T)child; + } + } + return null; + } + public static boolean methodAlwaysThrowsException(@NotNull PsiMethod method) { final PsiCodeBlock body = method.getBody(); if (body == null) { diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnaryPlus.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnaryPlus.html index e67f9b5387bb..63f6c6b7b26d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnaryPlus.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnaryPlus.html @@ -5,6 +5,8 @@ its presence may represent a coding error, particularly in combination with the

Use the checkbox below to only report when an unary plus is used together with a binary or another unary expression. +This means the inspection won't warn when an unary plus expression is for example used as a variable initializer, as an argument to a method +or as the right-hand side of an assignment. In such cases it is much less confusing.

diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java index 33925cea2eec..0ee552f8b3c8 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java @@ -27,10 +27,10 @@ public class VariableNotUsedInsideIf { } void bat(String s) { - if (s != null) { + if (s != null) { System.out.println(); } - if (s == null) { + if (s == null) { } else { @@ -38,24 +38,24 @@ public class VariableNotUsedInsideIf { } void money(String s) { - if (((s) != (null))) { + if (((s) != (null))) { System.out.println(); } } void x(Integer x){ - if (x != null) { + if (x != null) { System.out.println(); } } int x(Integer x, int y){ - if (x != null) return y;//oops, wrong one + if (x != null) return y;//oops, wrong one return y; } int conditional(Integer x) { - return x == null ? 1 : someValue(); + return x == null ? 1 : someValue(); } private int someValue() { @@ -64,6 +64,6 @@ public class VariableNotUsedInsideIf { void perenthesis(String[] args) { - String message = (args == null) ? "not null" : "null"; + String message = (args == null) ? "not null" : "null"; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml deleted file mode 100644 index c3a2f7643220..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - VariableNotUsedInsideIf.java - 30 - Reference checked for 'null' is not used inside 'if' - <code>s</code> is not used inside if #loc - - - - VariableNotUsedInsideIf.java - 33 - Reference checked for 'null' is not used inside 'if' - <code>s</code> is not used inside if #loc - - - - VariableNotUsedInsideIf.java - 41 - Reference checked for 'null' is not used inside 'if' - <code>s</code> is not used inside if #loc - - - - VariableNotUsedInsideIf.java - 47 - Reference checked for 'null' is not used inside 'if' - <code>x</code> checked for 'null' is not used inside 'if' #loc - - - - VariableNotUsedInsideIf.java - 53 - Reference checked for 'null' is not used inside 'if' - <code>x</code> checked for 'null' is not used inside 'if' #loc - - - - VariableNotUsedInsideIf.java - 58 - Reference checked for 'null' is not used inside 'if' - <code>x</code> checked for 'null' is not used inside conditional #loc - - - - VariableNotUsedInsideIf.java - 67 - Reference checked for 'null' is not used inside 'if' - <code>args</code> checked for 'null' is not used inside conditional #loc - - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspectionTest.java index c5d9dd1ade5a..fc5688820b96 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspectionTest.java @@ -1,10 +1,18 @@ package com.siyeh.ig.bugs; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; -public class VariableNotUsedInsideIfInspectionTest extends IGInspectionTestCase { +public class VariableNotUsedInsideIfInspectionTest extends LightInspectionTestCase { - public void test() throws Exception { - doTest("com/siyeh/igtest/bugs/variable_not_used_inside_if", new VariableNotUsedInsideIfInspection()); + public void testVariableNotUsedInsideIf() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new VariableNotUsedInsideIfInspection(); } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java index 05f97c65e75b..4902b5cd344c 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java @@ -59,6 +59,21 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { protected void processIntention(final Editor editor, @NotNull PsiElement element) { final PsiMethodReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, PsiMethodReferenceExpression.class); LOG.assertTrue(referenceExpression != null); + final PsiLambdaExpression expr = convertMethodReferenceToLambda(referenceExpression); + final Runnable runnable = new Runnable() { + public void run() { + introduceQualifierAsLocalVariable(editor, expr); + } + }; + final Application application = ApplicationManager.getApplication(); + if (application.isUnitTestMode()) { + runnable.run(); + } else { + application.invokeLater(runnable); + } + } + + public static PsiLambdaExpression convertMethodReferenceToLambda(final PsiMethodReferenceExpression referenceExpression) { final PsiElement resolve = referenceExpression.resolve(); final PsiType functionalInterfaceType = referenceExpression.getFunctionalInterfaceType(); final PsiClassType.ClassResolveResult functionalInterfaceResolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); @@ -87,20 +102,21 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { final Map map = new HashMap(); final UniqueNameGenerator nameGenerator = new UniqueNameGenerator(); - final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(element.getProject()); + final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(referenceExpression.getProject()); final String paramsString = StringUtil.join(parameters, new Function() { @Override public String fun(PsiParameter parameter) { final int parameterIndex = parameterList.getParameterIndex(parameter); String baseName; if (isReceiver && parameterIndex == 0) { - final SuggestedNameInfo nameInfo = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, psiSubstitutor.substitute(parameter.getType())); + final SuggestedNameInfo + nameInfo = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, psiSubstitutor.substitute(parameter.getType())); baseName = nameInfo.names.length > 0 ? nameInfo.names[0] : parameter.getName(); } else { final String initialName = psiParameters != null ? psiParameters[parameterIndex - (isReceiver ? 1 : 0)].getName() : parameter.getName(); baseName = codeStyleManager.variableNameToPropertyName(initialName, VariableKind.PARAMETER); - } + } if (baseName != null) { String parameterName = nameGenerator.generateUniqueName(codeStyleManager.suggestUniqueVariableName(baseName, referenceExpression, true)); @@ -133,7 +149,7 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { } final boolean onArrayRef = - JavaPsiFacade.getElementFactory(element.getProject()).getArrayClass(PsiUtil.getLanguageLevel(element)) == containingClass; + JavaPsiFacade.getElementFactory(referenceExpression.getProject()).getArrayClass(PsiUtil.getLanguageLevel(referenceExpression)) == containingClass; final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement(); if (isReceiver){ @@ -149,7 +165,7 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { buf.append(qualifier.getText()).append("."); } } - } + } //new or method name buf.append(referenceExpression.getReferenceName()); @@ -209,7 +225,7 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)referenceExpression - .replace(JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText(buf.toString(), referenceExpression)); + .replace(JavaPsiFacade.getElementFactory(referenceExpression.getProject()).createExpressionFromText(buf.toString(), referenceExpression)); PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)typeCastExpression.getOperand(); if (RedundantCastUtil.isCastRedundant(typeCastExpression)) { final PsiExpression operand = typeCastExpression.getOperand(); @@ -219,21 +235,10 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention { final PsiExpression singleExpression = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression, body); if (singleExpression != null) { body.replace(singleExpression); - } + } } - final PsiLambdaExpression expr = lambdaExpression; - final Runnable runnable = new Runnable() { - public void run() { - introduceQualifierAsLocalVariable(editor, expr); - } - }; - final Application application = ApplicationManager.getApplication(); - if (application.isUnitTestMode()) { - runnable.run(); - } else { - application.invokeLater(runnable); - } + return lambdaExpression; } private static void introduceQualifierAsLocalVariable(Editor editor, PsiLambdaExpression lambdaExpression) { diff --git a/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java index e32b3f9f26ae..dcdd1422bcae 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java @@ -16,7 +16,7 @@ package com.intellij.execution.junit; public class AllInDirectoryConfigurationProducer extends AbstractAllInDirectoryConfigurationProducer { - protected AllInDirectoryConfigurationProducer() { + public AllInDirectoryConfigurationProducer() { super(JUnitConfigurationType.getInstance()); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index bcf5ce815146..6da637dd5210 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -612,6 +612,9 @@ public class JUnitConfiguration extends JavaTestConfigurationBase { final String fqName = myPattern.iterator().next(); return (fqName.contains("*") ? fqName : StringUtil.getShortName(fqName)) + (size > 1 ? " and " + (size - 1) + " more" : ""); } + if (TEST_CATEGORY.equals(TEST_OBJECT)) { + return "@Category(" + (StringUtil.isEmpty(CATEGORY_NAME) ? "Invalid" : CATEGORY_NAME) + ")"; + } final String className = JavaExecutionUtil.getPresentableClassName(getMainClassName()); if (TEST_METHOD.equals(TEST_OBJECT)) { return className + '.' + getMethodName(); diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java index 86af619ccbfd..35d1343e5a12 100644 --- a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import java.util.LinkedHashSet; import java.util.Set; public class PatternConfigurationProducer extends AbstractPatternBasedConfigurationProducer { - protected PatternConfigurationProducer() { + public PatternConfigurationProducer() { super(JUnitConfigurationType.getInstance()); } diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java index 29eec8b69a98..7e51cab029da 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java @@ -16,7 +16,7 @@ package com.intellij.execution.junit; public class TestClassConfigurationProducer extends AbstractTestClassConfigurationProducer { - protected TestClassConfigurationProducer() { + public TestClassConfigurationProducer() { super(JUnitConfigurationType.getInstance()); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java index 9382e9701fc4..16ef2e3d87a3 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java @@ -16,7 +16,7 @@ package com.intellij.execution.junit; public class TestMethodConfigurationProducer extends AbstractTestMethodConfigurationProducer { - protected TestMethodConfigurationProducer() { + public TestMethodConfigurationProducer() { super(JUnitConfigurationType.getInstance()); } } diff --git a/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java b/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java index 80ffbf8852dc..a9784fbe256f 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java @@ -16,6 +16,7 @@ package com.jetbrains.python.documentation.docstrings; import com.google.common.collect.Lists; +import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; @@ -122,15 +123,11 @@ public class PyStructuredDocstringFormatter { final Map env = new HashMap(); PythonEnvUtil.setPythonDontWriteBytecode(env); - final ProcessOutput output = PySdkUtil.getProcessOutput(formatter.newCommandLine(sdkHome, Lists.newArrayList()), - new File(sdkHome).getParent(), - env, 5000, data, true); - if (output.isTimeout()) { - LOG.info("timeout when calculating docstring"); - return null; - } - else if (output.getExitCode() != 0) { - LOG.info("error when calculating docstring: " + output.getStderr()); + final GeneralCommandLine commandLine = formatter.newCommandLine(sdkHome, Lists.newArrayList()); + LOG.debug("Command for launching docstring formatter: " + commandLine.getCommandLineString()); + + final ProcessOutput output = PySdkUtil.getProcessOutput(commandLine, new File(sdkHome).getParent(), env, 5000, data, true); + if (!output.checkSuccess(LOG)) { return null; } return output.getStdout(); diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java index 4cd9326ddc78..d3a212dcde71 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java @@ -42,7 +42,8 @@ public class PyRemoteSdkFlavor extends CPythonSdkFlavor { @Override public boolean isValidSdkHome(String path) { - return StringUtil.isNotEmpty(path) && checkName(NAMES, getExecutableName(path)) && (path.startsWith("ssh:") || path.startsWith("vagrant:")); + return StringUtil.isNotEmpty(path) && checkName(NAMES, getExecutableName(path)) + && (path.startsWith("ssh:") || path.startsWith("vagrant:") || path.startsWith("docker:")); } private static boolean checkName(String[] names, @Nullable String name) { diff --git a/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java b/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java index fa3e1ac80913..64b01de08f81 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlCommenter.java @@ -64,7 +64,8 @@ public class XmlCommenter implements EscapingCommenter { String suffix = getBlockCommentSuffix(); int start = range.getStartOffset(); - if (CharArrayUtil.regionMatches(document.getCharsSequence(), start, prefix)) { + int prefixStart = start = CharArrayUtil.shiftForward(document.getCharsSequence(), start, " \t\n"); + if (CharArrayUtil.regionMatches(document.getCharsSequence(), prefixStart, prefix)) { start += prefix.length(); } int end = range.getEndOffset(); @@ -83,7 +84,7 @@ public class XmlCommenter implements EscapingCommenter { if (CharArrayUtil.regionMatches(document.getCharsSequence(), start, GT)) { document.replaceString(start, start + GT.length(), ESCAPED_GT); } - if (CharArrayUtil.regionMatches(document.getCharsSequence(), range.getStartOffset(), prefix + "-")) { + if (CharArrayUtil.regionMatches(document.getCharsSequence(), prefixStart, prefix + "-")) { document.insertString(start, " "); } if (CharArrayUtil.regionMatches(document.getCharsSequence(), range.getEndOffset() - suffix.length() - 1, "-" + suffix)) {