Generate class members (functions, properties, nested classes).
This commit is contained in:
committed by
Dmitry Petrov
parent
19e95d232a
commit
703d3405ed
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -30,7 +29,38 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
||||
fun generateClass(ktClassOrObject: KtClassOrObject): IrClass {
|
||||
val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
|
||||
val irClass = IrClassImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset, IrDeclarationOrigin.DEFINED, descriptor)
|
||||
// TODO generate members
|
||||
|
||||
generatePropertiesDeclaredInPrimaryConstructor(irClass, ktClassOrObject)
|
||||
generateMembersDeclaredInClassbody(irClass, ktClassOrObject)
|
||||
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun generatePropertiesDeclaredInPrimaryConstructor(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||
ktClassOrObject.getPrimaryConstructor()?.let { ktPrimaryConstructor ->
|
||||
for (ktParameter in ktPrimaryConstructor.valueParameters) {
|
||||
if (ktParameter.hasValOrVar()) {
|
||||
irClass.addMember(generatePropertyForPrimaryConstructorParameter(ktParameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateMembersDeclaredInClassbody(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||
ktClassOrObject.getBody()?.let { ktClassBody ->
|
||||
for (ktDeclaration in ktClassBody.declarations) {
|
||||
val irMember = declarationGenerator.generateMemberDeclaration(ktDeclaration)
|
||||
irClass.addMember(irMember)
|
||||
if (irMember is IrProperty) {
|
||||
irMember.getter?.let { irClass.addMember(it) }
|
||||
irMember.setter?.let { irClass.addMember(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter): IrDeclaration {
|
||||
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
|
||||
return IrSimplePropertyImpl(ktParameter.startOffset, ktParameter.endOffset, IrDeclarationOrigin.DEFINED, propertyDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-36
@@ -49,62 +49,41 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
|
||||
IrTypeAliasImpl(ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED,
|
||||
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration))
|
||||
|
||||
fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction): IrFunction {
|
||||
val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktNamedFunction)
|
||||
val body = generateFunctionBody(functionDescriptor, ktNamedFunction.bodyExpression ?: TODO("function without body expression"))
|
||||
return createFunction(ktNamedFunction, functionDescriptor, body)
|
||||
fun generateFunctionDeclaration(ktFunction: KtNamedFunction): IrFunction {
|
||||
val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||
val body = ktFunction.bodyExpression?.let { generateFunctionBody(functionDescriptor, it) }
|
||||
return IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset, IrDeclarationOrigin.DEFINED,
|
||||
functionDescriptor, body)
|
||||
}
|
||||
|
||||
fun generatePropertyDeclaration(ktProperty: KtProperty): IrProperty {
|
||||
val propertyDescriptor = getPropertyDescriptor(ktProperty)
|
||||
if (ktProperty.hasDelegate()) TODO("handle delegated property")
|
||||
val initializer = ktProperty.initializer?.let { generateInitializerBody(propertyDescriptor, it) }
|
||||
val irProperty = createSimpleProperty(ktProperty, propertyDescriptor, initializer)
|
||||
val irProperty = IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
|
||||
propertyDescriptor, initializer)
|
||||
|
||||
ktProperty.getter?.let { ktGetter ->
|
||||
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter)
|
||||
val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?")
|
||||
val getterBody = generateFunctionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter"))
|
||||
createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody)
|
||||
val irGetterBody = generateFunctionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter"))
|
||||
val irGetter = IrPropertyGetterImpl(ktGetter.startOffset, ktGetter.endOffset, IrDeclarationOrigin.DEFINED,
|
||||
getterDescriptor, irGetterBody)
|
||||
irProperty.getter = irGetter
|
||||
}
|
||||
|
||||
ktProperty.setter?.let { ktSetter ->
|
||||
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter)
|
||||
val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?")
|
||||
val setterBody = generateFunctionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter"))
|
||||
createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody)
|
||||
val irSetterBody = generateFunctionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter"))
|
||||
val irSetter = IrPropertySetterImpl(ktSetter.startOffset, ktSetter.endOffset, IrDeclarationOrigin.DEFINED,
|
||||
setterDescriptor, irSetterBody)
|
||||
irProperty.setter = irSetter
|
||||
}
|
||||
|
||||
return irProperty
|
||||
}
|
||||
|
||||
fun createFunction(ktFunction: KtFunction, functionDescriptor: FunctionDescriptor, body: IrBody): IrFunction =
|
||||
IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, functionDescriptor, body)
|
||||
|
||||
fun createSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor, valueInitializer: IrBody?): IrSimpleProperty =
|
||||
IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, propertyDescriptor, valueInitializer)
|
||||
|
||||
fun createPropertyGetter(
|
||||
ktPropertyAccessor: KtPropertyAccessor,
|
||||
irProperty: IrProperty,
|
||||
getterDescriptor: PropertyGetterDescriptor,
|
||||
getterBody: IrBody
|
||||
): IrPropertyGetter =
|
||||
IrPropertyGetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, getterDescriptor, getterBody)
|
||||
.apply { irProperty.getter = this }
|
||||
|
||||
fun createPropertySetter(
|
||||
ktPropertyAccessor: KtPropertyAccessor,
|
||||
irProperty: IrProperty,
|
||||
setterDescriptor: PropertySetterDescriptor,
|
||||
setterBody: IrBody
|
||||
) : IrPropertySetter =
|
||||
IrPropertySetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, setterDescriptor, setterBody)
|
||||
.apply { irProperty.setter = this }
|
||||
|
||||
private fun getPropertyDescriptor(ktProperty: KtProperty): PropertyDescriptor {
|
||||
val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.ir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
|
||||
interface IrConstructor : IrFunction {
|
||||
override val declarationKind: IrDeclarationKind
|
||||
get() = IrDeclarationKind.CONSTRUCTOR
|
||||
|
||||
override val descriptor: ConstructorDescriptor
|
||||
}
|
||||
|
||||
class IrConstructorImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
override val descriptor: ConstructorDescriptor
|
||||
) : IrFunctionBase(startOffset, endOffset, origin), IrConstructor {
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: ConstructorDescriptor,
|
||||
body: IrBody
|
||||
) : this(startOffset, endOffset, origin, descriptor) {
|
||||
this.body = body
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitConstructor(this, data)
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
interface IrFunction : IrDeclaration {
|
||||
override val descriptor: FunctionDescriptor
|
||||
val body: IrBody
|
||||
val body: IrBody?
|
||||
|
||||
override val declarationKind: IrDeclarationKind
|
||||
get() = IrDeclarationKind.FUNCTION
|
||||
@@ -32,21 +32,23 @@ interface IrFunction : IrDeclaration {
|
||||
abstract class IrFunctionBase(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
body: IrBody? = null
|
||||
origin: IrDeclarationOrigin
|
||||
) : IrDeclarationBase(startOffset, endOffset, origin), IrFunction {
|
||||
init {
|
||||
body?.setTreeLocation(this, FUNCTION_BODY_SLOT)
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
body: IrBody
|
||||
) : this(startOffset, endOffset, origin) {
|
||||
this.body = body
|
||||
}
|
||||
|
||||
private var bodyImpl: IrBody? = body
|
||||
override var body: IrBody
|
||||
get() = bodyImpl!!
|
||||
final override var body: IrBody? = null
|
||||
set(newValue) {
|
||||
newValue.assertDetached()
|
||||
bodyImpl?.detach()
|
||||
bodyImpl = newValue
|
||||
newValue.setTreeLocation(this, FUNCTION_BODY_SLOT)
|
||||
newValue?.assertDetached()
|
||||
field?.detach()
|
||||
field = newValue
|
||||
newValue?.setTreeLocation(this, FUNCTION_BODY_SLOT)
|
||||
}
|
||||
|
||||
override fun getChild(slot: Int): IrElement? =
|
||||
@@ -63,7 +65,7 @@ abstract class IrFunctionBase(
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
body.accept(visitor, data)
|
||||
body?.accept(visitor, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +73,18 @@ class IrFunctionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
override val descriptor: FunctionDescriptor,
|
||||
body: IrBody
|
||||
) : IrFunctionBase(startOffset, endOffset, origin, body) {
|
||||
override val descriptor: FunctionDescriptor
|
||||
) : IrFunctionBase(startOffset, endOffset, origin) {
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: FunctionDescriptor,
|
||||
body: IrBody?
|
||||
) : this(startOffset, endOffset, origin, descriptor) {
|
||||
this.body = body
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitFunction(this, data)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ interface IrElementVisitor<out R, in D> {
|
||||
fun visitFunction(declaration: IrFunction, data: D): R = visitDeclaration(declaration, data)
|
||||
fun visitPropertyGetter(declaration: IrPropertyGetter, data: D): R = visitFunction(declaration, data)
|
||||
fun visitPropertySetter(declaration: IrPropertySetter, data: D): R = visitFunction(declaration, data)
|
||||
fun visitConstructor(declaration: IrConstructor, data: D): R = visitFunction(declaration, data)
|
||||
fun visitProperty(declaration: IrProperty, data: D): R = visitDeclaration(declaration, data)
|
||||
fun visitSimpleProperty(declaration: IrSimpleProperty, data: D): R = visitProperty(declaration, data)
|
||||
fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data)
|
||||
|
||||
@@ -12,6 +12,7 @@ FILE /arrayAugmentedAssignment1.kt
|
||||
RETURN type=kotlin.Nothing
|
||||
CONST Int type=kotlin.Int value='42'
|
||||
CLASS CLASS C
|
||||
PROPERTY public final val x: kotlin.IntArray getter=null setter=null
|
||||
FUN public fun testVariable(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
VAR var x: kotlin.IntArray
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
FILE /arrayAugmentedAssignment2.kt
|
||||
CLASS INTERFACE IA
|
||||
FUN public abstract operator fun get(/*0*/ index: kotlin.String): kotlin.Int
|
||||
CLASS INTERFACE IB
|
||||
FUN public abstract operator fun IA.set(/*0*/ index: kotlin.String, /*1*/ value: kotlin.Int): kotlin.Unit
|
||||
FUN public fun IB.test(/*0*/ a: IA): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
BLOCK type=kotlin.Unit operator=PLUSEQ
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
FILE /assignments.kt
|
||||
CLASS CLASS Ref
|
||||
PROPERTY public final var x: kotlin.Int getter=null setter=null
|
||||
FUN public fun test1(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
VAR var x: kotlin.Int
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
FILE /chainOfSafeCalls.kt
|
||||
CLASS CLASS C
|
||||
FUN public final fun foo(): C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
THIS public final class C type=C
|
||||
FUN public final fun bar(): C?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
THIS public final class C type=C
|
||||
FUN public fun test(/*0*/ nc: C?): C?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
FILE /conventionComparisons.kt
|
||||
CLASS INTERFACE IA
|
||||
CLASS INTERFACE IB
|
||||
FUN public abstract operator fun IA.compareTo(/*0*/ other: IA): kotlin.Int
|
||||
FUN public fun IB.test1(/*0*/ a1: IA, /*1*/ a2: IA): kotlin.Boolean
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
|
||||
@@ -1,7 +1,33 @@
|
||||
FILE /forWithImplicitReceivers.kt
|
||||
CLASS OBJECT FiveTimes
|
||||
CLASS CLASS IntCell
|
||||
PROPERTY public final var value: kotlin.Int getter=null setter=null
|
||||
CLASS INTERFACE IReceiver
|
||||
FUN public open operator fun FiveTimes.iterator(): IntCell
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
CALL .<init> type=IntCell operator=null
|
||||
value: CONST Int type=kotlin.Int value='5'
|
||||
FUN public open operator fun IntCell.hasNext(): kotlin.Boolean
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
CALL .GT0 type=kotlin.Boolean operator=GT
|
||||
arg0: CALL .compareTo type=kotlin.Int operator=GT
|
||||
$this: CALL .<get-value> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: $RECEIVER of: hasNext type=IntCell
|
||||
other: CONST Int type=kotlin.Int value='0'
|
||||
FUN public open operator fun IntCell.next(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
BLOCK type=kotlin.Int operator=POSTFIX_DECR
|
||||
VAR val tmp0: kotlin.Int
|
||||
CALL .<get-value> type=kotlin.Int operator=POSTFIX_DECR
|
||||
$this: $RECEIVER of: next type=IntCell
|
||||
CALL .<set-value> type=kotlin.Unit operator=POSTFIX_DECR
|
||||
$this: $RECEIVER of: next type=IntCell
|
||||
<set-?>: CALL .dec type=kotlin.Int operator=POSTFIX_DECR
|
||||
$this: GET_VAR tmp0 type=kotlin.Int operator=null
|
||||
GET_VAR tmp0 type=kotlin.Int operator=null
|
||||
FUN public fun IReceiver.test(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
BLOCK type=kotlin.Unit operator=FOR_LOOP
|
||||
|
||||
+6
@@ -1,6 +1,12 @@
|
||||
FILE /safeCalls.kt
|
||||
CLASS CLASS Ref
|
||||
PROPERTY public final var value: kotlin.Int getter=null setter=null
|
||||
CLASS INTERFACE IHost
|
||||
FUN public open fun kotlin.String.extLength(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: $RECEIVER of: extLength type=kotlin.String
|
||||
FUN public fun test1(/*0*/ x: kotlin.String?): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
|
||||
+2
@@ -1,10 +1,12 @@
|
||||
FILE /values.kt
|
||||
CLASS ENUM_CLASS Enum
|
||||
CLASS ENUM_ENTRY A
|
||||
CLASS OBJECT A
|
||||
PROPERTY public val a: kotlin.Int = 0 getter=null setter=null
|
||||
EXPRESSION_BODY
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
CLASS CLASS Z
|
||||
CLASS OBJECT Companion
|
||||
FUN public fun test1(): Enum
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing
|
||||
|
||||
Reference in New Issue
Block a user