Object literal expressions.
This commit is contained in:
committed by
Dmitry Petrov
parent
86a52e6426
commit
41d772d636
+53
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user