mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-stubs] Part of IDEA-246761 Support type annotations in various places of class stubs
Supported: 1. Class extends list 2. Class implements list 3. Class type parameter bounds 4. Method type parameter bounds 5. Throws list Not supported yet: 1. Class type parameters 2. Method type parameters 3. Method receiver type GitOrigin-RevId: 7ca87689c52726ede9d22cb7ec683692af66ba06
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cff373e542
commit
119ec1ae16
@@ -35,6 +35,8 @@ public class TypeInfo {
|
||||
private static final int HAS_TYPE_ANNOTATIONS = 0x20;
|
||||
private static final int HAS_ARRAY_COUNT = 0x40;
|
||||
private static final int HAS_ELLIPSIS = 0x80;
|
||||
|
||||
public static final TypeInfo[] EMPTY_ARRAY = {};
|
||||
|
||||
private static final String[] ourIndexFrequentType;
|
||||
private static final TObjectIntHashMap<String> ourFrequentTypeIndex;
|
||||
@@ -54,7 +56,7 @@ public class TypeInfo {
|
||||
assert ourFrequentTypeIndex.size() < FREQUENT_INDEX_MASK;
|
||||
}
|
||||
|
||||
private static final TypeInfo NULL = new TypeInfo(null, (byte)0, false);
|
||||
private static final TypeInfo NULL = new TypeInfo(null);
|
||||
|
||||
public final String text;
|
||||
public final byte arrayCount;
|
||||
@@ -73,6 +75,20 @@ public class TypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a non-array type info
|
||||
*
|
||||
* @param text type text (not array)
|
||||
*/
|
||||
public TypeInfo(String text) {
|
||||
this(text, (byte)0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text type text (not array)
|
||||
* @param arrayCount number of array components (including vararg component, if any)
|
||||
* @param ellipsis if true, the last array component should be interpreted as vararg
|
||||
*/
|
||||
public TypeInfo(String text, byte arrayCount, boolean ellipsis) {
|
||||
this.text = text == null ? null : internFrequentType(text);
|
||||
this.arrayCount = arrayCount;
|
||||
@@ -80,7 +96,7 @@ public class TypeInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param typeAnnotations set type annotations. Could be called only once during the creation.
|
||||
* @param typeAnnotations set type annotations. Could be called only once.
|
||||
*/
|
||||
public void setTypeAnnotations(@NotNull TypeAnnotationContainer typeAnnotations) {
|
||||
if (myTypeAnnotations != null) {
|
||||
@@ -89,6 +105,9 @@ public class TypeInfo {
|
||||
myTypeAnnotations = typeAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type annotations associated with this type.
|
||||
*/
|
||||
public @NotNull TypeAnnotationContainer getTypeAnnotations() {
|
||||
return myTypeAnnotations == null ? TypeAnnotationContainer.EMPTY : myTypeAnnotations;
|
||||
}
|
||||
|
||||
@@ -18,32 +18,27 @@ package com.intellij.psi.impl.compiled;
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClsReferenceListImpl extends ClsRepositoryPsiElement<PsiClassReferenceListStub> implements PsiReferenceList {
|
||||
private static final ClsJavaCodeReferenceElementImpl[] EMPTY_REFS_ARRAY = new ClsJavaCodeReferenceElementImpl[0];
|
||||
|
||||
private final NotNullLazyValue<ClsJavaCodeReferenceElementImpl[]> myRefs;
|
||||
private final NotNullLazyValue<PsiJavaCodeReferenceElement[]> myRefs;
|
||||
|
||||
public ClsReferenceListImpl(@NotNull PsiClassReferenceListStub stub) {
|
||||
super(stub);
|
||||
myRefs = new AtomicNotNullLazyValue<ClsJavaCodeReferenceElementImpl[]>() {
|
||||
myRefs = new AtomicNotNullLazyValue<PsiJavaCodeReferenceElement[]>() {
|
||||
@Override
|
||||
protected ClsJavaCodeReferenceElementImpl @NotNull [] compute() {
|
||||
String[] strings = getStub().getReferencedNames();
|
||||
if (strings.length > 0) {
|
||||
ClsJavaCodeReferenceElementImpl[] refs = new ClsJavaCodeReferenceElementImpl[strings.length];
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
refs[i] = new ClsJavaCodeReferenceElementImpl(ClsReferenceListImpl.this, strings[i]);
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
else {
|
||||
return EMPTY_REFS_ARRAY;
|
||||
protected PsiJavaCodeReferenceElement @NotNull [] compute() {
|
||||
TypeInfo[] types = getStub().getTypes();
|
||||
if (types.length <= 0) {
|
||||
return PsiJavaCodeReferenceElement.EMPTY_ARRAY;
|
||||
}
|
||||
return ContainerUtil.map2Array(types, PsiJavaCodeReferenceElement.class, info ->
|
||||
new ClsJavaCodeReferenceElementImpl(ClsReferenceListImpl.this, info.text, info.getTypeAnnotations()));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -70,10 +65,13 @@ public class ClsReferenceListImpl extends ClsRepositoryPsiElement<PsiClassRefere
|
||||
|
||||
@Override
|
||||
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
|
||||
String[] names = getStub().getReferencedNames();
|
||||
if (names.length != 0) {
|
||||
switch (getRole()) {
|
||||
PsiClassType @NotNull [] types = getStub().getReferencedTypes();
|
||||
if (types.length != 0) {
|
||||
Role role = getRole();
|
||||
switch (role) {
|
||||
case EXTENDS_BOUNDS_LIST:
|
||||
buffer.append(' ').append(PsiKeyword.EXTENDS).append(' ');
|
||||
break;
|
||||
case EXTENDS_LIST:
|
||||
buffer.append(PsiKeyword.EXTENDS).append(' ');
|
||||
break;
|
||||
@@ -87,9 +85,9 @@ public class ClsReferenceListImpl extends ClsRepositoryPsiElement<PsiClassRefere
|
||||
buffer.append(PsiKeyword.WITH).append(' ');
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (i > 0) buffer.append(", ");
|
||||
buffer.append(names[i]);
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (i > 0) buffer.append(role == Role.EXTENDS_BOUNDS_LIST ? " & " : ", ");
|
||||
buffer.append(types[i].getCanonicalText(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +95,13 @@ public class ClsReferenceListImpl extends ClsRepositoryPsiElement<PsiClassRefere
|
||||
@Override
|
||||
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
|
||||
setMirrorCheckingType(element, null);
|
||||
setMirrors(getReferenceElements(), SourceTreeToPsiMap.<PsiReferenceList>treeToPsiNotNull(element).getReferenceElements());
|
||||
PsiJavaCodeReferenceElement[] mirrorRefs = SourceTreeToPsiMap.<PsiReferenceList>treeToPsiNotNull(element).getReferenceElements();
|
||||
PsiJavaCodeReferenceElement[] stubRefs = getReferenceElements();
|
||||
if (mirrorRefs.length == 0 && stubRefs.length == 1 && CommonClassNames.JAVA_LANG_OBJECT.equals(stubRefs[0].getQualifiedName())) {
|
||||
// annotated Object type is supported in stubs but not supported in decompiler yet
|
||||
return;
|
||||
}
|
||||
setMirrors(stubRefs, mirrorRefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,6 +116,6 @@ public class ClsReferenceListImpl extends ClsRepositoryPsiElement<PsiClassRefere
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiReferenceList";
|
||||
return "PsiReferenceList:" + getRole();
|
||||
}
|
||||
}
|
||||
@@ -280,15 +280,7 @@ public class ClsTypeParameterImpl extends ClsRepositoryPsiElement<PsiTypeParamet
|
||||
@Override
|
||||
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
|
||||
buffer.append(getName());
|
||||
|
||||
PsiJavaCodeReferenceElement[] bounds = getExtendsList().getReferenceElements();
|
||||
if (bounds.length > 0) {
|
||||
buffer.append(" extends ");
|
||||
for (int i = 0; i < bounds.length; i++) {
|
||||
if (i > 0) buffer.append(" & ");
|
||||
buffer.append(bounds[i].getCanonicalText());
|
||||
}
|
||||
}
|
||||
appendText(getExtendsList(), indentLevel, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,9 +3,11 @@ package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import one.util.streamex.EntryStream;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
@@ -65,11 +67,25 @@ class FirstPassData implements Function<@NotNull String, @NotNull String> {
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param componentName record component name
|
||||
* @return true if given component is var-arg
|
||||
*/
|
||||
public boolean isVarArgComponent(@NotNull String componentName) {
|
||||
return componentName.equals(myVarArgRecordComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jvmNames array JVM type names (e.g. throws list, implements list)
|
||||
* @return list of TypeInfo objects that correspond to given types
|
||||
*/
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public List<TypeInfo> createTypes(String @Nullable [] jvmNames) {
|
||||
return jvmNames == null ? null :
|
||||
ContainerUtil.map(jvmNames, jvmName -> new TypeInfo(mapJvmClassNameToJava(jvmName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jvmName JVM class name like java/util/Map$Entry
|
||||
* @return Java class name like java.util.Map.Entry
|
||||
|
||||
@@ -1,43 +1,91 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||
import com.intellij.psi.impl.java.stubs.PsiTypeParameterListStub;
|
||||
import com.intellij.psi.impl.java.stubs.PsiTypeParameterStub;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiClassReferenceListStubImpl;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterListStubImpl;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterStubImpl;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.cls.ClsFormatException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.TypeReference;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.util.Pair.pair;
|
||||
|
||||
public final class SignatureParsing {
|
||||
private SignatureParsing() { }
|
||||
|
||||
public static class TypeParametersDeclaration {
|
||||
static final TypeParametersDeclaration EMPTY = new TypeParametersDeclaration(Collections.emptyList());
|
||||
|
||||
private final List<TypeParameterDeclaration> myDeclarations;
|
||||
|
||||
@NotNull
|
||||
public static List<Pair<String, String[]>> parseTypeParametersDeclaration(CharacterIterator signature, Function<String, String> mapping) throws ClsFormatException {
|
||||
if (signature.current() != '<') {
|
||||
return Collections.emptyList();
|
||||
private TypeParametersDeclaration(List<TypeParameterDeclaration> declarations) {
|
||||
myDeclarations = declarations;
|
||||
}
|
||||
|
||||
List<Pair<String, String[]>> typeParameters = new ArrayList<>();
|
||||
TypeInfo getBoundType(TypeReference ref) {
|
||||
int typeParameterIndex = ref.getTypeParameterIndex();
|
||||
int boundIndex = ref.getTypeParameterBoundIndex();
|
||||
if (typeParameterIndex < myDeclarations.size()) {
|
||||
TypeParameterDeclaration typeParam = myDeclarations.get(typeParameterIndex);
|
||||
if (boundIndex < typeParam.myBounds.length) {
|
||||
return typeParam.myBounds[boundIndex];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void createTypeParameterList(StubElement<?> parent) {
|
||||
PsiTypeParameterListStub listStub = new PsiTypeParameterListStubImpl(parent);
|
||||
for (TypeParameterDeclaration parameter : this.myDeclarations) {
|
||||
PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(listStub, parameter.myTypeParameter);
|
||||
TypeInfo[] info = parameter.myBounds;
|
||||
if (info.length > 0 && info[0].text == null) {
|
||||
info = Arrays.copyOfRange(info, 1, info.length);
|
||||
}
|
||||
new PsiClassReferenceListStubImpl(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TypeParameterDeclaration {
|
||||
private final String myTypeParameter;
|
||||
private final TypeInfo[] myBounds;
|
||||
|
||||
private TypeParameterDeclaration(String parameter, TypeInfo[] bounds) {
|
||||
myTypeParameter = parameter;
|
||||
myBounds = bounds;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeParametersDeclaration parseTypeParametersDeclaration(CharacterIterator signature, Function<String, String> mapping) throws ClsFormatException {
|
||||
if (signature.current() != '<') {
|
||||
return TypeParametersDeclaration.EMPTY;
|
||||
}
|
||||
|
||||
List<TypeParameterDeclaration> typeParameters = new ArrayList<>();
|
||||
signature.next();
|
||||
while (signature.current() != '>') {
|
||||
typeParameters.add(parseTypeParameter(signature, mapping));
|
||||
}
|
||||
signature.next();
|
||||
return typeParameters;
|
||||
return new TypeParametersDeclaration(typeParameters);
|
||||
}
|
||||
|
||||
private static Pair<String, String[]> parseTypeParameter(CharacterIterator signature, Function<String, String> mapping) throws ClsFormatException {
|
||||
private static TypeParameterDeclaration parseTypeParameter(CharacterIterator signature, Function<String, String> mapping) throws ClsFormatException {
|
||||
StringBuilder name = new StringBuilder();
|
||||
while (signature.current() != ':' && signature.current() != CharacterIterator.DONE) {
|
||||
name.append(signature.current());
|
||||
@@ -48,27 +96,15 @@ public final class SignatureParsing {
|
||||
}
|
||||
String parameterName = mapping.fun(name.toString());
|
||||
|
||||
// postpone list allocation till a second bound is seen; ignore sole Object bound
|
||||
List<String> bounds = null;
|
||||
boolean jlo = false;
|
||||
List<TypeInfo> bounds = new SmartList<>();
|
||||
while (signature.current() == ':') {
|
||||
signature.next();
|
||||
String bound = parseTopLevelClassRefSignature(signature, mapping);
|
||||
if (bound == null) continue;
|
||||
if (bounds == null) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(bound)) {
|
||||
jlo = true;
|
||||
continue;
|
||||
}
|
||||
bounds = new SmartList<>();
|
||||
if (jlo) {
|
||||
bounds.add(CommonClassNames.JAVA_LANG_OBJECT);
|
||||
}
|
||||
}
|
||||
bounds.add(bound);
|
||||
if (!bounds.isEmpty() && bound == null) continue;
|
||||
bounds.add(new TypeInfo(bound));
|
||||
}
|
||||
|
||||
return pair(parameterName, ArrayUtilRt.toStringArray(bounds));
|
||||
return new TypeParameterDeclaration(parameterName, bounds.toArray(TypeInfo.EMPTY_ARRAY));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiNameHelper;
|
||||
import com.intellij.psi.impl.cache.ModifierFlags;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing.TypeParametersDeclaration;
|
||||
import com.intellij.psi.impl.java.stubs.*;
|
||||
import com.intellij.psi.impl.java.stubs.impl.*;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -26,6 +25,7 @@ import org.jetbrains.org.objectweb.asm.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -58,6 +58,8 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
private PsiClassStub<?> myResult;
|
||||
private PsiModifierListStub myModList;
|
||||
private PsiRecordHeaderStub myHeaderStub;
|
||||
private Map<TypeInfo, TypeAnnotationContainer.Builder> myAnnoBuilders;
|
||||
private ClassInfo myClassInfo;
|
||||
|
||||
public StubBuildingVisitor(T classSource, InnerClassSourceStrategy<T> innersStrategy, StubElement<?> parent, int access, String shortName) {
|
||||
this(classSource, innersStrategy, parent, access, shortName, false, false);
|
||||
@@ -105,38 +107,37 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
myHeaderStub = new PsiRecordHeaderStubImpl(myResult);
|
||||
}
|
||||
|
||||
ClassInfo info = null;
|
||||
if (signature != null) {
|
||||
try {
|
||||
info = parseClassSignature(signature);
|
||||
myClassInfo = parseClassSignature(signature);
|
||||
}
|
||||
catch (ClsFormatException e) {
|
||||
if (LOG.isDebugEnabled()) LOG.debug("source=" + mySource + " signature=" + signature, e);
|
||||
}
|
||||
}
|
||||
if (info == null) {
|
||||
info = parseClassDescription(superName, interfaces);
|
||||
if (myClassInfo == null) {
|
||||
myClassInfo = parseClassDescription(superName, interfaces);
|
||||
}
|
||||
|
||||
newTypeParameterList(myResult, info.typeParameters);
|
||||
myClassInfo.typeParameters.createTypeParameterList(myResult);
|
||||
|
||||
if (myResult.isInterface()) {
|
||||
if (info.interfaceNames != null && myResult.isAnnotationType()) {
|
||||
info.interfaceNames.remove(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION);
|
||||
if (myClassInfo.interfaces != null && myResult.isAnnotationType()) {
|
||||
myClassInfo.interfaces.removeIf(info -> info.text.equals(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION));
|
||||
}
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtilRt.toStringArray(info.interfaceNames));
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtilRt.EMPTY_STRING_ARRAY);
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, myClassInfo.interfaces);
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, Collections.emptyList());
|
||||
}
|
||||
else {
|
||||
if (info.superName == null || "java/lang/Object".equals(superName) ||
|
||||
if (myClassInfo.superType == null ||
|
||||
myResult.isEnum() && "java/lang/Enum".equals(superName) ||
|
||||
myResult.isRecord() && "java/lang/Record".equals(superName)) {
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtilRt.EMPTY_STRING_ARRAY);
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, Collections.emptyList());
|
||||
}
|
||||
else {
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, new String[]{info.superName});
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, Collections.singletonList(myClassInfo.superType));
|
||||
}
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtilRt.toStringArray(info.interfaceNames));
|
||||
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, myClassInfo.interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,34 +158,27 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
ClassInfo result = new ClassInfo();
|
||||
CharacterIterator iterator = new StringCharacterIterator(signature);
|
||||
result.typeParameters = SignatureParsing.parseTypeParametersDeclaration(iterator, myFirstPassData);
|
||||
result.superName = SignatureParsing.parseTopLevelClassRefSignature(iterator, myFirstPassData);
|
||||
String superName = SignatureParsing.parseTopLevelClassRefSignature(iterator, myFirstPassData);
|
||||
result.superType = superName == null ? null : new TypeInfo(superName);
|
||||
while (iterator.current() != CharacterIterator.DONE) {
|
||||
String name = SignatureParsing.parseTopLevelClassRefSignature(iterator, myFirstPassData);
|
||||
if (name == null) throw new ClsFormatException();
|
||||
if (result.interfaceNames == null) result.interfaceNames = new SmartList<>();
|
||||
result.interfaceNames.add(name);
|
||||
if (result.interfaces == null) result.interfaces = new SmartList<>();
|
||||
result.interfaces.add(new TypeInfo(name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ClassInfo parseClassDescription(String superClass, String[] superInterfaces) {
|
||||
ClassInfo result = new ClassInfo();
|
||||
result.typeParameters = ContainerUtil.emptyList();
|
||||
result.superName = superClass != null ? myFirstPassData.mapJvmClassNameToJava(superClass) : null;
|
||||
result.interfaceNames = superInterfaces == null ? null : ContainerUtil.map(superInterfaces, myFirstPassData);
|
||||
result.typeParameters = TypeParametersDeclaration.EMPTY;
|
||||
result.superType = superClass != null ? new TypeInfo(myFirstPassData.mapJvmClassNameToJava(superClass)) : null;
|
||||
result.interfaces = myFirstPassData.createTypes(superInterfaces);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void newTypeParameterList(StubElement<?> parent, List<Pair<String, String[]>> parameters) {
|
||||
PsiTypeParameterListStub listStub = new PsiTypeParameterListStubImpl(parent);
|
||||
for (Pair<String, String[]> parameter : parameters) {
|
||||
PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(listStub, parameter.first);
|
||||
newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, parameter.second);
|
||||
}
|
||||
}
|
||||
|
||||
private static void newReferenceList(@NotNull JavaClassReferenceListElementType type, StubElement<?> parent, String @NotNull [] types) {
|
||||
new PsiClassReferenceListStubImpl(type, parent, types);
|
||||
private static void newReferenceList(@NotNull JavaClassReferenceListElementType type, StubElement<?> parent, @Nullable List<TypeInfo> types) {
|
||||
new PsiClassReferenceListStubImpl(type, parent, types == null ? TypeInfo.EMPTY_ARRAY : types.toArray(TypeInfo.EMPTY_ARRAY));
|
||||
}
|
||||
|
||||
private static int packCommonFlags(int access) {
|
||||
@@ -244,6 +238,37 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
return new AnnotationTextCollector(desc, myFirstPassData, text -> new PsiAnnotationStubImpl(myModList, text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||
TypeReference ref = new TypeReference(typeRef);
|
||||
TypeInfo info = null;
|
||||
if (ref.getSort() == TypeReference.CLASS_TYPE_PARAMETER_BOUND) {
|
||||
info = myClassInfo.typeParameters.getBoundType(ref);
|
||||
}
|
||||
else if (ref.getSort() == TypeReference.CLASS_EXTENDS) {
|
||||
int index = ref.getSuperTypeIndex();
|
||||
if (index == -1) {
|
||||
info = myClassInfo.superType;
|
||||
}
|
||||
else if (index >= 0 && index < myClassInfo.interfaces.size()) {
|
||||
info = myClassInfo.interfaces.get(index);
|
||||
}
|
||||
}
|
||||
if (info == null) return null;
|
||||
if (myAnnoBuilders == null) {
|
||||
myAnnoBuilders = new HashMap<>();
|
||||
}
|
||||
return myAnnoBuilders.computeIfAbsent(info, typeInfo -> new TypeAnnotationContainer.Builder(typeInfo, myFirstPassData))
|
||||
.collect(typePath, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (myAnnoBuilders != null) {
|
||||
myAnnoBuilders.values().forEach(TypeAnnotationContainer.Builder::build);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
if (isSet(access, Opcodes.ACC_SYNTHETIC)) return;
|
||||
@@ -369,7 +394,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
|
||||
PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packMethodFlags(access, myResult.isInterface()));
|
||||
|
||||
newTypeParameterList(stub, info.typeParameters);
|
||||
info.typeParameters.createTypeParameterList(stub);
|
||||
|
||||
boolean isEnumConstructor = isConstructor && isEnum;
|
||||
boolean isInnerClassConstructor = isConstructor && !isEnum && isInner() && !isGroovyClosure(canonicalMethodName);
|
||||
@@ -398,11 +423,11 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
new PsiModifierListStubImpl(parameterStub, 0);
|
||||
}
|
||||
|
||||
newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, ArrayUtilRt.toStringArray(info.throwTypes));
|
||||
newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, info.throwTypes);
|
||||
|
||||
int paramIgnoreCount = isEnumConstructor ? 2 : isInnerClassConstructor ? 1 : 0;
|
||||
int localVarIgnoreCount = isEnumConstructor ? 3 : isInnerClassConstructor ? 2 : !isStatic ? 1 : 0;
|
||||
return new MethodAnnotationCollectingVisitor(stub, modList, paramStubs, paramIgnoreCount, localVarIgnoreCount, myFirstPassData);
|
||||
return new MethodAnnotationCollectingVisitor(stub, info, modList, paramStubs, paramIgnoreCount, localVarIgnoreCount, myFirstPassData);
|
||||
}
|
||||
|
||||
private boolean isInner() {
|
||||
@@ -447,11 +472,11 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
while (iterator.current() == '^') {
|
||||
iterator.next();
|
||||
if (result.throwTypes == null) result.throwTypes = new SmartList<>();
|
||||
result.throwTypes.add(SignatureParsing.parseTypeString(iterator, myFirstPassData));
|
||||
result.throwTypes.add(new TypeInfo(SignatureParsing.parseTypeString(iterator, myFirstPassData)));
|
||||
}
|
||||
if (exceptions != null && (result.throwTypes == null || exceptions.length > result.throwTypes.size())) {
|
||||
// a signature may be inconsistent with exception list - in this case, the more complete list takes precedence
|
||||
result.throwTypes = ContainerUtil.map(exceptions, myFirstPassData);
|
||||
result.throwTypes = myFirstPassData.createTypes(exceptions);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -459,25 +484,25 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
|
||||
private MethodInfo parseMethodDescription(String desc, String[] exceptions) {
|
||||
MethodInfo result = new MethodInfo();
|
||||
result.typeParameters = ContainerUtil.emptyList();
|
||||
result.typeParameters = TypeParametersDeclaration.EMPTY;
|
||||
result.returnType = toJavaType(Type.getReturnType(desc), myFirstPassData);
|
||||
result.argTypes = ContainerUtil.map(Type.getArgumentTypes(desc), type -> toJavaType(type, myFirstPassData));
|
||||
result.throwTypes = exceptions == null ? null : ContainerUtil.map(exceptions, myFirstPassData);
|
||||
result.throwTypes = myFirstPassData.createTypes(exceptions);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static class ClassInfo {
|
||||
private List<Pair<String, String[]>> typeParameters;
|
||||
private String superName;
|
||||
private List<String> interfaceNames;
|
||||
private TypeParametersDeclaration typeParameters;
|
||||
private TypeInfo superType;
|
||||
private List<TypeInfo> interfaces;
|
||||
}
|
||||
|
||||
private static class MethodInfo {
|
||||
private List<Pair<String, String[]>> typeParameters;
|
||||
private TypeParametersDeclaration typeParameters;
|
||||
private String returnType;
|
||||
private List<String> argTypes;
|
||||
private List<String> throwTypes;
|
||||
private List<TypeInfo> throwTypes;
|
||||
}
|
||||
|
||||
private static final class FieldAnnotationCollectingVisitor extends FieldVisitor {
|
||||
@@ -546,8 +571,8 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
|
||||
private static final class MethodAnnotationCollectingVisitor extends MethodVisitor {
|
||||
private final PsiMethodStub myOwner;
|
||||
@NotNull
|
||||
private final PsiModifierListStub myModList;
|
||||
private final @NotNull MethodInfo myMethodInfo;
|
||||
private final @NotNull PsiModifierListStub myModList;
|
||||
private final PsiParameterStubImpl[] myParamStubs;
|
||||
private final int myParamCount;
|
||||
private final int myLocalVarIgnoreCount;
|
||||
@@ -559,6 +584,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
private Map<TypeInfo, TypeAnnotationContainer.Builder> myAnnoBuilders;
|
||||
|
||||
private MethodAnnotationCollectingVisitor(PsiMethodStub owner,
|
||||
@NotNull MethodInfo methodInfo,
|
||||
@NotNull PsiModifierListStub modList,
|
||||
PsiParameterStubImpl[] paramStubs,
|
||||
int paramIgnoreCount,
|
||||
@@ -566,6 +592,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
@NotNull FirstPassData firstPassData) {
|
||||
super(ASM_API);
|
||||
myOwner = owner;
|
||||
myMethodInfo = methodInfo;
|
||||
myModList = modList;
|
||||
myParamStubs = paramStubs;
|
||||
myParamCount = paramStubs.length;
|
||||
@@ -609,6 +636,15 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
info = myParamStubs[parameterIndex].getType(false);
|
||||
}
|
||||
}
|
||||
else if (ref.getSort() == TypeReference.METHOD_TYPE_PARAMETER_BOUND) {
|
||||
info = myMethodInfo.typeParameters.getBoundType(ref);
|
||||
}
|
||||
else if (ref.getSort() == TypeReference.THROWS) {
|
||||
int index = ref.getExceptionIndex();
|
||||
if (index < myMethodInfo.throwTypes.size()) {
|
||||
info = myMethodInfo.throwTypes.get(index);
|
||||
}
|
||||
}
|
||||
if (info == null) return null;
|
||||
if (myAnnoBuilders == null) {
|
||||
myAnnoBuilders = new HashMap<>();
|
||||
|
||||
+26
-10
@@ -7,6 +7,8 @@ import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiNameHelper;
|
||||
import com.intellij.psi.PsiReferenceList;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.compiled.TypeAnnotationContainer;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiClassReferenceListStubImpl;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
|
||||
import com.intellij.psi.impl.source.PsiReferenceListImpl;
|
||||
@@ -18,6 +20,7 @@ import com.intellij.psi.stubs.StubInputStream;
|
||||
import com.intellij.psi.stubs.StubOutputStream;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -56,10 +59,16 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
|
||||
|
||||
@Override
|
||||
public void serialize(@NotNull PsiClassReferenceListStub stub, @NotNull StubOutputStream dataStream) throws IOException {
|
||||
String[] names = stub.getReferencedNames();
|
||||
dataStream.writeVarInt(names.length);
|
||||
for (String name : names) {
|
||||
dataStream.writeName(name);
|
||||
TypeInfo[] types = stub.getTypes();
|
||||
boolean hasAnnotations = ContainerUtil.exists(types, info -> !info.getTypeAnnotations().isEmpty());
|
||||
dataStream.writeVarInt(hasAnnotations ? -types.length : types.length);
|
||||
for (TypeInfo info : types) {
|
||||
dataStream.writeName(info.text);
|
||||
}
|
||||
if (hasAnnotations) {
|
||||
for (TypeInfo info : types) {
|
||||
TypeAnnotationContainer.writeTypeAnnotations(dataStream, info.getTypeAnnotations());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,11 +76,18 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
|
||||
@Override
|
||||
public PsiClassReferenceListStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
|
||||
int len = dataStream.readVarInt();
|
||||
String[] names = ArrayUtil.newStringArray(len);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = dataStream.readNameString();
|
||||
boolean hasAnnotations = len < 0;
|
||||
len = Math.abs(len);
|
||||
TypeInfo[] infos = new TypeInfo[len];
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
infos[i] = new TypeInfo(dataStream.readNameString());
|
||||
}
|
||||
return new PsiClassReferenceListStubImpl(this, parentStub, names);
|
||||
if (hasAnnotations) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
infos[i].setTypeAnnotations(TypeAnnotationContainer.readTypeAnnotations(dataStream));
|
||||
}
|
||||
}
|
||||
return new PsiClassReferenceListStubImpl(this, parentStub, infos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,9 +103,9 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
|
||||
}
|
||||
|
||||
if (role == PsiReferenceList.Role.EXTENDS_LIST) {
|
||||
StubElement parentStub = stub.getParentStub();
|
||||
StubElement<?> parentStub = stub.getParentStub();
|
||||
if (parentStub instanceof PsiClassStub) {
|
||||
PsiClassStub psiClassStub = (PsiClassStub)parentStub;
|
||||
PsiClassStub<?> psiClassStub = (PsiClassStub<?>)parentStub;
|
||||
if (psiClassStub.isEnum()) {
|
||||
sink.occurrence(JavaStubIndexKeys.SUPER_CLASSES, "Enum");
|
||||
}
|
||||
|
||||
+14
@@ -21,11 +21,25 @@ package com.intellij.psi.impl.java.stubs;
|
||||
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiReferenceList;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface PsiClassReferenceListStub extends StubElement<PsiReferenceList> {
|
||||
/**
|
||||
* @return types
|
||||
*/
|
||||
PsiClassType @NotNull [] getReferencedTypes();
|
||||
|
||||
/**
|
||||
* @return type names
|
||||
*/
|
||||
String @NotNull [] getReferencedNames();
|
||||
|
||||
/**
|
||||
* @return array of TypeInfo objects
|
||||
*/
|
||||
@NotNull TypeInfo @NotNull [] getTypes();
|
||||
|
||||
@NotNull PsiReferenceList.Role getRole();
|
||||
}
|
||||
+39
-10
@@ -1,26 +1,38 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.java.stubs.impl;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl;
|
||||
import com.intellij.psi.impl.compiled.TypeAnnotationContainer;
|
||||
import com.intellij.psi.impl.java.stubs.JavaClassReferenceListElementType;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiClassReferenceListStubImpl extends StubBase<PsiReferenceList> implements PsiClassReferenceListStub {
|
||||
private final String[] myNames;
|
||||
private volatile PsiClassType[] myTypes;
|
||||
private final TypeInfo @NotNull [] myInfos;
|
||||
private volatile PsiClassType [] myTypes;
|
||||
|
||||
public PsiClassReferenceListStubImpl(@NotNull JavaClassReferenceListElementType type, StubElement parent, String @NotNull [] names) {
|
||||
this(type, parent, ContainerUtil.map2Array(names, TypeInfo.class, TypeInfo::new));
|
||||
}
|
||||
|
||||
public PsiClassReferenceListStubImpl(@NotNull JavaClassReferenceListElementType type, StubElement parent,
|
||||
TypeInfo @NotNull [] infos) {
|
||||
super(parent, type);
|
||||
ObjectUtils.assertAllElementsNotNull(names);
|
||||
myNames = names;
|
||||
for (TypeInfo info : infos) {
|
||||
if (info == null) throw new IllegalArgumentException();
|
||||
if (info.text == null) throw new IllegalArgumentException();
|
||||
}
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,14 +43,24 @@ public class PsiClassReferenceListStubImpl extends StubBase<PsiReferenceList> im
|
||||
}
|
||||
return types.clone();
|
||||
}
|
||||
|
||||
private boolean shouldSkipSoleObject() {
|
||||
final boolean compiled = ((JavaClassReferenceListElementType)getStubType()).isCompiled(this);
|
||||
return compiled && myInfos.length == 1 && myInfos[0].text.equals(CommonClassNames.JAVA_LANG_OBJECT) &&
|
||||
myInfos[0].getTypeAnnotations().isEmpty();
|
||||
}
|
||||
|
||||
private PsiClassType @NotNull [] createTypes() {
|
||||
PsiClassType[] types = myNames.length == 0 ? PsiClassType.EMPTY_ARRAY : new PsiClassType[myNames.length];
|
||||
PsiClassType[] types = myInfos.length == 0 ? PsiClassType.EMPTY_ARRAY : new PsiClassType[myInfos.length];
|
||||
|
||||
final boolean compiled = ((JavaClassReferenceListElementType)getStubType()).isCompiled(this);
|
||||
if (compiled) {
|
||||
if (shouldSkipSoleObject()) return PsiClassType.EMPTY_ARRAY;
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
types[i] = new PsiClassReferenceType(new ClsJavaCodeReferenceElementImpl(getPsi(), myNames[i]), null);
|
||||
TypeInfo info = myInfos[i];
|
||||
TypeAnnotationContainer annotations = info.getTypeAnnotations();
|
||||
ClsJavaCodeReferenceElementImpl reference = new ClsJavaCodeReferenceElementImpl(getPsi(), info.text, annotations);
|
||||
types[i] = new PsiClassReferenceType(reference, null).annotate(annotations.getProvider(reference));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -48,7 +70,7 @@ public class PsiClassReferenceListStubImpl extends StubBase<PsiReferenceList> im
|
||||
final PsiReferenceList psi = getPsi();
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
try {
|
||||
final PsiJavaCodeReferenceElement ref = factory.createReferenceFromText(myNames[i], psi);
|
||||
final PsiJavaCodeReferenceElement ref = factory.createReferenceFromText(myInfos[i].text, psi);
|
||||
((PsiJavaCodeReferenceElementImpl)ref).setKindWhenDummy(PsiJavaCodeReferenceElementImpl.Kind.CLASS_NAME_KIND);
|
||||
types[i] = factory.createType(ref);
|
||||
}
|
||||
@@ -72,7 +94,14 @@ public class PsiClassReferenceListStubImpl extends StubBase<PsiReferenceList> im
|
||||
|
||||
@Override
|
||||
public String @NotNull [] getReferencedNames() {
|
||||
return myNames.clone();
|
||||
if (myInfos.length == 0 || shouldSkipSoleObject()) return ArrayUtil.EMPTY_STRING_ARRAY;
|
||||
return ContainerUtil.map2Array(myInfos, String.class, info -> info.text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TypeInfo @NotNull [] getTypes() {
|
||||
if (shouldSkipSoleObject()) return TypeInfo.EMPTY_ARRAY;
|
||||
return myInfos.clone();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -83,6 +112,6 @@ public class PsiClassReferenceListStubImpl extends StubBase<PsiReferenceList> im
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiRefListStub[" + getRole() + ':' + String.join(", ", myNames) + ']';
|
||||
return "PsiRefListStub[" + getRole() + ':' + String.join(", ", getReferencedNames()) + ']';
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
|
||||
public static final int STUB_VERSION = 49;
|
||||
public static final int STUB_VERSION = 50;
|
||||
|
||||
public JavaFileElementType() {
|
||||
super("java.FILE", JavaLanguage.INSTANCE);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
// IntelliJ API Decompiler stub source generated from a class file
|
||||
// Implementation of methods is not available
|
||||
|
||||
package pkg;
|
||||
|
||||
public class ExtendsObjectAnnotated extends java.lang.@pkg.TA Object {
|
||||
public ExtendsObjectAnnotated() { /* compiled code */ }
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
package pkg;
|
||||
|
||||
public interface TypeAnno <T> extends java.io.Serializable {
|
||||
public interface TypeAnno <T extends java.lang.@pkg.TA(11) Object> extends java.io.@pkg.TA(12) Serializable, java.lang.@pkg.TA(13) Comparable<@pkg.TA(14) T> {
|
||||
java.lang.@pkg.TA(0) String field = "";
|
||||
|
||||
java.util.@pkg.TA(-1) List<java.lang.@pkg.TA String> get1TypeParam();
|
||||
@@ -31,9 +31,11 @@ public interface TypeAnno <T> extends java.io.Serializable {
|
||||
|
||||
java.util.@pkg.TA(0) List<@pkg.TA(1) ? super java.lang.@pkg.TA(2) String @pkg.TA(3) []> getSuperArrayInList();
|
||||
|
||||
<M extends java.lang.CharSequence> @pkg.TA(1) M getTypeParameter();
|
||||
<M extends java.lang.@pkg.TA(0) CharSequence> @pkg.TA(1) M getTypeParameter();
|
||||
|
||||
<M extends java.lang.CharSequence & java.io.Serializable> @pkg.TA(2) M getTypeParameter2();
|
||||
<M extends java.lang.@pkg.TA(0) CharSequence & java.io.@pkg.TA(1) Serializable> @pkg.TA(2) M getTypeParameter2();
|
||||
|
||||
<M extends java.lang.@pkg.TA(0) Object & java.util.@pkg.TA(1) List<@pkg.TA(2) ? super java.lang.@pkg.TA(3) String @pkg.TA(4) []>, N extends java.lang.@pkg.TA(5) Object, P> @pkg.TA(6) M getTypeParameterComplex();
|
||||
|
||||
pkg.@pkg.TA(0) Outer.@pkg.TA(1) Middle.@pkg.TA(2) Inner getInner();
|
||||
|
||||
@@ -45,7 +47,7 @@ public interface TypeAnno <T> extends java.io.Serializable {
|
||||
|
||||
pkg.@pkg.TA(0) Outer<pkg.@pkg.TA(1) Outer @pkg.TA(2) []>.@pkg.TA(3) Middle<@pkg.TA(4) ? extends pkg.@pkg.TA(5) Outer.@pkg.TA(6) Middle.@pkg.TA(7) Inner @pkg.TA(8) []>.@pkg.TA(9) Inner<pkg.@pkg.TA(10) Outer<@pkg.TA(11) ?>.@pkg.TA(12) Middle<@pkg.TA(13) ? super pkg.@pkg.TA(14) Outer>.@pkg.TA(15) Inner<@pkg.TA(16) ?> @pkg.TA(17) []> @pkg.TA(18) [] getMixed();
|
||||
|
||||
void inThrows() throws java.lang.Exception, java.lang.Error;
|
||||
void inThrows() throws java.lang.@pkg.TA(0) Exception, java.lang.@pkg.TA(1) Error;
|
||||
|
||||
void inParameter(java.util.@pkg.TA(0) List<java.lang.@pkg.TA(1) String> list, java.util.@pkg.TA(2) List<java.lang.@pkg.TA(3) String> list1);
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
package pkg;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
public class ExtendsObjectAnnotated extends @TA Object {}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TA {}
|
||||
@@ -6,7 +6,7 @@ import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface TypeAnno<@TA(10) T extends @TA(11) Object> extends @TA(12) Serializable {
|
||||
public interface TypeAnno<@TA(10) T extends @TA(11) Object> extends @TA(12) Serializable, @TA(13) Comparable<@TA(14) T> {
|
||||
@TA(-1) List<@TA String> get1TypeParam();
|
||||
|
||||
@TA(-1) Map<@TA(0) String, @TA(1) String> get2TypeParams();
|
||||
@@ -35,6 +35,8 @@ public interface TypeAnno<@TA(10) T extends @TA(11) Object> extends @TA(12) Seri
|
||||
<M extends @TA(0) CharSequence> @TA(1) M getTypeParameter();
|
||||
|
||||
<M extends @TA(0) CharSequence & @TA(1) Serializable> @TA(2) M getTypeParameter2();
|
||||
|
||||
<M extends @TA(0) Object & @TA(1) List<@TA(2) ? super @TA(3) String @TA(4) []>, N extends @TA(5) Object, P extends Object> @TA(6) M getTypeParameterComplex();
|
||||
|
||||
@TA(0) Outer.@TA(1) Middle.@TA(2) Inner getInner();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ PsiJavaFileStub []
|
||||
PsiModifierListStub[mask=1025]
|
||||
PsiTypeParameterListStub
|
||||
PsiTypeParameter[T]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:]
|
||||
PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object]
|
||||
PsiRefListStub[EXTENDS_LIST:java.io.Serializable]
|
||||
PsiRefListStub[IMPLEMENTS_LIST:]
|
||||
PsiFieldStub[field:java.lang.String=""]
|
||||
|
||||
@@ -53,6 +53,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
public void testSuspiciousParameterNames() { doTest(); }
|
||||
public void testTypeAnnotations() { doTest(); }
|
||||
public void testTypeAnno() { doTest(); }
|
||||
public void testExtendsObjectAnnotated() { doTest(); }
|
||||
public void testRecordTest() { doTest(); }
|
||||
|
||||
public void testTextPsiMismatch() {
|
||||
|
||||
Reference in New Issue
Block a user