Object literal expressions.

This commit is contained in:
Dmitry Petrov
2016-08-30 14:32:08 +03:00
committed by Dmitry Petrov
parent 86a52e6426
commit 41d772d636
6 changed files with 146 additions and 1 deletions
@@ -0,0 +1,53 @@
/*
* 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.psi2ir.generators
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
class LocalClassGenerator(statementGenerator: StatementGenerator): StatementGeneratorExtension(statementGenerator) {
fun generateObjectLiteral(expression: KtObjectLiteralExpression): IrStatement {
val objectLiteralType = getInferredTypeWithImplicitCastsOrFail(expression)
val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, objectLiteralType, IrOperator.OBJECT_LITERAL)
val irClass = DeclarationGenerator(statementGenerator.context).generateClassOrObjectDeclaration(expression.objectDeclaration)
irBlock.addStatement(irClass)
val objectConstructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?:
throw AssertionError("Object literal should have a primary constructor: ${irClass.descriptor}")
assert(objectConstructor.dispatchReceiverParameter == null) {
"Object literal constructor should have no dispatch receiver parameter: $objectConstructor"
}
assert(objectConstructor.extensionReceiverParameter == null) {
"Object literal constructor should have no extension receiver parameter: $objectConstructor"
}
assert(objectConstructor.valueParameters.size == 0) {
"Object literal constructor should have no value parameters: $objectConstructor"
}
irBlock.addStatement(IrCallImpl(expression.startOffset, expression.endOffset, objectLiteralType,
objectConstructor, IrOperator.OBJECT_LITERAL))
return irBlock
}
}
@@ -336,6 +336,9 @@ class StatementGenerator(
override fun visitNamedFunction(function: KtNamedFunction, data: Nothing?): IrStatement =
LocalFunctionGenerator(this).generateFunction(function)
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Nothing?): IrStatement =
LocalClassGenerator(this).generateObjectLiteral(expression)
}
abstract class StatementGeneratorExtension(val statementGenerator: StatementGenerator) : GeneratorWithScope {
@@ -86,9 +86,9 @@ interface IrOperator {
object LAMBDA : IrOperatorImpl("LAMBDA")
object ANONYMOUS_FUNCTION : IrOperatorImpl("ANONYMOUS_FUNCTION")
object OBJECT_LITERAL : IrOperatorImpl("OBJECT_LITERAL")
object SUPER_CONSTRUCTOR_CALL : IrOperatorImpl("SUPER_CONSTRUCTOR_CALL")
object DELEGATING_CONSTRUCTOR_CALL : IrOperatorImpl("DELEGATING_CONSTRUCTOR_CALL")
object INITIALIZE_PROPERTY_FROM_PARAMETER : IrOperatorImpl("INITIALIZE_PROPERTY_FROM_PARAMETER")
object ANONYMOUS_INITIALIZER : IrOperatorImpl("ANONYMOUS_INITIALIZER")
@@ -0,0 +1,28 @@
interface IFoo {
fun foo()
}
val test1 = object {}
val test2 = object : IFoo {
override fun foo() {
println("foo")
}
}
class Outer {
abstract inner class Inner : IFoo
fun test3() = object : Inner() {
override fun foo() {
println("foo")
}
}
}
fun Outer.test4() =
object : Outer.Inner() {
override fun foo() {
println("foo")
}
}
@@ -0,0 +1,55 @@
FILE /objectLiteralExpressions.kt
CLASS INTERFACE IFoo
FUN public abstract fun foo(): kotlin.Unit
PROPERTY public val test1: kotlin.Any getter=null setter=null
EXPRESSION_BODY
BLOCK type=test1.<no name provided> operator=OBJECT_LITERAL
CLASS CLASS <no name provided>
FUN public constructor <no name provided>()
BLOCK_BODY
CALL .<init> type=test1.<no name provided> operator=OBJECT_LITERAL
PROPERTY public val test2: IFoo getter=null setter=null
EXPRESSION_BODY
BLOCK type=test2.<no name provided> operator=OBJECT_LITERAL
CLASS CLASS <no name provided>
FUN public constructor <no name provided>()
BLOCK_BODY
FUN public open override /*1*/ fun foo(): kotlin.Unit
BLOCK_BODY
CALL .println type=kotlin.Unit operator=null
message: CONST String type=kotlin.String value='foo'
CALL .<init> type=test2.<no name provided> operator=OBJECT_LITERAL
CLASS CLASS Outer
FUN public constructor Outer()
BLOCK_BODY
CLASS CLASS Inner
FUN public constructor Inner()
BLOCK_BODY
FUN public final fun test3(): Outer.Inner
BLOCK_BODY
RETURN type=kotlin.Nothing from=test3
BLOCK type=Outer.test3.<no name provided> operator=OBJECT_LITERAL
CLASS CLASS <no name provided>
FUN public constructor <no name provided>()
BLOCK_BODY
CALL .<init> type=Outer.Inner operator=SUPER_CONSTRUCTOR_CALL
$this: THIS public final class Outer type=Outer
FUN public open override /*1*/ fun foo(): kotlin.Unit
BLOCK_BODY
CALL .println type=kotlin.Unit operator=null
message: CONST String type=kotlin.String value='foo'
CALL .<init> type=Outer.test3.<no name provided> operator=OBJECT_LITERAL
FUN public fun Outer.test4(): Outer.Inner
BLOCK_BODY
RETURN type=kotlin.Nothing from=test4
BLOCK type=test4.<no name provided> operator=OBJECT_LITERAL
CLASS CLASS <no name provided>
FUN public constructor <no name provided>()
BLOCK_BODY
CALL .<init> type=Outer.Inner operator=SUPER_CONSTRUCTOR_CALL
$this: $RECEIVER of: test4 type=Outer
FUN public open override /*1*/ fun foo(): kotlin.Unit
BLOCK_BODY
CALL .println type=kotlin.Unit operator=null
message: CONST String type=kotlin.String value='foo'
CALL .<init> type=test4.<no name provided> operator=OBJECT_LITERAL
@@ -85,6 +85,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("objectLiteralExpressions.kt")
public void testObjectLiteralExpressions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/objectLiteralExpressions.kt");
doTest(fileName);
}
@TestMetadata("primaryConstructor.kt")
public void testPrimaryConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/primaryConstructor.kt");