Provide DeclarationStubGenerator as a separate class in IR utilities

This commit is contained in:
Dmitry Petrov
2017-05-23 14:29:22 +03:00
parent 7204a929f3
commit 6fd762cfce
4 changed files with 159 additions and 107 deletions
@@ -0,0 +1,144 @@
/*
* Copyright 2010-2017 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.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.scopes.MemberScope
class DeclarationStubGenerator(val symbolTable: SymbolTable) {
fun generateEmptyModuleFragmentStub(descriptor: ModuleDescriptor, irBuiltIns: IrBuiltIns): IrModuleFragment =
IrModuleFragmentImpl(descriptor, irBuiltIns)
fun generateEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment =
symbolTable.declareExternalPackageFragment(descriptor)
fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration =
when (descriptor) {
is ClassDescriptor ->
if (DescriptorUtils.isEnumEntry(descriptor))
generateEnumEntryStub(descriptor)
else
generateClassStub(descriptor)
is ClassConstructorDescriptor ->
generateConstructorStub(descriptor)
is FunctionDescriptor ->
generateFunctionStub(descriptor)
is PropertyDescriptor ->
generatePropertyStub(descriptor)
else ->
throw AssertionError("Unexpected member descriptor: $descriptor")
}
fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty =
IrPropertyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
).also { irProperty ->
val getterDescriptor = descriptor.getter
if (getterDescriptor == null) {
irProperty.backingField =
symbolTable.declareField(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
)
}
else {
irProperty.getter = generateFunctionStub(getterDescriptor)
}
irProperty.setter = descriptor.setter?.let { generateFunctionStub(it) }
}
fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction =
symbolTable.declareSimpleFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
).also { irFunction ->
generateTypeParameterStubs(descriptor.typeParameters, irFunction)
generateValueParametersStubs(descriptor.valueParameters, irFunction)
}
fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor =
symbolTable.declareConstructor(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
).also { irConstructor ->
generateValueParametersStubs(descriptor.valueParameters, irConstructor)
}
fun generateValueParametersStubs(valueParameters: Collection<ValueParameterDescriptor>, function: IrFunction) {
valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) }
}
fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter =
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
).also { irValueParameter ->
if (descriptor.declaresDefaultValue()) {
irValueParameter.defaultValue =
IrExpressionBodyImpl(IrErrorExpressionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, descriptor.type,
"Stub expression for default value of ${descriptor.name}"
))
}
}
fun generateClassStub(descriptor: ClassDescriptor): IrClass =
symbolTable.declareClass(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
).also { irClass ->
generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass)
generateChildStubs(descriptor.constructors, irClass)
generateMemberStubs(descriptor.defaultType.memberScope, irClass)
generateMemberStubs(descriptor.staticScope, irClass)
}
fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry =
symbolTable.declareEnumEntry(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
descriptor
)
fun generateTypeParameterStubs(typeParameters: List<TypeParameterDescriptor>, container: IrTypeParametersContainer) {
typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) }
}
fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter =
IrTypeParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, descriptor)
fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) {
generateChildStubs(memberScope.getContributedDescriptors(), container)
}
fun generateChildStubs(descriptors: Collection<DeclarationDescriptor>, container: IrDeclarationContainer) {
descriptors.sortedWith(StableDescriptorsComparator).mapTo(container.declarations) { generateMemberStub(it) }
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2017 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.util
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy
import java.util.*
object StableDescriptorsComparator : Comparator<DeclarationDescriptor> {
override fun compare(member1: DeclarationDescriptor?, member2: DeclarationDescriptor?): Int {
if (member1 == member2) return 0
if (member1 == null) return -1
if (member2 == null) return 1
val image1 = DESCRIPTOR_RENDERER.render(member1)
val image2 = DESCRIPTOR_RENDERER.render(member2)
return image1.compareTo(image2)
}
private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions {
withDefinedIn = false
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OPEN_OVERRIDE
includePropertyConstant = true
classifierNamePolicy = ClassifierNamePolicy.FULLY_QUALIFIED
verbose = true
modifiers = DescriptorRendererModifier.ALL
}
}