summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com/intellij/psi/impl
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-psi-impl/src/com/intellij/psi/impl')
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java7
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java20
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java40
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java136
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java67
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java44
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java29
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java137
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java13
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java52
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java14
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java45
17 files changed, 339 insertions, 315 deletions
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index 0de45be17786..77fd0081d161 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -493,6 +493,13 @@ public class PsiImplUtil {
return PsiUtil.captureToplevelWildcards(type, expression);
}
+ final PsiElement parent = toplevel.getParent();
+ if (parent instanceof PsiExpressionList &&
+ PsiUtil.isLanguageLevel8OrHigher(parent) &&
+ parent.getParent() instanceof PsiCallExpression) {
+ return PsiUtil.captureToplevelWildcards(type, expression);
+ }
+
final PsiType normalized = doNormalizeWildcardByPosition(type, expression, toplevel);
LOG.assertTrue(normalized.isValid(), type);
if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(toplevel)) {
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 36a725aa3135..369ce919f5a1 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
@@ -15,15 +15,18 @@
*/
package com.intellij.psi.impl.compiled;
+import com.intellij.diagnostic.PluginException;
import com.intellij.ide.caches.FileContent;
import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationManager;
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;
@@ -35,6 +38,7 @@ import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
+import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
import com.intellij.psi.impl.PsiFileEx;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
@@ -324,7 +328,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
setMirror(mirrorTreeElement);
}
catch (InvalidMirrorException e) {
- LOG.error(file.getPath(), e);
+ LOG.error(file.getPath(), wrapException(e, file));
}
finally {
section.done();
@@ -337,6 +341,18 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
return mirrorTreeElement.getPsi();
}
+ private static Exception wrapException(InvalidMirrorException e, VirtualFile file) {
+ ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+ if (decompiler instanceof ClassFileDecompilers.Light) {
+ PluginId pluginId = PluginManagerCore.getPluginByClassName(decompiler.getClass().getName());
+ if (pluginId != null) {
+ return new PluginException(e, pluginId);
+ }
+ }
+
+ return e;
+ }
+
@Override
public PsiFile getDecompiledPsiFile() {
return (PsiFile)getMirror();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
index 599f756adbc1..16d971238684 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
@@ -17,8 +17,7 @@ package com.intellij.psi.impl.compiled;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.openapi.util.NullableLazyValue;
-import com.intellij.openapi.util.VolatileNullableLazyValue;
+import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
@@ -28,7 +27,6 @@ import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement {
@NonNls static final char VARIANCE_NONE = '\0';
@@ -41,18 +39,18 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
private final PsiElement myParent;
private final String myTypeText;
private final char myVariance;
- private final NullableLazyValue<ClsElementImpl> myChild;
+ private final NotNullLazyValue<Ref<ClsElementImpl>> myChild;
private final NotNullLazyValue<PsiType> myCachedType;
public ClsTypeElementImpl(@NotNull PsiElement parent, @NotNull String typeText, char variance) {
myParent = parent;
myTypeText = TypeInfo.internFrequentType(typeText);
myVariance = variance;
- myChild = new VolatileNullableLazyValue<ClsElementImpl>() {
- @Nullable
+ myChild = new AtomicNotNullLazyValue<Ref<ClsElementImpl>>() {
+ @NotNull
@Override
- protected ClsElementImpl compute() {
- return calculateChild();
+ protected Ref<ClsElementImpl> compute() {
+ return Ref.create(calculateChild());
}
};
myCachedType = new AtomicNotNullLazyValue<PsiType>() {
@@ -67,7 +65,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
@Override
@NotNull
public PsiElement[] getChildren() {
- ClsElementImpl child = myChild.getValue();
+ ClsElementImpl child = myChild.getValue().get();
return child != null ? new PsiElement[]{child} : PsiElement.EMPTY_ARRAY;
}
@@ -111,7 +109,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
setMirrorCheckingType(element, JavaElementType.TYPE);
- ClsElementImpl child = myChild.getValue();
+ ClsElementImpl child = myChild.getValue().get();
if (child != null) {
child.setMirror(element.getFirstChildNode());
}
@@ -157,7 +155,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText);
if (result != null) return result;
- ClsElementImpl childElement = myChild.getValue();
+ ClsElementImpl childElement = myChild.getValue().get();
if (childElement instanceof ClsTypeElementImpl) {
if (isArray()) {
switch (myVariance) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
index a43c02d8a7a4..f304fe250bae 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.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.
@@ -30,16 +30,16 @@ import java.util.List;
/**
* @author max
*/
-public class PsiClassReferenceType extends PsiClassType {
+public class PsiClassReferenceType extends PsiClassType.Stub {
@NotNull
private final PsiJavaCodeReferenceElement myReference;
- public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) {
- this(reference, langLevel, collectAnnotations(reference));
+ public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level) {
+ this(reference, level, collectAnnotations(reference));
}
- public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel, @NotNull PsiAnnotation[] annotations) {
- super(langLevel, annotations);
+ public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level, @NotNull PsiAnnotation[] annotations) {
+ super(level, annotations);
myReference = reference;
}
@@ -89,7 +89,7 @@ public class PsiClassReferenceType extends PsiClassType {
return resolveGenerics().getElement();
}
- private static class DelegatingClassResolveResult implements ClassResolveResult {
+ private static class DelegatingClassResolveResult implements PsiClassType.ClassResolveResult {
private final JavaResolveResult myDelegate;
private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) {
@@ -182,19 +182,37 @@ public class PsiClassReferenceType extends PsiClassType {
@NotNull
@Override
public String getPresentableText() {
- return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference);
+ String presentableText = PsiNameHelper.getPresentableText(myReference);
+ PsiAnnotation[] annotations = getAnnotations();
+ if (annotations.length == 0) return presentableText;
+
+ StringBuilder sb = new StringBuilder();
+ PsiNameHelper.appendAnnotations(sb, annotations, false);
+ sb.append(presentableText);
+ return sb.toString();
}
@NotNull
@Override
- public String getCanonicalText() {
- return myReference.getCanonicalText();
+ public String getCanonicalText(boolean annotated) {
+ return getText(annotated);
}
@NotNull
@Override
public String getInternalCanonicalText() {
- return getAnnotationsTextPrefix(true, false, true) + getCanonicalText();
+ return getText(true);
+ }
+
+ private String getText(boolean annotated) {
+ if (myReference instanceof PsiJavaCodeReferenceElementImpl) {
+ PsiAnnotation[] annotations = getAnnotations();
+ if (!annotated || annotations.length == 0) annotations = null;
+ return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations);
+ }
+ else {
+ return myReference.getCanonicalText();
+ }
}
@NotNull
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
index 9456c29f6ceb..77a45011144d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.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.
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.source;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -30,11 +31,12 @@ import java.util.List;
/**
* @author dsl
*/
-public class PsiImmediateClassType extends PsiClassType {
+public class PsiImmediateClassType extends PsiClassType.Stub {
private final PsiClass myClass;
private final PsiSubstitutor mySubstitutor;
private final PsiManager myManager;
private String myCanonicalText;
+ private String myCanonicalTextAnnotated;
private String myPresentableText;
private String myInternalCanonicalText;
@@ -80,15 +82,15 @@ public class PsiImmediateClassType extends PsiClassType {
this(aClass, substitutor, null, PsiAnnotation.EMPTY_ARRAY);
}
- public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) {
- this(aClass, substitutor, languageLevel, PsiAnnotation.EMPTY_ARRAY);
+ public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel level) {
+ this(aClass, substitutor, level, PsiAnnotation.EMPTY_ARRAY);
}
public PsiImmediateClassType(@NotNull PsiClass aClass,
@NotNull PsiSubstitutor substitutor,
- @Nullable LanguageLevel languageLevel,
- @NotNull PsiAnnotation[] annotations) {
- super(languageLevel, annotations);
+ @Nullable LanguageLevel level,
+ @NotNull PsiAnnotation... annotations) {
+ super(level, annotations);
myClass = aClass;
myManager = aClass.getManager();
mySubstitutor = substitutor;
@@ -138,112 +140,119 @@ public class PsiImmediateClassType extends PsiClassType {
@Override
public String getPresentableText() {
if (myPresentableText == null) {
- StringBuilder buffer = new StringBuilder();
- buildText(myClass, mySubstitutor, buffer, false, false);
- myPresentableText = buffer.toString();
+ myPresentableText = getText(TextType.PRESENTABLE, true);
}
return myPresentableText;
}
@NotNull
@Override
- public String getCanonicalText() {
- if (myCanonicalText == null) {
- assert mySubstitutor.isValid();
- StringBuilder buffer = new StringBuilder();
- buildText(myClass, mySubstitutor, buffer, true, false);
- myCanonicalText = buffer.toString();
+ public String getCanonicalText(boolean annotated) {
+ String cached = annotated ? myCanonicalTextAnnotated : myCanonicalText;
+ if (cached == null) {
+ cached = getText(TextType.CANONICAL, annotated);
+ if (annotated) myCanonicalTextAnnotated = cached;
+ else myCanonicalText = cached;
}
- return myCanonicalText;
+ return cached;
}
@NotNull
@Override
public String getInternalCanonicalText() {
if (myInternalCanonicalText == null) {
- StringBuilder buffer = new StringBuilder();
- buildText(myClass, mySubstitutor, buffer, true, true);
- myInternalCanonicalText = buffer.toString();
+ myInternalCanonicalText = getText(TextType.INT_CANONICAL, true);
}
return myInternalCanonicalText;
}
+ private enum TextType { PRESENTABLE, CANONICAL, INT_CANONICAL }
+
+ private String getText(@NotNull TextType textType, boolean annotated) {
+ assert mySubstitutor.isValid();
+ StringBuilder buffer = new StringBuilder();
+ buildText(myClass, mySubstitutor, buffer, textType, annotated);
+ return buffer.toString();
+ }
+
private void buildText(@NotNull PsiClass aClass,
@NotNull PsiSubstitutor substitutor,
@NotNull StringBuilder buffer,
- boolean canonical,
- boolean internal) {
+ @NotNull TextType textType,
+ boolean annotated) {
if (aClass instanceof PsiAnonymousClass) {
- ClassResolveResult baseResolveResult = ((PsiAnonymousClass) aClass).getBaseClassType().resolveGenerics();
+ ClassResolveResult baseResolveResult = ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics();
PsiClass baseClass = baseResolveResult.getElement();
- PsiSubstitutor baseSub = baseResolveResult.getSubstitutor();
if (baseClass != null) {
- buildText(baseClass, baseSub, buffer, canonical, internal);
+ buildText(baseClass, baseResolveResult.getSubstitutor(), buffer, textType, false);
}
return;
}
- if (canonical == internal) {
- buffer.append(getAnnotationsTextPrefix(internal, false, true));
- }
+ boolean qualified = textType != TextType.PRESENTABLE;
PsiClass enclosingClass = null;
if (!aClass.hasModifierProperty(PsiModifier.STATIC)) {
- final PsiElement parent = aClass.getParent();
+ PsiElement parent = aClass.getParent();
if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) {
enclosingClass = (PsiClass)parent;
}
}
if (enclosingClass != null) {
- buildText(enclosingClass, substitutor, buffer, canonical, false);
+ buildText(enclosingClass, substitutor, buffer, textType, false);
buffer.append('.');
- buffer.append(aClass.getName());
}
- else {
- final String name;
- if (!canonical) {
- name = aClass.getName();
- }
- else {
- final String qualifiedName = aClass.getQualifiedName();
- if (qualifiedName == null) {
- name = aClass.getName();
- }
- else {
- name = qualifiedName;
+ else if (qualified) {
+ String fqn = aClass.getQualifiedName();
+ if (fqn != null) {
+ String prefix = StringUtil.getPackageName(fqn);
+ if (!StringUtil.isEmpty(prefix)) {
+ buffer.append(prefix);
+ buffer.append('.');
}
}
- buffer.append(name);
}
+ if (annotated) {
+ PsiNameHelper.appendAnnotations(buffer, getAnnotations(), qualified);
+ }
+
+ buffer.append(aClass.getName());
+
PsiTypeParameter[] typeParameters = aClass.getTypeParameters();
if (typeParameters.length > 0) {
- StringBuilder pineBuffer = new StringBuilder();
- pineBuffer.append('<');
+ int pos = buffer.length();
+ buffer.append('<');
+
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
PsiUtilCore.ensureValid(typeParameter);
- if (i > 0) pineBuffer.append(',');
- final PsiType substitutionResult = substitutor.substitute(typeParameter);
+
+ if (i > 0) {
+ buffer.append(',');
+ if (textType == TextType.PRESENTABLE) buffer.append(' ');
+ }
+
+ PsiType substitutionResult = substitutor.substitute(typeParameter);
if (substitutionResult == null) {
- pineBuffer = null;
+ buffer.setLength(pos);
+ pos = -1;
break;
}
PsiUtil.ensureValidType(substitutionResult);
- if (canonical) {
- if (internal) {
- pineBuffer.append(substitutionResult.getInternalCanonicalText());
- }
- else {
- pineBuffer.append(substitutionResult.getCanonicalText());
- }
+
+ if (textType == TextType.PRESENTABLE) {
+ buffer.append(substitutionResult.getPresentableText());
+ }
+ else if (textType == TextType.CANONICAL) {
+ buffer.append(substitutionResult.getCanonicalText(annotated));
}
else {
- pineBuffer.append(substitutionResult.getPresentableText());
+ buffer.append(substitutionResult.getInternalCanonicalText());
}
}
- if (pineBuffer != null) {
- buffer.append(pineBuffer);
+
+ if (pos >= 0) {
buffer.append('>');
}
}
@@ -265,7 +274,6 @@ public class PsiImmediateClassType extends PsiClassType {
return false;
}
return equals(patternType);
-
}
@Override
@@ -277,14 +285,12 @@ public class PsiImmediateClassType extends PsiClassType {
@Override
@NotNull
public LanguageLevel getLanguageLevel() {
- if (myLanguageLevel != null) return myLanguageLevel;
- return PsiUtil.getLanguageLevel(myClass);
+ return myLanguageLevel != null ? myLanguageLevel : PsiUtil.getLanguageLevel(myClass);
}
@NotNull
@Override
- public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
- if (languageLevel.equals(myLanguageLevel)) return this;
- return new PsiImmediateClassType(myClass, mySubstitutor, languageLevel,getAnnotations());
+ public PsiClassType setLanguageLevel(@NotNull LanguageLevel level) {
+ return level.equals(myLanguageLevel) ? this : new PsiImmediateClassType(myClass, mySubstitutor, level, getAnnotations());
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
index 396b750c8c2a..5ee1243b09ce 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.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.
@@ -49,6 +49,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.List;
public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference {
@@ -255,36 +256,47 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
@Override
@NotNull
public String getCanonicalText() {
+ return getCanonicalText(false, null);
+ }
+
+ @NotNull
+ public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) {
switch (getKind()) {
case CLASS_NAME_KIND:
case CLASS_OR_PACKAGE_NAME_KIND:
case CLASS_IN_QUALIFIED_NEW_KIND:
final PsiElement target = resolve();
if (target instanceof PsiClass) {
- final PsiClass aClass = (PsiClass)target;
- String name = aClass.getQualifiedName();
- if (name == null) {
- name = aClass.getName(); //?
+ PsiClass aClass = (PsiClass)target;
+ StringBuilder buffer = new StringBuilder();
+
+ PsiElement qualifier = getQualifier();
+ String prefix = null;
+ if (qualifier instanceof PsiJavaCodeReferenceElementImpl) {
+ prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null);
}
- final PsiType[] types = getTypeParameters();
- if (types.length == 0) {
- final PsiElement qualifier = getQualifier();
- if (qualifier instanceof PsiJavaCodeReferenceElement) {
- return StringUtil.getQualifiedName(((PsiJavaCodeReferenceElement)qualifier).getCanonicalText(), aClass.getName());
+ else {
+ String fqn = aClass.getQualifiedName();
+ if (fqn != null) {
+ prefix = StringUtil.getPackageName(fqn);
}
- return name;
}
- final StringBuilder buf = new StringBuilder();
- buf.append(name);
- buf.append('<');
- for (int i = 0; i < types.length; i++) {
- if (i > 0) buf.append(',');
- buf.append(types[i].getCanonicalText());
+ if (!StringUtil.isEmpty(prefix)) {
+ buffer.append(prefix);
+ buffer.append('.');
}
- buf.append('>');
- return buf.toString();
+ if (annotated) {
+ List<PsiAnnotation> list = annotations != null ? Arrays.asList(annotations) : getAnnotations();
+ PsiNameHelper.appendAnnotations(buffer, list, true);
+ }
+
+ buffer.append(aClass.getName());
+
+ PsiNameHelper.appendTypeArgs(buffer, getTypeParameters(), true, annotated);
+
+ return buffer.toString();
}
else if (target instanceof PsiPackage) {
return ((PsiPackage)target).getQualifiedName();
@@ -293,6 +305,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
LOG.assertTrue(target == null, target);
return getNormalizedText();
}
+
case PACKAGE_NAME_KIND:
case CLASS_FQ_NAME_KIND:
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
@@ -327,7 +340,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) {
VariableResolverProcessor processor = new VariableResolverProcessor(referenceElement, containingFile);
- PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, incompleteCode);
+ PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, true);
result = processor.getResult();
if (result.length == 0 && kind == CLASS_NAME_KIND) {
result = referenceElement.resolve(PACKAGE_NAME_KIND, containingFile);
@@ -457,16 +470,16 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
case CLASS_FQ_OR_PACKAGE_NAME_KIND:
case CLASS_OR_PACKAGE_NAME_KIND: {
int classKind = kind == CLASS_OR_PACKAGE_NAME_KIND ? CLASS_NAME_KIND : CLASS_FQ_NAME_KIND;
- JavaResolveResult[] result = resolve(classKind,containingFile);
+ JavaResolveResult[] result = resolve(classKind, containingFile);
if (result.length == 1 && !result[0].isAccessible()) {
- JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND,containingFile);
+ JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND, containingFile);
if (packageResult.length != 0) {
result = packageResult;
}
}
else if (result.length == 0) {
- result = resolve(PACKAGE_NAME_KIND,containingFile);
+ result = resolve(PACKAGE_NAME_KIND, containingFile);
}
return result;
@@ -607,7 +620,12 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
for (PsiAnnotation annotation : annotations) {
if (annotation.getParent() != newParent) {
- newParent.addAfter(annotation, anchor);
+ if (anchor != null) {
+ newParent.addAfter(annotation, anchor);
+ }
+ else {
+ newParent.add(annotation);
+ }
annotation.delete();
}
}
@@ -935,7 +953,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
final PsiReferenceParameterList parameterList = getParameterList();
if (parameterList == null) return PsiType.EMPTY_ARRAY;
return parameterList.getTypeArguments();
-
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
index 5b76439ef406..20db589bef5c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
@@ -225,15 +225,21 @@ public class JavaResolveUtil {
return true;
}
- public static void substituteResults(@NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
+ public static void substituteResults(final @NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
if (result.length > 0 && result[0].getElement() instanceof PsiClass) {
- PsiType[] parameters = ref.getTypeParameters();
for (int i = 0; i < result.length; i++) {
- CandidateInfo resolveResult = (CandidateInfo)result[i];
- PsiElement resultElement = resolveResult.getElement();
+ final CandidateInfo resolveResult = (CandidateInfo)result[i];
+ final PsiElement resultElement = resolveResult.getElement();
if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) {
- PsiSubstitutor substitutor = resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters);
- result[i] = new CandidateInfo(resolveResult, substitutor);
+ PsiSubstitutor substitutor = resolveResult.getSubstitutor();
+ result[i] = new CandidateInfo(resolveResult, substitutor) {
+ @NotNull
+ @Override
+ public PsiSubstitutor getSubstitutor() {
+ final PsiType[] parameters = ref.getTypeParameters();
+ return super.getSubstitutor().putAll((PsiClass)resultElement, parameters);
+ }
+ };
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
index a52ea73a18d5..b4b188c772cc 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.resolve.graphInference;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
@@ -102,7 +101,7 @@ public class FunctionalInterfaceParameterizationUtil {
return null;
}
- final PsiSubstitutor substitutor = session.resolveDependencies(session.getInferenceVariables());
+ final PsiSubstitutor substitutor = session.retrieveNonPrimitiveEqualsBounds(session.getInferenceVariables());
final PsiType[] newTypeParameters = new PsiType[parameters.length];
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
@@ -119,14 +118,10 @@ public class FunctionalInterfaceParameterizationUtil {
return null;
}
- if (!TypeConversionUtil.containsWildcards(parameterization)) {
+ if (!TypeConversionUtil.containsWildcards(parameterization) && psiClassType.isAssignableFrom(parameterization)) {
return parameterization;
}
- if (!psiClassType.isAssignableFrom(parameterization)) {
- return null;
- }
-
return getNonWildcardParameterization((PsiClassType)psiClassType);
}
return null;
@@ -169,27 +164,32 @@ public class FunctionalInterfaceParameterizationUtil {
for (int i = 0; i < parameters.length; i++) {
PsiType paramType = parameters[i];
if (paramType instanceof PsiWildcardType) {
- final PsiClassType[] extendsListTypes = typeParameters[i].getExtendsListTypes();
- final PsiClassType Bi = extendsListTypes.length > 0 ? extendsListTypes[0]
- : PsiType.getJavaLangObject(psiClass.getManager(),
- GlobalSearchScope.allScope(psiClass.getProject()));
- if (PsiPolyExpressionUtil.mentionsTypeParameters(Bi, typeParametersSet)) {
- return null;
+ final PsiType bound = GenericsUtil.eliminateWildcards(((PsiWildcardType)paramType).getBound(), false);
+ if (((PsiWildcardType)paramType).isSuper()) {
+ newParameters[i] = bound;
}
-
- final PsiType bound = ((PsiWildcardType)paramType).getBound();
- if (bound == null) {
- newParameters[i] = Bi;
- } else if (((PsiWildcardType)paramType).isExtends()){
- newParameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false));
- } else {
- newParameters[i] = GenericsUtil.eliminateWildcards(bound, false);
+ else {
+ newParameters[i] = bound != null ? bound : PsiType.getJavaLangObject(psiClass.getManager(), psiClassType.getResolveScope());
+ for (PsiClassType paramBound : typeParameters[i].getExtendsListTypes()) {
+ if (!PsiPolyExpressionUtil.mentionsTypeParameters(paramBound, typeParametersSet)) {
+ newParameters[i] = GenericsUtil.getGreatestLowerBound(paramBound, newParameters[i]);
+ }
+ }
}
} else {
newParameters[i] = paramType;
}
}
- return JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+
+ if (!isWellFormed(psiClass, typeParameters, newParameters)) {
+ return null;
+ }
+
+ final PsiClassType parameterization = JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+ if (!psiClassType.isAssignableFrom(parameterization)) {
+ return null;
+ }
+ return parameterization;
}
return null;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
index cc666815c2d2..f30c7ae6382c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
@@ -110,18 +110,6 @@ public class InferenceIncorporationPhase {
}
}
}
-
- //todo no such a rule in spec?!
- for (PsiType lowerBound : lowerBounds) {
- if (mySession.isProperType(lowerBound)) {
- final PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.put(inferenceVariable.getParameter(), lowerBound);
- for (PsiType upperBound : upperBounds) {
- if (!mySession.isProperType(upperBound)) {
- addConstraint(new StrictSubtypingConstraint(substitutor.substitute(upperBound), lowerBound));
- }
- }
- }
- }
}
for (Pair<PsiTypeParameter[], PsiClassType> capture : myCaptures) {
@@ -389,21 +377,4 @@ public class InferenceIncorporationPhase {
}
}
}
-
- public PsiSubstitutor checkIncorporated(PsiSubstitutor substitutor, Collection<InferenceVariable> variables) {
- for (InferenceVariable variable : variables) { //todo equals bounds?
- for (PsiType lowerBound : variable.getBounds(InferenceBound.LOWER)) {
- lowerBound = substitutor.substitute(lowerBound);
- if (mySession.isProperType(lowerBound)) {
- for (PsiType upperBound : variable.getBounds(InferenceBound.UPPER)) {
- upperBound = substitutor.substitute(upperBound);
- if (mySession.isProperType(upperBound) && !TypeConversionUtil.isAssignable(upperBound, lowerBound)) {
- return null;
- }
- }
- }
- }
- }
- return substitutor;
- }
}
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 abde4616fe77..53911011bc17 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
@@ -20,15 +20,8 @@ import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
import com.intellij.psi.infos.MethodCandidateInfo;
-import com.intellij.psi.scope.MethodProcessorSetupFailedException;
-import com.intellij.psi.scope.PsiConflictResolver;
-import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
-import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
-import com.intellij.psi.scope.processor.MethodResolverProcessor;
-import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
@@ -174,7 +167,8 @@ public class InferenceSession {
return true;
}
- private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, PsiSubstitutor substitutor) {
+ private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, @Nullable PsiSubstitutor substitutor) {
+ if (substitutor == null) return null;
PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType());
if (parameterType instanceof PsiEllipsisType) {
final PsiExpression arg = args[i];
@@ -213,7 +207,7 @@ public class InferenceSession {
PsiMethod parentMethod) {
if (!repeatInferencePhases(true)) {
//inferred result would be checked as candidate won't be applicable
- return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
+ return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
}
if (parentMethod != null) {
@@ -299,17 +293,17 @@ public class InferenceSession {
}
}
} else {
- return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
+ return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
}
return prepareSubstitution();
}
- public PsiSubstitutor resolveDependencies(Collection<InferenceVariable> variables) {
+ public PsiSubstitutor retrieveNonPrimitiveEqualsBounds(Collection<InferenceVariable> variables) {
PsiSubstitutor substitutor = mySiteSubstitutor;
for (InferenceVariable variable : variables) {
final PsiType equalsBound = getEqualsBound(variable, substitutor);
- if (equalsBound != PsiType.NULL) {
+ if (!(equalsBound instanceof PsiPrimitiveType)) {
substitutor = substitutor.put(variable.getParameter(), equalsBound);
}
}
@@ -340,9 +334,13 @@ public class InferenceSession {
return false;
}
- public void initBounds(PsiTypeParameter... typeParameters) {
+ public boolean initBounds(PsiTypeParameter... typeParameters) {
+ boolean sameMethodCall = false;
for (PsiTypeParameter parameter : typeParameters) {
- if (myInferenceVariables.containsKey(parameter)) continue;
+ if (myInferenceVariables.containsKey(parameter)) {
+ sameMethodCall = true;
+ continue;
+ }
InferenceVariable variable = new InferenceVariable(parameter);
boolean added = false;
final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
@@ -359,29 +357,19 @@ public class InferenceSession {
}
myInferenceVariables.put(parameter, variable);
}
- }
-
- public void addCapturedVariable(PsiTypeParameter param) {
- initBounds(param);
+ return sameMethodCall;
}
private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
- if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method) ||
- context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) {
+ if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method)) {
PsiType returnType = method.getReturnType();
if (!PsiType.VOID.equals(returnType) && returnType != null) {
- returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context);
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
if (targetType == null) {
- targetType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(context, false, new Computable<PsiType>() {
- @Override
- public PsiType compute() {
- return getTargetType(context);
- }
- });
+ targetType = getTargetType(context);
}
if (targetType != null) {
- registerConstraints(returnType, targetType);
+ registerConstraints(PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType);
}
}
}
@@ -397,7 +385,7 @@ public class InferenceSession {
public void registerConstraints(PsiType returnType, PsiType targetType) {
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
- final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
+ final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutor.substitute(inferenceVariable.getParameter()), myContext)));
}
else {
@@ -412,7 +400,7 @@ public class InferenceSession {
PsiTypeParameter[] copy = new PsiTypeParameter[typeParameters.length];
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
- copy[i] = elementFactory.createTypeParameterFromText(typeParameter.getName(), null);
+ copy[i] = elementFactory.createTypeParameterFromText("rCopy" + typeParameter.getName(), null);
initBounds(copy[i]);
subst = subst.put(typeParameter, elementFactory.createType(copy[i]));
}
@@ -495,7 +483,7 @@ public class InferenceSession {
return false;
}
- private PsiType getTargetType(final PsiExpression context) {
+ private static PsiType getTargetType(final PsiExpression context) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
if (parent instanceof PsiExpressionList) {
PsiElement gParent = parent.getParent();
@@ -505,28 +493,8 @@ public class InferenceSession {
if (gParent instanceof PsiCallExpression) {
final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList();
if (argumentList != null) {
- final Pair<PsiMethod, PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
- final PsiFile placeFile = context.getContainingFile();
- final JavaMethodsConflictResolver conflictResolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(placeFile)){
- @Override
- protected PsiType[] getArgumentTypes() {
- return InferenceSession.getArgumentTypes(argumentList, context);
- }
- };
- final MethodCandidatesProcessor processor = new MethodResolverProcessor((PsiCallExpression)gParent, placeFile, new PsiConflictResolver[]{conflictResolver}) {
- @Override
- protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
- return getArgumentTypes(argumentList, context);
- }
- };
- try {
- PsiScopesUtil.setupAndRunProcessor(processor, (PsiCallExpression)gParent, false);
- }
- catch (MethodProcessorSetupFailedException e) {
- return null;
- }
- final JavaResolveResult[] results = processor.getResult();
- return results.length == 1 ? getTypeByMethod(context, argumentList, pair, results[0], results[0].getElement()) : null;
+ final JavaResolveResult result = ((PsiCallExpression)gParent).resolveMethodGenerics();
+ return getTypeByMethod(context, argumentList, result, result.getElement());
}
}
} else if (parent instanceof PsiConditionalExpression) {
@@ -546,30 +514,9 @@ public class InferenceSession {
return null;
}
- private static PsiType[] getArgumentTypes(PsiExpressionList argumentList, PsiExpression context) {
- if (argumentList != null) {
- final PsiExpression[] expressions = argumentList.getExpressions();
- final int idx = LambdaUtil.getLambdaIdx(argumentList, context);
- final PsiType[] types = PsiType.createArray(expressions.length);
- for (int i = 0; i < expressions.length; i++) {
- if (i != idx) {
- types[i] = expressions[i].getType();
- }
- else {
- types[i] = PsiType.NULL;
- }
- }
- return types;
- }
- else {
- return null;
- }
- }
-
- private PsiType getTypeByMethod(PsiExpression context,
- PsiExpressionList argumentList,
- Pair<PsiMethod, PsiSubstitutor> pair,
- JavaResolveResult result, PsiElement parentMethod) {
+ private static PsiType getTypeByMethod(PsiExpression context,
+ PsiExpressionList argumentList,
+ final JavaResolveResult result, PsiElement parentMethod) {
if (parentMethod instanceof PsiMethod) {
final PsiParameter[] parameters = ((PsiMethod)parentMethod).getParameterList().getParameters();
if (parameters.length == 0) return null;
@@ -581,23 +528,13 @@ public class InferenceSession {
}
final int i = ArrayUtilRt.find(args, arg);
if (i < 0) return null;
- final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(argumentList, PsiCallExpression.class);
- if (callExpression != null && callExpression.getTypeArguments().length > 0) {
- return getParameterType(parameters, args, i, ((MethodCandidateInfo)result).typeArgumentsSubstitutor());
- }
- final PsiType parameterType = getParameterType(parameters, args, i, pair != null ? pair.second : PsiSubstitutor.EMPTY);
- args[i] = null;
- final PsiTypeParameter[] typeParameters = ((PsiMethod)parentMethod).getTypeParameters();
- final InferenceSession session = new InferenceSession(typeParameters, ((MethodCandidateInfo)result).getSiteSubstitutor(), myManager, argumentList);
- session.initExpressionConstraints(parameters, args, argumentList, (PsiMethod)parentMethod);
- if (session.tryToInfer(parameters, args, callExpression, (PsiMethod)parentMethod) != null) {
- return null;
- }
- final Collection<PsiTypeParameter> params = session.getTypeParams();
- initBounds(params.toArray(new PsiTypeParameter[params.size()]));
- liftBounds(session.getInferenceVariables());
- final PsiSubstitutor substitutor = ((MethodCandidateInfo)result).getSiteSubstitutor();
- return substitutor.substitute(parameterType);
+ return getParameterType(parameters, args, i, PsiResolveHelper.ourGraphGuard.doPreventingRecursion(argumentList.getParent(), false,
+ new Computable<PsiSubstitutor>() {
+ @Override
+ public PsiSubstitutor compute() {
+ return result.getSubstitutor();
+ }
+ }));
}
return null;
}
@@ -720,7 +657,7 @@ public class InferenceSession {
while (!allVars.isEmpty()) {
final List<InferenceVariable> vars = InferenceVariablesOrder.resolveOrder(allVars, this);
if (!myIncorporationPhase.hasCaptureConstraints(vars)) {
- final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor, true);
+ final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor);
if (firstSubstitutor != null) {
substitutor = firstSubstitutor;
allVars.removeAll(vars);
@@ -731,7 +668,7 @@ public class InferenceSession {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
for (InferenceVariable var : vars) {
final PsiTypeParameter parameter = var.getParameter();
- final PsiTypeParameter copy = elementFactory.createTypeParameterFromText(parameter.getName(), null);
+ final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
final PsiType lub = getLowerBound(var, substitutor);
final PsiType glb = getUpperBound(var, substitutor);
final InferenceVariable zVariable = new InferenceVariable(copy);
@@ -744,6 +681,8 @@ public class InferenceSession {
zVariable.addBound(lub, InferenceBound.LOWER);
}
myInferenceVariables.put(copy, zVariable);
+ allVars.add(zVariable);
+ var.addBound(elementFactory.createType(copy), InferenceBound.EQ);
}
myIncorporationPhase.forgetCaptures(vars);
if (!myIncorporationPhase.incorporate()) {
@@ -762,7 +701,7 @@ public class InferenceSession {
}, substitutor);
}
- private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor, boolean checkResult) {
+ private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor) {
for (InferenceVariable var : vars) {
LOG.assertTrue(var.getInstantiation() == PsiType.NULL);
final PsiTypeParameter typeParameter = var.getParameter();
@@ -781,7 +720,7 @@ public class InferenceSession {
}
}
- return checkResult ? myIncorporationPhase.checkIncorporated(substitutor, vars) : substitutor;
+ return substitutor;
}
private PsiType getUpperBound(InferenceVariable var, PsiSubstitutor substitutor) {
@@ -872,7 +811,7 @@ public class InferenceSession {
}
//resolve input variables
- PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor, true);
+ PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor);
if (substitutor == null) {
return false;
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 a67b64eea669..a629175b9d48 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
@@ -48,17 +48,6 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
return true;
}
- if (myExpression instanceof PsiCallExpression) {
- final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
- if (argumentList != null) {
- for (PsiExpression expression : argumentList.getExpressions()) {
- if (PsiPolyExpressionUtil.isPolyExpression(expression)) {
- //todo additional constraints [JDK-8033488]
- }
- }
- }
- return true;
- }
if (myExpression instanceof PsiParenthesizedExpression) {
constraints.add(new CheckedExceptionCompatibilityConstraint(((PsiParenthesizedExpression)myExpression).getExpression(), myT));
return true;
@@ -122,7 +111,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
final PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
final PsiMethod method;
if (((PsiMethodReferenceExpression)myExpression).isExact()) {
- final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).resolve();
+ final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).getPotentiallyApplicableMember();
if (resolve instanceof PsiMethod) {
method = (PsiMethod)resolve;
} else {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index 30628e36beb6..ebcbda6a2926 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -21,10 +21,13 @@ import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
import com.intellij.psi.infos.MethodCandidateInfo;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -99,22 +102,51 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (typeParams != null) {
- for (PsiTypeParameter typeParam : typeParams) {
- session.addCapturedVariable(typeParam);
- }
+ final HashSet<PsiTypeParameter> oldBounds = new HashSet<PsiTypeParameter>(session.getTypeParams());
+ final boolean sameMethodCall = session.initBounds(typeParams);
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
+ final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
+ session.collectDependencies(returnType, variables);
+ final PsiTypeParameter[] params = new PsiTypeParameter[typeParams.length];
+ for (int i = 0; i < typeParams.length; i++) {
+ if (variables.contains(session.getInferenceVariable(typeParams[i]))) {
+ params[i] = JavaPsiFacade.getElementFactory(myExpression.getProject()).createTypeParameterFromText("copyOf" + myExpression.hashCode() + typeParams[i].getName(), null);
+ substitutor = substitutor.put(typeParams[i], JavaPsiFacade.getElementFactory(myExpression.getProject()).createType(params[i]));
+ }
+ else {
+ params[i] = typeParams[i];
+ }
+ }
+ final PsiSubstitutor siteSubstitutor = resolveResult instanceof MethodCandidateInfo && method != null && !method.isConstructor()
+ ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() : PsiSubstitutor.EMPTY;
+ for (PsiTypeParameter typeParameter : siteSubstitutor.getSubstitutionMap().keySet()) {
+ substitutor = substitutor.put(typeParameter, substitutor.substitute(siteSubstitutor.substitute(typeParameter)));
+ }
+
+ final Collection<PsiTypeParameter> params1 = session.getTypeParams();
+ final InferenceSession callSession = new InferenceSession(params1.toArray(new PsiTypeParameter[params1.size()]), substitutor, myExpression.getManager(), myExpression);
+ callSession.initBounds(params);
if (method != null) {
- //typeParams are already included
- final Collection<PsiTypeParameter> params = session.getTypeParams();
- InferenceSession callSession = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor()
- : PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
callSession.initExpressionConstraints(parameters, args, myExpression, method);
- callSession.registerConstraints(returnType, myT);
- if (callSession.repeatInferencePhases(true)) {
- session.liftBounds(callSession.getInferenceVariables());
+ }
+ final boolean accepted = callSession.repeatInferencePhases(true);
+ if (!accepted) {
+ //todo return false;
+ }
+ callSession.registerConstraints(method != null && !PsiUtil.isRawSubstitutor(method, siteSubstitutor) ? siteSubstitutor.substitute(returnType) : returnType, substitutor.substitute(returnType));
+ if (callSession.repeatInferencePhases(true)) {
+ final Collection<InferenceVariable> inferenceVariables = callSession.getInferenceVariables();
+ if (sameMethodCall) {
+ for (Iterator<InferenceVariable> iterator = inferenceVariables.iterator(); iterator.hasNext(); ) {
+ InferenceVariable variable = iterator.next();
+ if (oldBounds.contains(variable.getParameter())) {
+ iterator.remove();
+ }
+ }
}
+ session.liftBounds(inferenceVariables);
}
final PsiType capturedReturnType = myExpression instanceof PsiMethodCallExpression
? PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, substitutor)
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
index 7e2443a8232f..cbb1db809c4a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
@@ -109,6 +109,11 @@ public class TypeEqualityConstraint implements ConstraintFormula {
return true;
}
+ if (myT instanceof PsiCapturedWildcardType && myS instanceof PsiCapturedWildcardType) {
+ return new TypeEqualityConstraint(((PsiCapturedWildcardType)myT).getWildcard(),
+ ((PsiCapturedWildcardType)myS).getWildcard()).reduce(session, constraints);
+ }
+
return false;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
index 58c29706c1a3..18ff2d110ad9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
@@ -25,7 +25,6 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,18 +54,19 @@ public class JavaSharedImplUtil {
return type;
}
+ // collects annotations bound to C-style arrays
private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor, PsiAnnotation stopAt) {
- List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>();
+ List<PsiAnnotation[]> annotations = ContainerUtil.newSmartList();
List<PsiAnnotation> current = null;
- boolean stop = false;
+ boolean found = (stopAt == null), stop = false;
for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) {
if (child instanceof PsiComment || child instanceof PsiWhiteSpace) continue;
if (child instanceof PsiAnnotation) {
- if (current == null) current = new SmartList<PsiAnnotation>();
+ if (current == null) current = ContainerUtil.newSmartList();
current.add((PsiAnnotation)child);
- if (child == stopAt) stop = true;
+ if (child == stopAt) found = stop = true;
continue;
}
@@ -80,8 +80,8 @@ public class JavaSharedImplUtil {
}
}
- // stop == true means annotation is misplaced
- return stop ? null : annotations;
+ // annotation is misplaced (either located before the anchor or has no following brackets)
+ return !found || stop ? null : annotations;
}
public static void normalizeBrackets(@NotNull PsiVariable variable) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java
index f6ba9fdf5af4..918d7fed7237 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.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.
@@ -131,7 +131,7 @@ public class JavaTreeGenerator implements TreeGenerator {
type = PsiType.getJavaLangObject(manager, GlobalSearchScope.projectScope(manager.getProject()));
}
- String text = type.getPresentableText();
+ String text = type.getCanonicalText(true);
PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(original.getProject()).getParserFacade();
PsiTypeElement element = parserFacade.createTypeElementFromText(text, original);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
index cf40d04ca427..1d8693efc55c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 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.
@@ -38,7 +38,8 @@ public class ExpressionPsiElement extends CompositePsiElement {
@Override
public void replaceChildInternal(@NotNull ASTNode child, @NotNull TreeElement newElement) {
- if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
+ if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType()) &&
+ ElementType.EXPRESSION_BIT_SET.contains(newElement.getElementType())) {
boolean needParenth = ReplaceExpressionUtil.isNeedParenthesis(child, newElement);
if (needParenth) {
newElement = SourceUtil.addParenthToReplacedChild(JavaElementType.PARENTH_EXPRESSION, newElement, getManager());
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 fdd02e86ebb3..084be88d7428 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
@@ -499,6 +499,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiClass pClass = pResult.getElement();
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
if (receiverSubstitutor != null) {
+ if (!method.hasTypeParameters() && signature.getParameterTypes().length == 1) return receiverSubstitutor;
psiSubstitutor = receiverSubstitutor;
}
}
@@ -638,20 +639,26 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
}
}
- checkSpecifics(firstCandidates,
- varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
-
- checkSpecifics(secondCandidates,
- varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
-
if (myQualifierResolveResult.isReferenceTypeQualified() && getReferenceNameElement() instanceof PsiIdentifier) {
//If the first search produces a static method, and no non-static method is applicable for the second search, then the result of the first search is the compile-time declaration.
- filterStaticCorrectCandidates(firstCandidates, true);
+ CandidateInfo candidateInfo = filterStaticCorrectCandidates(firstCandidates, secondCandidates, true);
+ if (candidateInfo != null) {
+ return candidateInfo;
+ }
//If the second search produces a non-static method, and no static method is applicable for the first search, then the result of the second search is the compile-time declaration.
- filterStaticCorrectCandidates(secondCandidates, false);
+ candidateInfo = filterStaticCorrectCandidates(secondCandidates, firstCandidates, false);
+ if (candidateInfo != null) {
+ return candidateInfo;
+ }
}
+ checkSpecifics(firstCandidates,
+ varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
+
+ checkSpecifics(secondCandidates,
+ varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
+
final int acceptedCount = firstCandidates.size() + secondCandidates.size();
if (acceptedCount == 1) {
return !firstCandidates.isEmpty() ? firstCandidates.get(0) : secondCandidates.get(0);
@@ -684,17 +691,29 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
/**
* 15.13.1
*/
- private void filterStaticCorrectCandidates(List<CandidateInfo> firstCandidates,
+ private CandidateInfo filterStaticCorrectCandidates(List<CandidateInfo> firstCandidates,
+ List<CandidateInfo> secondCandidates,
boolean shouldBeStatic) {
- for (Iterator<CandidateInfo> iterator = firstCandidates.iterator(); iterator.hasNext(); ) {
- final PsiElement element = iterator.next().getElement();
+ if (firstCandidates.size() == 1) {
+ final CandidateInfo candidateInfo = firstCandidates.get(0);
+ final PsiElement element = candidateInfo.getElement();
if (element instanceof PsiMethod) {
final boolean isStatic = ((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC);
- if (shouldBeStatic && !isStatic || !shouldBeStatic && isStatic) {
- iterator.remove();
+ if (shouldBeStatic && isStatic || !shouldBeStatic && !isStatic) {
+ for (CandidateInfo secondCandidate : secondCandidates) {
+ final PsiElement psiElement = secondCandidate.getElement();
+ if (psiElement instanceof PsiMethod) {
+ final boolean oppositeStatic = ((PsiMethod)psiElement).hasModifierProperty(PsiModifier.STATIC);
+ if (shouldBeStatic && !oppositeStatic || !shouldBeStatic && oppositeStatic) {
+ return null;
+ }
+ }
+ }
+ return candidateInfo;
}
}
}
+ return null;
}
private boolean isCorrectAssignment(PsiType[] signatureParameterTypes2,