diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index fc13858daac9..d10b656ad6a8 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -307,7 +307,10 @@ public abstract class SourcePosition implements Navigatable{ } public static SourcePosition createFromElement(PsiElement element) { - final PsiElement navigationElement = element.getNavigationElement(); + ApplicationManager.getApplication().assertReadAccessAllowed(); + PsiElement navigationElement = element.getNavigationElement(); + final SmartPsiElementPointer pointer = + SmartPointerManager.getInstance(navigationElement.getProject()).createSmartPsiElementPointer(navigationElement); final PsiFile psiFile; if (JspPsiUtil.isInJspFile(navigationElement)) { psiFile = JspPsiUtil.getJspFile(navigationElement); @@ -318,12 +321,19 @@ public abstract class SourcePosition implements Navigatable{ return new SourcePositionCache(psiFile) { @Override protected PsiElement calcPsiElement() { - return navigationElement; + ApplicationManager.getApplication().assertReadAccessAllowed(); + return pointer.getElement(); } @Override protected int calcOffset() { - return navigationElement.getTextOffset(); + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Integer compute() { + PsiElement elem = pointer.getElement(); + return elem != null ? elem.getTextOffset() : -1; + } + }); } }; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index dc392cec131b..eb9f162a909d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -263,13 +263,14 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element; - final PsiMethod psiMethod = methodCall.resolveMethod(); + JavaResolveResult result = methodCall.resolveMethodGenerics(); + final PsiMethod psiMethod = (PsiMethod)result.getElement(); if (psiMethod == null) { return null; } final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); - final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod); + final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod, result.getSubstitutor()); if (qualifierByMethodCall != null) { return qualifierByMethodCall + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodExpression.getReferenceName(); } @@ -324,7 +325,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp private static String getQualifierTextByMethodCall(final PsiMethodCallExpression methodCall, final PsiType functionalInterfaceType, final PsiParameter[] parameters, - final PsiMethod psiMethod) { + final PsiMethod psiMethod, + final PsiSubstitutor substitutor) { final PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression(); @@ -332,7 +334,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp LOG.assertTrue(containingClass != null); if (qualifierExpression != null) { - boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod); + boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(functionalInterfaceType, methodCall), containingClass, substitutor); return isReceiverType ? composeReceiverQualifierText(parameters, psiMethod, containingClass, qualifierExpression) : qualifierExpression.getText(); } @@ -422,7 +424,6 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (lambdaExpression == null) return; PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return; - String functionalTypeText = functionalInterfaceType.getCanonicalText(); final String methodRefText = createMethodReferenceText(element, functionalInterfaceType, lambdaExpression.getParameterList().getParameters()); diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 1fd4e786509f..b9cd4b2a1393 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -30,10 +30,10 @@ public class PsiMethodReferenceUtil { public static final Logger LOG = Logger.getInstance("#" + PsiMethodReferenceUtil.class.getName()); public static boolean hasReceiver(PsiType[] parameterTypes, QualifierResolveResult qualifierResolveResult, PsiMethodReferenceExpression methodRef) { - if (parameterTypes.length > 0 && + if (parameterTypes.length > 0 && !methodRef.isConstructor() && - isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) && - isStaticallyReferenced(methodRef)) { + isStaticallyReferenced(methodRef) && + isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor())) { return true; } return false; @@ -46,7 +46,7 @@ public class PsiMethodReferenceUtil { LOG.assertTrue(containingClass != null); PsiSubstitutor subst = result.getSubstitutor(); PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass(); - if (qContainingClass != null && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod)resolve)) { + if (qContainingClass != null && isReceiverType(getFirstParameterType(functionalInterfaceType, expression), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } @@ -202,53 +202,27 @@ public class PsiMethodReferenceUtil { return true; } - public static boolean isReceiverType(@Nullable PsiClass aClass, @Nullable PsiClass containingClass) { - return InheritanceUtil.isInheritorOrSelf(aClass, containingClass, true); - } - - public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - if (containingClass != null) { - receiverType = getExpandedType(receiverType, containingClass); + //if P1, ..., Pn is not empty and P1 is a subtype of ReferenceType, then the method reference expression is treated as + // if it were a method invocation expression with argument expressions of types P2, ...,Pn. + public static boolean isReceiverType(@Nullable PsiType receiverType, PsiClass containingClass, PsiSubstitutor psiSubstitutor) { + if (receiverType == null) { + return false; } - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(receiverType); - final PsiClass receiverClass = resolveResult.getElement(); - if (receiverClass != null && isReceiverType(receiverClass, containingClass)) { - if (emptyOrRaw(containingClass, psiSubstitutor)) { - return true; - } - final PsiSubstitutor derivedSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, receiverClass, psiSubstitutor); - return derivedSubstitutor != null && TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, derivedSubstitutor), receiverType); - } - return false; + return TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, psiSubstitutor), + getExpandedType(receiverType, containingClass)); } - private static boolean emptyOrRaw(PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - return PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor) || - psiSubstitutor.getSubstitutionMap().isEmpty(); - } - - public static boolean isReceiverType(PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) { + public static PsiType getFirstParameterType(PsiType functionalInterfaceType, PsiElement context) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement()); if (function != null) { final int interfaceMethodParamsLength = function.getParameterTypes().length; if (interfaceMethodParamsLength > 0) { - final PsiType firstParamType = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); - boolean isReceiver = isReceiverType(firstParamType, - containingClass, PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor()); - if (isReceiver) { - if (referencedMethod == null){ - if (interfaceMethodParamsLength == 1) return true; - return false; - } - if (referencedMethod.getParameterList().getParametersCount() != interfaceMethodParamsLength - 1) { - return false; - } - return true; - } + PsiType type = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); + return type != null ? PsiUtil.captureToplevelWildcards(type, context) : null; } } - return false; + return null; } private static PsiType getExpandedType(PsiType type, @NotNull PsiElement typeElement) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index 87eb8b804b08..cf974c91f980 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -176,7 +176,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai private static boolean isAddressed(List expectedThrownTypes, PsiType thrownType) { for (PsiType expectedThrownType : expectedThrownTypes) { - if (TypeConversionUtil.isAssignable(expectedThrownType, thrownType)) { + if (TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(thrownType), expectedThrownType)) { return true; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 2408bbba5bff..e640caf1f802 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; @@ -480,7 +479,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase PsiClass qContainingClass = PsiMethodReferenceUtil.getQualifierResolveResult(this).getContainingClass(); if (qContainingClass != null && containingClass != null && - PsiMethodReferenceUtil.isReceiverType(left, containingClass, (PsiMethod)resolve)) { + PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(left, this), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java new file mode 100644 index 000000000000..476d30ab3cf2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java @@ -0,0 +1,38 @@ +import java.io.IOException; + +class Test { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} +class Test1 { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + class MyEx extends Exception{} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java new file mode 100644 index 000000000000..a0621c1726f7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java @@ -0,0 +1,28 @@ +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +class Test { + + static class Base { + public BigDecimal getTotal() { + return null; + } + } + + public static void foo(List list, List list1) { + System.out.println(add(list, Base::getTotal)); + list1.forEach(Base::getTotal); + } + + + public static BigDecimal add(Collection objectsThatHaveBigDecimals, Function functionToGet) { + return objectsThatHaveBigDecimals == null ? null : objectsThatHaveBigDecimals.stream().map(functionToGet).reduce(null, Test::add); + } + + public static BigDecimal add(BigDecimal... sequence) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java new file mode 100644 index 000000000000..6015c09a1c24 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java @@ -0,0 +1,9 @@ +import java.util.Collection; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; + +class Test { + public static int sum(Collection collection, ToIntFunction mapper) { + return collection.stream().collect(Collectors.summingInt(mapper)); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java index ea3d7f543801..e6934f2715e7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java @@ -35,6 +35,10 @@ public class Java8RegressionTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA136887() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index ca5ce7e44e96..f0636eb92e57 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -142,6 +142,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testCheckedExceptionsConstraintsSubstitutions1() throws Exception { + doTest(); + } + public void testCheckedExceptionsConstraintsSubstitutionsDeepInBody() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 810019f54bd0..dad206251e3e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -382,6 +382,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testSecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/lib/markdown4j-2.2.jar b/lib/markdown4j-2.2.jar new file mode 100644 index 000000000000..65030fa08205 Binary files /dev/null and b/lib/markdown4j-2.2.jar differ diff --git a/platform/core-impl/src/com/intellij/mock/MockDumbService.java b/platform/core-impl/src/com/intellij/mock/MockDumbService.java index b1fe7ae2a727..e97a9f64c7f3 100644 --- a/platform/core-impl/src/com/intellij/mock/MockDumbService.java +++ b/platform/core-impl/src/com/intellij/mock/MockDumbService.java @@ -22,6 +22,8 @@ import com.intellij.openapi.project.DumbModeTask; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.ModificationTracker; +import com.intellij.openapi.util.SimpleModificationTracker; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -36,6 +38,11 @@ public class MockDumbService extends DumbService { myProject = project; } + @Override + public ModificationTracker getModificationTracker() { + return new SimpleModificationTracker(); + } + @Override public boolean isDumb() { return false; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 3a9401308de1..f4894afc9eb1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -289,7 +289,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } advanceProgress(1); - tool.inspectionFinished(session, holder); if (holder.hasResults()) { appendDescriptors(myFile, holder.getResults(), toolWrapper); } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index bed9f0267e4f..cabb8f3f2494 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -308,6 +308,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search if (mySearchResults.getMatchesCount() >= mySearchResults.getMatchesLimit()) return; for (FindResult range : mySearchResults.getOccurrences()) { + if (range.getEndOffset() > mySearchResults.getEditor().getDocument().getTextLength()) continue; TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES); if (range.getLength() == 0) { attributes = attributes.clone(); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 3a8b93a92b11..566625c7378b 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1773,8 +1773,8 @@ public class UIUtil { } private static int THEME_BASED_TEXT_LCD_CONTRAST = 0; - private static int BEST_DARK_LCD_CONTRAST = 100; - private static int BEST_LIGHT_LCD_CONTRAST = 200; + private static int BEST_DARK_LCD_CONTRAST = 250; + private static int BEST_LIGHT_LCD_CONTRAST = 100; public static void setHintingForLCDText(Graphics2D g2d) { diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 0756d656a55a..2a7103ceb9cf 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.coverage.view; import com.intellij.coverage.*; @@ -235,9 +250,13 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { : PsiFile.EMPTY_ARRAY; } }); - for (PsiFile file : childFiles) { + for (final PsiFile file : childFiles) { if (file instanceof PsiJavaFile) { - PsiClass[] classes = ((PsiJavaFile)file).getClasses(); + PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass[] compute() { + return ((PsiJavaFile) file).getClasses(); + } + }); if (classes.length > 0) { PsiClass aClass = classes[0]; if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue;