DeclarationStubGenerator uses IrTypes

This commit is contained in:
Dmitry Petrov
2018-04-26 16:03:52 +03:00
parent 1353cf879c
commit 372f280578
10 changed files with 75 additions and 63 deletions
@@ -19,11 +19,12 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.AnnotationGenerator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
import org.jetbrains.kotlin.psi2ir.transformations.generateAnnotationsForDeclarations
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList
@@ -63,4 +64,9 @@ class Psi2IrTranslator(val configuration: Psi2IrConfiguration = Psi2IrConfigurat
irElement.patchDeclarationParents()
}
private fun generateAnnotationsForDeclarations(context: GeneratorContext, irElement: IrElement) {
val annotationGenerator = AnnotationGenerator(context.moduleDescriptor, context.symbolTable)
irElement.acceptVoid(annotationGenerator)
}
}
@@ -1,114 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.psi2ir.transformations.AnnotationGenerator
import org.jetbrains.kotlin.psi2ir.transformations.ScopedTypeParametersResolver
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ConstantValueGenerator(
private val moduleDescriptor: ModuleDescriptor,
private val symbolTable: SymbolTable,
private val annotationGenerator: AnnotationGenerator?,
private val scopedTypeParameterResolver: ScopedTypeParametersResolver?
) {
constructor(
context: GeneratorContext,
annotationGenerator: AnnotationGenerator? = null
) : this(context.moduleDescriptor, context.symbolTable, annotationGenerator, null)
fun generateConstantValueAsExpression(
startOffset: Int,
endOffset: Int,
constantValue: ConstantValue<*>,
varargElementType: KotlinType? = null
): IrExpression {
val constantType = constantValue.getType(moduleDescriptor)
return when (constantValue) {
is StringValue -> IrConstImpl.string(startOffset, endOffset, constantType, constantValue.value)
is IntValue -> IrConstImpl.int(startOffset, endOffset, constantType, constantValue.value)
is UIntValue -> IrConstImpl.int(startOffset, endOffset, constantType, constantValue.value)
is NullValue -> IrConstImpl.constNull(startOffset, endOffset, constantType)
is BooleanValue -> IrConstImpl.boolean(startOffset, endOffset, constantType, constantValue.value)
is LongValue -> IrConstImpl.long(startOffset, endOffset, constantType, constantValue.value)
is ULongValue -> IrConstImpl.long(startOffset, endOffset, constantType, constantValue.value)
is DoubleValue -> IrConstImpl.double(startOffset, endOffset, constantType, constantValue.value)
is FloatValue -> IrConstImpl.float(startOffset, endOffset, constantType, constantValue.value)
is CharValue -> IrConstImpl.char(startOffset, endOffset, constantType, constantValue.value)
is ByteValue -> IrConstImpl.byte(startOffset, endOffset, constantType, constantValue.value)
is UByteValue -> IrConstImpl.byte(startOffset, endOffset, constantType, constantValue.value)
is ShortValue -> IrConstImpl.short(startOffset, endOffset, constantType, constantValue.value)
is UShortValue -> IrConstImpl.short(startOffset, endOffset, constantType, constantValue.value)
is ArrayValue -> {
val arrayElementType = varargElementType ?: constantType.getArrayElementType()
IrVarargImpl(
startOffset, endOffset,
constantType,
arrayElementType,
constantValue.value.map {
generateConstantValueAsExpression(startOffset, endOffset, it, null)
}
)
}
is EnumValue -> {
val enumEntryDescriptor =
constantType.memberScope.getContributedClassifier(constantValue.enumEntryName, NoLookupLocation.FROM_BACKEND)
?: throw AssertionError("No such enum entry ${constantValue.enumEntryName} in $constantType")
if (enumEntryDescriptor !is ClassDescriptor) {
throw AssertionError("Enum entry $enumEntryDescriptor should be a ClassDescriptor")
}
IrGetEnumValueImpl(
startOffset, endOffset,
constantType,
symbolTable.referenceEnumEntry(enumEntryDescriptor)
)
}
is AnnotationValue -> {
if (annotationGenerator == null) throw AssertionError("Unexpected AnnotationValue: $constantValue")
annotationGenerator.generateAnnotationConstructorCall(constantValue.value)
}
is KClassValue -> {
val classifierType = constantValue.value
val classifierDescriptor = classifierType.constructor.declarationDescriptor
?: throw AssertionError("Unexpected KClassValue: $classifierType")
val typeParameterSymbol = classifierDescriptor.safeAs<TypeParameterDescriptor>()?.let {
scopedTypeParameterResolver?.resolveScopedTypeParameter(it)
}
IrClassReferenceImpl(
startOffset, endOffset,
constantValue.getType(moduleDescriptor),
typeParameterSymbol ?: symbolTable.referenceClassifier(classifierDescriptor),
classifierType
)
}
else -> TODO("Unexpected constant value: ${constantValue.javaClass.simpleName} $constantValue")
}
}
private fun KotlinType.getArrayElementType() = builtIns.getArrayElementType(this)
}
@@ -22,13 +22,13 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.transformations.AnnotationGenerator
import org.jetbrains.kotlin.ir.util.AnnotationGenerator
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile
class ModuleGenerator(override val context: GeneratorContext) : Generator {
private val annotationGenerator = AnnotationGenerator(context)
private val annotationGenerator = AnnotationGenerator(context.moduleDescriptor, context.symbolTable)
fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment =
generateModuleFragmentWithoutDependencies(ktFiles).also { irModule ->
@@ -41,7 +41,9 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
}
fun generateUnboundSymbolsAsDependencies(irModule: IrModuleFragment) {
ExternalDependenciesGenerator(context.symbolTable, context.irBuiltIns).generateUnboundSymbolsAsDependencies(irModule)
ExternalDependenciesGenerator(
irModule.descriptor, context.symbolTable, context.irBuiltIns
).generateUnboundSymbolsAsDependencies(irModule)
}
private fun generateFiles(ktFiles: Collection<KtFile>): List<IrFile> {
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrTypeAliasImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.ConstantValueGenerator
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
@@ -42,7 +43,6 @@ import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import java.lang.AssertionError
class StatementGenerator(
val bodyGenerator: BodyGenerator,
@@ -206,7 +206,7 @@ class StatementGenerator(
)
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression =
ConstantValueGenerator(context).generateConstantValueAsExpression(
ConstantValueGenerator(context.moduleDescriptor, context.symbolTable, null).generateConstantValueAsExpression(
expression.startOffset,
expression.endOffset,
constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
@@ -1,148 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.generators.ConstantValueGenerator
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun generateAnnotationsForDeclarations(context: GeneratorContext, irElement: IrElement) {
val annotationGenerator = AnnotationGenerator(context.moduleDescriptor, context.symbolTable)
irElement.acceptVoid(annotationGenerator)
}
class AnnotationGenerator(
moduleDescriptor: ModuleDescriptor,
private val symbolTable: SymbolTable
) : IrElementVisitorVoid {
constructor(context: GeneratorContext) : this(context.moduleDescriptor, context.symbolTable)
private val scopedTypeParameterResolver = ScopedTypeParametersResolver()
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable, this, scopedTypeParameterResolver)
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitDeclaration(declaration: IrDeclaration) {
if (declaration is IrTypeParametersContainer) {
scopedTypeParameterResolver.enterTypeParameterScope(declaration)
}
generateAnnotationsForDeclaration(declaration)
visitElement(declaration)
if (declaration is IrTypeParametersContainer) {
scopedTypeParameterResolver.leaveTypeParameterScope()
}
}
override fun visitValueParameter(declaration: IrValueParameter) {
super.visitValueParameter(declaration)
val descriptor = declaration.descriptor
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is PropertySetterDescriptor) {
containingDeclaration.correspondingProperty.annotations.getUseSiteTargetedAnnotations()
.filter { it.target == AnnotationUseSiteTarget.SETTER_PARAMETER }
.generateAnnotationConstructorCalls(declaration)
}
descriptor.type.annotations.getAllAnnotations()
.filter { it.target == AnnotationUseSiteTarget.RECEIVER }
.generateAnnotationConstructorCalls(declaration)
}
private fun generateAnnotationsForDeclaration(declaration: IrDeclaration) {
declaration.descriptor.annotations.getAllAnnotations()
.filter { isAnnotationTargetMatchingDeclaration(it.target, declaration) }
.generateAnnotationConstructorCalls(declaration)
}
private fun List<AnnotationWithTarget>.generateAnnotationConstructorCalls(declaration: IrDeclaration) {
mapTo(declaration.annotations) {
generateAnnotationConstructorCall(it.annotation)
}
}
fun generateAnnotationConstructorCall(annotationDescriptor: AnnotationDescriptor): IrCall {
val annotationType = annotationDescriptor.type
val annotationClassDescriptor = annotationType.constructor.declarationDescriptor as? ClassDescriptor
?: throw AssertionError("No declaration descriptor for annotation $annotationDescriptor")
assert(DescriptorUtils.isAnnotationClass(annotationClassDescriptor)) {
"Annotation class expected: $annotationClassDescriptor"
}
val primaryConstructorDescriptor =
annotationClassDescriptor.unsubstitutedPrimaryConstructor
?: annotationClassDescriptor.constructors.singleOrNull()
?: throw AssertionError("No constructor for annotation class $annotationClassDescriptor")
val primaryConstructorSymbol = symbolTable.referenceConstructor(primaryConstructorDescriptor)
val psi = annotationDescriptor.source.safeAs<PsiSourceElement>()?.psi
val startOffset = psi?.startOffset ?: UNDEFINED_OFFSET
val endOffset = psi?.startOffset ?: UNDEFINED_OFFSET
val irCall = IrCallImpl(
startOffset, endOffset, annotationType,
primaryConstructorSymbol, primaryConstructorDescriptor,
typeArgumentsCount = 0
)
for (valueParameter in primaryConstructorDescriptor.valueParameters) {
val argumentIndex = valueParameter.index
val argumentValue = annotationDescriptor.allValueArguments[valueParameter.name] ?: continue
val irArgument =
constantValueGenerator.generateConstantValueAsExpression(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
argumentValue,
valueParameter.varargElementType
)
irCall.putValueArgument(argumentIndex, irArgument)
}
return irCall
}
private fun isAnnotationTargetMatchingDeclaration(target: AnnotationUseSiteTarget?, element: IrElement): Boolean =
when (element) {
is IrProperty ->
target == null || target == AnnotationUseSiteTarget.PROPERTY
is IrField ->
target == AnnotationUseSiteTarget.FIELD || target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
is IrSimpleFunction ->
target == null || target == AnnotationUseSiteTarget.PROPERTY_GETTER || target == AnnotationUseSiteTarget.PROPERTY_SETTER
is IrValueParameter ->
target == null || target == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
else -> target == null
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.util.ScopedTypeParametersResolver
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.psi2ir.containsNull
@@ -1,36 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import java.util.*
class ScopedTypeParametersResolver {
private val typeParameterScopes = ArrayDeque<Map<TypeParameterDescriptor, IrTypeParameterSymbol>>()
fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) {
typeParameterScopes.addFirst(
typeParametersContainer.typeParameters.associate {
it.descriptor to it.symbol
}
)
}
fun leaveTypeParameterScope() {
typeParameterScopes.removeFirst()
}
fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? {
for (scope in typeParameterScopes) {
val local = scope[typeParameterDescriptor]
if (local != null) return local
}
return null
}
}
@@ -1,106 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.psi2ir.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.transformations.AnnotationGenerator
import org.jetbrains.kotlin.psi2ir.transformations.ScopedTypeParametersResolver
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
class TypeTranslator(
moduleDescriptor: ModuleDescriptor,
private val symbolTable: SymbolTable
) {
constructor(context: GeneratorContext) : this(context.moduleDescriptor, context.symbolTable)
private val annotationGenerator = AnnotationGenerator(moduleDescriptor, symbolTable)
private val typeParametersResolver = ScopedTypeParametersResolver()
fun enterScope(irElement: IrTypeParametersContainer) {
typeParametersResolver.enterTypeParameterScope(irElement)
}
fun leaveScope() {
typeParametersResolver.leaveTypeParameterScope()
}
private fun resolveTypeParameter(typeParameterDescriptor: TypeParameterDescriptor) =
typeParametersResolver.resolveScopedTypeParameter(typeParameterDescriptor)
?: symbolTable.referenceTypeParameter(typeParameterDescriptor)
fun translateType(ktType: KotlinType): IrType =
translateType(ktType, Variance.INVARIANT).type
private fun translateType(ktType0: KotlinType, variance: Variance): IrTypeProjection {
// TODO "old" JVM BE does this for reified type arguments. Is it ok for arbitrary subexpressions?
val ktTypeUpper = approximateCapturedTypes(ktType0).upper
when {
ktTypeUpper.isError -> return IrErrorTypeImpl(translateTypeAnnotations(ktTypeUpper.annotations), variance)
ktTypeUpper.isFlexible() -> return translateType(ktTypeUpper.upperIfFlexible(), variance)
ktTypeUpper.isDynamic() -> return IrDynamicTypeImpl(translateTypeAnnotations(ktTypeUpper.annotations), variance)
}
val ktTypeConstructor = ktTypeUpper.constructor
val ktTypeDescriptor = ktTypeConstructor.declarationDescriptor ?: throw AssertionError("No descriptor for type $ktTypeUpper")
return when (ktTypeDescriptor) {
is TypeParameterDescriptor ->
IrSimpleTypeImpl(
resolveTypeParameter(ktTypeDescriptor),
ktTypeUpper.isMarkedNullable,
emptyList(),
translateTypeAnnotations(ktTypeUpper.annotations),
variance
)
is ClassDescriptor ->
IrSimpleTypeImpl(
symbolTable.referenceClass(ktTypeDescriptor),
ktTypeUpper.isMarkedNullable,
translateTypeArguments(ktTypeUpper.arguments),
translateTypeAnnotations(ktTypeUpper.annotations),
variance
)
else ->
throw AssertionError("Unexpected type descriptor $ktTypeDescriptor :: ${ktTypeDescriptor::class}")
}
}
private fun translateTypeAnnotations(annotations: Annotations): List<IrCall> =
annotations.getAllAnnotations().map {
// TODO filter out annotation targets
annotationGenerator.generateAnnotationConstructorCall(it.annotation)
}
private fun translateTypeArguments(arguments: List<TypeProjection>) =
arguments.map {
// TODO starProjection
translateType(it.type, it.projectionKind)
}
}