Skip to content
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

Feature/kotlin 1.9.0 #48

Merged
merged 8 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
java-version: 8

- name: Setup Gradle
uses: gradle/gradle-build-action@v2
uses: gradle/gradle-build-action@v2.4.2

- name: Run local tests
run: ./gradlew :kace-compiler:test
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: "Tagged Release"

on:
push:
tags:
- "v*"

jobs:
tagged-release:
name: "Tagged Release"
runs-on: "ubuntu-latest"

steps:
- uses: "marvinpinto/[email protected]"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ kace {
The Kace currently supports the above four most commonly used types. Other types supported by kotlin-android-extensions such as android.app.Fragment, android.app.Dialog, kotlinx.android.extensions.LayoutContainer are deprecated or rarely used, currently not supported by the Kace

## Version compatible
| Kace | Kotlin | AGP | Gradle |
|--------------|---------------|-------|--------|
| 1.7.0-1.0.4 | 1.7.0 | 4.2.0 | 6.7.1 |
| 1.8.0-1.0.4 | 1.8.0~1.8.10 | 4.2.0 | 6.8.3 |
| 1.8.20-1.0.4 | 1.8.20 | 4.2.0 | 6.8.3 |
| Kace | Kotlin | AGP | Gradle |
|--------------|--------------|-------|--------|
| 1.7.0-1.0.4 | 1.7.0 | 4.2.0 | 6.7.1 |
| 1.8.0-1.0.4 | 1.8.0~1.8.10 | 4.2.0 | 6.8.3 |
| 1.8.20-1.1.0 | 1.8.20 | 4.2.0 | 6.8.3 |
| 1.9.0-1.1.0 | 1.9.0 | 4.2.2 | 6.8.3 |

Since the goal of the Kace is to help developers easily upgrade to Kotlin 1.8, the minimum supported version of Kotlin is relatively high

Expand Down
11 changes: 6 additions & 5 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ kace {
Kace 目前支持了以上四种最常用的类型,其他 kotlin-android-extensions 支持的类型如 android.app.Fragment, android.app.Dialog, kotlinx.android.extensions.LayoutContainer 等,由于被废弃或者使用较少,Kace 目前没有做支持

## 版本兼容
| Kace | Kotlin | AGP | Gradle |
|----------------------|--------|-------|--------|
| 1.7.0-1.0.4 | 1.7.0 | 4.2.0 | 6.7.1 |
| 1.8.0-1.0.4 | 1.8.0~1.8.10 | 4.2.0 | 6.8.3 |
| 1.8.20-1.0.4 | 1.8.20 | 4.2.0 | 6.8.3 |
| Kace | Kotlin | AGP | Gradle |
|--------------|--------------|-------|--------|
| 1.7.0-1.0.4 | 1.7.0 | 4.2.0 | 6.7.1 |
| 1.8.0-1.0.4 | 1.8.0~1.8.10 | 4.2.0 | 6.8.3 |
| 1.8.20-1.1.0 | 1.8.20 | 4.2.0 | 6.8.3 |
| 1.9.0-1.1.0 | 1.9.0 | 4.2.2 | 6.8.3 |

由于 Kace 的目标是帮助开发者更方便地迁移到 Kotlin 1.8,因此 Kotlin 最低支持版本比较高

Expand Down
9 changes: 5 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "4.2.0" apply false
id("com.android.library") version "4.2.0" apply false
id("org.jetbrains.kotlin.android") version "1.8.20" apply false
id("com.android.application") version "4.2.2" apply false
id("com.android.library") version "4.2.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
id("com.vanniktech.maven.publish") version "0.18.0" apply false
id("com.github.gmazzo.buildconfig") version "2.1.0" apply false
}

allprojects {
repositories {
maven { setUrl("https://mirrors.tencent.com/nexus/repository/maven-public/") }
mavenCentral()
google()
maven { setUrl("https://oss.sonatype.org/content/repositories/snapshots/") }
}

Expand Down
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.1.0
VERSION_NAME=1.9.0-1.2.0-SNAPSHOT

GROUP=com.kanyun.kace

Expand Down
3 changes: 1 addition & 2 deletions kace-compiler/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ dependencies {
testImplementation(kotlin("test-junit"))
testImplementation("org.jetbrains.kotlin:kotlin-compiler-embeddable")

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

val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.freeCompilerArgs += listOf(
"-Xjvm-default=enable",
"-opt-in=kotlin.RequiresOptIn",
"-Xcontext-receivers"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.kanyun.kace.compiler.utils.irThis
import com.kanyun.kace.compiler.utils.isAndroidExtensions
import com.kanyun.kace.compiler.utils.symbolOfAndroidExtensionImpl
import com.kanyun.kace.compiler.utils.typeOfAndroidExtensionsBase
import com.kanyun.kace.compiler.utils.typeOfJavaClass
import com.kanyun.kace.compiler.utils.typeOfView
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
Expand Down Expand Up @@ -85,6 +86,7 @@ class KaceIrTransformer(private val context: IrPluginContext) : IrElementTransfo

addValueParameter("owner", context.typeOfAndroidExtensionsBase())
addValueParameter("id", context.symbols.int.defaultType)
addValueParameter("viewClass", context.typeOfJavaClass())

body = IrBlockBodyBuilder(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ val ANDROID_VIEW_CLASS_ID = classId("android.view", "View")
val ANDROID_ACTIVITY_CLASS_ID = classId("android.app", "Activity")
val ANDROIDX_FRAGMENT_CLASS_ID = classId("androidx.fragment.app", "Fragment")

val JAVA_CLASS_CLASS_ID = classId("java.lang", "Class")

val IMPLICIT_ANDROID_EXTENSIONS_CLASS_IDS = setOf(
ANDROID_ACTIVITY_CLASS_ID,
ANDROIDX_FRAGMENT_CLASS_ID,
Expand Down
12 changes: 8 additions & 4 deletions kace-compiler/src/main/java/com/kanyun/kace/compiler/utils/Ir.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.functions

Expand All @@ -32,10 +33,11 @@ fun IrClass.findViewByIdCached(pluginContext: IrPluginContext): IrSimpleFunction

fun IrFunction.isFindViewByIdCached(pluginContext: IrPluginContext): Boolean {
return name.identifier == FIND_VIEW_BY_ID_CACHED_NAME &&
valueParameters.size == 2 &&
valueParameters[0].type ==
pluginContext.referenceClass(ANDROID_EXTENSIONS_BASE_CLASS_ID)?.defaultType &&
valueParameters[1].type == pluginContext.symbols.int.defaultType
valueParameters.size == 3 &&
valueParameters[0].type == pluginContext.typeOfAndroidExtensionsBase() &&
valueParameters[1].type == pluginContext.symbols.int.defaultType &&
// java.lang.Class<T> -> java.lang.Class
valueParameters[2].type.classifierOrNull?.defaultType == pluginContext.typeOfJavaClass()
}

fun IrClass.isAndroidExtensions(): Boolean {
Expand All @@ -47,5 +49,7 @@ fun IrPluginContext.typeOfAndroidExtensionsBase() =

fun IrPluginContext.typeOfView() = referenceClass(ANDROID_VIEW_CLASS_ID)!!.defaultType

fun IrPluginContext.typeOfJavaClass() = referenceClass(JAVA_CLASS_CLASS_ID)!!.defaultType

fun IrPluginContext.symbolOfAndroidExtensionImpl() =
referenceClass(ANDROID_EXTENSIONS_IMPL_CLASS_ID)!!
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ package com.kanyun.kace.compiler

import com.bennyhuo.kotlin.compiletesting.extensions.module.KotlinModule
import com.bennyhuo.kotlin.compiletesting.extensions.module.checkResult
import com.bennyhuo.kotlin.compiletesting.extensions.source.FileBasedModuleInfoLoader
import com.bennyhuo.kotlin.compiletesting.extensions.source.TextBasedModuleInfoLoader
import com.kanyun.kace.compiler.options.Options
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.Test
import java.io.File

class KaceTest {

Expand All @@ -37,7 +38,9 @@ class KaceTest {

@OptIn(ExperimentalCompilerApi::class)
private fun testBase(fileName: String, useK2: Boolean) {
val loader = FileBasedModuleInfoLoader("testData/$fileName")
val source = File("testData/source.txt").readText()
val expect = File("testData/$fileName").readText()
val loader = TextBasedModuleInfoLoader("$source\n$expect")
val sourceModuleInfos = loader.loadSourceModuleInfos()

Options.isEnabled.set(true)
Expand Down
168 changes: 16 additions & 152 deletions kace-compiler/testData/K1.txt
Original file line number Diff line number Diff line change
@@ -1,139 +1,3 @@
// SOURCE
// FILE: Activity.java
package android.app;

public class Activity {

}
// FILE: BaseActivity.java
package android.app;

import android.app.Activity;

public class BaseActivity extends Activity {

}
// FILE: BaseKotlinActivity.kt
package android.app

import android.app.Activity

open class BaseKotlinActivity : Activity() {

}
// FILE: Base2Activity.java
package android.app;

import android.app.Activity;

public class Base2Activity extends BaseKotlinActivity {

}
// FILE: View.java
package android.view;

public class View {
public String value;
public View(String value) {
this.value = value;
}

public String toString() {
return value;
}
}
// FILE: AndroidExtensionsBase.java
package com.kanyun.kace;

import android.view.View;

public interface AndroidExtensionsBase {

<T extends View> T findViewByIdCached(AndroidExtensionsBase owner, int id);

}
// FILE: common.kt
package com.kanyun.kace

import android.view.View

interface AndroidExtensions: AndroidExtensionsBase {
override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? = error("Never called!")
}
class AndroidExtensionsImpl: AndroidExtensions {

private val map = HashMap<Int, View>()

init {
List(10) {
map[it] = View("$it")
}
}

override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
println(owner::class)
return map[id] as T?
}
}

// FILE: Main.kt [MainKt#main]
import com.kanyun.kace.AndroidExtensions
import com.kanyun.kace.AndroidExtensionsBase
import com.kanyun.kace.AndroidExtensionsImpl
import android.view.View
import android.app.Activity
import android.app.BaseActivity
import android.app.Base2Activity

class MainActivity : AndroidExtensions by AndroidExtensionsImpl() {

}

class SecondActivity : AndroidExtensions {

}

class ThirdActivity : AndroidExtensions {

override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
println(owner::class)
return View("Third!!") as T?
}
}

open class FourthActivity : Activity() {

}


class FifthActivity : BaseActivity() {

}

class SixthActivity : Base2Activity() {

}

fun main() {
val main = MainActivity()
println(main.findViewByIdCached<View>(main, 0))

val second = SecondActivity()
println(second.findViewByIdCached<View>(second, 1))

val third = ThirdActivity()
println(third.findViewByIdCached<View>(third, 2))

val fouth = FourthActivity()
println(fouth.findViewByIdCached<View>(fouth, 3))

val fifth = FifthActivity()
println(fifth.findViewByIdCached<View>(fifth, 4))

val sixth = SixthActivity()
println(sixth.findViewByIdCached<View>(sixth, 7))
}

// EXPECT
// FILE: compiles.log
OK
Expand All @@ -153,46 +17,46 @@ class SixthActivity
// FILE: Main.kt.ir
class MainActivity : AndroidExtensions {
private val $$delegate_0: AndroidExtensionsImpl = AndroidExtensionsImpl()
override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
return <this>.$$delegate_0.findViewByIdCached(owner, id)
override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int, viewClass: Class<T>): T? {
return <this>.$$delegate_0.findViewByIdCached(owner, id, viewClass)
}
}
class SecondActivity : AndroidExtensions {
private var $$androidExtensionsImpl: AndroidExtensionsImpl = AndroidExtensionsImpl()
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id)
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int, viewClass: Class<T>): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id, viewClass)
}
}
class ThirdActivity : AndroidExtensions {
override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
override fun <T: View?> findViewByIdCached(owner: AndroidExtensionsBase, id: Int, viewClass: Class<T>): T? {
println(<<IrGetClassImpl>>)
return View("Third!!")
}
}
open class FourthActivity : Activity, AndroidExtensions {
private var $$androidExtensionsImpl: AndroidExtensionsImpl = AndroidExtensionsImpl()
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id)
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int, viewClass: Class<T>): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id, viewClass)
}
}
class FifthActivity : BaseActivity, AndroidExtensions {
private var $$androidExtensionsImpl: AndroidExtensionsImpl = AndroidExtensionsImpl()
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id)
override fun <T: View> findViewByIdCached(owner: AndroidExtensionsBase, id: Int, viewClass: Class<T>): T? {
return <this>.$$androidExtensionsImpl.findViewByIdCached(owner, id, viewClass)
}
}
class SixthActivity : Base2Activity
class SixthActivity : Base2Activity
fun main() {
val main = MainActivity()
println(main.findViewByIdCached(main, 0))
println(main.findViewByIdCached(main, 0, View::class.java))
val second = SecondActivity()
println(second.findViewByIdCached(second, 1))
println(second.findViewByIdCached(second, 1, View::class.java))
val third = ThirdActivity()
println(third.findViewByIdCached(third, 2))
println(third.findViewByIdCached(third, 2, View::class.java))
val fouth = FourthActivity()
println(fouth.findViewByIdCached(fouth, 3))
println(fouth.findViewByIdCached(fouth, 3, View::class.java))
val fifth = FifthActivity()
println(fifth.findViewByIdCached(fifth, 4))
println(fifth.findViewByIdCached(fifth, 4, View::class.java))
val sixth = SixthActivity()
println(sixth.findViewByIdCached(sixth, 7))
println(sixth.findViewByIdCached(sixth, 7, View::class.java))
}
Loading
Loading