diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInStubBuilder.kt index 505a8b346af..ecf6875563a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInStubBuilder.kt @@ -51,10 +51,10 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() { val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) val fileStub = createFileStub(packageFqName) - createCallableStubs( + createDeclarationsStubs( fileStub, context, ProtoContainer.Package(packageFqName, context.nameResolver, context.typeTable, source = null), - packageProto.functionList, packageProto.propertyList + packageProto ) for (classProto in file.classesToDecompile) { createClassStub( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt index 002d2630b41..fe71a33617c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/CallableClsStubBuilder.kt @@ -31,12 +31,23 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.MemberKind import org.jetbrains.kotlin.serialization.ProtoBuf.Modality import org.jetbrains.kotlin.serialization.deserialization.* -fun createCallableStubs( +fun createDeclarationsStubs( + parentStub: StubElement, + outerContext: ClsStubBuilderContext, + protoContainer: ProtoContainer, + packageProto: ProtoBuf.Package +) { + createDeclarationsStubs( + parentStub, outerContext, protoContainer, packageProto.functionList, packageProto.propertyList, packageProto.typeAliasList) +} + +fun createDeclarationsStubs( parentStub: StubElement, outerContext: ClsStubBuilderContext, protoContainer: ProtoContainer, functionProtos: List, - propertyProtos: List + propertyProtos: List, + typeAliasesProtos: List ) { for (propertyProto in propertyProtos) { if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) { @@ -48,6 +59,10 @@ fun createCallableStubs( FunctionClsStubBuilder(parentStub, outerContext, protoContainer, functionProto).build() } } + + for (typeAliasProto in typeAliasesProtos) { + createTypeAliasStub(parentStub, typeAliasProto, protoContainer, outerContext) + } } fun createConstructorStub( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt index 4cecf43b33c..627621fb1d0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt @@ -226,7 +226,8 @@ private class ClassClsStubBuilder( } } - createCallableStubs(classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList) + createDeclarationsStubs( + classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList, classProto.typeAliasList) } private fun isClass(): Boolean { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt index c71f7d33e30..93722d92d85 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt @@ -44,6 +44,7 @@ import java.util.* class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { fun createTypeReferenceStub(parent: StubElement, type: Type) { + if (type.hasAbbreviatedType()) return createTypeReferenceStub(parent, type.abbreviatedType) val typeReference = KotlinPlaceHolderStubImpl(parent, KtStubElementTypes.TYPE_REFERENCE) val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot { @@ -61,7 +62,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { } when { - type.hasClassName() -> createClassReferenceTypeStub(effectiveParent, type, annotations) + type.hasClassName() || type.hasTypeAliasName() -> createClassReferenceTypeStub(effectiveParent, type, annotations) type.hasTypeParameter() -> createTypeParameterStub(c.typeParameters[type.typeParameter]) type.hasTypeParameterName() -> createTypeParameterStub(c.nameResolver.getName(type.typeParameterName)) } @@ -77,7 +78,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { } } - val classId = c.nameResolver.getClassId(type.className) + assert(type.hasClassName() || type.hasTypeAliasName()) { + "Class reference stub must have either class or type alias name" + } + + val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName) val shouldBuildAsFunctionType = isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe()) && type.argumentList.none { it.projection == Projection.STAR } if (shouldBuildAsFunctionType) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt index fef3338265a..4516e8a143d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.FlagsToModifiers import org.jetbrains.kotlin.idea.stubindex.KotlinFileStubForIde import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader @@ -37,7 +36,6 @@ import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.impl.* import org.jetbrains.kotlin.resolve.jvm.JvmClassName -import org.jetbrains.kotlin.serialization.Flags import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer @@ -62,8 +60,8 @@ fun createPackageFacadeStub( ): KotlinFileStubImpl { val fileStub = KotlinFileStubForIde.forFile(packageFqName, packageFqName.isRoot) setupFileStub(fileStub, packageFqName) - createCallableStubs(fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), - packageProto.functionList, packageProto.propertyList) + createDeclarationsStubs( + fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), packageProto) return fileStub } @@ -78,7 +76,7 @@ fun createFileFacadeStub( val container = ProtoContainer.Package( packageFqName, c.nameResolver, c.typeTable, JvmPackagePartSource(JvmClassName.byClassId(ClassId.topLevel(facadeFqName)), null) ) - createCallableStubs(fileStub, c, container, packageProto.functionList, packageProto.propertyList) + createDeclarationsStubs(fileStub, c, container, packageProto) return fileStub } @@ -98,7 +96,7 @@ fun createMultifileClassStub( val partContext = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) val container = ProtoContainer.Package(packageFqName, partContext.nameResolver, partContext.typeTable, JvmPackagePartSource(partFile)) - createCallableStubs(fileStub, partContext, container, packageProto.functionList, packageProto.propertyList) + createDeclarationsStubs(fileStub, partContext, container, packageProto) } return fileStub } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/typeAliasClsStubBuilding.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/typeAliasClsStubBuilding.kt new file mode 100644 index 00000000000..36bad31040b --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/typeAliasClsStubBuilding.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.decompiler.stubBuilder + +import com.intellij.psi.PsiElement +import com.intellij.psi.stubs.StubElement +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.VISIBILITY +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl +import org.jetbrains.kotlin.serialization.Flags +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer +import org.jetbrains.kotlin.serialization.deserialization.TypeTable + +fun createTypeAliasStub( + parent: StubElement, + typeAliasProto: ProtoBuf.TypeAlias, + protoContainer: ProtoContainer, + context: ClsStubBuilderContext +) { + val shortName = context.nameResolver.getName(typeAliasProto.name) + + val classId = when (protoContainer) { + is ProtoContainer.Class -> protoContainer.classId.createNestedClassId(shortName) + is ProtoContainer.Package -> ClassId.topLevel(protoContainer.fqName.child(shortName)) + } + + val typeAlias = + KotlinTypeAliasStubImpl( + parent, classId.shortClassName.ref(), classId.asSingleFqName().ref(), + isTopLevel = !classId.isNestedClass) + + createModifierListStubForDeclaration(typeAlias, typeAliasProto.flags, arrayListOf(VISIBILITY), listOf()) + + val typeStubBuilder = TypeClsStubBuilder(context) + val restConstraints = typeStubBuilder.createTypeParameterListStub(typeAlias, typeAliasProto.typeParameterList) + assert(restConstraints.isEmpty()) { + "'where' constraints are not allowed for type aliases" + } + + if (Flags.HAS_ANNOTATIONS.get(typeAliasProto.flags)) { + // TODO: support annotations + // createAnnotationStubs(context.components.annotationLoader.loadClassAnnotations(thisAsProtoContainer), modifierList) + } + + typeStubBuilder.createTypeReferenceStub(typeAlias, typeAliasProto.underlyingType) +} diff --git a/idea/testData/decompiler/decompiledText/TypeAliases.expected.kt b/idea/testData/decompiler/decompiledText/TypeAliases.expected.kt index ec608b2128e..e6040911e0b 100644 --- a/idea/testData/decompiler/decompiledText/TypeAliases.expected.kt +++ b/idea/testData/decompiler/decompiledText/TypeAliases.expected.kt @@ -7,4 +7,6 @@ public final class TypeAliases public constructor() { public final fun foo(a: dependency.A /* = () -> kotlin.Unit */, b: test.TypeAliases.B /* = (dependency.A /* = () -> kotlin.Unit */) -> kotlin.Unit */, ta: test.Outer.Inner.TA /* = kotlin.collections.Map, kotlin.collections.Map> */): kotlin.Unit { /* compiled code */ } public typealias B = (dependency.A) -> kotlin.Unit + + private typealias Parametrized = kotlin.collections.Map } diff --git a/idea/testData/decompiler/decompiledText/TypeAliases/TypeAliases.kt b/idea/testData/decompiler/decompiledText/TypeAliases/TypeAliases.kt index 2e2b7168473..c3af14d21b8 100644 --- a/idea/testData/decompiler/decompiledText/TypeAliases/TypeAliases.kt +++ b/idea/testData/decompiler/decompiledText/TypeAliases/TypeAliases.kt @@ -8,10 +8,16 @@ class Outer { } } +annotation class Ann class TypeAliases { typealias B = (A) -> Unit + fun foo(a: A, b: B, ta: Outer.Inner.TA) { b.invoke(a) } + + // TODO: annotations are unsupported yet + @Ann + private typealias Parametrized = Map } diff --git a/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembers.kt b/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembers.kt index 8051a809315..015b207ef0a 100644 --- a/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembers.kt +++ b/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembers.kt @@ -24,4 +24,6 @@ private fun probablyNothing(): Nothing = throw IllegalStateException() private val certainlyNothing: kotlin.Nothing = throw IllegalStateException() -class Nothing \ No newline at end of file +private typealias Alias = (E) -> E + +class Nothing diff --git a/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembersKt.txt b/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembersKt.txt index 7aecfedc532..d5eb6129406 100644 --- a/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembersKt.txt +++ b/idea/testData/decompiler/stubBuilder/TopLevelMembersKt/TopLevelMembersKt.txt @@ -117,3 +117,17 @@ PsiJetFileStubImpl[package=foo.TopLevelMembers] USER_TYPE: REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=Int] + TYPEALIAS:[fqName=foo.TopLevelMembers.Alias, isTopLevel=true, name=Alias] + MODIFIER_LIST:[private] + TYPE_PARAMETER_LIST: + TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=E] + TYPE_REFERENCE: + FUNCTION_TYPE: + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null] + TYPE_REFERENCE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=E] + TYPE_REFERENCE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=E] diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/Dependency.kt b/idea/testData/decompiler/stubBuilder/TypeAliases/Dependency.kt new file mode 100644 index 00000000000..f6e5c1108e8 --- /dev/null +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/Dependency.kt @@ -0,0 +1,7 @@ +package dependency + +typealias A = () -> Unit + +fun foo(a: A) { + a.invoke() +} diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt new file mode 100644 index 00000000000..c3af14d21b8 --- /dev/null +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt @@ -0,0 +1,23 @@ +package test + +import dependency.* + +class Outer { + inner class Inner { + typealias TA = Map, Map> + } +} + +annotation class Ann +class TypeAliases { + + typealias B = (A) -> Unit + + fun foo(a: A, b: B, ta: Outer.Inner.TA) { + b.invoke(a) + } + + // TODO: annotations are unsupported yet + @Ann + private typealias Parametrized = Map +} diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt new file mode 100644 index 00000000000..a6f6bc688da --- /dev/null +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt @@ -0,0 +1,106 @@ +PsiJetFileStubImpl[package=test] + PACKAGE_DIRECTIVE: + REFERENCE_EXPRESSION:[referencedName=test] + IMPORT_LIST: + CLASS:[fqName=test.TypeAliases, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=TypeAliases, superNames=[]] + MODIFIER_LIST:[public final] + PRIMARY_CONSTRUCTOR: + MODIFIER_LIST:[public] + VALUE_PARAMETER_LIST: + CLASS_BODY: + FUN:[fqName=test.TypeAliases.foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=foo] + MODIFIER_LIST:[public final] + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=a] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=dependency] + REFERENCE_EXPRESSION:[referencedName=A] + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=b] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=test] + REFERENCE_EXPRESSION:[referencedName=TypeAliases] + REFERENCE_EXPRESSION:[referencedName=B] + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=ta] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=test] + REFERENCE_EXPRESSION:[referencedName=Outer] + TYPE_ARGUMENT_LIST: + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=String] + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Double] + REFERENCE_EXPRESSION:[referencedName=Inner] + TYPE_ARGUMENT_LIST: + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Int] + REFERENCE_EXPRESSION:[referencedName=TA] + TYPE_ARGUMENT_LIST: + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Boolean] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Unit] + TYPEALIAS:[fqName=test.TypeAliases.B, isTopLevel=false, name=B] + MODIFIER_LIST:[public] + TYPE_REFERENCE: + FUNCTION_TYPE: + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=dependency] + REFERENCE_EXPRESSION:[referencedName=A] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Unit] + TYPEALIAS:[fqName=test.TypeAliases.Parametrized, isTopLevel=false, name=Parametrized] + MODIFIER_LIST:[private] + TYPE_PARAMETER_LIST: + TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=E] + TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=F] + TYPE_REFERENCE: + USER_TYPE: + USER_TYPE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=collections] + REFERENCE_EXPRESSION:[referencedName=Map] + TYPE_ARGUMENT_LIST: + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=E] + TYPE_PROJECTION:[projectionKind=NONE] + TYPE_REFERENCE: + USER_TYPE: + REFERENCE_EXPRESSION:[referencedName=F] diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderTestGenerated.java index bd2065ec807..0d40356e7d9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderTestGenerated.java @@ -179,6 +179,12 @@ public class ClsStubBuilderTestGenerated extends AbstractClsStubBuilderTest { doTest(fileName); } + @TestMetadata("TypeAliases") + public void testTypeAliases() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/TypeAliases/"); + doTest(fileName); + } + @TestMetadata("TypeBoundsAndDelegationSpecifiers") public void testTypeBoundsAndDelegationSpecifiers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/TypeBoundsAndDelegationSpecifiers/");