Skip to content

Generics in Kotlin codegen (#88) #720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

nikitavlaev
Copy link
Member

@nikitavlaev nikitavlaev commented Aug 12, 2022

Description

Refactored imports to support kotlin builtins (List, Map, e.t.c).
Added generics propagation using callables.
Added filling generics with Any? and *.
Reworked Kotlin type render.
Fixed assemble model generation in concrete.
Fixed bug with backticks.

Fixes #88

Slides

Type of Change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How Has This Been Tested?

Automated Testing

All previously disabled tests for Kotlin compilation.

Manual Scenario

Not applicable.

Checklist (remove irrelevant options):

This is the author self-check list

  • The change followed the style guidelines of the UTBot project
  • Self-review of the code is passed
  • The change contains enough commentaries, particularly in hard-to-understand areas
  • No new warnings
  • All tests pass locally with my changes

@nikitavlaev nikitavlaev force-pushed the nikitavlaev/kotlin-codegen-generics branch from a35be48 to a456874 Compare August 14, 2022 22:01
@nikitavlaev nikitavlaev requested review from sergeypospelov and removed request for EgorkaKulikov and Damtev August 15, 2022 12:22
@nikitavlaev nikitavlaev self-assigned this Aug 15, 2022
@nikitavlaev nikitavlaev force-pushed the nikitavlaev/kotlin-codegen-generics branch 2 times, most recently from 47fb89f to b2ed51f Compare August 15, 2022 16:34
@@ -760,8 +930,7 @@ open class ClassId @JvmOverloads constructor(
open val allConstructors: Sequence<ConstructorId>
get() = jClass.declaredConstructors.asSequence().map { it.executableId }

open val typeParameters: TypeParameters
get() = TypeParameters()
open val typeParameters: TypeParameters = TypeParameters()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write a comment about issues with reusing ClassIds for different models.

caller[executable](*args.toTypedArray())
caller[executable](
*args.toTypedArray(),
typeParameters = executable.returnType.typeParameters
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xD

@@ -692,6 +692,7 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:

override fun toString(): String = printer.toString()

protected abstract fun <T: Import> reorderImports(imports: List<T>): List<T>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain, please, for what purpose?

@nikitavlaev nikitavlaev force-pushed the nikitavlaev/kotlin-codegen-generics branch from b2ed51f to af60704 Compare August 16, 2022 12:59
else -> {
// we cannot access kClass for BuiltinClassId
// we cannot use simple name here because this class can be not imported
if (id is BuiltinClassId) id.name else id.kClass.id.asString()
var main = builtInNameOrNull(id) ?: if (id is BuiltinClassId) id.name else id.kClass.id.asString()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rewrite it with buildString { ... }

@@ -821,8 +821,8 @@ internal fun CgContextOwner.importUtilMethodDependencies(id: MethodId) {
for (classId in outerMostTestClass.regularImportsByUtilMethod(id, codegenLanguage)) {
importIfNeeded(classId)
}
for (methodId in outerMostTestClass.staticImportsByUtilMethod(id)) {
collectedImports += StaticImport(methodId.classId.canonicalName, methodId.name)
for (methodId in currentTestClass.staticImportsByUtilMethod(id)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

}.map { processGenerics(it, engine.methodUnderTest.callable) }
}

private fun processGenericsForEnvironmentModels(models: EnvironmentModels, callable: KCallable<*>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move it to another file?

}
}

private fun processGenerics(result: UtResult, callable: KCallable<*>): UtResult {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

Comment on lines 427 to 429
override fun processGenerics(type: KType) {
classId.typeParameters.fromType(type)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add TODO on propagating generics into fields and mocks.

@@ -505,6 +531,150 @@ data class UtAssembleModel(
val finalInstantiationModel
get() = instantiationChain.lastOrNull()

private fun TypeTree.cmp(other: TypeTree): Boolean {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to another module


class WildcardTypeParameter : TypeParameters(emptyList())
class WildcardTypeParameter: ClassId("org.utbot.framework.plugin.api.WildcardTypeParameter")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not Object?

// TODO might cause problems with type params when program synthesis comes
// assume that last statement is constructor call
instantiationChain.lastOrNull()?.let inst@ { lastStatement ->
(lastStatement as? UtExecutableCallModel)?.let {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add explicit identifier for it

}

it.params.mapIndexed { i, param ->
function?.parameters?.getOrNull(i)?.type?.let { it1 -> param.processGenerics(it1) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it1

}
is Method -> {
try {
val f = Method::class.java.getDeclaredField("signature")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to ReflectionUtil.kt

parsedSignature.parameterTypes.forEachIndexed { paramId, param ->
if (param::class != parsedSignature.returnType::class) return@forEachIndexed

param as? TypeArgument ?: error("Only TypeArgument is expected")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

// check if parameter types are equal to return types
// e.g. <T:Ljava/lang/Object;>(Ljava/util/List<TT;>;)Ljava/util/List<TT;>;
parsedSignature.parameterTypes.forEachIndexed { paramId, param ->
if (param::class != parsedSignature.returnType::class) return@forEachIndexed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

}
}

for (model in modificationsChain) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mark it as hack?

@nikitavlaev nikitavlaev force-pushed the nikitavlaev/kotlin-codegen-generics branch 2 times, most recently from 39d0e5f to 3fabd2b Compare August 17, 2022 06:55
Refactored imports to support kotlin builtins (List, Map, e.t.c).
Added generics propagation using callables.
Added filling generics with Any? and *.
Reworked Kotlin type render.
Fixed assemble model generation in concrete.
Fixed bug with backticks.
@nikitavlaev nikitavlaev force-pushed the nikitavlaev/kotlin-codegen-generics branch from 3fabd2b to 5900dc3 Compare September 4, 2022 20:14
@sergeypospelov
Copy link
Member

We need to refactor our type system to safely support generic types. Now the have very implicit and error prone realization.

@Damtev Damtev mentioned this pull request Oct 4, 2022
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generics in Kotlin codegen
2 participants