Skip to content

Commit

Permalink
Merge pull request #40 from kanyun-inc/feature/support-k2
Browse files Browse the repository at this point in the history
Support k2
  • Loading branch information
RicardoJiang authored May 30, 2023
2 parents 2b135a0 + 1279565 commit 9d1d7ef
Show file tree
Hide file tree
Showing 28 changed files with 477 additions and 90 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Check spotless
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache

- name: Run local tests
run: ./gradlew :kace-compiler:test

Expand All @@ -48,5 +45,8 @@ jobs:
distribution: 'zulu'
java-version: 11

- name: Check spotless
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache

- name: Test AGP compatibility
run: chmod +x ./test_agp.sh && ./test_agp.sh
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ kotlin.code.style=official
android.nonTransitiveRClass=true

KOTLIN_PLUGIN_ID=com.kanyun.kace
VERSION_NAME=1.8.20-1.0.5
VERSION_NAME=1.8.20-1.1.0-SNAPSHOT

GROUP=com.kanyun.kace

Expand Down
8 changes: 5 additions & 3 deletions gradle/init.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
*/

val ktlintVersion = "0.43.0"
val ktlintVersion = "0.49.1"

initscript {
val spotlessVersion = "6.11.0"
val spotlessVersion = "6.19.0"

repositories {
mavenCentral()
Expand All @@ -38,7 +38,9 @@ rootProject {
ktlint(ktlintVersion).userData(
mapOf(
"android" to "true",
"max_line_length" to "200"
"max_line_length" to "200",
"ij_kotlin_allow_trailing_comma" to "false",
"ij_kotlin_allow_trailing_comma_on_call_site" to "false"
)
)
licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
Expand Down
8 changes: 6 additions & 2 deletions kace-compiler/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ dependencies {
testImplementation(kotlin("test-junit"))
testImplementation("org.jetbrains.kotlin:kotlin-compiler-embeddable")

testImplementation("com.bennyhuo.kotlin:kotlin-compile-testing-extensions:1.8.0.0")
testImplementation("com.bennyhuo.kotlin:kotlin-compile-testing-extensions:1.8.0.1")
}

val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.freeCompilerArgs += listOf("-Xjvm-default=enable", "-opt-in=kotlin.RequiresOptIn")
compileKotlin.kotlinOptions.freeCompilerArgs += listOf(
"-Xjvm-default=enable",
"-opt-in=kotlin.RequiresOptIn",
"-Xcontext-receivers"
)
compileKotlin.kotlinOptions.jvmTarget = "1.8"

buildConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ class KaceCommandLineProcessor : CommandLineProcessor {
override fun processOption(
option: AbstractCliOption,
value: String,
configuration: CompilerConfiguration
configuration: CompilerConfiguration,
) = Options.processOption(option, value, configuration)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension

@OptIn(ExperimentalCompilerApi::class)
@AutoService(CompilerPluginRegistrar::class)
class KaceCompilerPluginRegistrar : CompilerPluginRegistrar() {

override val supportsK2: Boolean = false
override val supportsK2: Boolean = true
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
IrGenerationExtension.registerExtension(KaceIrGenerationExtension())
SyntheticResolveExtension.registerExtension(KaceSyntheticResolveExtension())
FirExtensionRegistrarAdapter.registerExtension(KaceFirExtensionRegistrar())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 KanYun
*
* 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 com.kanyun.kace.compiler

import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar

class KaceFirExtensionRegistrar : FirExtensionRegistrar() {
override fun ExtensionRegistrarContext.configurePlugin() {
+::KaceFirSupertypeGenerationExtension
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2022 KanYun
*
* 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 com.kanyun.kace.compiler

import com.kanyun.kace.compiler.utils.ANDROID_EXTENSIONS_CLASS_ID
import com.kanyun.kace.compiler.utils.IMPLICIT_ANDROID_EXTENSIONS_CLASS_IDS
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.name.ClassId

/**
* Created by benny at 2023/5/29 14:47.
*/
@OptIn(SymbolInternals::class)
class KaceFirSupertypeGenerationExtension(
session: FirSession,
) : FirSupertypeGenerationExtension(session) {

context(TypeResolveServiceContainer) override fun computeAdditionalSupertypes(
classLikeDeclaration: FirClassLikeDeclaration,
resolvedSupertypes: List<FirResolvedTypeRef>,
): List<FirResolvedTypeRef> {
var shouldAddSuperType = false
OUTER@ for (superTypeRef in resolvedSupertypes) {
val superType = superTypeRef.type
val classIds = listOf(superType.classId) + superType.allSuperTypeClassIds()
for (classId in classIds) {
if (classId == ANDROID_EXTENSIONS_CLASS_ID) {
shouldAddSuperType = false
break@OUTER
}
if (!shouldAddSuperType && classId in IMPLICIT_ANDROID_EXTENSIONS_CLASS_IDS) {
shouldAddSuperType = true
}
}
}

if (!shouldAddSuperType) return emptyList()

return listOf(
buildResolvedTypeRef {
type = ANDROID_EXTENSIONS_CLASS_ID.constructClassLikeType(
emptyArray(),
isNullable = false,
)
},
)
}

private fun FirClassLikeDeclaration.supertypeRefs() = when (this) {
is FirRegularClass -> superTypeRefs
is FirTypeAlias -> listOf(expandedTypeRef)
else -> emptyList()
}

private fun ConeKotlinType.allSuperTypeClassIds(): List<ClassId> {
if (this !is ConeClassLikeType) return emptyList()
val superTypeModuleSession = toSymbol(session)?.moduleData?.session ?: return emptyList()
val superTypeFir = lookupTag.toSymbol(superTypeModuleSession)?.fir ?: return emptyList()
return listOf(superTypeFir.classId) + superTypeFir.supertypeRefs().flatMap {
it.coneTypeSafe<ConeKotlinType>()?.allSuperTypeClassIds() ?: emptyList()
}
}

override fun needTransformSupertypes(declaration: FirClassLikeDeclaration): Boolean {
return declaration is FirClass &&
declaration.origin == FirDeclarationOrigin.Source &&
declaration.superTypeRefs.isNotEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ class KaceIrTransformer(private val context: IrPluginContext) : IrElementTransfo
// private val $$androidExtensionsImpl = AndroidExtensionsImpl()
val androidExtensionsField = declaration.addField(
DELEGATE_FIELD_NAME,
androidExtensionImpl.defaultType
androidExtensionImpl.defaultType,
).apply {
initializer = DeclarationIrBuilder(
context,
symbol,
symbol.owner.startOffset,
symbol.owner.endOffset
symbol.owner.endOffset,
).run {
irExprBody(irCall(androidExtensionImpl.constructors.first()))
}
Expand All @@ -78,7 +78,7 @@ class KaceIrTransformer(private val context: IrPluginContext) : IrElementTransfo
declaration.addOverride(
ANDROID_EXTENSIONS_FQNAME,
FIND_VIEW_BY_ID_CACHED_NAME,
IrUninitializedType
IrUninitializedType,
).apply {
val parameterT = addTypeParameter("T", context.typeOfView())
returnType = parameterT.defaultType.makeNullable()
Expand All @@ -90,22 +90,22 @@ class KaceIrTransformer(private val context: IrPluginContext) : IrElementTransfo
context,
Scope(this.symbol),
SYNTHETIC_OFFSET,
SYNTHETIC_OFFSET
SYNTHETIC_OFFSET,
).apply {
val androidExtensionsValue = irGetField(irThis(), androidExtensionsField)
+irReturn(
irCall(
androidExtensionImpl.owner.findViewByIdCached(this@KaceIrTransformer.context)!!.symbol
androidExtensionImpl.owner.findViewByIdCached(this@KaceIrTransformer.context)!!.symbol,
).apply {
dispatchReceiver = androidExtensionsValue

valueParameters.forEachIndexed { index, irValueParameter ->
putValueArgument(
index,
irGet(irValueParameter.type, irValueParameter.symbol)
irGet(irValueParameter.type, irValueParameter.symbol),
)
}
}
},
)
}.doBuild()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.kanyun.kace.compiler.utils.IMPLICIT_ANDROID_EXTENSIONS_TYPES
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.js.descriptorUtils.getKotlinTypeFqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
Expand All @@ -43,7 +43,7 @@ class KaceSyntheticResolveExtension : SyntheticResolveExtension {
val superTypeNames = supertypes.asSequence().flatMap {
listOf(it) + it.supertypes()
}.map {
it.getJetTypeFqName(false)
it.getKotlinTypeFqName(false)
}

var shouldAddSuperType = false
Expand All @@ -58,8 +58,8 @@ class KaceSyntheticResolveExtension : SyntheticResolveExtension {
val androidExtensionsType = thisDescriptor.module.findClassAcrossModuleDependencies(
ClassId(
FqName(ANDROID_EXTENSIONS_PACKAGE_NAME),
Name.identifier(ANDROID_EXTENSIONS_CLASS_NAME)
)
Name.identifier(ANDROID_EXTENSIONS_CLASS_NAME),
),
)

checkNotNull(androidExtensionsType) {
Expand All @@ -69,8 +69,9 @@ class KaceSyntheticResolveExtension : SyntheticResolveExtension {
supertypes.add(
KotlinTypeFactory.simpleNotNullType(
TypeAttributes.Empty,
androidExtensionsType, emptyList()
)
androidExtensionsType,
emptyList(),
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package com.kanyun.kace.compiler.options

import java.lang.ref.WeakReference
import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption
import org.jetbrains.kotlin.compiler.plugin.CliOption
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import java.lang.ref.WeakReference

object Options {

Expand All @@ -30,15 +30,18 @@ object Options {
description: String,
valueDescription: String,
required: Boolean = false,
allowMultipleOccurrences: Boolean = false
allowMultipleOccurrences: Boolean = false,
) {

private val key = CompilerConfigurationKey.create<T>(name)
private var value: T? = null

val option = CliOption(
name, valueDescription, description,
required, allowMultipleOccurrences
name,
valueDescription,
description,
required,
allowMultipleOccurrences,
)

fun config(value: String?, configuration: CompilerConfiguration) {
Expand Down Expand Up @@ -71,7 +74,7 @@ object Options {
"isEnabled",
false,
"Enable this plugin.",
"<true/false>"
"<true/false>",
)

val allOptions = Options::class.java.declaredFields.filter {
Expand All @@ -83,7 +86,7 @@ object Options {
fun processOption(
option: AbstractCliOption,
value: String,
configuration: CompilerConfiguration
configuration: CompilerConfiguration,
) {
allOptions.firstOrNull {
it.option == option
Expand Down
Loading

0 comments on commit 9d1d7ef

Please sign in to comment.