Multiple minor fixes.

This commit is contained in:
Dmitry Petrov
2016-09-02 18:09:48 +03:00
committed by Dmitry Petrov
parent da93f57afb
commit ea83407dce
11 changed files with 65 additions and 41 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -25,7 +24,6 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtSecondaryConstructor import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi2ir.generators.getResolvedCall
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
@@ -35,6 +33,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.upperIfFlexible import org.jetbrains.kotlin.types.upperIfFlexible
import java.lang.Exception
fun KotlinType.containsNull() = fun KotlinType.containsNull() =
KotlinTypeChecker.DEFAULT.isSubtypeOf(builtIns.nullableNothingType, this.upperIfFlexible()) KotlinTypeChecker.DEFAULT.isSubtypeOf(builtIns.nullableNothingType, this.upperIfFlexible())
@@ -42,19 +41,12 @@ fun KotlinType.containsNull() =
fun KtElement.deparenthesize(): KtElement = fun KtElement.deparenthesize(): KtElement =
if (this is KtExpression) KtPsiUtil.safeDeparenthesize(this) else this if (this is KtExpression) KtPsiUtil.safeDeparenthesize(this) else this
val CallableDescriptor.explicitReceiverType: KotlinType?
get() {
extensionReceiverParameter?.let { return it.type }
dispatchReceiverParameter?.let { return it.type }
return null
}
fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean { fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean {
var lastValueParameterIndex = -1 var lastValueParameterIndex = -1
for (valueArgument in call.valueArguments) { for (valueArgument in call.valueArguments) {
val argumentMapping = getArgumentMapping(valueArgument) val argumentMapping = getArgumentMapping(valueArgument)
if (argumentMapping !is ArgumentMatch || argumentMapping.isError()) { if (argumentMapping !is ArgumentMatch || argumentMapping.isError()) {
throw AssertionError("Value argument in function call is mapped with error") throw Exception("Value argument in function call is mapped with error")
} }
val argumentIndex = argumentMapping.valueParameter.index val argumentIndex = argumentMapping.valueParameter.index
if (argumentIndex < lastValueParameterIndex) { if (argumentIndex < lastValueParameterIndex) {
@@ -86,8 +86,13 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
} }
private fun StatementGenerator.generateReturnExpression(ktExpression: KtExpression, irBlockBody: IrBlockBodyImpl) { private fun StatementGenerator.generateReturnExpression(ktExpression: KtExpression, irBlockBody: IrBlockBodyImpl) {
val irExpression = generateExpression(ktExpression) val irReturnExpression = generateStatement(ktExpression)
irBlockBody.addStatement(irExpression.wrapWithReturn()) if (irReturnExpression is IrExpression) {
irBlockBody.addStatement(irReturnExpression.wrapWithReturn())
}
else {
irBlockBody.addStatement(irReturnExpression)
}
} }
private fun IrExpression.wrapWithReturn() = private fun IrExpression.wrapWithReturn() =
@@ -56,9 +56,9 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
if (descriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $descriptor") if (descriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $descriptor")
return call.callReceiver.call { dispatchReceiver, extensionReceiver -> return call.callReceiver.call { dispatchReceiver, extensionReceiver ->
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, descriptor) val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, descriptor)
irCall.dispatchReceiver = dispatchReceiver?.load()
irCall.extensionReceiver = extensionReceiver?.load()
addParametersToCall(startOffset, endOffset, call, irCall, descriptor.returnType) addParametersToCall(startOffset, endOffset, call, irCall, descriptor.returnType)
} }
} }
@@ -19,13 +19,11 @@ package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClassImpl import org.jetbrains.kotlin.ir.declarations.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.mapValueParameters import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -91,9 +89,17 @@ class DataClassMembersGenerator(
private val IMUL = INT.findFirstFunction("times") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) } private val IMUL = INT.findFirstFunction("times") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) }
private val IADD = INT.findFirstFunction("plus") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) } private val IADD = INT.findFirstFunction("plus") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) }
private fun getHashCodeFunction(type: KotlinType): CallableDescriptor = private fun getHashCodeFunction(type: KotlinType): CallableDescriptor {
(type.constructor.declarationDescriptor as? ClassDescriptor)?.findFirstFunction("hashCode") { it.valueParameters.isEmpty() } ?: val typeConstructorDescriptor = type.constructor.declarationDescriptor
throw AssertionError("Unexpected type: $type") when (typeConstructorDescriptor) {
is ClassDescriptor ->
return typeConstructorDescriptor.findFirstFunction("hashCode") { it.valueParameters.isEmpty() }
is TypeParameterDescriptor ->
return getHashCodeFunction(context.builtIns.anyType) // TODO
else ->
throw AssertionError("Unexpected type: $type")
}
}
override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) { override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) { buildMember(function) {
@@ -60,8 +60,9 @@ class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : Stateme
val type = getErrorExpressionType(ktName) val type = getErrorExpressionType(ktName)
val irErrorCall = IrErrorCallExpressionImpl(ktName.startOffset, ktName.endOffset, type, "") // TODO problem description? val irErrorCall = IrErrorCallExpressionImpl(ktName.startOffset, ktName.endOffset, type, "") // TODO problem description?
irErrorCall.explicitReceiver = (ktName.parent as? KtDotQualifiedExpression)?.let { irErrorCall.explicitReceiver = (ktName.parent as? KtDotQualifiedExpression)?.let { ktParent ->
statementGenerator.generateExpression(it.receiverExpression) if (ktParent.receiverExpression == ktName) null
else statementGenerator.generateExpression(ktParent.receiverExpression)
} }
return irErrorCall return irErrorCall
@@ -22,16 +22,13 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
class GeneratorContext( class GeneratorContext(
val moduleDescriptor: ModuleDescriptor, val moduleDescriptor: ModuleDescriptor,
val bindingContext: BindingContext val bindingContext: BindingContext
) { ) {
val storageManager: StorageManager = LockBasedStorageManager.NO_LOCKS
val sourceManager = PsiSourceManager() val sourceManager = PsiSourceManager()
val syntheticDescriptorsFactory by lazy { SyntheticDescriptorsFactory(storageManager) } val syntheticDescriptorsFactory = SyntheticDescriptorsFactory()
val reflectionTypes = ReflectionTypes(moduleDescriptor) val reflectionTypes = ReflectionTypes(moduleDescriptor)
val builtIns: KotlinBuiltIns get() = moduleDescriptor.builtIns val builtIns: KotlinBuiltIns get() = moduleDescriptor.builtIns
@@ -20,29 +20,36 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertyAccessorDescriptor.Kind.MEMBER_PROPERTY
import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertyAccessorDescriptor.Kind.STATIC_PROPERTY import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertyAccessorDescriptor.Kind.STATIC_PROPERTY
import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertyGetterDescriptorImpl import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertyGetterDescriptorImpl
import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertySetterDescriptorImpl import org.jetbrains.kotlin.ir.descriptors.IrSyntheticPropertySetterDescriptorImpl
import org.jetbrains.kotlin.storage.StorageManager
import java.lang.AssertionError import java.lang.AssertionError
import java.util.*
class SyntheticDescriptorsFactory(storageManager: StorageManager) { class SyntheticDescriptorsFactory {
private val propertyGetters = storageManager.createMemoizedFunction<PropertyDescriptor, PropertyGetterDescriptor> { private val propertyGetters = HashMap<PropertyDescriptor, PropertyGetterDescriptor>()
property ->
when { private fun generateGetter(property: PropertyDescriptor): PropertyGetterDescriptor {
return when {
isStaticPropertyInClass(property) -> isStaticPropertyInClass(property) ->
IrSyntheticPropertyGetterDescriptorImpl(property, STATIC_PROPERTY) IrSyntheticPropertyGetterDescriptorImpl(property, STATIC_PROPERTY)
isPropertyInClass(property) ->
IrSyntheticPropertyGetterDescriptorImpl(property, MEMBER_PROPERTY)
else -> else ->
throw AssertionError("Don't know how to create synthetic getter for $property") throw AssertionError("Don't know how to create synthetic getter for $property")
} }
} }
private val propertySetters = storageManager.createMemoizedFunction<PropertyDescriptor, PropertySetterDescriptor> { private val propertySetters = HashMap<PropertyDescriptor, PropertySetterDescriptor>()
property ->
when { private fun generateSetter(property: PropertyDescriptor): PropertySetterDescriptor {
return when {
isStaticPropertyInClass(property) -> isStaticPropertyInClass(property) ->
IrSyntheticPropertySetterDescriptorImpl(property, STATIC_PROPERTY) IrSyntheticPropertySetterDescriptorImpl(property, STATIC_PROPERTY)
isPropertyInClass(property) ->
IrSyntheticPropertySetterDescriptorImpl(property, MEMBER_PROPERTY)
else -> else ->
throw AssertionError("Don't know how to create synthetic setter for $property") throw AssertionError("Don't know how to create synthetic setter for $property")
} }
@@ -53,9 +60,12 @@ class SyntheticDescriptorsFactory(storageManager: StorageManager) {
propertyDescriptor.dispatchReceiverParameter == null && propertyDescriptor.dispatchReceiverParameter == null &&
propertyDescriptor.extensionReceiverParameter == null propertyDescriptor.extensionReceiverParameter == null
private fun isPropertyInClass(propertyDescriptor: PropertyDescriptor): Boolean =
propertyDescriptor.containingDeclaration is ClassDescriptor
fun getOrCreatePropertyGetter(propertyDescriptor: PropertyDescriptor): PropertyGetterDescriptor = fun getOrCreatePropertyGetter(propertyDescriptor: PropertyDescriptor): PropertyGetterDescriptor =
propertyGetters(propertyDescriptor) propertyGetters.getOrPut(propertyDescriptor) { generateGetter(propertyDescriptor) }
fun getOrCreatePropertySetter(propertyDescriptor: PropertyDescriptor): PropertySetterDescriptor = fun getOrCreatePropertySetter(propertyDescriptor: PropertyDescriptor): PropertySetterDescriptor =
propertySetters(propertyDescriptor) propertySetters.getOrPut(propertyDescriptor) { generateSetter(propertyDescriptor) }
} }
@@ -21,6 +21,6 @@ import java.io.File
abstract class AbstractPsi2IrAcceptanceTestCase : AbstractIrGeneratorTestCase() { abstract class AbstractPsi2IrAcceptanceTestCase : AbstractIrGeneratorTestCase() {
override fun doTest(wholeFile: File, testFiles: List<TestFile>) { override fun doTest(wholeFile: File, testFiles: List<TestFile>) {
// Just make sure that nothing interesting happens - e.g., no exceptions thrown // Just make sure that nothing interesting happens - e.g., no exceptions thrown
generateIrFilesAsSingleModule(testFiles) generateIrFilesAsSingleModule(testFiles, true)
} }
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.ir package org.jetbrains.kotlin.ir
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrElement { interface IrElement {
@@ -73,7 +74,7 @@ fun IrElement.assertDetached() {
} }
fun IrElement.throwNoSuchSlot(slot: Int): Nothing = fun IrElement.throwNoSuchSlot(slot: Int): Nothing =
throw AssertionError("$this: no such slot $slot") throw AssertionError("${this.render()}: no such slot $slot")
inline fun <reified T : IrElement> IrElement.assertCast(): T = inline fun <reified T : IrElement> IrElement.assertCast(): T =
if (this is T) this else throw AssertionError("Expected ${T::class.simpleName}: $this") if (this is T) this else throw AssertionError("Expected ${T::class.simpleName}: $this")
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
interface IrSyntheticPropertyAccessorDescriptor : PropertyAccessorDescriptor { interface IrSyntheticPropertyAccessorDescriptor : PropertyAccessorDescriptor {
enum class Kind { enum class Kind {
STATIC_PROPERTY STATIC_PROPERTY,
MEMBER_PROPERTY
} }
val kind: Kind val kind: Kind
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.SETTER_ARGUMENT_INDEX import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.assertDetached
import org.jetbrains.kotlin.ir.detach
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrPropertyAccessorCallBase( abstract class IrPropertyAccessorCallBase(
@@ -106,4 +104,17 @@ class IrSetterCallImpl(
argumentImpl?.detach() argumentImpl?.detach()
argumentImpl = null argumentImpl = null
} }
override fun getChild(slot: Int): IrElement? =
when (slot) {
SETTER_ARGUMENT_INDEX -> argumentImpl
else -> super.getChild(slot)
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
SETTER_ARGUMENT_INDEX -> putArgument(slot, newChild.assertCast())
else -> super.replaceChild(slot, newChild)
}
}
} }