summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com/intellij
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-psi-impl/src/com/intellij')
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java44
-rw-r--r--java/java-psi-impl/src/com/intellij/core/CorePsiPackageImplementationHelper.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java2
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java2
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java27
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java21
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelper.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java11
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java20
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java13
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java213
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java21
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java6
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java6
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java58
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java5
18 files changed, 345 insertions, 163 deletions
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
index f4154bc4fe1a..9b6c23e79b00 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
@@ -625,6 +625,11 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
int leftStart = method.getParameterList().getTextRange().getEndOffset();
+ int bodyStart = body.getTextRange().getStartOffset();
+ if (bodyStart > leftStart && !StringUtil.isEmptyOrSpaces(document.getCharsSequence().subSequence(leftStart + 1, bodyStart))) {
+ return false;
+ }
+
int leftEnd = statement.getTextRange().getStartOffset();
int rightStart = statement.getTextRange().getEndOffset();
int rightEnd = body.getTextRange().getEndOffset();
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
index 1f642b18d1b1..67b1ef813de8 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
@@ -501,6 +501,7 @@ public class JavaDocInfoGenerator {
buffer.append("<b>");
buffer.append(field.getName());
appendInitializer(buffer, field);
+ enumConstantOrdinal(buffer, field, field.getContainingClass(), "\n");
buffer.append("</b>");
}
@@ -638,7 +639,7 @@ public class JavaDocInfoGenerator {
String text = o.toString();
PsiType type = variable.getType();
if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
- text = "\"" + StringUtil.shortenPathWithEllipsis(text, 120) + "\"";
+ text = "\"" + StringUtil.escapeLineBreak(StringUtil.shortenPathWithEllipsis(text, 120)) + "\"";
}
else if (type.equalsToText("char")) text = "'" + text + "'";
try {
@@ -754,7 +755,20 @@ public class JavaDocInfoGenerator {
}
final PsiAnnotationMemberValue value = pair.getValue();
if (value != null) {
- buffer.append(XmlStringUtil.escapeString(value.getText()));
+ if (value instanceof PsiArrayInitializerMemberValue) {
+ buffer.append("{");
+ boolean firstMember = true;
+
+ for(PsiAnnotationMemberValue memberValue:((PsiArrayInitializerMemberValue)value).getInitializers()) {
+ if (!firstMember) buffer.append(",");
+ firstMember = false;
+
+ appendLinkOrText(buffer, memberValue, generateLink);
+ }
+ buffer.append("}");
+ } else {
+ appendLinkOrText(buffer, value, generateLink);
+ }
}
}
buffer.append(")");
@@ -778,6 +792,32 @@ public class JavaDocInfoGenerator {
}
}
+ private static void appendLinkOrText(StringBuilder buffer,
+ PsiAnnotationMemberValue memberValue,
+ boolean generateLink) {
+ if (generateLink && memberValue instanceof PsiQualifiedReferenceElement) {
+ String text = ((PsiQualifiedReferenceElement)memberValue).getCanonicalText();
+ PsiElement resolve = ((PsiQualifiedReferenceElement)memberValue).resolve();
+
+ if (resolve instanceof PsiField) {
+ PsiField field = (PsiField)resolve;
+ PsiClass aClass = field.getContainingClass();
+ int startOfPropertyNamePosition = text.lastIndexOf('.');
+
+ if (startOfPropertyNamePosition != -1) {
+ text = text.substring(0, startOfPropertyNamePosition) + '#' + text.substring(startOfPropertyNamePosition + 1);
+ }
+ else {
+ if (aClass != null) text = aClass.getQualifiedName() + '#' + field.getName();
+ }
+ generateLink(buffer, text, aClass != null? aClass.getName() + '.' + field.getName():null, memberValue, false);
+ return;
+ }
+ }
+
+ buffer.append(XmlStringUtil.escapeString(memberValue.getText()));
+ }
+
public static boolean isDocumentedAnnotationType(@Nullable PsiElement annotationType) {
return annotationType instanceof PsiClass && AnnotationUtil.isAnnotated((PsiClass)annotationType, "java.lang.annotation.Documented", false);
}
diff --git a/java/java-psi-impl/src/com/intellij/core/CorePsiPackageImplementationHelper.java b/java/java-psi-impl/src/com/intellij/core/CorePsiPackageImplementationHelper.java
index 5a97f596d983..51e010e05d29 100644
--- a/java/java-psi-impl/src/com/intellij/core/CorePsiPackageImplementationHelper.java
+++ b/java/java-psi-impl/src/com/intellij/core/CorePsiPackageImplementationHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.impl.file.PsiPackageImplementationHelper;
import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -27,31 +28,34 @@ import com.intellij.psi.search.GlobalSearchScope;
public class CorePsiPackageImplementationHelper extends PsiPackageImplementationHelper {
private static final ModificationTracker[] EMPTY_DEPENDENCY = {ModificationTracker.NEVER_CHANGED};
+ @NotNull
@Override
- public GlobalSearchScope adjustAllScope(PsiPackage psiPackage, GlobalSearchScope globalSearchScope) {
+ public GlobalSearchScope adjustAllScope(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope globalSearchScope) {
return globalSearchScope;
}
+ @NotNull
@Override
- public VirtualFile[] occursInPackagePrefixes(PsiPackage psiPackage) {
+ public VirtualFile[] occursInPackagePrefixes(@NotNull PsiPackage psiPackage) {
return VirtualFile.EMPTY_ARRAY;
}
@Override
- public void handleQualifiedNameChange(PsiPackage psiPackage, String newQualifiedName) {
+ public void handleQualifiedNameChange(@NotNull PsiPackage psiPackage, @NotNull String newQualifiedName) {
}
@Override
- public void navigate(PsiPackage psiPackage, boolean requestFocus) {
+ public void navigate(@NotNull PsiPackage psiPackage, boolean requestFocus) {
}
@Override
- public boolean packagePrefixExists(PsiPackage psiPackage) {
+ public boolean packagePrefixExists(@NotNull PsiPackage psiPackage) {
return false;
}
+ @NotNull
@Override
- public Object[] getDirectoryCachedValueDependencies(PsiPackage cachedValueProvider) {
+ public Object[] getDirectoryCachedValueDependencies(@NotNull PsiPackage cachedValueProvider) {
return EMPTY_DEPENDENCY;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
index 59a4e10d40fe..7fc4a2245941 100644
--- a/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
+++ b/java/java-psi-impl/src/com/intellij/psi/NonClasspathClassFinder.java
@@ -248,7 +248,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
}
@NotNull
- public static GlobalSearchScope addNonClasspathScope(Project project, GlobalSearchScope base) {
+ public static GlobalSearchScope addNonClasspathScope(@NotNull Project project, @NotNull GlobalSearchScope base) {
GlobalSearchScope scope = base;
for (PsiElementFinder finder : Extensions.getExtensions(EP_NAME, project)) {
if (finder instanceof NonClasspathClassFinder) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
index 9c9525aef859..d53bb2e26820 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
@@ -389,7 +389,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
else {
//unbounded
- substituted = PsiWildcardType.createExtends(manager, substitutedBoundType);
+ substituted = substitutedBoundType instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)substitutedBoundType).getWildcard() : PsiWildcardType.createExtends(manager, substitutedBoundType);
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
index 6ab8174ce28a..20c11a7ccb39 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
@@ -27,8 +27,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.progress.NonCancelableSection;
-import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.ui.Queryable;
@@ -323,7 +322,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
synchronized (myMirrorLock) {
mirrorTreeElement = myMirrorFileElement;
if (mirrorTreeElement == null) {
- VirtualFile file = getVirtualFile();
+ final VirtualFile file = getVirtualFile();
CharSequence mirrorText = ClassFileDecompiler.decompileText(file);
String ext = JavaFileType.INSTANCE.getDefaultExtension();
@@ -335,16 +334,18 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
mirrorTreeElement = SourceTreeToPsiMap.psiToTreeNotNull(mirror);
// IMPORTANT: do not take lock too early - FileDocumentManager.saveToString() can run write action
- NonCancelableSection section = ProgressIndicatorProvider.startNonCancelableSectionIfSupported();
- try {
- setMirror(mirrorTreeElement);
- }
- catch (InvalidMirrorException e) {
- LOG.error(file.getPath(), wrapException(e, file));
- }
- finally {
- section.done();
- }
+ final TreeElement finalMirrorTreeElement = mirrorTreeElement;
+ ProgressManager.getInstance().executeNonCancelableSection(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ setMirror(finalMirrorTreeElement);
+ }
+ catch (InvalidMirrorException e) {
+ LOG.error(file.getPath(), wrapException(e, file));
+ }
+ }
+ });
myMirrorFileElement = mirrorTreeElement;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
index 9129052bf74f..93fd1ebbd935 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaPsiFacadeImpl;
@@ -46,7 +47,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Queryable {
- public static boolean DEBUG = false;
private volatile CachedValue<PsiModifierList> myAnnotationList;
private volatile CachedValue<Collection<PsiDirectory>> myDirectories;
private volatile CachedValue<Collection<PsiDirectory>> myDirectoriesWithLibSources;
@@ -72,6 +72,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
}
}
+ @NotNull
private CachedValue<Collection<PsiDirectory>> createCachedDirectories(final boolean includeLibrarySources) {
return CachedValuesManager.getManager(myManager.getProject()).createCachedValue(new CachedValueProvider<Collection<PsiDirectory>>() {
@Override
@@ -131,6 +132,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
}
}
+ @Override
public String toString() {
return "PsiPackage:" + getQualifiedName();
}
@@ -141,6 +143,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
return getClasses(allScope());
}
+ @NotNull
protected GlobalSearchScope allScope() {
return PsiPackageImplementationHelper.getInstance().adjustAllScope(this, GlobalSearchScope.allScope(getProject()));
}
@@ -177,7 +180,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
}
@NotNull
- private PsiClass[] getCachedClassesByName(String name) {
+ private PsiClass[] getCachedClassesByName(@NotNull String name) {
if (DumbService.getInstance(getProject()).isDumb()) {
return getCachedClassInDumbMode(name);
}
@@ -215,7 +218,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
}
@Override
- public boolean containsClassNamed(String name) {
+ public boolean containsClassNamed(@NotNull String name) {
return getCachedClassesByName(name).length > 0;
}
@@ -247,7 +250,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
}
@Nullable
- private PsiPackage findSubPackageByName(String name) {
+ private PsiPackage findSubPackageByName(@NotNull String name) {
final String qName = getQualifiedName();
final String subpackageQName = qName.isEmpty() ? name : qName + "." + name;
return getFacade().findPackage(subpackageQName);
@@ -270,11 +273,11 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
if (nameHint != null) {
final String shortName = nameHint.getName(state);
final PsiClass[] classes = findClassByShortName(shortName, scope);
- if (!processClasses(processor, state, classes, Condition.TRUE)) return false;
+ if (!processClasses(processor, state, classes, Conditions.<String>alwaysTrue())) return false;
}
else {
PsiClass[] classes = getClasses(scope);
- if (!processClasses(processor, state, classes, nameCondition != null ? nameCondition : Condition.TRUE)) return false;
+ if (!processClasses(processor, state, classes, nameCondition != null ? nameCondition : Conditions.<String>alwaysTrue())) return false;
}
}
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.PACKAGE)) {
@@ -302,7 +305,9 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
return true;
}
- private static boolean processClasses(PsiScopeProcessor processor, ResolveState state, PsiClass[] classes,
+ private static boolean processClasses(@NotNull PsiScopeProcessor processor,
+ @NotNull ResolveState state,
+ @NotNull PsiClass[] classes,
@NotNull Condition<String> nameCondition) {
for (PsiClass aClass : classes) {
String name = aClass.getName();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelper.java
index 050786c617f0..4ca3f1fead43 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelper.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,22 +19,26 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public abstract class PsiPackageImplementationHelper {
- public abstract GlobalSearchScope adjustAllScope(PsiPackage psiPackage, GlobalSearchScope globalSearchScope);
+ @NotNull
+ public abstract GlobalSearchScope adjustAllScope(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope globalSearchScope);
- public abstract VirtualFile[] occursInPackagePrefixes(PsiPackage psiPackage);
+ @NotNull
+ public abstract VirtualFile[] occursInPackagePrefixes(@NotNull PsiPackage psiPackage);
- public abstract void handleQualifiedNameChange(PsiPackage psiPackage, String newQualifiedName);
+ public abstract void handleQualifiedNameChange(@NotNull PsiPackage psiPackage, @NotNull String newQualifiedName);
- public abstract void navigate(PsiPackage psiPackage, boolean requestFocus);
+ public abstract void navigate(@NotNull PsiPackage psiPackage, boolean requestFocus);
- public abstract boolean packagePrefixExists(PsiPackage psiPackage);
+ public abstract boolean packagePrefixExists(@NotNull PsiPackage psiPackage);
- public abstract Object[] getDirectoryCachedValueDependencies(PsiPackage cachedValueProvider);
+ @NotNull
+ public abstract Object[] getDirectoryCachedValueDependencies(@NotNull PsiPackage cachedValueProvider);
public static PsiPackageImplementationHelper getInstance() {
return ServiceManager.getService(PsiPackageImplementationHelper.class);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
index 78c5c2d8fdc8..fd38e3ddaf56 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
@@ -399,9 +399,14 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
@Override
public PsiElement getOriginalElement() {
- PsiClass originalClass = (PsiClass)getContainingClass().getOriginalElement();
- PsiField originalField = originalClass.findFieldByName(getName(), false);
- return originalField != null ? originalField : this;
+ PsiClass containingClass = getContainingClass();
+ if (containingClass != null) {
+ PsiField originalField = ((PsiClass)containingClass.getOriginalElement()).findFieldByName(getName(), false);
+ if (originalField != null) {
+ return originalField;
+ }
+ }
+ return this;
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
index e77e7ad01f5e..799f9b459e69 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
@@ -324,4 +324,24 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
final PsiElement declarationScope = getDeclarationScope();
return new LocalSearchScope(declarationScope);
}
+
+ @Override
+ public PsiElement getOriginalElement() {
+ PsiElement parent = getParent();
+ if (parent instanceof PsiParameterList) {
+ PsiElement gParent = parent.getParent();
+ if (gParent instanceof PsiMethod) {
+ PsiElement originalMethod = gParent.getOriginalElement();
+ if (originalMethod instanceof PsiMethod) {
+ int index = ((PsiParameterList)parent).getParameterIndex(this);
+ PsiParameter[] originalParameters = ((PsiMethod)originalMethod).getParameterList().getParameters();
+ if (index < originalParameters.length) {
+ return originalParameters[index];
+ }
+ }
+ }
+ }
+ return this;
+ }
+
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
index 556bf7152b68..a27dfe5adb83 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source.resolve;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -211,16 +210,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
.getSubstitutionForTypeParameter(typeParam, param, arg, isContraVariantPosition, languageLevel);
}
- private PsiInferenceHelper myTestHelper;
-
- public void setTestHelper(PsiInferenceHelper testHelper) {
- myTestHelper = testHelper;
- }
-
- public PsiInferenceHelper getInferenceHelper(LanguageLevel languageLevel) {
- if (ApplicationManager.getApplication().isUnitTestMode() && myTestHelper != null) {
- return myTestHelper;
- }
+ @NotNull
+ public PsiInferenceHelper getInferenceHelper(@NotNull LanguageLevel languageLevel) {
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
return new PsiGraphInferenceHelper(myManager);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 35db6c29bc0c..a1b4570e5361 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -174,7 +174,6 @@ public class InferenceSession {
}
}
}
- return true;
}
if (expr instanceof PsiLambdaExpression) {
if (!((PsiLambdaExpression)expr).hasFormalParameterTypes()) {
@@ -234,7 +233,7 @@ public class InferenceSession {
!MethodCandidateInfo.ourOverloadGuard.currentStack().contains(PsiUtil.skipParenthesizedExprUp(parent.getParent()))) {
final Set<ConstraintFormula> additionalConstraints = new LinkedHashSet<ConstraintFormula>();
if (parameters.length > 0) {
- collectAdditionalConstraints(parameters, args, properties.getMethod(), PsiSubstitutor.EMPTY, additionalConstraints, properties.isVarargs(), true);
+ collectAdditionalConstraints(parameters, args, properties.getMethod(), PsiSubstitutor.EMPTY, additionalConstraints, properties.isVarargs());
}
if (!additionalConstraints.isEmpty() && !proceedWithAdditionalConstraints(additionalConstraints)) {
@@ -264,67 +263,113 @@ public class InferenceSession {
PsiMethod parentMethod,
PsiSubstitutor siteSubstitutor,
Set<ConstraintFormula> additionalConstraints,
- boolean varargs, boolean toplevel) {
+ boolean varargs) {
for (int i = 0; i < args.length; i++) {
- if (args[i] != null) {
- InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(args[i], PsiCallExpression.class));
- if (session == null) {
- session = this;
- }
- PsiType parameterType = session.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
- if (!isPertinentToApplicability(args[i], parentMethod)) {
- additionalConstraints.add(new ExpressionCompatibilityConstraint(args[i], parameterType));
+ final PsiExpression arg = PsiUtil.skipParenthesizedExprDown(args[i]);
+ if (arg != null) {
+ final InferenceSession nestedCallSession = findNestedCallSession(arg);
+ final PsiType parameterType =
+ nestedCallSession.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
+ if (!isPertinentToApplicability(arg, parentMethod)) {
+ additionalConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType));
}
- additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(args[i], parameterType));
- if (args[i] instanceof PsiCallExpression && PsiPolyExpressionUtil.isPolyExpression(args[i])) {
+ additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(arg, parameterType));
+ if (arg instanceof PsiCallExpression) {
//If the expression is a poly class instance creation expression (15.9) or a poly method invocation expression (15.12),
//the set contains all constraint formulas that would appear in the set C when determining the poly expression's invocation type.
- final PsiCallExpression callExpression = (PsiCallExpression)args[i];
- collectAdditionalConstraints(additionalConstraints, callExpression);
- } else if (args[i] instanceof PsiLambdaExpression && toplevel) {
- final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(parameterType);
- if (interfaceReturnType != null) {
- final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)args[i]);
- for (PsiExpression returnExpression : returnExpressions) {
- if (returnExpression instanceof PsiCallExpression) {
- final PsiCallExpression callExpression = (PsiCallExpression)returnExpression;
- collectAdditionalConstraints(additionalConstraints, callExpression);
- }
- }
+ final PsiMethod calledMethod = getCalledMethod((PsiCallExpression)arg);
+ if (PsiPolyExpressionUtil.isMethodCallPolyExpression(arg, calledMethod)) {
+ collectAdditionalConstraints(additionalConstraints, (PsiCallExpression)arg);
}
+ } else if (arg instanceof PsiLambdaExpression) {
+ collectLambdaReturnExpression(additionalConstraints, (PsiLambdaExpression)arg, parameterType);
}
}
}
}
+ private static PsiMethod getCalledMethod(PsiCallExpression arg) {
+ final PsiExpressionList argumentList = arg.getArgumentList();
+ if (argumentList == null || argumentList.getExpressions().length == 0) {
+ return null;
+ }
+
+ MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
+ if (properties != null) {
+ return properties.getMethod();
+ }
+ final JavaResolveResult resolveResult = getMethodResult(arg);
+ return resolveResult instanceof MethodCandidateInfo ? (PsiMethod)resolveResult.getElement() : null;
+ }
+
+ private void collectLambdaReturnExpression(Set<ConstraintFormula> additionalConstraints,
+ PsiLambdaExpression lambdaExpression,
+ PsiType parameterType) {
+ final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(parameterType);
+ if (interfaceReturnType != null) {
+ final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(lambdaExpression);
+ for (PsiExpression returnExpression : returnExpressions) {
+ processReturnExpression(additionalConstraints, returnExpression, interfaceReturnType);
+ }
+ }
+ }
+
+ private void processReturnExpression(Set<ConstraintFormula> additionalConstraints,
+ PsiExpression returnExpression,
+ PsiType functionalType) {
+ if (returnExpression instanceof PsiCallExpression) {
+ final PsiMethod calledMethod = getCalledMethod((PsiCallExpression)returnExpression);
+ if (PsiPolyExpressionUtil.isMethodCallPolyExpression(returnExpression, calledMethod)) {
+ collectAdditionalConstraints(additionalConstraints, (PsiCallExpression)returnExpression);
+ }
+ }
+ else if (returnExpression instanceof PsiParenthesizedExpression) {
+ processReturnExpression(additionalConstraints, ((PsiParenthesizedExpression)returnExpression).getExpression(), functionalType);
+ }
+ else if (returnExpression instanceof PsiConditionalExpression) {
+ processReturnExpression(additionalConstraints, ((PsiConditionalExpression)returnExpression).getThenExpression(), functionalType);
+ processReturnExpression(additionalConstraints, ((PsiConditionalExpression)returnExpression).getElseExpression(), functionalType);
+ }
+ else if (returnExpression instanceof PsiLambdaExpression) {
+ collectLambdaReturnExpression(additionalConstraints, (PsiLambdaExpression)returnExpression, functionalType);
+ }
+ }
+
private void collectAdditionalConstraints(final Set<ConstraintFormula> additionalConstraints,
final PsiCallExpression callExpression) {
PsiExpressionList argumentList = callExpression.getArgumentList();
if (argumentList != null) {
- final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(argumentList, PsiLambdaExpression.class);
- final Computable<JavaResolveResult> computableResolve = new Computable<JavaResolveResult>() {
- @Override
- public JavaResolveResult compute() {
- return callExpression.resolveMethodGenerics();
- }
- };
+ final JavaResolveResult result = getMethodResult(callExpression);
MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
- final JavaResolveResult result = properties != null ? null :
- expression == null
- ? computableResolve.compute()
- : PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, false, computableResolve);
final PsiMethod method = result instanceof MethodCandidateInfo ? ((MethodCandidateInfo)result).getElement() : properties != null ? properties.getMethod() : null;
if (method != null) {
final PsiExpression[] newArgs = argumentList.getExpressions();
final PsiParameter[] newParams = method.getParameterList().getParameters();
if (newParams.length > 0) {
collectAdditionalConstraints(newParams, newArgs, method, result != null ? ((MethodCandidateInfo)result).getSiteSubstitutor() : properties.getSubstitutor(),
- additionalConstraints, result != null ? ((MethodCandidateInfo)result).isVarargs() : properties.isVarargs(), false);
+ additionalConstraints, result != null ? ((MethodCandidateInfo)result).isVarargs() : properties.isVarargs());
}
}
}
}
+ private static JavaResolveResult getMethodResult(final PsiCallExpression callExpression) {
+ final PsiExpressionList argumentList = callExpression.getArgumentList();
+
+ final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(argumentList, PsiLambdaExpression.class);
+ final Computable<JavaResolveResult> computableResolve = new Computable<JavaResolveResult>() {
+ @Override
+ public JavaResolveResult compute() {
+ return callExpression.resolveMethodGenerics();
+ }
+ };
+ MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
+ return properties != null ? null :
+ expression == null
+ ? computableResolve.compute()
+ : PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, false, computableResolve);
+ }
+
public PsiSubstitutor retrieveNonPrimitiveEqualsBounds(Collection<InferenceVariable> variables) {
PsiSubstitutor substitutor = mySiteSubstitutor;
for (InferenceVariable variable : variables) {
@@ -702,7 +747,7 @@ public class InferenceSession {
}
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
- final PsiTypeParameter[] freshParameters = createFreshVariables(vars);
+ final PsiTypeParameter[] freshParameters = createFreshVariables(vars, substitutor);
for (int i = 0; i < freshParameters.length; i++) {
PsiTypeParameter parameter = freshParameters[i];
final InferenceVariable var = vars.get(i);
@@ -725,7 +770,7 @@ public class InferenceSession {
return substitutor;
}
- private PsiTypeParameter[] createFreshVariables(final List<InferenceVariable> vars) {
+ private PsiTypeParameter[] createFreshVariables(final List<InferenceVariable> vars, final PsiSubstitutor siteSubstitutor) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
@@ -742,7 +787,7 @@ public class InferenceSession {
final String classText = "class I<" + StringUtil.join(vars, new Function<InferenceVariable, String>() {
@Override
public String fun(InferenceVariable variable) {
- final PsiType glb = composeBound(variable, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, ySubstitutor, true);
+ final PsiType glb = composeBound(variable, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, ySubstitutor.putAll(siteSubstitutor), true);
return getFreshVariableName(variable) + " extends " + glb.getInternalCanonicalText();
}
}, ", ") + ">{}";
@@ -860,46 +905,67 @@ public class InferenceSession {
//extract subset of constraints
final Set<ConstraintFormula> subset = buildSubset(additionalConstraints);
- //collect all input variables of selection
+ //collect all input variables of selection
final Set<InferenceVariable> varsToResolve = new LinkedHashSet<InferenceVariable>();
for (ConstraintFormula formula : subset) {
if (formula instanceof InputOutputConstraintFormula) {
- final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)formula).getInputVariables(this);
- if (inputVariables != null) {
- for (InferenceVariable inputVariable : inputVariables) {
- varsToResolve.addAll(inputVariable.getDependencies(this));
- }
- varsToResolve.addAll(inputVariables);
- }
+ collectVarsToResolve(varsToResolve, (InputOutputConstraintFormula)formula);
}
}
- //resolve input variables
- PsiSubstitutor substitutor = resolveSubset(varsToResolve, siteSubstitutor);
- if (substitutor == null) {
- return false;
+ for (ConstraintFormula formula : subset) {
+ if (!processOneConstraint(formula, siteSubstitutor, varsToResolve)) return false;
}
+ }
+ return true;
+ }
- if (myContext instanceof PsiCallExpression) {
- PsiExpressionList argumentList = ((PsiCallExpression)myContext).getArgumentList();
- LOG.assertTrue(argumentList != null);
- MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
+ private void collectVarsToResolve(Set<InferenceVariable> varsToResolve, InputOutputConstraintFormula formula) {
+ final Set<InferenceVariable> inputVariables = formula.getInputVariables(this);
+ if (inputVariables != null) {
+ for (InferenceVariable inputVariable : inputVariables) {
+ varsToResolve.addAll(inputVariable.getDependencies(this));
}
+ varsToResolve.addAll(inputVariables);
+ }
+ }
- try {
- for (ConstraintFormula additionalConstraint : subset) {
- additionalConstraint.apply(substitutor, true);
- }
-
- myConstraints.addAll(subset);
- if (!repeatInferencePhases(true)) {
- return false;
+ private boolean processOneConstraint(ConstraintFormula formula, PsiSubstitutor siteSubstitutor, Set<InferenceVariable> varsToResolve) {
+ if (formula instanceof ExpressionCompatibilityConstraint) {
+ final PsiExpression expression = ((ExpressionCompatibilityConstraint)formula).getExpression();
+ final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(expression, PsiCallExpression.class, false);
+ if (callExpression != null) {
+ final InferenceSession session = myNestedSessions.get(callExpression);
+ if (session != null) {
+ formula.apply(session.myInferenceSubstitution, true);
+ collectVarsToResolve(varsToResolve, (InputOutputConstraintFormula)formula);
}
}
- finally {
- LambdaUtil.ourFunctionTypes.set(null);
+ }
+
+ //resolve input variables
+ PsiSubstitutor substitutor = resolveSubset(varsToResolve, siteSubstitutor);
+ if (substitutor == null) {
+ return false;
+ }
+
+ if (myContext instanceof PsiCallExpression) {
+ PsiExpressionList argumentList = ((PsiCallExpression)myContext).getArgumentList();
+ LOG.assertTrue(argumentList != null);
+ MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
+ }
+
+ try {
+ formula.apply(substitutor, true);
+
+ myConstraints.add(formula);
+ if (!repeatInferencePhases(true)) {
+ return false;
}
}
+ finally {
+ LambdaUtil.ourFunctionTypes.set(null);
+ }
return true;
}
@@ -1139,9 +1205,6 @@ public class InferenceSession {
}
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg);
- if (sReturnType == PsiType.VOID) {
- return returnExpressions.isEmpty() && session == null;
- }
if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(sReturnType), TypeConversionUtil.erasure(tReturnType)) &&
@@ -1197,10 +1260,6 @@ public class InferenceSession {
return true;
}
- if (sReturnType == PsiType.VOID && session != null) {
- return false;
- }
-
final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && sReturnType != PsiType.VOID;
final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && tReturnType != PsiType.VOID;
@@ -1295,6 +1354,14 @@ public class InferenceSession {
return myInferenceSubstitution.substitute(type);
}
+ public InferenceSession findNestedCallSession(PsiExpression arg) {
+ InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(arg, PsiCallExpression.class));
+ if (session == null) {
+ session = this;
+ }
+ return session;
+ }
+
public PsiType startWithFreshVars(PsiType type) {
PsiSubstitutor s = PsiSubstitutor.EMPTY;
for (InferenceVariable variable : myInferenceVariables) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
index 8d91b620f798..da7b4b78930a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
@@ -17,6 +17,7 @@ package com.intellij.psi.impl.source.resolve.graphInference;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightTypeParameter;
+import com.intellij.psi.util.PsiUtil;
import java.util.*;
@@ -49,6 +50,10 @@ public class InferenceVariable extends LightTypeParameter {
}
public boolean addBound(PsiType classType, InferenceBound inferenceBound) {
+ if (inferenceBound == InferenceBound.EQ &&
+ PsiUtil.resolveClassInClassTypeOnly(classType) == this) {
+ return false;
+ }
List<PsiType> list = myBounds.get(inferenceBound);
if (list == null) {
list = new ArrayList<PsiType>();
@@ -77,20 +82,18 @@ public class InferenceVariable extends LightTypeParameter {
}
}
+ if (!session.hasCapture(this) && dependencies.isEmpty()) {
+ return dependencies;
+ }
+
next:
for (InferenceVariable variable : session.getInferenceVariables()) {
if (!dependencies.contains(variable) && variable != this) {
- nextBound:
- for (List<PsiType> bounds : myBounds.values()) { //todo
+ for (List<PsiType> bounds : variable.myBounds.values()) { //todo
if (bounds != null) {
for (PsiType bound : bounds) {
- final Set<InferenceVariable> deps = new HashSet<InferenceVariable>();
- session.collectDependencies(bound, deps);
- if (deps.isEmpty()) {
- continue nextBound;
- }
-
- if (deps.contains(this)) {
+ final InferenceVariable inferenceVariable = session.getInferenceVariable(bound);
+ if (inferenceVariable == this) {
dependencies.add(variable);
continue next;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
index c282481e79c0..f7e9badfa33c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
@@ -3,6 +3,7 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import java.util.List;
@@ -62,8 +63,9 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible
return false;
}
- returnType = session.substituteWithInferenceVariables(substitutor.substitute(returnType));
- if (!session.isProperType(returnType)) {
+ InferenceSession callsession = session.findNestedCallSession(myExpression);
+ returnType = callsession.substituteWithInferenceVariables(substitutor.substitute(returnType));
+ if (!callsession.isProperType(returnType)) {
for (PsiExpression returnExpression : returnExpressions) {
constraints.add(new ExpressionCompatibilityConstraint(returnExpression, returnType));
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
index fbfd8195fc11..b5e4188e1644 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
@@ -169,11 +169,11 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
LOG.assertTrue(referencedMethodReturnType != null, method);
- session.initBounds(method.getTypeParameters());
+ session.initBounds(myExpression, method.getTypeParameters());
if (!PsiTreeUtil.isContextAncestor(containingClass, myExpression, false) ||
PsiUtil.getEnclosingStaticElement(myExpression, containingClass) != null) {
- session.initBounds(containingClass.getTypeParameters());
+ session.initBounds(myExpression, containingClass.getTypeParameters());
}
//if i) the method reference elides NonWildTypeArguments,
@@ -243,7 +243,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
if (qualifierClass != null) {
- session.initBounds(qualifierClass.getTypeParameters());
+ session.initBounds(myExpression, qualifierClass.getTypeParameters());
constraints.add(new StrictSubtypingConstraint(session.substituteWithInferenceVariables(qualifierType),
session.substituteWithInferenceVariables(substitutor.substitute(targetParameters[0].getType()))));
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java
index 412b09eadec3..6b3c104aab35 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java
@@ -92,8 +92,22 @@ public class StrictSubtypingConstraint implements ConstraintFormula {
return false;
}
- if (!(myS instanceof PsiClassType)) return false;
- PsiClassType.ClassResolveResult SResult = ((PsiClassType)myS).resolveGenerics();
+ PsiClassType.ClassResolveResult SResult = null;
+ if (myS instanceof PsiIntersectionType) {
+ for (PsiType conjunct : ((PsiIntersectionType)myS).getConjuncts()) {
+ if (conjunct instanceof PsiClassType) {
+ final PsiClassType.ClassResolveResult conjunctResult = ((PsiClassType)conjunct).resolveGenerics();
+ if (InheritanceUtil.isInheritorOrSelf(conjunctResult.getElement(), CClass, true)) {
+ SResult = conjunctResult;
+ break;
+ }
+ }
+ }
+ } else if (myS instanceof PsiClassType) {
+ SResult = ((PsiClassType)myS).resolveGenerics();
+ }
+
+ if (SResult == null) return false;
PsiClass SClass = SResult.getElement();
if (((PsiClassType)myT).isRaw()) {
return SClass != null && InheritanceUtil.isInheritorOrSelf(SClass, CClass, true);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
index 069f667d92cf..9d35ace98cf4 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
@@ -30,7 +30,6 @@ import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.containers.IntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -78,16 +77,11 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
@Override
public boolean isVoidCompatible() {
final PsiElement body = getBody();
- if (body != null) {
- try {
- ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy
- .getInstance());
- int startOffset = controlFlow.getStartOffset(body);
- int endOffset = controlFlow.getEndOffset(body);
- return startOffset != -1 && endOffset != -1 && !ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset);
- }
- catch (AnalysisCanceledException e) {
- return true;
+ if (body instanceof PsiCodeBlock) {
+ for (PsiReturnStatement statement : PsiUtil.findReturnStatements((PsiCodeBlock)body)) {
+ if (statement.getReturnValue() != null) {
+ return false;
+ }
}
}
return true;
@@ -96,18 +90,25 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
@Override
public boolean isValueCompatible() {
final PsiElement body = getBody();
- if (body != null) {
+ if (body instanceof PsiCodeBlock) {
try {
- final ControlFlow controlFlow =
- ControlFlowFactory.getInstance(getProject()).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
- if (ControlFlowUtil.findExitPointsAndStatements(controlFlow, 0, controlFlow.getSize(), new IntArrayList(),
- PsiReturnStatement.class,
- PsiThrowStatement.class).isEmpty()) {
+ ControlFlow controlFlow =
+ ControlFlowFactory.getInstance(getProject()).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy
+ .getInstance());
+ int startOffset = controlFlow.getStartOffset(body);
+ int endOffset = controlFlow.getEndOffset(body);
+ if (startOffset != -1 && endOffset != -1 && ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset)) {
return false;
}
}
catch (AnalysisCanceledException e) {
- return true;
+ return false;
+ }
+
+ for (PsiReturnStatement statement : PsiUtil.findReturnStatements((PsiCodeBlock)body)) {
+ if (statement.getReturnValue() == null) {
+ return false;
+ }
}
}
return true;
@@ -200,17 +201,36 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
}
}
+
+ //A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
+ // The arity of the target type's function type is the same as the arity of the lambda expression.
+ // If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
+ // If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
+ PsiType methodReturnType = interfaceMethod.getReturnType();
if (checkReturnType) {
final String uniqueVarName = JavaCodeStyleManager.getInstance(getProject()).suggestUniqueVariableName("l", this, true);
final String canonicalText = toArray(leftType).getCanonicalText();
final PsiStatement assignmentFromText = JavaPsiFacade.getElementFactory(getProject())
.createStatementFromText(canonicalText + " " + uniqueVarName + " = " + getText(), this);
final PsiLocalVariable localVariable = (PsiLocalVariable)((PsiDeclarationStatement)assignmentFromText).getDeclaredElements()[0];
- PsiType methodReturnType = interfaceMethod.getReturnType();
if (methodReturnType != null) {
return LambdaHighlightingUtil.checkReturnTypeCompatible((PsiLambdaExpression)localVariable.getInitializer(),
substitutor.substitute(methodReturnType)) == null;
}
+ } else {
+ final PsiElement body = getBody();
+ if (methodReturnType == PsiType.VOID) {
+ if (body instanceof PsiCodeBlock) {
+ return isVoidCompatible();
+ } else {
+ return LambdaUtil.isExpressionStatementExpression(body);
+ }
+ } else {
+ if (body instanceof PsiCodeBlock) {
+ return isValueCompatible();
+ }
+ return body instanceof PsiExpression;
+ }
}
return true;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
index 3d9ea08125a8..6bb33be05ea5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
@@ -158,7 +158,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
// A lambda expression or a method reference expression is potentially compatible with a type variable if the type variable is a type parameter of the candidate method.
final PsiClass paramClass = PsiUtil.resolveClassInType(paramType);
if (paramClass instanceof PsiTypeParameter && ((PsiTypeParameter)paramClass).getOwner() == method) continue;
- if (!lambdaExpression.isAcceptable(((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType), lambdaExpression.hasFormalParameterTypes())) {
+ if (!lambdaExpression.isAcceptable(((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType),
+ InferenceSession.isPertinentToApplicability(lambdaExpression, method))) {
iterator.remove();
}
}
@@ -397,7 +398,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
@MethodCandidateInfo.ApplicabilityLevelConstant
- protected int checkApplicability(@NotNull List<CandidateInfo> conflicts) {
+ public int checkApplicability(@NotNull List<CandidateInfo> conflicts) {
@MethodCandidateInfo.ApplicabilityLevelConstant int maxApplicabilityLevel = 0;
boolean toFilter = false;
for (CandidateInfo conflict : conflicts) {