mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PsiTypeElementImpl: compute type parameter reference based on parent
GitOrigin-RevId: 7c302e763b94e9de7bc014c1a5ab3bd11a886522
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8af6291573
commit
15e1ca57c9
@@ -25,8 +25,13 @@ import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -200,17 +205,102 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
public boolean isInferredType() {
|
||||
return PsiUtil.isJavaToken(getFirstChild(), JavaTokenType.VAR_KEYWORD) || getTypeInfo().myInferred;
|
||||
}
|
||||
|
||||
private boolean isArrayType() {
|
||||
for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
if (PsiUtil.isJavaToken(child, JavaTokenType.ELLIPSIS) || PsiUtil.isJavaToken(child, JavaTokenType.LBRACKET)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private @NotNull ClassReferencePointer getReferenceComputable(@NotNull PsiJavaCodeReferenceElement ref) {
|
||||
final PsiElement parent = getParent();
|
||||
if (parent instanceof PsiMethod || parent instanceof PsiVariable) {
|
||||
PsiElement parent = getParent();
|
||||
int depth = 0;
|
||||
PsiElement cur = this;
|
||||
boolean arrayOnly = true;
|
||||
while (parent instanceof PsiTypeElementImpl && PsiTreeUtil.getChildOfType(parent, PsiTypeElementImpl.class) == cur) {
|
||||
cur = parent;
|
||||
if (!((PsiTypeElementImpl)parent).isArrayType()) {
|
||||
arrayOnly = false;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
depth++;
|
||||
}
|
||||
if ((parent instanceof PsiMethod || parent instanceof PsiVariable) && arrayOnly) {
|
||||
return computeFromTypeOwner(parent, new WeakReference<>(ref));
|
||||
}
|
||||
if (parent instanceof PsiReferenceParameterList) {
|
||||
PsiJavaCodeReferenceElement parentRef = ObjectUtils.tryCast(parent.getParent(), PsiJavaCodeReferenceElement.class);
|
||||
if (parentRef != null) {
|
||||
PsiTypeElementImpl parentType = ObjectUtils.tryCast(parentRef.getParent(), PsiTypeElementImpl.class);
|
||||
if (parentType != null) {
|
||||
int index = ArrayUtil.indexOf(((PsiReferenceParameterList)parent).getTypeParameterElements(), cur);
|
||||
if (index != -1) {
|
||||
ClassReferencePointer computable = parentType.getReferenceComputable(parentRef);
|
||||
return computeFromParentType(computable, index, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ClassReferencePointer.constant(ref);
|
||||
}
|
||||
|
||||
private static @NotNull ClassReferencePointer computeFromTypeOwner(PsiElement parent, @NotNull WeakReference<PsiJavaCodeReferenceElement> ref) {
|
||||
private static @NotNull ClassReferencePointer computeFromParentType(ClassReferencePointer parent, int index, int depth) {
|
||||
return new ClassReferencePointer() {
|
||||
@Override
|
||||
public @Nullable PsiJavaCodeReferenceElement retrieveReference() {
|
||||
PsiJavaCodeReferenceElement ref = parent.retrieveReference();
|
||||
if (ref == null) return null;
|
||||
PsiReferenceParameterList list = ref.getParameterList();
|
||||
if (list == null) return null;
|
||||
PsiTypeElement[] elements = list.getTypeParameterElements();
|
||||
if (index >= elements.length) return null;
|
||||
PsiTypeElementImpl subElement = ObjectUtils.tryCast(elements[index], PsiTypeElementImpl.class);
|
||||
if (subElement == null) return null;
|
||||
for (int i = 0; i < depth; i++) {
|
||||
subElement = PsiTreeUtil.getChildOfType(subElement, PsiTypeElementImpl.class);
|
||||
if (subElement == null) return null;
|
||||
}
|
||||
return subElement.getReferenceElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiJavaCodeReferenceElement retrieveNonNullReference() {
|
||||
PsiJavaCodeReferenceElement ref = parent.retrieveNonNullReference();
|
||||
PsiReferenceParameterList list = ref.getParameterList();
|
||||
if (list == null) {
|
||||
throw new IllegalStateException("Parent reference has type arguments: " + ref.getText());
|
||||
}
|
||||
PsiTypeElement[] elements = list.getTypeParameterElements();
|
||||
if (index >= elements.length) {
|
||||
throw new IllegalStateException(
|
||||
"Parent reference has too few type arguments (required: " + (index + 1) + "; " + ref.getText() + ")");
|
||||
}
|
||||
PsiTypeElementImpl subElement = ObjectUtils.tryCast(elements[index], PsiTypeElementImpl.class);
|
||||
for (int i = 0; i < depth; i++) {
|
||||
subElement = PsiTreeUtil.getChildOfType(subElement, PsiTypeElementImpl.class);
|
||||
if (subElement == null) break;
|
||||
}
|
||||
PsiJavaCodeReferenceElement subRef = subElement == null ? null : subElement.getReferenceElement();
|
||||
if (subRef == null) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid subElement: " + ref.getText() + ";" + elements[index].getText() + "; wanted depth = " + depth);
|
||||
}
|
||||
return subRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parent + "<#" + index + ">" + (depth == 0 ? "" : "-> " + depth);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static @NotNull ClassReferencePointer computeFromTypeOwner(PsiElement parent,
|
||||
@NotNull WeakReference<PsiJavaCodeReferenceElement> ref) {
|
||||
return new ClassReferencePointer() {
|
||||
volatile WeakReference<PsiJavaCodeReferenceElement> myCache = ref;
|
||||
|
||||
@@ -230,7 +320,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
@Nullable
|
||||
private PsiType calcTypeByParent() {
|
||||
PsiType type = parent instanceof PsiMethod ? ((PsiMethod)parent).getReturnType() : ((PsiVariable)parent).getType();
|
||||
if (type instanceof PsiArrayType) { //for c-style array, e.g. String args[]
|
||||
if (type instanceof PsiArrayType) { //also, for c-style array, e.g. String args[]
|
||||
return type.getDeepComponentType();
|
||||
}
|
||||
return type;
|
||||
|
||||
Reference in New Issue
Block a user