diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 3fde52bed99..5f254a33a49 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi2ir.transformations.AnnotationGenerator import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator import org.jetbrains.kotlin.psi2ir.transformations.generateAnnotationsForDeclarations diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGenerator.kt index 3827075929b..451b88570ff 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ConstantValueGenerator.kt @@ -6,28 +6,36 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.expressions.IrExpression 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.resolve.constants.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.builtIns class ConstantValueGenerator( - private val context: GeneratorContext, - private val annotationGenerator: AnnotationGenerator? = null + private val moduleDescriptor: ModuleDescriptor, + private val symbolTable: SymbolTable, + private val annotationGenerator: AnnotationGenerator? ) { + constructor( + context: GeneratorContext, + annotationGenerator: AnnotationGenerator? = null + ) : this(context.moduleDescriptor, context.symbolTable, annotationGenerator) + fun generateConstantValueAsExpression( startOffset: Int, endOffset: Int, constantValue: ConstantValue<*>, varargElementType: KotlinType? = null ): IrExpression { - val constantType = constantValue.getType(context.moduleDescriptor) + val constantType = constantValue.getType(moduleDescriptor) return when (constantValue) { is StringValue -> IrConstImpl.string(startOffset, endOffset, constantType, constantValue.value) @@ -63,7 +71,7 @@ class ConstantValueGenerator( IrGetEnumValueImpl( startOffset, endOffset, constantType, - context.symbolTable.referenceEnumEntry(enumEntryDescriptor) + symbolTable.referenceEnumEntry(enumEntryDescriptor) ) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/AnnotationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/AnnotationGenerator.kt index aab1d0f9c14..e6ab5cc06e3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/AnnotationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/AnnotationGenerator.kt @@ -6,6 +6,7 @@ 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 @@ -15,6 +16,7 @@ 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 @@ -26,12 +28,18 @@ import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun generateAnnotationsForDeclarations(context: GeneratorContext, irElement: IrElement) { - irElement.acceptVoid(AnnotationGenerator(context)) + val annotationGenerator = AnnotationGenerator(context.moduleDescriptor, context.symbolTable) + irElement.acceptVoid(annotationGenerator) } -class AnnotationGenerator(private val context: GeneratorContext) : IrElementVisitorVoid { +class AnnotationGenerator( + moduleDescriptor: ModuleDescriptor, + private val symbolTable: SymbolTable +) : IrElementVisitorVoid { - private val constantValueGenerator = ConstantValueGenerator(context, this) + constructor(context: GeneratorContext) : this(context.moduleDescriptor, context.symbolTable) + + private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable, this) override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) @@ -82,7 +90,7 @@ class AnnotationGenerator(private val context: GeneratorContext) : IrElementVisi val primaryConstructorDescriptor = annotationClassDescriptor.safeAs()?.unsubstitutedPrimaryConstructor ?: throw AssertionError("No primary constructor for annotation class $annotationClassDescriptor") - val primaryConstructorSymbol = context.symbolTable.referenceConstructor(primaryConstructorDescriptor) + val primaryConstructorSymbol = symbolTable.referenceConstructor(primaryConstructorDescriptor) val psi = annotationDescriptor.source.safeAs()?.psi val startOffset = psi?.startOffset ?: UNDEFINED_OFFSET diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index 4b41267498f..7f46394fdd5 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -34,42 +34,27 @@ import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isNullabilityFlexible import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.upperIfFlexible -import java.util.* fun insertImplicitCasts(builtIns: KotlinBuiltIns, element: IrElement, symbolTable: SymbolTable) { element.transformChildren(InsertImplicitCasts(builtIns, symbolTable), null) } class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symbolTable: SymbolTable) : IrElementTransformerVoid() { - private val typeParameterScopes = ArrayDeque>() + + private val typeParameterResolver = ScopedTypeParametersResolver() private inline fun runInTypeParameterScope(typeParametersContainer: IrTypeParametersContainer, fn: () -> T): T { - enterTypeParameterScope(typeParametersContainer) + typeParameterResolver.enterTypeParameterScope(typeParametersContainer) val result = fn() - leaveTypeParameterScope() + typeParameterResolver.leaveTypeParameterScope() return result } - private fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) { - typeParameterScopes.addFirst( - typeParametersContainer.typeParameters.associate { - it.descriptor to it.symbol - } - ) - } - - private fun leaveTypeParameterScope() { - typeParameterScopes.removeFirst() - } - - private fun resolveScopedTypeParameter(classifier: ClassifierDescriptor): IrTypeParameterSymbol? { - if (classifier !is TypeParameterDescriptor) return null - for (scope in typeParameterScopes) { - val local = scope[classifier] - if (local != null) return local - } - return null - } + private fun resolveScopedTypeParameter(classifier: ClassifierDescriptor): IrTypeParameterSymbol? = + if (classifier is TypeParameterDescriptor) + typeParameterResolver.resolveScopedTypeParameter(classifier) + else + null override fun visitCallableReference(expression: IrCallableReference): IrExpression = expression.transformPostfix { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/ScopedTypeParametersResolver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/ScopedTypeParametersResolver.kt new file mode 100644 index 00000000000..df323645f55 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/ScopedTypeParametersResolver.kt @@ -0,0 +1,36 @@ +/* + * 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>() + + 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 + } +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/types/TypeTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/types/TypeTranslator.kt new file mode 100644 index 00000000000..1e10397f2c7 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/types/TypeTranslator.kt @@ -0,0 +1,128 @@ +/* + * 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.impl.IrTypeImpl +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.* + +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): IrTypeImpl = + translateType(ktType, Variance.INVARIANT) + + private fun translateType(ktType: KotlinType, variance: Variance): IrTypeImpl { + if (ktType.isFlexible()) { + return translateType(ktType.upperIfFlexible(), variance) + } + + val ktTypeConstructor = ktType.constructor + val ktTypeDescriptor = ktTypeConstructor.declarationDescriptor + + return when (ktTypeDescriptor) { + is TypeParameterDescriptor -> + IrTypeImpl( + resolveTypeParameter(ktTypeDescriptor), + ktType.isMarkedNullable, + emptyList(), + translateTypeAnnotations(ktType.annotations), + variance + ) + + is ClassDescriptor -> + IrTypeImpl( + symbolTable.referenceClass(ktTypeDescriptor), + ktType.isMarkedNullable, + translateTypeArguments(ktType.arguments), + translateTypeAnnotations(ktType.annotations), + variance + ) + + else -> + TODO() + } + } + + private fun translateTypeAnnotations(annotations: Annotations): List = + annotations.getAllAnnotations().map { + // TODO filter out annotation targets + annotationGenerator.generateAnnotationConstructorCall(it.annotation) + } + + private fun translateTypeArguments(arguments: List) = + arguments.map { + // TODO starProjection + translateType(it.type, it.projectionKind) + } + + private inner class SimpleTranslationVisitor : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclaration(declaration: IrDeclaration) { + if (declaration is IrTypeParametersContainer) { + enterScope(declaration) + } + declaration.acceptChildrenVoid(this) + if (declaration is IrTypeParametersContainer) { + leaveScope() + } + } + + override fun visitExpression(expression: IrExpression) { + translateType(expression.type) + expression.acceptChildrenVoid(this) + } + } + + companion object { + + fun tryTranslateAllExpressionTypes( + element: IrElement, + context: GeneratorContext + ) { + element.acceptVoid(TypeTranslator(context).SimpleTranslationVisitor()) + } + + } +} + diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeImpl.kt index 3b30fa16a5c..35c7b2c3eee 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeImpl.kt @@ -26,17 +26,16 @@ class IrTypeImpl( annotations: List ) : this(classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT) + constructor( + other: IrType, + variance: Variance + ) : this(other.classifier, other.hasQuestionMark, other.arguments, other.annotations, variance) + override val type: IrType get() = this } fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection = - if (type !is IrTypeImpl || type.variance != variance) - IrTypeImpl( - type.classifier, - type.hasQuestionMark, - type.arguments, - type.annotations, - variance - ) + if (type is IrTypeImpl && type.variance == variance) + type else - type \ No newline at end of file + IrTypeImpl(type, variance) \ No newline at end of file