Repository: JyAether/Aether Branch: main Commit: 067addb978aa Files: 112 Total size: 442.6 KB Directory structure: gitextract_t7d67c2l/ ├── .fleet/ │ └── receipt.json ├── .gitignore ├── README.md ├── annotations/ │ ├── build.gradle.kts │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── aether/ │ └── annotations/ │ ├── ComposeMirror.kt │ └── Reflectable.kt ├── build.gradle.kts ├── composeApp/ │ ├── build.gradle.kts │ └── src/ │ ├── androidMain/ │ │ ├── AndroidManifest.xml │ │ ├── kotlin/ │ │ │ ├── Myapplicaton.kt │ │ │ └── org/ │ │ │ └── example/ │ │ │ └── project/ │ │ │ ├── MainActivity.kt │ │ │ └── Platform.android.kt │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ └── strings.xml │ ├── commonMain/ │ │ ├── composeResources/ │ │ │ └── drawable/ │ │ │ └── compose-multiplatform.xml │ │ └── kotlin/ │ │ └── org/ │ │ └── example/ │ │ └── project/ │ │ ├── App.kt │ │ ├── Greeting.kt │ │ └── Platform.kt │ ├── iosMain/ │ │ └── kotlin/ │ │ └── org/ │ │ └── example/ │ │ └── project/ │ │ ├── MainViewController.kt │ │ └── Platform.ios.kt │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── aether/ │ └── composeapp/ │ └── example/ │ └── ReflectableExample.kt ├── core/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── aether/ │ │ └── core/ │ │ └── runtime/ │ │ └── ExampleInstrumentedTest.kt │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── assets/ │ │ │ ├── test0_compose.json │ │ │ └── test1_compose.json │ │ ├── java/ │ │ │ └── com/ │ │ │ └── aether/ │ │ │ └── core/ │ │ │ └── runtime/ │ │ │ ├── AppContextManager.kt │ │ │ ├── AstRuntime.kt │ │ │ ├── ClassMirror.kt │ │ │ ├── KtAstVisitor.kt │ │ │ ├── Node.kt │ │ │ ├── ProgramStack.kt │ │ │ ├── ProjectHelper.kt │ │ │ ├── Structs.kt │ │ │ ├── StructsImpl.kt │ │ │ ├── context.kt │ │ │ ├── deliver/ │ │ │ │ ├── TemplateProvider.kt │ │ │ │ └── binding.kt │ │ │ ├── entity/ │ │ │ │ └── SimpleMember.kt │ │ │ ├── mirror/ │ │ │ │ └── MirrorHelper.kt │ │ │ ├── proxy/ │ │ │ │ └── ProxyBinding.kt │ │ │ ├── reflectable/ │ │ │ │ ├── ClassMirror.kt │ │ │ │ ├── ClassMirrorBase.kt │ │ │ │ ├── ComposeComponentDescriptor.kt │ │ │ │ ├── ComposeComponentRegistry.kt │ │ │ │ ├── ComposeMirror.kt │ │ │ │ ├── ComposeMirrorRuntime.kt │ │ │ │ ├── ComposeReflectRuntime.kt │ │ │ │ ├── DeclarationMirror.kt │ │ │ │ ├── MethodMirrorImpl.kt │ │ │ │ ├── Mirror.kt │ │ │ │ ├── ParamInfo.kt │ │ │ │ └── widgets/ │ │ │ │ ├── ColumnMirror.kt │ │ │ │ ├── MaterialThemeMirror.kt │ │ │ │ ├── TextMirror.kt │ │ │ │ ├── TextStyleMirror.kt │ │ │ │ └── TypographyMirror.kt │ │ │ └── utils/ │ │ │ └── JsonReader.kt │ │ └── res/ │ │ ├── drawable/ │ │ │ ├── ic_launcher_background.xml │ │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── values/ │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── values-night/ │ │ └── themes.xml │ └── test/ │ └── java/ │ └── com/ │ └── aether/ │ └── core/ │ ├── ExampleUnitTest.kt │ ├── compose/ │ │ ├── ColumArgsComposeExpressText.kt │ │ ├── ColumComposeNameExpressText.kt │ │ ├── DemoCompose.kt │ │ ├── DemoComposeColor.kt │ │ └── NameExpressComposeNameExpressText.kt │ ├── express/ │ │ ├── ArgsComposeTest.kt │ │ ├── ColumArgsExpressComposeTest.kt │ │ ├── ColumExpressComposeTest.kt │ │ ├── DemoEmptyFunctionExpress.kt │ │ ├── DemoFunctionExpress.kt │ │ ├── DemoTest.kt │ │ ├── InstanceComposeTest.kt │ │ ├── InstanceCreationExpressionTest.kt │ │ ├── InstanceJsonEmptyCreationExpressionTest.kt │ │ ├── InstanceTest.kt │ │ └── NameExpressComposeTest.kt │ └── runtime/ │ └── ExampleUnitTest.kt ├── gradle/ │ ├── libs.versions.toml │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── iosApp/ │ ├── Configuration/ │ │ └── Config.xcconfig │ ├── iosApp/ │ │ ├── Assets.xcassets/ │ │ │ ├── AccentColor.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── ContentView.swift │ │ ├── Info.plist │ │ ├── Preview Content/ │ │ │ └── Preview Assets.xcassets/ │ │ │ └── Contents.json │ │ └── iOSApp.swift │ └── iosApp.xcodeproj/ │ └── project.pbxproj ├── processor/ │ ├── build.gradle.kts │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── aether/ │ │ └── processor/ │ │ ├── ComposeMirrorProcessor.kt │ │ ├── ComposeMirrorProcessor2.kt │ │ ├── ComposeReflectProcessor.kt │ │ └── ReflectableProcessor.kt │ └── resources/ │ └── META-INF/ │ └── services/ │ └── com.google.devtools.ksp.processing.SymbolProcessorProvider └── settings.gradle.kts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .fleet/receipt.json ================================================ // Project generated by Kotlin Multiplatform Wizard { "spec": { "template_id": "kmt", "targets": { "android": { "ui": [ "compose" ] }, "ios": { "ui": [ "compose" ] } } }, "timestamp": "2025-04-06T08:25:58.346564588Z" } ================================================ FILE: .gitignore ================================================ *.iml .kotlin .gradle **/build/ xcuserdata !src/**/build/ local.properties .idea .DS_Store captures .externalNativeBuild .cxx *.xcodeproj/* !*.xcodeproj/project.pbxproj !*.xcodeproj/xcshareddata/ !*.xcodeproj/project.xcworkspace/ !*.xcworkspace/contents.xcworkspacedata **/xcshareddata/WorkspaceSettings.xcsettings ================================================ FILE: README.md ================================================ **一、介绍** * **Aether**:业内首次创新性基于 AST + Runtime 构建 KMP + CMP 的动态化方案,实现逻辑页面动态下发。 * 全流程覆盖开发至运维。提升发版效率与热修复能力,有效缓解 KMP 缺失的动态化,可大范围推动 Android KMP 的生态发展。 * 但因为个人精力有限,还有很多工程化的能力需要建设,期待社区一起未来后续将强化复杂语法支持与生态建设,降低开发成本、优化体验并扩大业务覆盖;推进大前端融合,实现跨终端一致性体验。 * 目前实现最小的实验原型,后续依赖于社区一起建设。 --- **二、项目结构** * `/composeApp` 是用于在 Compose Multiplatform 应用程序之间共享代码的部分。 它包含以下几个子文件夹: - `commonMain` 用于所有目标平台通用的代码。 - 其他文件夹是针对特定平台编译的 Kotlin 代码。例如,如果你想在 iOS 部分使用 Apple 的 CoreCrypto, 则应该在 `iosMain` 文件夹中编写相关调用。 * `/iosApp` 包含 iOS 应用程序。即使你通过 Compose Multiplatform 共享 UI, 你仍然需要这个入口点来启动你的 iOS 应用。这也是你添加 SwiftUI 代码的地方。 * `/core` 模块是 Aether 的核心模块。 git --- **三、挑战** * 工作量巨大,需要保持耐心,笔者在业余时间进行探索,几乎已经投入全部时间。 * 项目较为复杂,核心链路虽然跑通了,但是一些复杂的语法还未支持,需要保持一定耐心去兼容。之所以开源出来也是希望依赖于社区同学一起投入进来。 * 因为牵扯到 AST 和 DSL 的转换和解析执行虚拟机的加载,对于排查问题有一定的门槛,边界异常逻辑处理需要后继者更为注意。 --- ================================================ FILE: annotations/build.gradle.kts ================================================ plugins { kotlin("jvm") } java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlin { jvmToolchain(17) } dependencies { implementation(kotlin("stdlib")) } tasks.withType { kotlinOptions { jvmTarget = "17" } } ================================================ FILE: annotations/src/main/java/com/aether/annotations/ComposeMirror.kt ================================================ package com.aether.annotations @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.SOURCE) annotation class ComposeMirror ================================================ FILE: annotations/src/main/java/com/aether/annotations/Reflectable.kt ================================================ package com.aether.annotations /** * 用于标记可反射的Compose组件类 */ @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.SOURCE) annotation class Reflectable( val name: String = "", val description: String = "" ) /** * 用于标记可反射的Compose函数 */ @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.SOURCE) annotation class ReflectableFunction( val name: String = "", val description: String = "" ) // 标记要生成反射元数据的注解 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class GenerateMirror ================================================ FILE: build.gradle.kts ================================================ plugins { // this is necessary to avoid the plugins to be loaded multiple times // in each subproject's classloader alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.kotlinMultiplatform) apply false alias(libs.plugins.kotlinAndroid) apply false } ================================================ FILE: composeApp/build.gradle.kts ================================================ import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.ExperimentalComposeLibrary plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidApplication) alias(libs.plugins.composeMultiplatform) } configurations.implementation { exclude(group = "org.jetbrains", module = "annotations") } kotlin { android { compilations.all { kotlinOptions { jvmTarget = "17" } } } sourceSets { val androidMain by getting { dependencies { implementation(compose.preview) implementation(libs.androidx.activity.compose) } } @OptIn(ExperimentalComposeLibrary::class) val commonMain by getting { dependencies { implementation(project(":core")) implementation(project(":annotations")) implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) implementation(compose.ui) implementation(compose.components.resources) implementation(compose.preview) implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.runtime.compose) } } } } android { namespace = "org.example.project" compileSdk = 34 defaultConfig { applicationId = "org.example.project" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = 34 versionCode = 1 versionName = "1.0" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } packagingOptions { resources.excludes.add("kotlin/reflect/reflect.kotlin_builtins") resources.excludes.add("kotlin/internal/internal.kotlin_builtins") resources.excludes.add("kotlin/kotlin.kotlin_builtins") resources.excludes.add("kotlin/coroutines/coroutines.kotlin_builtins") resources.excludes.add("kotlin/ranges/ranges.kotlin_builtins") resources.excludes.add("kotlin/collections/collections.kotlin_builtins") resources.excludes.add("kotlin/annotation/annotation.kotlin_builtins") excludes.addAll(listOf( "META-INF/DEPENDENCIES", "META-INF/LICENSE", "META-INF/LICENSE.txt", "META-INF/NOTICE", "META-INF/NOTICE.txt", "META-INF/ASL2.0" )) } buildTypes { getByName("release") { isMinifyEnabled = false } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } buildToolsVersion = "34.0.0" } dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") debugImplementation(compose.uiTooling) implementation(compose.ui) implementation(compose.preview) implementation(project(":annotations")) implementation(project(":core")) } ================================================ FILE: composeApp/src/androidMain/AndroidManifest.xml ================================================ ================================================ FILE: composeApp/src/androidMain/kotlin/Myapplicaton.kt ================================================ package org.example.project import android.app.Application import com.aether.core.runtime.reflectable.ComposeComponentFactory.initializeComposeMirrors class MyApplication : Application() { override fun onCreate() { super.onCreate() // 初始化 Compose 镜像反射系统 initializeComposeMirrors() // 其他初始化代码... } } ================================================ FILE: composeApp/src/androidMain/kotlin/org/example/project/MainActivity.kt ================================================ package org.example.project import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.aether.core.runtime.deliver.ExampleUsage class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // App() ExampleUsage() } } } @Preview @Composable fun AppAndroidPreview() { App() } ================================================ FILE: composeApp/src/androidMain/kotlin/org/example/project/Platform.android.kt ================================================ package org.example.project import android.os.Build class AndroidPlatform : Platform { override val name: String = "Android ${Build.VERSION.SDK_INT}" } actual fun getPlatform(): Platform = AndroidPlatform() ================================================ FILE: composeApp/src/androidMain/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml ================================================ ================================================ FILE: composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml ================================================ ================================================ FILE: composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml ================================================ ================================================ FILE: composeApp/src/androidMain/res/values/strings.xml ================================================ KotlinProject ================================================ FILE: composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml ================================================ ================================================ FILE: composeApp/src/commonMain/kotlin/org/example/project/App.kt ================================================ package org.example.project import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import org.jetbrains.compose.resources.painterResource import kotlinproject.composeapp.generated.resources.Res import kotlinproject.composeapp.generated.resources.compose_multiplatform @Composable fun App() { MaterialTheme { var showContent by remember { mutableStateOf(false) } Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { Button(onClick = { showContent = !showContent }) { Text("Click me!") } AnimatedVisibility(showContent) { val greeting = remember { Greeting().greet() } Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { Text("Compose: $greeting") } } } } } ================================================ FILE: composeApp/src/commonMain/kotlin/org/example/project/Greeting.kt ================================================ package org.example.project class Greeting { private val platform = getPlatform() fun greet(): String { return "Hello, ${platform.name}!" } } ================================================ FILE: composeApp/src/commonMain/kotlin/org/example/project/Platform.kt ================================================ package org.example.project interface Platform { val name: String } expect fun getPlatform(): Platform ================================================ FILE: composeApp/src/iosMain/kotlin/org/example/project/MainViewController.kt ================================================ package org.example.project import androidx.compose.ui.window.ComposeUIViewController fun MainViewController() = ComposeUIViewController { App() } ================================================ FILE: composeApp/src/iosMain/kotlin/org/example/project/Platform.ios.kt ================================================ package org.example.project import platform.UIKit.UIDevice class IOSPlatform: Platform { override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } actual fun getPlatform(): Platform = IOSPlatform() ================================================ FILE: composeApp/src/main/AndroidManifest.xml ================================================ ================================================ FILE: composeApp/src/main/java/com/aether/composeapp/example/ReflectableExample.kt ================================================ package com.aether.composeapp.example import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.aether.annotations.ReflectableFunction import com.aether.core.runtime.reflectable.ComposeComponentFactory /** * 一个可反射的文本组件 */ @ReflectableFunction( name = "CustomText", description = "A custom text component with padding" ) @Composable fun CustomText(text: String, modifier: Modifier = Modifier) { Text( text = text, modifier = modifier.padding(16.dp) ) } /** * 一个可反射的按钮组件 */ @ReflectableFunction( name = "CustomButton", description = "A custom button component with text" ) @Composable fun CustomButton( text: String, onClick: () -> Unit, modifier: Modifier = Modifier ) { Button( onClick = onClick, modifier = modifier ) { Text(text) } } /** * 一个可反射的容器组件 */ @ReflectableFunction( name = "CustomContainer", description = "A custom container component" ) @Composable fun CustomContainer( content: @Composable () -> Unit, modifier: Modifier = Modifier ) { Column(modifier = modifier) { content() } } /** * 一个可反射的复合组件 */ //@ReflectableFunction( // name = "ComplexComponent", // description = "A complex component combining multiple elements" //) //@Composable //fun ComplexComponent( // title: String, // buttonText: String, // onButtonClick: () -> Unit //) { // CustomContainer { // CustomText(text = title) // CustomButton( // text = buttonText, // onClick = onButtonClick // ) // } //} /** * 示例用法 */ @Composable fun ExampleUsage() { // 注册组件 } ================================================ FILE: core/.gitignore ================================================ /build ================================================ FILE: core/build.gradle.kts ================================================ plugins { alias(libs.plugins.androidLibrary) alias(libs.plugins.kotlinAndroid) } android { namespace = "com.aether.core.runtime" compileSdk = 34 buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.8" // This version works with Kotlin 1.8.22 } // android { // composeOptions { // kotlinCompilerExtensionVersion = "1.5.15" // } // } // defaultConfig { // minSdk = 34 // targetSdk = 34 // versionCode = 1 // versionName = "1.0" // // testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" // } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = "17" } } configurations.implementation { exclude(group = "com.intellij", module = "annotations") } dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.androidx.material) testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.junit) androidTestImplementation(libs.androidx.espresso.core) // Kotlin 标准库 // implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.20") // AndroidX Core KTX implementation("androidx.core:core-ktx:1.3.1") // AndroidX AppCompat implementation("androidx.appcompat:appcompat:1.2.0") // Material Design 组件 // implementation("com.google.android.material:material:1.2.1") // ConstraintLayout implementation("androidx.constraintlayout:constraintlayout:2.0.1") // JUnit 测试框架 // testImplementation("junit:junit:4.13.2") // AndroidX 测试扩展 JUnit // androidTestImplementation("androidx.test.ext:junit:1.1.2") // Espresso 测试框架 androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0") // Kotlin 编译器 implementation("org.jetbrains.kotlin:kotlin-compiler:1.8.20") { exclude(group = "com.google.guava", module = "guava") } implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") implementation("androidx.compose.ui:ui:1.6.0") implementation("androidx.compose.material:material:1.6.0") // implementation("androidx.compose.runtime:runtime:1.6.0") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") // implementation("com.google.firebase:firebase-inappmessaging-display:17.2.0") // implementation("com.google.guava:guava:27.0.1-android") // implementation("com.google.guava:guava:27.0.1-jre") implementation("com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava") // implementation("com.google.code.gson:gson:2.8.8") implementation("com.fasterxml.jackson.core:jackson-databind:2.14.2") } ================================================ FILE: core/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile -keep class androidx.compose.** { *; } -dontwarn androidx.compose.** ================================================ FILE: core/src/androidTest/java/com/aether/core/runtime/ExampleInstrumentedTest.kt ================================================ package com.aether.core.runtime import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Test import org.junit.runner.RunWith import org.junit.Assert.* /** * Instrumented test, which will execute on an Android device. * * See [testing documentation](http://d.android.com/tools/testing). */ @RunWith(AndroidJUnit4::class) class ExampleInstrumentedTest { @Test fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.aether.core.runtime", appContext.packageName) } } ================================================ FILE: core/src/main/AndroidManifest.xml ================================================ ================================================ FILE: core/src/main/assets/test0_compose.json ================================================ { "directives": [ { "type": "ImportDirective", "importPath": "androidx.compose.material.Text", "alias": null, "name": "Text" }, { "type": "ImportDirective", "importPath": "androidx.compose.runtime.Composable", "alias": null, "name": "Composable" } ], "declarations": [ { "type": "ClassDeclaration", "name": "DemoCompose", "members": [ { "type": "MethodDeclaration", "name": "Main", "parameters": [], "typeParameters": [], "body": { "type": "BlockStatement", "body": [ { "type": "InstanceCreationExpression", "constructorName": "Text", "argumentList": { "type": "ArgumentList", "arguments": [ { "type": "Argument", "body": { "type": "StringTemplateExpression", "name": null, "body": { "type": "StringTemplateEntry", "body": null, "value": "这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换" } } } ] }, "valueArgument": [] } ] }, "isStatic": false, "isGetter": true, "isSetter": false } ], "body": {} } ], "type": "CompilationUnit" } ================================================ FILE: core/src/main/assets/test1_compose.json ================================================ { "directives" : [ { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.background", "alias" : null, "name" : "background" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.layout.Box", "alias" : null, "name" : "Box" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.layout.Column", "alias" : null, "name" : "Column" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.layout.fillMaxWidth", "alias" : null, "name" : "fillMaxWidth" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.layout.height", "alias" : null, "name" : "height" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.layout.padding", "alias" : null, "name" : "padding" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.foundation.shape.RoundedCornerShape", "alias" : null, "name" : "RoundedCornerShape" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.material.Button", "alias" : null, "name" : "Button" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.material.Text", "alias" : null, "name" : "Text" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.runtime.Composable", "alias" : null, "name" : "Composable" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.ui.Alignment", "alias" : null, "name" : "Alignment" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.ui.Modifier", "alias" : null, "name" : "Modifier" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.ui.draw.clip", "alias" : null, "name" : "clip" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.ui.graphics.Color", "alias" : null, "name" : "Color" }, { "type" : "ImportDirective", "importPath" : "androidx.compose.ui.unit.dp", "alias" : null, "name" : "dp" } ], "declarations" : [ { "type" : "ClassDeclaration", "name" : "DemoCompose", "members" : [ { "type" : "MethodDeclaration", "name" : "Main", "parameters" : [ ], "typeParameters" : [ ], "body" : { "type" : "BlockStatement", "body" : [ { "type" : "InstanceCreationExpression", "constructorName" : "Column", "argumentList" : { "type" : "ArgumentList", "arguments" : [ { "type" : "Argument", "body" : { "type" : "MethodInvocation", "name" : null, "methodName" : { "type" : "CallExpression", "methodName" : { "type" : "Identifier", "name" : "fillMaxWidth" }, "target" : { "type" : "Identifier", "name" : "fillMaxWidth" }, "argumentList" : { "type" : "ArgumentList", "arguments" : [ ] }, "valueArgument" : [ ] }, "target" : { "type" : "Identifier", "name" : "Modifier" } } }, { "type" : "Argument", "body" : { "type" : "MethodInvocation", "name" : null, "methodName" : { "type" : "Identifier", "name" : "CenterHorizontally" }, "target" : { "type" : "Identifier", "name" : "Alignment" } } } ] }, "valueArgument" : [ ] } ] }, "isStatic" : false, "isGetter" : true, "isSetter" : false } ], "body" : { } } ], "type" : "CompilationUnit" } ================================================ FILE: core/src/main/java/com/aether/core/runtime/AppContextManager.kt ================================================ package com.aether.core.runtime import com.aether.core.runtime.AppContext object AppContextManager { private val contextHolder = ThreadLocal.withInitial { AppContext(null, "ROOT", emptyMap(), emptyMap()) } // 获取当前线程的 AppContext val context: AppContext get() = contextHolder.get() // 设置当前线程的 AppContext fun set(context: AppContext) { contextHolder.set(context) } fun get() :AppContext{ return context } // 移除当前线程的 AppContext fun removeContext() { contextHolder.remove() } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/AstRuntime.kt ================================================ package com.aether.core.runtime import android.text.TextUtils import com.aether.core.runtime.AppContextManager.context import com.aether.core.runtime.deliver.ComposableHolder import com.aether.core.runtime.deliver.invokeRunMain import com.aether.core.runtime.proxy.ProxyBinding import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeComponentFactory import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.SerializationFeature import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiFileFactory import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import java.io.File import java.lang.reflect.Modifier import java.util.Collections import java.util.UUID import kotlin.reflect.KClass import kotlin.reflect.jvm.javaMethod /// The `import` directive. class Import( /// The absolute URI of the imported library. val uri: String, /// The import prefix, or `null` if not specified. val prefix: String?, /// The list of namespace combinators to apply, not `null`. val combinators: List? ) { override fun toString(): String { return "Import(uri: $uri, prefix: $prefix, combinators: $combinators)" } } fun _exeAndRecMethodInvocation(methodInvocation: MethodInvocation): Any? { val programStack = context.get(ProgramStack::class.java) val scope = StackScope("Call method: ") // 创建 StackScope 实例 scope["node"] = methodInvocation // 将 methodInvocation 存入 scope programStack?.push(scope = scope) // 将 scope 压入程序栈 val result = _executeMethodInvocation2(methodInvocation) // 执行方法调用逻辑 programStack?.pop() // 弹出栈顶 return result // 返回结果 } fun _executeMethodInvocation2(methodInvocation: MethodInvocation): Any? { val runtime = context.get(AstRuntime::class.java)!! // 获取 AstRuntime,使用 !! 表示非空断言 val programStack = context.get(ProgramStack::class.java)!! // 获取 ProgramStack val methodName = methodInvocation.methodName val positionalArguments = mutableListOf() // 位置参数列表 val namedArguments = mutableMapOf() // 命名参数 Map // 处理方法的参数 if (!(methodInvocation.argumentList?.arguments == null || methodInvocation.argumentList.arguments.isEmpty())) { for (argument in methodInvocation.argumentList!!.arguments!!) { if (argument.isNamedExpression) { namedArguments.putAll(executeExpression(argument) as Map) } else { val arg = executeExpression(argument) if (arg != null) { positionalArguments.add( arg ) } } } } // 检查是否有 ComposableHolder 上下文 val holder = context.get(ComposableHolder::class.java) if (holder != null) { if (methodName?.name == "build" && methodInvocation.argumentList?.arguments?.isNotEmpty() == true) { // 确保有参数 // val arg = methodInvocation.argumentList?.arguments?.get(0) // if (arg != null && arg.isFunctionExpression) { // return doRunBuild(arg.asFunctionExpression()) // } } else if (methodName?.name == "runApp" && methodInvocation.argumentList?.arguments?.isNotEmpty() == true) { // val arg = methodInvocation.argumentList?.arguments?.get(0) // if (arg != null) { // return invokeRunApp(arg) // } } } var target: Any? = null if (methodInvocation.isCascaded) { // target = findCascadeAncestorTargetValue(methodInvocation) } else if (methodInvocation.target != null) { target = executeExpression(methodInvocation.target) } // // if (target == null) { // if (methodInvocation.isNullAware) { // return null // } // if (methodInvocation.target != null) { // throw RuntimeException("Null check operator used on a null value -> $methodName") // } // } // 如果没有目标对象 if (target == null) { // 查找实例 AST 方法或静态 AST 方法 val method = programStack.get(methodName!!.name) if (method != null) { return AstMethod.apply2(method, positionalArguments, namedArguments) } // 默认 AST 构造函数 val clazz = AstClass.forName(methodName!!.name) if (clazz != null) { return clazz.newInstance("", positionalArguments, namedArguments) } } else { methodInvocation.methodName // 如果目标是 AstClass if (target is AstClass) { if (target.hasConstructor(methodName!!.name)) { return target.newInstance(methodName.name, positionalArguments, namedArguments) } else { return target.invoke(methodName.name, positionalArguments, namedArguments) } } // 如果目标是 AstInstance val instance = AstInstance.forObject(target) if (instance != null) { val positionalArguments = mutableListOf() // 位置参数列表 val namedArguments = mutableMapOf() // 命名参数 Map return instance.invoke(methodName!!.name, positionalArguments, namedArguments) } throw RuntimeException("InstanceMirror for ${target::class} not found") } // 检查是否有顶层函数 // if (runtime.hasTopLevelFunction(methodName)) { // return runtime.invoke(methodName, positionalArguments, namedArguments) // } // // // 尝试通过反射调用顶层方法 // val libraryMirror = ReflectionBinding.instance.reflectTopLevelInvoke(methodName) // if (libraryMirror != null) { // val function = AstMethod.fromMirror(libraryMirror.declarations[methodName] as MethodMirror) // processArguments(function.parameters, positionalArguments, namedArguments) // return libraryMirror.invoke(methodName, positionalArguments, namedArguments) // } throw RuntimeException("Error: MethodInvocation -> $methodName, target: $target, runtimeType: ${target?.toString()}") } //fun executeMethodTarget( // methodInvocation: MethodInvocation, // methodName: String, // positionalArguments: List, // namedArguments: Map? = null //): Any? { // if (methodInvocation?.target != null) { // var target = executeExpression(methodInvocation.target!!) // if (target is AstClass) { // if (target.hasConstructor(methodName)) { // return target.newInstance(methodName, positionalArguments, namedArguments) // } else { // return target.invoke(methodName, positionalArguments, namedArguments) // } // } // val instance = AstInstance.forObject(target) // if (instance != null) { // return instance.invokeGetter(methodInvocation.methodName!!.name) // } // } // return null //} fun executeInstanceCreationExpression(instanceCreationExpression: InstanceCreationExpression): Any? { val positionalArguments = mutableListOf() val namedArguments = mutableMapOf() if (instanceCreationExpression.argumentList?.arguments?.isNotEmpty() == true) { for (arg in instanceCreationExpression!!.argumentList!!.arguments!!) { if (arg.isNamedExpression) { namedArguments.putAll(executeExpression(arg) as Map) } else { positionalArguments.add(executeExpression(arg)) } } } val constructorName = instanceCreationExpression.constructorName?.name val typeName = instanceCreationExpression.constructorName?.typeName if (typeName == null || constructorName == null) { println("Type $typeName is ${typeName == null} not found, constructorName is ${constructorName == null} not found") null } //TODO 这里依然有问题,需要 // 对于Compose组件,返回一个包含路径和参数的描述对象 // 而不是直接返回@Composable函数 val runtime = context.get(AstRuntime::class.java) val importDirective = runtime?.getReflectClass(typeName ?: "") val children = mutableListOf() instanceCreationExpression.children?.forEach { if (it.isInstanceCreationExpression) { val element = executeExpression(it) children.add(element as ComposeComponentDescriptor) } } if (ComposeComponentFactory.isComponentAvailable(importDirective?.uri ?: "")) { return ComposeComponentDescriptor( importDirective?.uri ?: "", positionalArguments, namedArguments, children ) } val astClass: AstClass? = AstClass.forName(typeName ?: "") return if (astClass != null) { astClass.newInstance(constructorName!!, positionalArguments, namedArguments) } else { println("Type $typeName not found") null } } fun executeExpression( expression: Expression, flag: String? = null, keepVariable: Boolean = false ): Any? { return try { val programStack = context.get(ProgramStack::class.java) if (expression.isIdentifier) { val name = expression.asIdentifier.name val variable = programStack?.getVariable(name) if (variable != null) { if (keepVariable) { return variable } else { if (variable.value is Expression) { return executeExpression(variable.value as Expression) } return variable.value } } val runtime = context.get(AstRuntime::class.java)!! val method = programStack?.get(name) if (method != null) { if (method.isGetter) { return AstMethod.apply2( method, positionalArguments = mutableListOf(), namedArguments = mutableMapOf() ) } val length = method.parameters.size val thisReference = context.get(ThisReference::class.java) val superReference = context.get(SuperReference::class.java) val innerStack = ProgramStack("closure", programStack) val overrides = mapOf( ProgramStack::class.java to { innerStack }, AstRuntime::class.java to { runtime }, ThisReference::class.java to { thisReference }, SuperReference::class.java to { superReference }) return when (length) { 0 -> { { context.run( name = "closure override", body = { AstMethod.apply2( method, positionalArguments = mutableListOf(), namedArguments = mutableMapOf() ) }, overrides = overrides ) } } // 1 -> { // { a -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a)) }, // overrides = overrides // ) // } // } // 2 -> { // { a, b -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a, b)) }, // overrides = overrides // ) // } // } // 3 -> { // { a, b, c -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a, b, c)) }, // overrides = overrides // ) // } // } // 4 -> { // { a, b, c, d -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a, b, c, d)) }, // overrides = overrides // ) // } // } // 5 -> { // { a, b, c, d, e -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a, b, c, d, e)) }, // overrides = overrides // ) // } // } // 6 -> { // { a, b, c, d, e, f -> // context.run( // name = "closure override", // body = { AstMethod.apply2(method, listOf(a, b, c, d, e, f)) }, // overrides = overrides // ) // } // } else -> { { context.run( name = "closure override", body = { AstMethod.apply2( method, positionalArguments = mutableListOf(), namedArguments = mutableMapOf() ) }, overrides = overrides ) } } } } else { } // val topLevelVariable = runtime.getTopLevelVariable(name) // if (topLevelVariable != null) { // if (keepVariable) { // return topLevelVariable // } else { // return topLevelVariable.value // } // } // val clazz = AstClass.forName(name) if (clazz != null) { return clazz } // 1. 通过反射获取 Log 类 // val reflectClass = runtime.getReflectClass(name) // if (reflectClass != null) { // val classInstance = Class.forName(reflectClass?.uri) // val methodArgs = ArrayList() // methodArgs.add("你好") // parseKtClass(reflectClass?.uri, "info", methodArgs) // if (classInstance != null) { // return classInstance // } // } return null // val libraryMirror = ReflectionBinding.instance.reflectTopLevelInvoke(name) // if (libraryMirror != null) { // return libraryMirror.invokeGetter(name) // } // // throw "Should not happen execute Identifier: ${expression.asIdentifier.name}" } else if (expression.isBlockStatement) { return _executeBlockStatement(expression.asBlockStatement, flag = flag); } else if (expression.isEmptyFunctionBody) { return null } else if (expression.isInstanceCreationExpression) { return executeInstanceCreationExpression( expression.asInstanceCreationExpression ); } else if (expression.isPropertyAccess) { // 取值表达式,如demo.test() val propertyAccess = expression.asPropertyAccess var target: Any? = null // if (propertyAccess.isCascaded) { // target = findCascadeAncestorTargetValue(propertyAccess) // } else { // target = executeExpression(propertyAccess.targetExpression!!) target = executeExpression(propertyAccess.targetExpression!!) // } val instance = AstInstance.forObject(target) if (instance != null && !propertyAccess.name.isNullOrEmpty()) { propertyAccess.name?.let { return instance.invokeGetter(it) } } if (target == null) { // if (propertyAccess.isNullAware) { // return null // } else { // throw IllegalArgumentException("Null check operator used on a null value") // } } else { } } else if (expression.isVariableDeclarationList) { return _executeVariableDeclaration(expression.asVariableDeclarationList) } else if (expression.isBinaryExpression) { return _executeBinaryExpression(expression.asBinaryExpression); } else if (expression.isReturnStatement) { var result: Any? = null if (expression.asReturnStatement.argument != null) { result = executeExpression(expression.asReturnStatement.argument!!) } returnFlags[flag ?: ""] = true return result } else if (expression.isIntegerLiteral) { return expression.asIntegerLiteral.value } else if (expression.isMethodInvocation) { //method调用 return _exeAndRecMethodInvocation(expression.asMethodInvocation); } else if (expression.isStringTemplateExpression) { //string var result: Any? = null if (expression.asStringTemplateExpression != null && expression.asStringTemplateExpression.target != null) { result = executeExpression(expression.asStringTemplateExpression.target!!) return result } return result } else if (expression.isStringLiteral) { return expression.asIntegerLiteral.value } else if (expression.isStringTemplateEntry) { return expression.asStringTemplateEntry.value } else if (expression.isBooleanLiteral) { return expression.asBooleanLiteral.value } else if (expression.isNamedExpression) { //获取named 参数值 val namedExpression = expression.asNamedExpression val mutableMapOf = mutableMapOf() mutableMapOf.put( namedExpression.name, executeExpression(namedExpression.argument!!) ) return mutableMapOf } else if (expression.isCallExpression) { //callFunction调用 val clazz = AstClass.forName(expression.asCallExpression.methodName) if (clazz != null) { return clazz } else { val runtime = context.get(AstRuntime::class.java)!! val function = runtime._program.getFunction(expression.asCallExpression.methodName) if (function != null) { val result = AstMethod.apply2( function, expression.asCallExpression.argumentList.arguments ?: emptyList(), emptyMap(), ) return result } return null } } else { println("executeExpression ${expression.type} not implement") } } catch (e: Exception) { // if (e is DynamicCardException) { // throw e // } else { throw DynamicException.fromExpression(expression, e.toString()) // } } return null } fun parseKtClass(className: String, methodName: String, methodArgs: List<*>) { // 假设这是从 PSI 解析生成的 Map val parsedMap: Map = mapOf( "className" to "org.example.MyClass", "methodName" to "myMethod", "methodArgs" to listOf("arg1", "arg2") ) // // 动态加载类并调用方法 // val className = parsedMap["className"] as String // val methodName = parsedMap["methodName"] as String // val methodArgs = parsedMap["methodArgs"] as List<*> try { // 1. 动态加载类 val clazz: Class<*> = Class.forName(className) val kClass: KClass<*> = clazz.kotlin // 2. 获取目标方法 val memberFunction = kClass.members.find { it.name == methodName } ?: throw NoSuchMethodException("No such method: $methodName") // 3. 调用方法 if (memberFunction is kotlin.reflect.KFunction<*>) { // 创建实例(如果需要) val instance = if (!clazz.isInterface && !Modifier.isStatic( memberFunction.javaMethod?.modifiers ?: 0 ) ) { clazz.getDeclaredConstructor().newInstance() } else { null } // 调用方法 val messages = arrayOf("你好") val result = memberFunction.call(instance, messages) println("Result of $methodName: $result") } else { throw IllegalArgumentException("$methodName is not a callable function") } } catch (e: Exception) { e.printStackTrace() } } class DynamicException(message: String?) : RuntimeException(message) { var stackTrace = "" companion object { fun fromExpression(expression: Expression, e: String): Throwable { System.out.println("error:" + e) return DynamicException(message = e) } } } fun _executeVariableDeclaration(variableDeclarationList: PropertyStatement): Any? { val programStack = context.get(ProgramStack::class.java)!! val variableDeclarator = variableDeclarationList.target // ignore: unnecessary_null_comparison // if (variableDeclarator.init == null) { // // 光定义,没有赋值的场景 // programStack.putVariable(variableDeclarator.name, null) // return null // TODO // } // if (variableDeclarator.init!!.isAwaitExpression) { // //await expression; // val value = _exeAndRecMethodInvocation(variableDeclarator.init!!.asAwaitExpression.expression) // programStack.putVariable(variableDeclarator.name, value) // } else if (variableDeclarator.init!!.isMethodInvocation) { // val value = _exeAndRecMethodInvocation(variableDeclarator.init!!.asMethodInvocation) // //存入声明的初始化变量值 // programStack.putVariable(variableDeclarator.name, value) // } else { // //存入声明的初始化变量值 val value = executeExpression(variableDeclarator!!) programStack.putVariable(variableDeclarationList.name, value) // } return null } //fun findCascadeAncestorTargetValue(child: Node): Any? { // fun helper(node: Node?): Any? { // return when { // node == null -> null // node is CascadeExpression -> node.targetValue // else -> helper(node.parent) // } // } // return helper(child) //} fun _executeBinaryExpression(binaryExpression: BinaryExpression): Any? { val evalLeft = executeExpression(binaryExpression.left) val evalRight = executeExpression(binaryExpression.right) val operator = binaryExpression.operator if (evalLeft is String || evalRight is String) { return when (operator) { "+" -> "$evalLeft$evalRight" else -> throw UnimplementedError("operator Int ${binaryExpression.operator}") } } if (evalLeft is Int && evalRight is Int) { return when (operator) { "+" -> evalLeft + evalRight "-" -> evalLeft - evalRight "*" -> evalLeft * evalRight "/" -> evalLeft / evalRight "<" -> evalLeft < evalRight ">" -> evalLeft > evalRight "<=" -> evalLeft <= evalRight ">=" -> evalLeft >= evalRight "==" -> evalLeft == evalRight "%" -> evalLeft % evalRight "<<" -> evalLeft shl evalRight "|" -> evalLeft or evalRight "&" -> evalLeft and evalRight ">>" -> evalLeft shr evalRight "!=" -> evalLeft != evalRight "/" -> evalLeft / evalRight else -> throw UnimplementedError("operator Int ${binaryExpression.operator}") } } if (evalLeft is Boolean && evalRight is Boolean) { return when (operator) { "&&" -> evalLeft && evalRight "||" -> evalLeft || evalRight else -> throw UnimplementedError("operator Boolean ${binaryExpression.operator}") } } return null } val returnFlags: MutableMap = mutableMapOf() fun _executeBlockStatement(block: BlockStatement, flag: String? = null): Any? { var flagTemp = flag if (flag == null) { flagTemp = UUID.randomUUID().toString() } val programStack = context.get(ProgramStack::class.java) programStack?.push(name = "Block statement") var result: Any? = null if (block.body?.isNotEmpty() == true) { for (expression in block.body!!) { if (returnFlags[flag] == true) { returnFlags.remove(flagTemp) break } result = executeExpression(expression, flag = flagTemp) } } programStack?.pop() return result } class AstRuntime(val _program: ProgramNode) { public var programStack: ProgramStack? = null init { // 创建并初始化 ProxyBinding 实例 val proxyBinding = ProxyBinding() proxyBinding.initInstances() this.programStack = ProgramStack("root stack:${_program.compilation.toUnit()["source"]}") } fun invoke2(memberName: String): AstMethod? { val function = _program.getFunction(memberName) return function } val classes: List get() { return context.run( name = "AstRuntime", body = { _program.classes }, overrides = mapOf( ProgramStack::class.java to { programStack }, AstRuntime::class.java to { this } ) ) as List } fun getClass(className: String): AstClass? { return context.run( name = "AstRuntime", body = { _program?.getClass(className) }, overrides = mapOf( ProgramStack::class.java to { programStack }, AstRuntime::class.java to { this } ) ) as AstClass? } fun getReflectClass(className: String): ImportDirective? { return _program?.getReflectClass(className) } fun invoke2( memberName: String, positionalArguments: List? = null, namedArguments: Map? = null ): Any? { return context.run( name = "Invoke top-level function or variables", body = { val function = _program?.getFunction(memberName) if (function != null) { context.run(name = "", body = { val result = AstMethod.apply2( function, positionalArguments ?: emptyList(), namedArguments ) if (result is Variable) { return@run result.value } invokeRunMain(result) return@run result }, overrides = mapOf(ProgramNode::class.java to { function.programNode })) } else { null } }, overrides = mapOf( ProgramStack::class.java to { programStack }, AstRuntime::class.java to { this }) ) } fun invoke( memberName: String, positionalArguments: List? = null, namedArguments: Map? = null ): Any? { return context.run( name = "Invoke top-level function or variables", body = { val function = _program?.getFunction(memberName) if (function != null) { context.run(name = "", body = { val result = AstMethod.apply2( function, positionalArguments ?: emptyList(), namedArguments ) if (result is Variable) { return@run result.value } return@run result }, overrides = mapOf(ProgramNode::class.java to { function.programNode })) } else { null } }, overrides = mapOf( ProgramStack::class.java to { programStack }, AstRuntime::class.java to { this }) ) } class LocalJson(val json: String) : ProgramEntity() { override val exists: Boolean get() = !TextUtils.isEmpty(json) val walker = ProgramDependencyWalker(); override fun createNode(): ProgramNode { val transformMap = transformMap(json) val node = walker.getNode(this, CompilationUnit.fromUnit(transformMap)) return node } fun transformMap(json: String): Map { try { // 序列化 Map 对象为 JSON 字符串 val objectMapper = ObjectMapper() // 禁用 FAIL_ON_EMPTY_BEANS 特性 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 反序列化 JSON 字符串为 Map 对象 @Suppress("UNCHECKED_CAST") val deserializedMap = objectMapper.readValue(json, HashMap::class.java) as Map println("Deserialized Map: $deserializedMap") return deserializedMap } catch (e: java.lang.Exception) { e.printStackTrace() } return emptyMap() } fun getClassFilePath(clazz: Class<*>): String? { // 尝试从保护域获取类文件的位置 clazz.protectionDomain?.codeSource?.location?.let { return try { // 如果是文件形式存在,则返回其路径 it.toURI().path } catch (e: Exception) { e.printStackTrace() null } } // 尝试通过类加载器获取资源路径 val resource = clazz.name.replace('.', '/') + ".class" val resourcePath = clazz.classLoader.getResource(resource)?.toURI()?.path if (resourcePath != null && resourcePath.endsWith(".jar")) { // 如果是在JAR内,则返回JAR文件路径 return resourcePath } return resourcePath?.removeSuffix(".class") } fun convertClassToPath(fullClassName: String): String { return "src/test/java/" + fullClassName.replace('.', '/') + ".kt" } override fun getRelativeEntity(uri: String): ProgramEntity { // 获取文件的目录路径 // val basePath = File(convertClassToPath(uri)).parentFile?.absolutePath // ?: throw IllegalArgumentException("Invalid base file path") return LocalFile(File(convertClassToPath(uri))) } private fun createCoreEnvironment(): KotlinCoreEnvironment { val disposable = Disposer.newDisposable() return KotlinCoreEnvironment.createForProduction( disposable, ProjectHelper.getConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES ) } fun parseKotlinCode(content: String, fileName: String = "DummyFile.kt"): KtFile { val project: Project = createCoreEnvironment().project val psiFileFactory = PsiFileFactory.getInstance(project) return psiFileFactory.createFileFromText(fileName, content) as KtFile } } class GeneraJson(val file: File) { fun createNodeToJson(): String? { val ktFile = parseKotlinCode(file.readText()) val visitor = MyKtVisitorV2() ktFile.accept(visitor) val unit = visitor.getResult() val json = transformJson(unit) return json } private fun transformJson(unit: Map): String? { try { // 序列化 Map 对象为 JSON 字符串 val objectMapper = ObjectMapper() // 禁用 FAIL_ON_EMPTY_BEANS 特性 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); val json: String? = objectMapper.writeValueAsString(unit) // 输出 JSON 字符串 println(json) return json } catch (e: java.lang.Exception) { e.printStackTrace() } return null } private fun transformMap(json: String): Map { try { // 序列化 Map 对象为 JSON 字符串 val objectMapper = ObjectMapper() // 禁用 FAIL_ON_EMPTY_BEANS 特性 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 反序列化 JSON 字符串为 Map 对象 @Suppress("UNCHECKED_CAST") val deserializedMap = objectMapper.readValue(json, HashMap::class.java) as Map println("Deserialized Map: $deserializedMap") return deserializedMap } catch (e: java.lang.Exception) { e.printStackTrace() } return emptyMap() } private fun createCoreEnvironment(): KotlinCoreEnvironment { val disposable = Disposer.newDisposable() return KotlinCoreEnvironment.createForProduction( disposable, ProjectHelper.getConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES ) } fun parseKotlinCode(content: String, fileName: String = "DummyFile.kt"): KtFile { val project: Project = createCoreEnvironment().project val psiFileFactory = PsiFileFactory.getInstance(project) return psiFileFactory.createFileFromText(fileName, content) as KtFile } } class LocalFile(val file: File) : ProgramEntity() { override val exists: Boolean get() = file.exists() val walker = ProgramDependencyWalker(); override fun createNode(): ProgramNode { val ktFile = parseKotlinCode(file.readText()) val visitor = MyKtVisitorV2() ktFile.accept(visitor) // val unit = visitor.getResult() val transformMap = transformMap(getDefaultJson()) val node = walker.getNode(this, CompilationUnit.fromUnit(transformMap)) return node } private fun transformJson(unit: Map) { try { // 序列化 Map 对象为 JSON 字符串 val objectMapper = ObjectMapper() // 禁用 FAIL_ON_EMPTY_BEANS 特性 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); val json: String? = objectMapper.writeValueAsString(unit) // 输出 JSON 字符串 println(json) // 反序列化 JSON 字符串为 Map 对象 @Suppress("UNCHECKED_CAST") val deserializedMap = objectMapper.readValue(json, HashMap::class.java) as Map println("Deserialized Map: $deserializedMap") } catch (e: java.lang.Exception) { e.printStackTrace() } } fun transformMap(json: String): Map { try { // 序列化 Map 对象为 JSON 字符串 val objectMapper = ObjectMapper() // 禁用 FAIL_ON_EMPTY_BEANS 特性 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 反序列化 JSON 字符串为 Map 对象 @Suppress("UNCHECKED_CAST") val deserializedMap = objectMapper.readValue(json, HashMap::class.java) as Map println("Deserialized Map: $deserializedMap") return deserializedMap } catch (e: java.lang.Exception) { e.printStackTrace() } return emptyMap() } fun getDefaultJson(): String { return "{\n" + " \"directives\" : [ ],\n" + " \"declarations\" : [ {\n" + " \"type\" : \"ClassDeclaration\",\n" + " \"name\" : \"DemoEmptyFunctionExpress\",\n" + " \"members\" : [ {\n" + " \"type\" : \"MethodDeclaration\",\n" + " \"name\" : \"test2\",\n" + " \"parameters\" : [ {\n" + " \"type\" : \"SimpleFormalParameter\",\n" + " \"name\" : \"index\",\n" + " \"typeName\" : \"Int\"\n" + " }, {\n" + " \"type\" : \"SimpleFormalParameter\",\n" + " \"name\" : \"item\",\n" + " \"typeName\" : \"String\"\n" + " } ],\n" + " \"typeParameters\" : [ ],\n" + " \"body\" : {\n" + " \"type\" : \"BlockStatement\",\n" + " \"body\" : [ {\n" + " \"type\" : \"PropertyStatement\",\n" + " \"name\" : \"a\",\n" + " \"initializer\" : {\n" + " \"type\" : \"INTEGER_CONSTANT\",\n" + " \"value\" : \"2\",\n" + " \"name\" : \"ConstantExpression\"\n" + " }\n" + " }, {\n" + " \"type\" : \"PropertyStatement\",\n" + " \"name\" : \"b\",\n" + " \"initializer\" : {\n" + " \"type\" : \"BinaryExpression\",\n" + " \"name\" : null,\n" + " \"operator\" : \"+\",\n" + " \"left\" : {\n" + " \"type\" : \"INTEGER_CONSTANT\",\n" + " \"value\" : \"2\",\n" + " \"name\" : \"ConstantExpression\"\n" + " },\n" + " \"right\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"index\"\n" + " }\n" + " }\n" + " }, {\n" + " \"type\" : \"ReturnStatement\",\n" + " \"argument\" : {\n" + " \"type\" : \"BinaryExpression\",\n" + " \"name\" : null,\n" + " \"operator\" : \"*\",\n" + " \"left\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"a\"\n" + " },\n" + " \"right\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"b\"\n" + " }\n" + " }\n" + " } ]\n" + " },\n" + " \"isStatic\" : true,\n" + " \"isGetter\" : false,\n" + " \"isSetter\" : false\n" + " } ],\n" + " \"body\" : { }\n" + " } ],\n" + " \"type\" : \"CompilationUnit\"\n" + "}" } fun getClassFilePath(clazz: Class<*>): String? { // 尝试从保护域获取类文件的位置 clazz.protectionDomain?.codeSource?.location?.let { return try { // 如果是文件形式存在,则返回其路径 it.toURI().path } catch (e: Exception) { e.printStackTrace() null } } // 尝试通过类加载器获取资源路径 val resource = clazz.name.replace('.', '/') + ".class" val resourcePath = clazz.classLoader.getResource(resource)?.toURI()?.path if (resourcePath != null && resourcePath.endsWith(".jar")) { // 如果是在JAR内,则返回JAR文件路径 return resourcePath } return resourcePath?.removeSuffix(".class") } fun convertClassToPath(fullClassName: String): String { return "src/test/java/" + fullClassName.replace('.', '/') + ".kt" } override fun getRelativeEntity(uri: String): ProgramEntity { // 获取文件的目录路径 // val basePath = File(convertClassToPath(uri)).parentFile?.absolutePath // ?: throw IllegalArgumentException("Invalid base file path") return LocalFile(File(convertClassToPath(uri))) } private fun createCoreEnvironment(): KotlinCoreEnvironment { val disposable = Disposer.newDisposable() return KotlinCoreEnvironment.createForProduction( disposable, ProjectHelper.getConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES ) } fun parseKotlinCode(content: String, fileName: String = "DummyFile.kt"): KtFile { val project: Project = createCoreEnvironment().project val psiFileFactory = PsiFileFactory.getInstance(project) return psiFileFactory.createFileFromText(fileName, content) as KtFile } } class ProgramDependencyWalker { val nodeMap = mutableMapOf() fun evaluate(node: ProgramNode) { node.evaluate() } fun evaluateScc(scc: List) { for (node in scc) { node.markCircular() } } fun getNode(entity: ProgramEntity, compilation: CompilationUnit): ProgramNode { val programNode = nodeMap.getOrPut(entity) { ProgramNode(entity, this, compilation) } programNode.dependencies = programNode.computeDependencies() return programNode } } // Assuming the ProgramNode class has these methods: class ProgramNode( val entity: ProgramEntity, val walker: ProgramDependencyWalker, val compilation: CompilationUnit ) { var _classDeclarations: Map? = null var _methodDeclarations: Map? = null var _variableDeclarators: Map? = null private val _classes: MutableMap = mutableMapOf() private val _functions: MutableMap = mutableMapOf() private val _topLevelVariables: MutableMap = mutableMapOf() var dependencies: List = emptyList() var data: MutableMap = mutableMapOf() fun evaluate() { // Implement the evaluation logic here TODO("Implement evaluate for ProgramNode") } fun markCircular() { // Implement the circular marking logic here TODO("Implement markCircular for ProgramNode") } private val methodDeclarations: Map? get() { if (_methodDeclarations == null) { // val result = mutableMapOf() // compilation.declarations // ?.filterIsInstance() // ?.forEach { declaration -> // result[declaration.name] = declaration // } // _functionDeclarations = result val result = mutableMapOf() compilation.declarations?.forEach { (it.get() as ClassDeclaration).members?.forEach { declaration -> if (declaration.get() is MethodDeclaration) { result[((declaration?.get() as MethodDeclaration).name ?: "")] = declaration.get() as MethodDeclaration _methodDeclarations = result } } } } return _methodDeclarations } val classes: List get() = compilation.declarations?.filter { it.isClassDeclaration } ?.map { it.asClassDeclaration } ?.mapNotNull { getClass(it.name) } ?.toList() ?: emptyList() fun ensureClassDeclarations() { var classDeclarations = _classDeclarations if (classDeclarations == null) { val result = mutableMapOf() compilation.declarations ?.filter { it.isClassDeclaration } ?.map { it.asClassDeclaration } ?.forEach { declaration -> result[declaration.name] = declaration } _classDeclarations = result.unmodifiable() } } fun getReflectClass(className: String, recursive: Boolean = true): ImportDirective? { val importDirective = data[className] return importDirective } fun getClass(className: String, recursive: Boolean = true): AstClass? { ensureClassDeclarations() _classes[className]?.let { return it } _classDeclarations?.get(className)?.let { val clazz = AstClass.fromClass(it, this) _classes[className] = clazz return clazz } if (!recursive) return null dependencies.forEach { it.getClass(className, recursive = false)?.let { clazz -> return clazz } } return null } fun Map.unmodifiable(): Map { return Collections.unmodifiableMap(this) } // 获取函数声明 fun getFunction(functionName: String, recursive: Boolean = true): AstMethod? { val functions = methodDeclarations if (functions != null && functions.containsKey(functionName)) { val functionDeclaration = functions[functionName] if (functionDeclaration != null) { return AstMethod.fromFunction(functionDeclaration, this) } } if (!recursive) { return null } for (dependency in dependencies) { val function = dependency.getFunction(functionName, recursive = false) if (function != null) { return function } } return null } private fun _visitNode( entity: ProgramEntity, dependencies: MutableSet, node: ProgramNode ) { for (directive in node.compilation.directives!!) { when (directive) { is ImportDirective -> { val import = Import(directive.uri, "", null) val newEntity = entity.getRelativeEntity(import.uri) val newNode = walker.nodeMap[newEntity] ?: run { if (newEntity.exists) { val newNode = newEntity.createNode() walker.nodeMap.putIfAbsent(newEntity, newNode) newNode } else null } if (newNode != null) { if (!dependencies.contains(newNode)) { dependencies.add(newNode) _visitNode(newEntity, dependencies, newNode) } } else { //反射 data[directive.name] = directive } } // is PartDirective -> { // val newEntity = entity.getRelativeEntity(directive.uri) // val newNode = walker.nodeMap[newEntity] ?: run { // if (newEntity.exists) { // val newNode = newEntity.createNode() // walker.nodeMap.putIfAbsent(newEntity, newNode) // newNode // } else null // } // newNode?.let { // if (!dependencies.contains(it)) { // dependencies.add(it) // _visitNode(newEntity, dependencies, it) // } // } // } } } } fun computeDependencies(): List { val dependencies = mutableSetOf() _visitNode(entity, dependencies, this) return dependencies.toList() } } abstract class ProgramEntity { abstract val exists: Boolean abstract fun createNode(): ProgramNode abstract fun getRelativeEntity(uri: String): ProgramEntity } // class ProgramNode( // private val walker: ProgramDependencyWalker, // private val compilation: CompilationUnit, // private val entity: ProgramEntity // ){ // //// private var imports: List? = null // //// val importsList: List //// get() { //// if (imports == null) { //// imports = compilation.directives //// .filterIsInstance() //// .map { directive -> //// Import(directive.uri, directive.prefix, _getCombinators(directive)) //// } //// .toList() //// } //// return imports!! //// } // // var isEvaluated: Boolean = false // //// val dependencies: List //// get() = if (isRecursive) super.getDependencies(this) else emptyList() // // var isRecursive: Boolean = true // // // private fun _evaluate() { // isEvaluated = true // } // // private fun _markCircular() { // isEvaluated = true // } // // private var classDeclarations: MutableMap? = null // private var functionDeclarations: MutableMap? = null // private var variableDeclarators: MutableMap? = null // // fun ensureClassDeclarations() { // var classDeclarations = this.classDeclarations // if (classDeclarations == null) { // val result = mutableMapOf() // compilation.declarations // .filterIsInstance() // .forEach { declaration -> // result[declaration.name] = declaration // } // classDeclarations = this.classDeclarations = // Collections.unmodifiableMap(result) // } // } // // private val classes = mutableMapOf() // private val functions = mutableMapOf() // private val topLevelVariables = mutableMapOf() // //// val classesList: List //// get() = compilation.declarations //// .filterIsInstance() //// .map { declaration -> //// getClass(declaration.name, recursive = false)!! //// } // //// fun getClass(className: String, recursive: Boolean = true): AstClass? { //// ensureClassDeclarations() //// if (classes.containsKey(className)) { //// return classes[className] //// } //// val classDecl = classDeclarations?.get(className) //// if (classDecl != null) { //// val clazz = AstClass.fromClass(classDecl, this) //// classes[className] = clazz //// return clazz //// } //// if (!recursive) return null //// //// for (dependency in dependencies) { //// val clazz = dependency.getClass(className, recursive = false) //// if (clazz != null) return clazz //// } //// return null //// } // // fun getFunction(functionName: String, recursive: Boolean = true): AstMethod? { // var functions = this.functionDeclarations // if (functions == null) { // val result = mutableMapOf() // compilation.declarations // .filterIsInstance() // .forEach { declaration -> // result[declaration.name] = declaration // } // functions = this.functionDeclarations = // Collections.unmodifiableMap(result) // } // functions?.get(functionName)?.let { // return AstMethod.fromFunction(it, this) // } // if (!recursive) return null // // for (dependency in dependencies) { // val function = dependency.getFunction(functionName, recursive = false) // if (function != null) return function // } // return null // } // // private val topLevel = mutableMapOf() // // fun getTopLevelVariable(variableName: String, recursive: Boolean = true): Variable? { // var topLevelVariables = this.variableDeclarators // if (topLevelVariables == null) { // val result = mutableMapOf() // compilation.declarations // .filterIsInstance() // .forEach { declaration -> // declaration.variables.declarationList.forEach { declarator -> // result[declarator.name] = declarator // } // } // topLevelVariables = this.variableDeclarators = // Collections.unmodifiableMap(result) // } // topLevelVariables?.get(variableName)?.let { // val variable = AstVariable.fromDeclarator(it) // return topLevel.computeIfAbsent(variableName) { // Variable.lazily(variableName) { // if (variable.initializer != null) { // val programStack = context.get()!! // programStack.push(name = "Top-Level variable initializer") // try { // executeExpression(variable.initializer) // } finally { // programStack.pop() // } // } // } // } // } // if (!recursive) return null // // for (dependency in dependencies) { // val topLevelVariable = dependency.getTopLevelVariable(variableName, recursive = false) // if (topLevelVariable != null) return topLevelVariable // } // return null // } // // // Helper methods and properties that need to be implemented or mapped to Kotlin equivalents // private fun _getCombinators(directive: ImportDirective): List { // // Implementation of _getCombinators // TODO("Implement _getCombinators") // } // //// private fun isPlatformUri(uri: Uri): Boolean { //// // Implementation of isPlatformUri //// TODO("Implement isPlatformUri") //// } // // private fun executeExpression(expression: Expression): Any? { // // Implementation of executeExpression // TODO("Implement executeExpression") // } // // companion object { // // Context or other static members can be placed here if needed // } // } // open fun executeExpression( expression: KtExpression, flag: String? = null, keepVariable: Boolean = false ): Any? { return try { // val programStack = context.get() ?: throw IllegalStateException("ProgramStack not found in context") // if (expression.isIdentifier) { // // } else if (expression.isStringLiteral) { // //string // return expression?.asStringLiteral()?.value; // } else { // println("executeExpression ${expression::class.simpleName} not implemented") // } } catch (e: Exception) { return null } } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/ClassMirror.kt ================================================ package com.aether.core.runtime import androidx.compose.runtime.Composable import com.aether.core.runtime.reflectable.ClassMirror import com.aether.core.runtime.reflectable.ClassMirrorBase import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeComponentDescriptor2 import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.MethodMirror import org.jetbrains.kotlin.builtins.StandardNames.FqNames.kProperty import java.lang.reflect.Modifier import kotlin.reflect.KCallable import kotlin.reflect.KClass import kotlin.reflect.KFunction import kotlin.reflect.KMutableProperty import kotlin.reflect.KParameter import kotlin.reflect.KProperty import kotlin.reflect.KType import kotlin.reflect.jvm.isAccessible import kotlin.reflect.jvm.javaMethod class _ClassMirror( private val classMirror: ClassMirrorBase, private val _name: String, override val superclass: AstClass?, private val _staticFields: Map, private val _staticGetters: Map, private val _staticSetters: Map, val _instanceFields: Map, val _instanceGetters: Map, val _instanceSetters: Map, private val _constructors: Map, // private val _node: ClassDeclaration, override val programNode: AstRuntime.ProgramNode ) : AstObject, AstClass() { companion object { fun fromMirror(mirror: ClassMirrorBase, programNode: AstRuntime.ProgramNode): _ClassMirror { var staticFields: Map = HashMap() val staticGetters: HashMap = HashMap() val staticSetters: HashMap = HashMap() val instanceFields: Map = mapOf() val instanceGetters: Map = mapOf() val instanceSetters: Map = mapOf() val constructors: Map = mapOf() return _ClassMirror( mirror, _name = mirror.simpleName ?: "", superclass = null, _staticFields = staticFields, _staticGetters = staticGetters, _staticSetters = staticSetters, _instanceFields = instanceFields, _instanceGetters = instanceGetters, _instanceSetters = instanceSetters, _constructors = constructors, programNode = programNode, ); } } private var _declarations: Map? = null private var _staticMembers: Map? = null private var _instanceMembers: Map? = null override val isAbstract: Boolean get() = TODO("Not yet implemented") override val declarations: Map get() = _declarations ?: run { val result = mutableMapOf() // kClass.members.forEach { member -> // when (member) { // is kotlin.reflect.KFunction -> result[member.name] = // AstMethod.fromMirror(member) // is kotlin.reflect.KProperty<*> -> result[member.name] = // AstVariable.fromKCallable(member) // } // } result.toMap().also { _declarations = it } } override val instanceFields: Map get() = TODO("Not yet implemented") override val instanceGetters: Map get() = TODO("Not yet implemented") override val instanceSetters: Map get() = TODO("Not yet implemented") override val staticFields: Map get() = TODO("Not yet implemented") override val staticGetters: Map get() = _staticMembers ?: run { val result = mutableMapOf() classMirror.staticMembers.forEach { simpleName, member -> result[simpleName] = AstMethod.fromMirror(member) } result.toMap().also { _staticMembers = it } } override val staticSetters: Map get() = TODO("Not yet implemented") override fun newInstance( constructorName: String, positionalArguments: List, namedArguments: Map? ): Any? { return classMirror.invoke(constructorName, positionalArguments, namedArguments) } override fun isSubclassOf(other: AstClass): Boolean { TODO("Not yet implemented") } override fun hasConstructor(constructorName: String): Boolean { return false } override val simpleName: String get() = _name override val qualifiedName: String get() = _name override val owner: AstDeclaration? get() = TODO("Not yet implemented") override val isPrivate: Boolean get() = throw NotImplementedError() override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { val method = staticGetters[memberName] ?: throw NoSuchMethodError("Member $memberName not found") return invokeStaticMethod(method, positionalArguments, namedArguments) } override fun invokeGetter(getterName: String): Any? { TODO("Not yet implemented") } override fun hasGetter(getterName: String): Boolean { TODO("Not yet implemented") } override fun invokeSetter(setterName: String, value: Any?): Any? { TODO("Not yet implemented") } override fun hasSetter(setterName: String): Boolean { TODO("Not yet implemented") } override fun hasRegularMethod(methodName: String): Boolean { TODO("Not yet implemented") } private fun invokeStaticMethod( name: AstMethod, positionalArguments: List, namedArguments: Map? ): Any? { val methodMirror = (name as _MethodMirror2)._methodMirror return ComposeComponentDescriptor2( methodMirror = methodMirror, "", positionalArguments = positionalArguments, namedArguments = namedArguments, children = null ) // return methodMirror?.invoke(null,namedArguments) } private fun buildParameters( kFunction: KFunction<*>, positionalArgs: List, namedArgs: Map? ): Map { val parameters = kFunction.parameters val result = mutableMapOf() // 处理位置参数 var positionalIndex = 0 for (param in parameters) { if (positionalIndex < positionalArgs.size && !param.isVararg) { result[param] = positionalArgs[positionalIndex] positionalIndex++ } else if (namedArgs?.containsKey(param.name) == true) { // 处理命名参数 result[param] = namedArgs[param.name] } else if (param.isVararg) { // 如果是可变参数,则需要特殊处理 val remainingPosArgs = positionalArgs.drop(positionalIndex) result[param] = if (remainingPosArgs.isNotEmpty()) remainingPosArgs.toTypedArray() else null } } return result } private fun convertType(type: KType, value: Any?): Any? { return when (type.classifier) { Double::class -> value?.toString()?.toDoubleOrNull() else -> value } } } //class _ClassMirror(private val _classMirror: ClassMirror) : AstObject, AstClass() { // private var _declarations: Map? = null // private var _staticMembers: Map? = null // private var _instanceMembers: Map? = null // // override val declarations: Map // get() = _declarations ?: run { // val result = mutableMapOf() // _classMirror.declarations.forEach { (name, mirror) -> // when (mirror) { // is MethodMirror -> result[name] = AstMethod.fromMirror(mirror) // is VariableMirrorBase -> result[name] = AstVariable.fromMirror(mirror) // } // } // result.toMap().also { _declarations = it } // } // // override val staticMembers: Map // get() = _staticMembers ?: run { // val result = mutableMapOf() // _classMirror.staticMembers.forEach { (name, mirror) -> // result[name] = AstMethod.fromMirror(mirror) // } // result.toMap().also { _staticMembers = it } // } // // override fun hasConstructor(constructorName: String): Boolean { // val methodName = if (constructorName.isEmpty()) simpleName else "$simpleName.$constructorName" // return (_classMirror.declarations[methodName] as? MethodMirror)?.isConstructor ?: false // } // // override fun invoke(memberName: String, positionalArguments: List, namedArguments: MutableMap?): Any? { // val method = staticMembers[memberName] ?: throw NoSuchMethodError("Member $memberName not found") //// processArguments(method.parameters, positionalArguments, namedArguments) // processArguments(mutableListOf(), positionalArguments, namedArguments) // return _classMirror.invoke(memberName, positionalArguments, namedArguments) // } // // // 其他方法类似转换... //} class _MethodMirror2(methodMirror: MethodMirror) : AstMethod { var _methodMirror: MethodMirror? = null init { this._methodMirror = methodMirror } companion object { fun fromMirror(mirror: KFunction<*>): _MethodMirror { return _MethodMirror(mirror); } fun fromMirror(mirror: MethodMirror): _MethodMirror2 { return _MethodMirror2(mirror); } } fun fromKCallable(member: KFunction<*>): AstDeclaration { return _MethodMirror.fromMirror(member) } val isMutable: Boolean // get() = kProperty is KMutableProperty<*> get() = true val setter: KCallable<*>? get() = if (isMutable) (kProperty as? KMutableProperty<*>)?.setter else null val isConstConstructor: Boolean get() = false // Kotlin does not have a direct equivalent of Dart's const constructors val isRedirectingConstructor: Boolean get() = false // Kotlin does not have redirecting constructors override val owner: AstDeclaration? get() = null // Unimplemented for simplicity override val isPrivate: Boolean get() = TODO("Not yet implemented") private var _parameters: List? = null override val parameters: List<_ParameterImpl> get() { return mutableListOf() } override val isStatic: Boolean get() = TODO("Not yet implemented") override val isAbstract: Boolean get() = TODO("Not yet implemented") override val returnType: AstType get() = throw UnimplementedError("returnType error") override val simpleName: String get() = _methodMirror?.simpleName ?: "" override val qualifiedName: String get() = _methodMirror?.qualifiedName ?: "" override fun toString(): String = "_MethodMirror($qualifiedName)" override val isSynthetic: Boolean // get() = kFunction.isSynthetic get() = true override val isRegularMethod: Boolean get() = TODO("Not yet implemented") override val isGetter: Boolean get() = TODO("Not yet implemented") override val isSetter: Boolean get() = TODO("Not yet implemented") override val isOperator: Boolean get() = TODO("Not yet implemented") override val isConstructor: Boolean get() = TODO("Not yet implemented") override val constructorName: String get() = TODO("Not yet implemented") override val programNode: AstRuntime.ProgramNode get() = throw UnsupportedOperationException() } class _MethodMirror(val kFunction: KFunction<*>) : AstMethod { var function: KFunction<*>? = null init { this.function = kFunction } companion object { fun fromMirror(mirror: KFunction<*>): _MethodMirror { return _MethodMirror(mirror); } fun fromMirror(mirror: MethodMirror): _MethodMirror2 { return _MethodMirror2(mirror); } } fun fromKCallable(member: KFunction<*>): AstDeclaration { return fromMirror(member) } val isBound: Boolean get() = kFunction.isInstanceBound() private fun KFunction<*>.isInstanceBound(): Boolean { return when { this is Function<*> -> { // 如果是 lambda 或局部函数,可能无法直接判断 false } else -> { // 检查是否有接收者参数 // parameters.firstOrNull()?.isInstanceParameter == true true } } } val isMutable: Boolean // get() = kProperty is KMutableProperty<*> get() = true val setter: KCallable<*>? get() = if (isMutable) (kProperty as? KMutableProperty<*>)?.setter else null val declaringClass: KClass<*>? get() = kFunction.declaringClass() private fun KFunction<*>.declaringClass(): KClass<*>? { return when { javaMethod != null -> javaMethod!!.declaringClass.kotlin // 如果是 Java 方法 else -> this.parameters.firstOrNull()?.type?.classifier as? KClass<*> } } override val constructorName: String get() = if (kFunction.name == "") declaringClass?.simpleName ?: "" else "" override val isAbstract: Boolean get() = kFunction.isAbstract val isConstConstructor: Boolean get() = false // Kotlin does not have a direct equivalent of Dart's const constructors override val isConstructor: Boolean get() = kFunction.name == "" val isFactoryConstructor: Boolean get() = false // Kotlin does not have factory constructors override val isGetter: Boolean get() = kFunction is KProperty<*> && !setter!!.isAccessible override val isOperator: Boolean get() = kFunction.name.startsWith("operator") override val isPrivate: Boolean get() = Modifier.isPrivate(kFunction.javaMethod?.modifiers ?: 0) val isRedirectingConstructor: Boolean get() = false // Kotlin does not have redirecting constructors override val isSetter: Boolean get() = kFunction is KMutableProperty<*> override val isStatic: Boolean get() = isBound override val owner: AstDeclaration? get() = null // Unimplemented for simplicity private var _parameters: List? = null override val parameters: List<_ParameterImpl> get() { // if (_parameters == null) { // _parameters = kFunction.parameters.map { AstParameter.fromKParameter(it) } // } // return _parameters!! return mutableListOf() } override val returnType: AstType get() = throw UnimplementedError("returnType error") override val simpleName: String get() = kFunction.name override val qualifiedName: String get() = "${kFunction.name}" override fun toString(): String = "_MethodMirror($qualifiedName)" override val isRegularMethod: Boolean get() = kFunction.name != "" && kFunction.name != "" override val isSynthetic: Boolean // get() = kFunction.isSynthetic get() = true override val programNode: AstRuntime.ProgramNode get() = throw UnsupportedOperationException() } private fun processArguments( parameters: List?, positionalArgs: List, namedArgs: Map? ) { // parameters.forEachIndexed { i, param -> // when { // param.isNamed && namedArgs?.containsKey(param.simpleName) == true -> { // namedArgs[param.simpleName] = // convertType(param, namedArgs.getValue(param.simpleName)) // } // i < positionalArgs.size -> { // positionalArgs[i] = convertType(param, positionalArgs[i]) // } // } // } } // _InstanceMirror.kt //class _InstanceMirror(private val _instanceMirror: InstanceMirror) : AstObject(), AstInstance { // override val type: AstClass get() = AstClass.fromMirror(_instanceMirror.type) // // override fun invoke(memberName: String, positionalArguments: List, namedArguments: Map?): Any? { // return context.run{ // val method = (type as _ClassMirror).instanceMembers[memberName] // ?: throw NoSuchMethodError("Method $memberName not found") // processArguments(method.parameters, positionalArguments, namedArguments) // _instanceMirror.invoke(memberName, positionalArguments, namedArguments) // } // } // 其他方法转换... //} //private fun convertType(param: AstParameter, value: Any?): Any? { // return when (param.reflectedType) { // Double::class -> value?.toString()?.toDoubleOrNull() // else -> value // } //} ================================================ FILE: core/src/main/java/com/aether/core/runtime/KtAstVisitor.kt ================================================ package com.aether.core.runtime import com.intellij.psi.PsiElement import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject // 自定义访问者类,继承 KtTreeVisitorVoid class MyKtVisitorV2 : KtVisitor, Void?>() { // 用于存储遍历结果的 Map private val result = mutableMapOf() // 获取遍历结果 fun getResult(): Map { return result.toMap() } // 遍历单个节点 private fun visitNode(node: KtElement?, data: Void?): Map? { // 调用 accept 方法,启动访问者模式的遍历 if (node != null) { return node.accept(this, data) } return null } // 遍历节点列表 private fun visitNodeList(nodes: List, data: Void?): List> { val maps = mutableListOf>() for (node in nodes) { val res = visitNode(node, data) if (res != null) { maps.add(res) } } return maps } override fun visitKtElement(element: KtElement, data: Void?): Map? { // println("Visiting element: ${element.text}") super.visitElement(element) return mutableMapOf() } override fun visitElement(element: PsiElement) { super.visitElement(element) } // override fun visitSimpleNameExpression( // node: KtSimpleNameExpression, // data: Void? // ): Map { // super.visitSimpleNameExpression(node, data) // println("Visiting Identifier: ${node.name}") // return mapOf( // "type" to "Identifier", // "name" to node.name, // ) // } override fun visitKtFile(file: KtFile, data: Void?): Map? { println("Visiting file: ${file.name}") // result["file"] = file.name // 处理包声明 // val packageDirective = file.packageDirective // if (packageDirective != null) { // println("Package: ${packageDirective.fqName.asString()}") // result["package"] = packageDirective.fqName.asString() // } // 处理导入语句 // for (import in file.importDirectives) { // println("Import: ${import.importPath?.toString()}") // result["directives"] = // result.getOrDefault("imports", mutableListOf()) as MutableList // (result["directives"] as MutableList).add( // import.importPath?.toString() ?: "Unknown" // ) // } val declarations = file.declarations if (declarations != null) { val directives = file.importDirectives println("Import: ${directives?.toString()}") result["directives"] = visitNodeList(directives, data) println("declarations: ${declarations.asSequence()}") result["declarations"] = visitNodeList(declarations, data) result["type"] = "CompilationUnit" } file.acceptChildren(this) return result } override fun visitBlockExpression( node: KtBlockExpression, data: Void? ): Map { super.visitBlockExpression(node, data) println("Visiting class: ${node.name}") return mapOf( "type" to "BlockStatement", "body" to visitNodeList(node.statements, data), ) } override fun visitObjectDeclaration( node: KtObjectDeclaration, data: Void? ): Map { // 1 val annotations = node.annotationEntries // return annotations.any { it.shortName()?.asString() == "JvmStatic" } // 2 val containingClass = function.containingClassOrObject // return containingClass is KtObjectDeclaration && containingClass.isCompanion() // 3 function.parent is KtFile println("Visiting visitObjectDeclaration: ${node.name}") return mapOf( "type" to "ClassDeclaration", "name" to node.name, "members" to visitNodeList(node.declarations, data), "body" to visitNode(node.body, data), ) } // 重写 visitClass 方法,处理类节点 override fun visitClass(klass: KtClass, data: Void?): Map? { println("Visiting class: ${klass.name}") super.visitClass(klass, data) return mapOf( "type" to "ClassDeclaration", "name" to klass.name, "members" to visitNodeList(klass.declarations, data), "body" to visitNode(klass.body, data), ) } override fun visitCallableReferenceExpression( expression: KtCallableReferenceExpression, data: Void? ): Map { super.visitCallableReferenceExpression(expression, data) return mapOf( "type" to "visitCallableReferenceExpression", "name" to expression.name, "targetExpression" to visitNode(expression.receiverExpression, data),//右边部分 ) } override fun visitLambdaExpression( expression: KtLambdaExpression, data: Void? ): Map { super.visitLambdaExpression(expression, data) println("Visiting visitLambdaExpression: ${expression.name}") return mapOf( "type" to "LambdaExpression", "name" to expression.name, "parameters" to visitNodeList(expression.valueParameters, data), "body" to visitNode(expression.bodyExpression, data), "returnType" to visitNode(expression.functionLiteral, data), ) } // override fun visitFunctionDeclaration(node: KtNamedFunction, data: Void?): Map? { // println("Visiting function: ${node.name}") // super.visitNamedFunction(node, data) // val parameters = visitNodeList(node.valueParameters, data) // return mapOf( // "type" to "FunctionDeclaration", // "name" to node.name, // "parameters" to parameters, // "typeParameters" to visitNodeList(node.typeParameters, data), // "body" to visitNode(node.bodyExpression, data), // "isStatic" to isStaticMethod(node), // "isGetter" to parameters.isEmpty(), // "isSetter" to (parameters.size == 1 && node.name!!.startsWith("set")), // "node" to node // ) // // } override fun visitNamedFunction(node: KtNamedFunction, data: Void?): Map? { println("Visiting function: ${node.name}") super.visitNamedFunction(node, data) val parameters = visitNodeList(node.valueParameters, data) return mapOf( "type" to "MethodDeclaration", "name" to node.name, "parameters" to parameters, "typeParameters" to visitNodeList(node.typeParameters, data), "body" to visitNode(node.bodyExpression, data), "isStatic" to isStaticMethod(node), "isGetter" to parameters.isEmpty(), "isSetter" to (parameters.size == 1 && node.name!!.startsWith("set")), // "node" to node ) } override fun visitValueArgumentList(node: KtValueArgumentList, data: Void?): Map { println("visitValueArgumentList: ${node.name}") super.visitValueArgumentList(node, data) return mapOf( "type" to "ArgumentList", "arguments" to visitNodeList(node.arguments, data), ) } override fun visitParameterList(node: KtParameterList, data: Void?): Map { println("Visiting function: ${node.name}") super.visitParameterList(node, data) return mapOf( "type" to "ParameterList", "name" to node.name, "parameters" to visitNodeList(node.parameters, data), ) } // 重写 visitProperty 方法,处理属性节点 override fun visitProperty(property: KtProperty, data: Void?): Map? { println("Visiting property: ${property.name}") super.visitProperty(property, data) return if (property.containingClassOrObject != null) { mapOf( "type" to "FieldDeclaration", "name" to property.name, "initializer" to visitNode(property.initializer, data), ) } else { mapOf( "type" to "PropertyStatement", "name" to property.name, "initializer" to visitNode(property.initializer, data), ) } } // 重写 visitBinaryExpression 方法,处理二元表达式 override fun visitBinaryExpression( expression: KtBinaryExpression, data: Void? ): Map? { println("Visiting binary expression: ${expression.text}") super.visitBinaryExpression(expression, data) return mapOf( "type" to "BinaryExpression", "name" to expression.name, "operator" to (expression.operationToken as KtSingleValueToken).value, "left" to visitNode(expression.left, data), "right" to visitNode(expression.right, data), // "node" to expression, ) } override fun visitReferenceExpression( expression: KtReferenceExpression, data: Void? ): Map { println("Visiting visitReferenceExpression: ${expression.text}") super.visitReferenceExpression(expression, data)//visitSimpleIdentifier return mapOf( "type" to "Identifier", "name" to expression.text, ) } override fun visitSecondaryConstructor( constructor: KtSecondaryConstructor, data: Void? ): Map? { super.visitSecondaryConstructor(constructor, null) println("Visiting visitSecondaryConstructor: ${constructor.name}") return mapOf( "type" to "SecondaryConstructor", "name" to constructor.name, "body" to visitNode(constructor.bodyExpression, data), "parameters" to visitNode(constructor.valueParameterList, data), ) } override fun visitStringTemplateExpression( expression: KtStringTemplateExpression, data: Void? ): Map { // 手动遍历子节点 for (entry in expression.entries) { when (entry) { is KtLiteralStringTemplateEntry -> { return mapOf( "type" to "StringTemplateExpression", "name" to entry.name, "body" to visitNode(entry, data), ) } is KtSimpleNameStringTemplateEntry -> visitNode(entry, data) // is KtExpressionStringTemplateEntry -> visitExpressionStringTemplateEntry(entry) else -> entry.accept(this) // 对于未知类型,可以使用 accept 方法 } } return super.visitStringTemplateExpression(expression, data) } override fun visitLiteralStringTemplateEntry( entry: KtLiteralStringTemplateEntry, data: Void? ): Map { super.visitLiteralStringTemplateEntry(entry, data) return mapOf( "type" to "StringTemplateEntry", "body" to visitNode(entry.expression, data), "value" to entry.text ) } override fun visitConstantExpression( expression: KtConstantExpression, data: Void? ): Map { super.visitConstantExpression(expression, data) return mapOf( "type" to expression.elementType.debugName, "value" to expression.text, "name" to "ConstantExpression", ) } override fun visitPrimaryConstructor( constructor: KtPrimaryConstructor, data: Void? ): Map? { println("Visiting visitPrimaryConstructor: ${constructor.name}") super.visitPrimaryConstructor(constructor, null) return mapOf( "type" to "PrimaryConstructor", "name" to constructor.name, "body" to visitNode(constructor.bodyExpression, data), "parameters" to visitNode(constructor.valueParameterList, data), ) } // // override fun visitTypeAlias(typeAlias: KtTypeAlias) { // println("Visiting visitTypeAlias: ${typeAlias.name}") // super.visitTypeAlias(typeAlias, null) // } // // override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) { // println("Visiting visitDestructuringDeclaration: ${destructuringDeclaration.name}") // super.visitDestructuringDeclaration(destructuringDeclaration, null) // } // // override fun visitDestructuringDeclarationEntry(multiDeclarationEntry: KtDestructuringDeclarationEntry) { // println("Visiting visitDestructuringDeclarationEntry: ${multiDeclarationEntry.name}") // super.visitDestructuringDeclarationEntry(multiDeclarationEntry, null) // } // // override fun visitScript(script: KtScript) { // println("Visiting visitScript: ${script?.name}") // super.visitScript(script, null) // } // // override fun visitImportAlias(importAlias: KtImportAlias) { // println("Visiting visitImportAlias: ${importAlias?.name}") // super.visitImportAlias(importAlias, null) // } // override fun visitImportDirective( node: KtImportDirective, data: Void? ): Map? { println("Visiting visitImportDirective: ${node?.name}") super.visitImportDirective(node, null) // node.importPath?.fqName?.asString() return mapOf( "type" to "ImportDirective", "importPath" to node.importPath?.pathStr, "alias" to node.alias?.text, "name" to node.importedFqName?.shortName()?.identifier, ) } // override fun visitImportList(importList: KtImportList, data: Void?): Map { // super.visitImportList(importList, data) // return mapOf( // "type" to "ImportList", // "imports" to visitNodeList(importList.imports, data), //// "prefix" to visitNode(node.pre,data), //// "combinators" to visitNode(node.comb,data), // ) // // } // // override fun visitModifierList(list: KtModifierList) { // println("Visiting visitModifierList: ${list?.name}") // super.visitModifierList(list, null) // } // // override fun visitAnnotation(annotation: KtAnnotation) { // println("Visiting visitAnnotation: ${annotation?.name}") // super.visitAnnotation(annotation, null) // } // // override fun visitAnnotationEntry(annotationEntry: KtAnnotationEntry) { // println("Visiting visitAnnotationEntry: ${annotationEntry?.name}") // super.visitAnnotationEntry(annotationEntry, null) // } // // override fun visitConstructorCalleeExpression(constructorCalleeExpression: KtConstructorCalleeExpression) { // println("Visiting visitConstructorCalleeExpression: ${constructorCalleeExpression?.name}") // super.visitConstructorCalleeExpression(constructorCalleeExpression, null) // } // override fun visitTypeParameterList( node: KtTypeParameterList, data: Void? ): Map? { println("Visiting visitTypeParameterList: ${node?.name}") super.visitTypeParameterList(node, null) return mapOf( "type" to "TypeParameterList", "typeParameters" to visitNodeList(node.parameters, data), ) } override fun visitTypeParameter(node: KtTypeParameter, data: Void?): Map? { println("Visiting visitTypeParameter: ${node?.name}") super.visitTypeParameter(node, null) return mapOf( "type" to "TypeParameter", "name" to node.name, "bound" to visitNode(node.extendsBound, data), ) } // // override fun visitEnumEntry(enumEntry: KtEnumEntry) { // println("Visiting visitEnumEntry: ${enumEntry?.name}") // super.visitEnumEntry(enumEntry, null) // } // override fun visitParameter(parameter: KtParameter, data: Void?): Map? { println("Visiting visitParameter: ${parameter?.name}") super.visitParameter(parameter, null) parameter return mapOf( "type" to "SimpleFormalParameter", "name" to parameter.name, "typeName" to parameter.typeReference?.text, ) } // // override fun visitSuperTypeList(list: KtSuperTypeList) { // println("Visiting visitSuperTypeList: ${list?.name}") // super.visitSuperTypeList(list, null) // } // // override fun visitSuperTypeListEntry(specifier: KtSuperTypeListEntry) { // println("Visiting visitSuperTypeList: ${specifier?.name}") // super.visitSuperTypeListEntry(specifier, null) // } // // override fun visitDelegatedSuperTypeEntry(specifier: KtDelegatedSuperTypeEntry) { // println("Visiting visitDelegatedSuperTypeEntry: ${specifier?.name}") // super.visitDelegatedSuperTypeEntry(specifier, null) // } // // override fun visitSuperTypeCallEntry(call: KtSuperTypeCallEntry) { // println("Visiting visitSuperTypeCallEntry: ${call?.name}") // super.visitSuperTypeCallEntry(call, null) // } // // override fun visitSuperTypeEntry(specifier: KtSuperTypeEntry) { // super.visitSuperTypeEntry(specifier, null) // } // // override fun visitContextReceiverList(contextReceiverList: KtContextReceiverList) { // super.visitContextReceiverList(contextReceiverList, null) // } // // override fun visitConstructorDelegationCall(call: KtConstructorDelegationCall) { // super.visitConstructorDelegationCall(call, null) // } // // override fun visitPropertyDelegate(delegate: KtPropertyDelegate) { // super.visitPropertyDelegate(delegate, null) // } // override fun visitArgument(argument: KtValueArgument, data: Void?): Map? { super.visitArgument(argument, null) return mapOf( "type" to "Argument", "isNamed" to argument.isNamed(), "name" to argument.getArgumentName()?.text, "body" to visitNode(argument.getArgumentExpression(), data), ) } // // override fun visitLoopExpression(loopExpression: KtLoopExpression) { // super.visitLoopExpression(loopExpression, null) // } // override fun visitLabeledExpression( node: KtLabeledExpression, data: Void? ): Map? { super.visitLabeledExpression(node, null) return visitNode(node.labelQualifier, data) } // // override fun visitPrefixExpression(expression: KtPrefixExpression) { // super.visitPrefixExpression(expression, null) // } // // override fun visitPostfixExpression(expression: KtPostfixExpression) { // super.visitPostfixExpression(expression, null) // } // // override fun visitUnaryExpression(expression: KtUnaryExpression) { // super.visitUnaryExpression(expression, null) // } // override fun visitReturnExpression( expression: KtReturnExpression, data: Void? ): Map? { println("Visiting visitReturnExpression: ${expression?.name}") return mapOf( "type" to "ReturnStatement", "argument" to visitNode(expression.returnedExpression, null), ) } // // override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) { // super.visitExpressionWithLabel(expression, null) // } // override fun visitThrowExpression( node: KtThrowExpression, data: Void? ): Map? { super.visitThrowExpression(node, null) println("Visiting visitThrowExpression: ${node?.name}") return mapOf( "type" to "ThrowExpression", "expression" to visitNode(node.thrownExpression, data), // "node" to node, ) } override fun visitBreakExpression( node: KtBreakExpression, data: Void? ): Map? { super.visitBreakExpression(node, null) println("Visiting visitBreakExpression: ${node?.name}") return mapOf( "type" to "BreakStatement", "label" to visitNode(node.labelQualifier, data), "target" to visitNode(node.getTargetLabel(), data), ) } // // override fun visitContinueExpression(expression: KtContinueExpression) { // super.visitContinueExpression(expression, null) // } // override fun visitIfExpression(node: KtIfExpression, data: Void?): Map? { super.visitIfExpression(node, null) println("Visiting visitIfExpression: ${node?.name}") return mapOf( "type" to "IfExpression", "condition" to visitNode(node.condition, data), "consequent" to visitNode(node.then, data), "alternate" to visitNode(node.`else`, data), ) } // // override fun visitWhenExpression(expression: KtWhenExpression) { // super.visitWhenExpression(expression, null) // } // // override fun visitCollectionLiteralExpression(expression: KtCollectionLiteralExpression) { // super.visitCollectionLiteralExpression(expression, null) // } // // override fun visitTryExpression(expression: KtTryExpression) { // super.visitTryExpression(expression, null) // } // // override fun visitForExpression(expression: KtForExpression) { // super.visitForExpression(expression, null) // } // // override fun visitWhileExpression(expression: KtWhileExpression) { // super.visitWhileExpression(expression, null) // } // // override fun visitDoWhileExpression(expression: KtDoWhileExpression) { // super.visitDoWhileExpression(expression, null) // } // // override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) { // super.visitLambdaExpression(lambdaExpression, null) // } // // override fun visitAnnotatedExpression(expression: KtAnnotatedExpression) { // super.visitAnnotatedExpression(expression, null) // } // override fun visitConstructorCalleeExpression( expression: KtConstructorCalleeExpression, data: Void? ): Map { println("Visiting visitConstructorCalleeExpression: ${expression?.name}") return super.visitConstructorCalleeExpression(expression, data) } /** * visitCallExpression 方法在 Kotlin 的 AST(抽象语法树)访问器模式中用于处理函数或构造函数的调用。 * 这意味着它不仅处理普通函数的调用,也包括对象实例化时构造函数的调用 * KtConstructorCalleeExpression专门用于表示对构造函数的引用 */ // override fun visitCallExpression( // expression: KtCallExpression, // data: Void? // ): Map? { // super.visitCallExpression(expression, null) // println("Visiting visitCallExpression: ${expression?.name}") // val callee = expression.calleeExpression // if (callee is KtConstructorCalleeExpression) { // // 这是一个构造函数调用 // println("Detected constructor call: ${callee.text}") // } // //这里因为没有办法区分是构造方法还是普通方法,所以通过方法名称的大写暂时先这样判断,后续优化吧 // if (expression.calleeExpression!!.text[0].isUpperCase()) { // return mapOf( // "type" to "InstanceCreationExpression", // "constructorName" to expression.calleeExpression?.text, // "argumentList" to visitNode(expression.valueArgumentList, data), // "valueArgument" to visitNodeList(expression.typeArguments, data), // ) // } else { // return mapOf( // "type" to "CallExpression", // "methodName" to visitNode(expression.calleeExpression, data), // "target" to visitNode(expression.calleeExpression, data), // "argumentList" to visitNode(expression.valueArgumentList, data), // "valueArgument" to visitNodeList(expression.typeArguments, data), // ) // } // } override fun visitCallExpression( expression: KtCallExpression, data: Void? ): Map? { super.visitCallExpression(expression, null) println("Visiting visitCallExpression: ${expression.calleeExpression?.text}") val callee = expression.calleeExpression if (callee is KtConstructorCalleeExpression) { // 这是一个构造函数调用 println("Detected constructor call: ${callee.text}") } // 检查是否有尾随 lambda val lambdaArgument = expression.lambdaArguments.firstOrNull() val childElements = mutableListOf?>() // 访问 lambda 体中的表达式 if (lambdaArgument != null) { val lambdaExpression = lambdaArgument.getLambdaExpression() val lambdaBody = lambdaExpression?.bodyExpression // 访问 lambda 体中的所有语句 if (lambdaBody != null) { val bodyStatements = when (lambdaBody) { is KtBlockExpression -> lambdaBody.statements else -> listOf(lambdaBody) // 如果不是块表达式,则将整个表达式视为单个语句 } // 遍历 lambda 体中的所有语句 for (statement in bodyStatements) { if (statement is KtCallExpression) { // 递归访问子调用表达式 childElements.add(visitCallExpression(statement, data)) } } } } // 判断是构造方法还是普通方法 if (expression.calleeExpression?.text?.firstOrNull()?.isUpperCase() == true) { return mapOf( "type" to "InstanceCreationExpression", "constructorName" to expression.calleeExpression?.text, "argumentList" to visitNode(expression.valueArgumentList, data), "typeArguments" to visitNodeList(expression.typeArguments, data), "children" to childElements // 添加子元素列表 ) } else { return mapOf( "type" to "CallExpression", "methodName" to visitNode(expression.calleeExpression, data), "target" to visitNode(expression.calleeExpression, data), "argumentList" to visitNode(expression.valueArgumentList, data), "typeArguments" to visitNodeList(expression.typeArguments, data), "children" to childElements // 添加子元素列表 ) } } override fun visitDotQualifiedExpression( expression: KtDotQualifiedExpression, data: Void? ): Map { //对应visitPropertyAccess println("Visiting DotQualifiedExpression: ${expression.name}") super.visitDotQualifiedExpression(expression, data) return mapOf( "type" to "MethodInvocation", "name" to expression.name, "methodName" to visitNode( expression.selectorExpression, data ),//右边部分 ,要执行的方法test1,指令的部分比如比如DemoTest.test1. "target" to visitNode(expression.receiverExpression, data),//左边部分,指令的部分比如比如DemoTest ) // return { // 'type': 'PropertyAccess', // 'id': _visitNode(node.propertyName), // 'target': _visitNode(node.target), // 'isCascaded': node.isCascaded, // 'isNullAware': node.isNullAware, // 'node': node, // }; } // // override fun visitArrayAccessExpression(expression: KtArrayAccessExpression) { // super.visitArrayAccessExpression(expression, null) // } // // override fun visitQualifiedExpression(expression: KtQualifiedExpression) { // super.visitQualifiedExpression(expression, null) // } // // override fun visitDoubleColonExpression(expression: KtDoubleColonExpression) { // super.visitDoubleColonExpression(expression, null) // } // // override fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression) { // super.visitCallableReferenceExpression(expression, null) // } // // override fun visitClassLiteralExpression(expression: KtClassLiteralExpression) { // super.visitClassLiteralExpression(expression, null) // } // // override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) { // super.visitDotQualifiedExpression(expression, null) // } // // override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression) { // super.visitSafeQualifiedExpression(expression, null) // } // // override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression) { // super.visitObjectLiteralExpression(expression, null) // } override fun visitCatchSection(catchClause: KtCatchClause, data: Void?): Map? { super.visitCatchSection(catchClause, null) println("Visiting visitCatchSection: ${catchClause?.name}") return mapOf( "type" to "CatchSection", "name" to catchClause.name, ) } // // override fun visitFinallySection(finallySection: KtFinallySection) { // super.visitFinallySection(finallySection, null) // } // override fun visitTypeArgumentList( node: KtTypeArgumentList, data: Void? ): Map? { super.visitTypeArgumentList(node, null) println("Visiting visitTypeArgumentList: ${node?.name}") return mapOf( "type" to "TypeArgumentList", "arguments" to visitNodeList(node.arguments, data), ) } override fun visitThisExpression( node: KtThisExpression, data: Void? ): Map? { super.visitThisExpression(node, null) println("Visiting visitThisExpression: ${node?.name}") return mapOf( "type" to "ThisExpression", ) } override fun visitSuperExpression( node: KtSuperExpression, data: Void? ): Map? { super.visitSuperExpression(node, null) println("Visiting visitSuperExpression: ${node?.name}") return mapOf( "type" to "SuperExpression", ) } // // override fun visitParenthesizedExpression(expression: KtParenthesizedExpression) { // super.visitParenthesizedExpression(expression, null) // } // // override fun visitInitializerList(list: KtInitializerList) { // super.visitInitializerList(list, null) // } // // override fun visitAnonymousInitializer(initializer: KtAnonymousInitializer) { // super.visitAnonymousInitializer(initializer, null) // } // // override fun visitScriptInitializer(initializer: KtScriptInitializer) { // super.visitScriptInitializer(initializer, null) // } // // override fun visitClassInitializer(initializer: KtClassInitializer) { // super.visitClassInitializer(initializer, null) // } // // override fun visitPropertyAccessor( // node: KtPropertyAccessor, // data: Void? // ): Map? { // super.visitPropertyAccessor(node, null) // println("Visiting visitProperty: ${node?.name}") // return mapOf( // "type" to "Property", // "id" to visitNode(node.property, data), // ) // } // // override fun visitTypeConstraintList(list: KtTypeConstraintList) { // super.visitTypeConstraintList(list, null) // } // // override fun visitTypeConstraint(constraint: KtTypeConstraint) { // super.visitTypeConstraint(constraint, null) // } // // // // override fun visitFunctionType(type: KtFunctionType) { // super.visitFunctionType(type, null) // } // // override fun visitSelfType(type: KtSelfType) { // super.visitSelfType(type, null) // } // // override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS) { // super.visitBinaryWithTypeRHSExpression(expression, null) // } // // override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) { // super.visitStringTemplateExpression(expression, null) // } // // override fun visitNullableType(nullableType: KtNullableType) { // super.visitNullableType(nullableType, null) // } // // override fun visitIntersectionType(intersectionType: KtIntersectionType) { // super.visitIntersectionType(intersectionType, null) // } // // override fun visitTypeProjection(typeProjection: KtTypeProjection) { // super.visitTypeProjection(typeProjection, null) // } // // override fun visitWhenEntry(jetWhenEntry: KtWhenEntry) { // super.visitWhenEntry(jetWhenEntry, null) // } // // override fun visitIsExpression(expression: KtIsExpression) { // super.visitIsExpression(expression, null) // } // // override fun visitWhenConditionIsPattern(condition: KtWhenConditionIsPattern) { // super.visitWhenConditionIsPattern(condition, null) // } // // override fun visitWhenConditionInRange(condition: KtWhenConditionInRange) { // super.visitWhenConditionInRange(condition, null) // } // // override fun visitWhenConditionWithExpression(condition: KtWhenConditionWithExpression) { // super.visitWhenConditionWithExpression(condition, null) // } // // override fun visitObjectDeclaration(declaration: KtObjectDeclaration) { // super.visitObjectDeclaration(declaration, null) // } private fun isStaticMethod(function: KtNamedFunction): Boolean { // 1. 检查是否为顶层函数 if (isTopLevelFunction(function)) { return true } if (isObjectMember(function)) { return true } // 2. 检查是否为伴生对象内的成员函数 if (isCompanionObjectMember(function)) { return true } // 3. 检查是否使用了 @JvmStatic 注解 if (hasJvmStaticAnnotation(function)) { return true } return false } private fun isTopLevelFunction(function: KtNamedFunction): Boolean { val parent = function.parent return parent is KtFile } private fun isObjectMember(function: KtNamedFunction): Boolean { val containingClass = function.containingClassOrObject return containingClass is KtObjectDeclaration } private fun isCompanionObjectMember(function: KtNamedFunction): Boolean { val containingClass = function.containingClassOrObject return containingClass is KtObjectDeclaration && containingClass.isCompanion() } private fun hasJvmStaticAnnotation(function: KtNamedFunction): Boolean { return function.annotationEntries.any { it.shortName?.asString() == "JvmStatic" } } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/Node.kt ================================================ package com.aether.core.runtime fun parseError(unit: Any): Nothing { throw Exception("Parse error: ${unit.toString()}") } abstract class Node( private val unit: Map ) { val type: String = unit["type"] as? String ?: throw IllegalArgumentException("Type not found in unit") var parent: Node? = null init { if (unit["type"] == null) { throw IllegalArgumentException("Type not found in unit") } } protected fun becomeParentOf(child: T?): T? { child?.parent = this return child } fun toUnit(): Map = unit // Assuming Expression is a subclass of Node and has a specific property or behavior // If Expression has a special way of setting its parent, you might need to adjust this method. // For now, we'll assume that all Nodes have the same parent-setting logic. } class Expression( expression: Node, isIdentifier: Boolean = false, isConstructorDeclaration: Boolean = false, isMethodInvocation: Boolean = false, isCallExpression: Boolean = false, isNamedExpression: Boolean = false, isMethodDeclaration: Boolean = false, isBlockStatement: Boolean = false, isEmptyFunctionBody: Boolean = false, isInstanceCreationExpression: Boolean = false, isClassDeclaration: Boolean = false, isPropertyAccess: Boolean = false, isIntegerLiteral: Boolean = false, isStringLiteral: Boolean = false, isStringTemplateEntry: Boolean = false, isStringTemplateExpression: Boolean = false, isBooleanLiteral: Boolean = false, isBinaryExpression: Boolean = false, isReturnStatement: Boolean = false, isVariableDeclarationList: Boolean = false, isFieldDeclaration: Boolean = false, isReferenceExpression: Boolean = false, unit: Map ) : Node(unit) { var expression: Node? = null; var isIdentifier: Boolean = false var isConstructorDeclaration: Boolean = false var isMethodInvocation: Boolean = false var isMethodDeclaration: Boolean = false var isCallExpression: Boolean = false var isNamedExpression: Boolean = false var isBlockStatement: Boolean = false var isEmptyFunctionBody: Boolean = false var isInstanceCreationExpression: Boolean = false var isClassDeclaration: Boolean = false var isPropertyAccess: Boolean = false var isIntegerLiteral: Boolean = false var isStringLiteral: Boolean = false var isStringTemplateEntry: Boolean = false var isStringTemplateExpression: Boolean = false var isBooleanLiteral: Boolean = false var isBinaryExpression: Boolean = false var isReturnStatement: Boolean = false var isVariableDeclarationList: Boolean = false var isFieldDeclaration: Boolean = false var isReferenceExpression: Boolean = false init { this.expression = expression this.isIdentifier = isIdentifier this.isConstructorDeclaration = isConstructorDeclaration this.isMethodInvocation = isMethodInvocation this.isMethodDeclaration = isMethodDeclaration this.isCallExpression = isCallExpression this.isNamedExpression = isNamedExpression this.isBlockStatement = isBlockStatement this.isEmptyFunctionBody = isEmptyFunctionBody this.isInstanceCreationExpression = isInstanceCreationExpression this.isClassDeclaration = isClassDeclaration this.isPropertyAccess = isPropertyAccess this.isIntegerLiteral = isIntegerLiteral this.isStringLiteral = isStringLiteral this.isStringTemplateEntry = isStringTemplateEntry this.isStringTemplateExpression = isStringTemplateExpression this.isBooleanLiteral = isBooleanLiteral this.isBinaryExpression = isBinaryExpression this.isReturnStatement = isReturnStatement this.isVariableDeclarationList = isVariableDeclarationList this.isFieldDeclaration = isFieldDeclaration this.isReferenceExpression = isReferenceExpression } fun get(): Node? { return expression } val asConstructorDeclaration: ConstructorDeclaration get() = expression as ConstructorDeclaration val asBlockStatement: BlockStatement get() = expression as BlockStatement val asInstanceCreationExpression: InstanceCreationExpression get() = expression as InstanceCreationExpression val asClassDeclaration: ClassDeclaration get() = expression as ClassDeclaration val asVariableDeclarationList: PropertyStatement get() = expression as PropertyStatement val asFieldDeclaration: FieldDeclaration get() = expression as FieldDeclaration val asPropertyAccess: PropertyAccess get() = expression as PropertyAccess val asReturnStatement: ReturnStatement get() = expression as ReturnStatement val asBinaryExpression: BinaryExpression get() = expression as BinaryExpression val asIntegerLiteral: IntegerLiteral get() = expression as IntegerLiteral val asStringLiteral: StringTemplateExpression get() = expression as StringTemplateExpression val asStringTemplateEntry: StringTemplateEntry get() = expression as StringTemplateEntry val asNamedExpression: Argument get() = expression as Argument val asBooleanLiteral: BooleanLiteral get() = expression as BooleanLiteral val asStringTemplateExpression: StringTemplateExpression get() = expression as StringTemplateExpression val asIdentifier: Identifier get() = expression as Identifier val asMethodInvocation: MethodInvocation get() = expression as MethodInvocation val asCallExpression: CallExpression get() = expression as CallExpression val asMethodExpression: MethodDeclaration get() = expression as MethodDeclaration companion object { fun fromUnit(unit: Map): Expression { val type = unit["type"] if (type == "ClassDeclaration") { return Expression( ClassDeclaration.fromUnit(unit), isClassDeclaration = true, unit = unit ) } else if (type == "MethodDeclaration") { return Expression( MethodDeclaration.fromUnit(unit), isMethodDeclaration = true, unit = unit ); } else if (type == "BlockStatement") { return Expression( BlockStatement.fromUnit(unit), isBlockStatement = true, unit = unit ); } else if (type == "EmptyFunctionBody") { return Expression( EmptyFunctionBody.fromUnit(unit), isEmptyFunctionBody = true, unit = unit ); } else if (type == "InstanceCreationExpression") { return Expression( InstanceCreationExpression.fromUnit(unit), isInstanceCreationExpression = true, unit = unit ); } else if (type == "ReturnStatement") { return Expression( ReturnStatement.fromUnit(unit), isReturnStatement = true, unit = unit ); } else if (type == "PropertyAccess") { return Expression( PropertyAccess.fromUnit(unit), isPropertyAccess = true, unit = unit ) } else if (type == "FieldDeclaration") { return Expression( FieldDeclaration.fromUnit(unit), isFieldDeclaration = true, unit = unit ) } else if (type == "PropertyStatement") { return Expression( PropertyStatement.fromUnit(unit), isVariableDeclarationList = true, unit = unit ) } else if (type == "ConstantExpression") { return Expression( ConstantExpression.fromUnit(unit), unit = unit ) } else if (type == "INTEGER_CONSTANT") { return Expression( IntegerLiteral.fromUnit(unit), isIntegerLiteral = true, unit = unit ); } else if (type == "StringTemplateExpression") { return Expression( StringTemplateExpression.fromUnit(unit), isStringTemplateExpression = true, unit = unit ) } else if (type == "StringLiteral") { return Expression( StringTemplateExpression.fromUnit(unit), isStringLiteral = true, unit = unit ) } else if (type == "BOOLEAN_CONSTANT") { return Expression( BooleanLiteral.fromUnit(unit), isBooleanLiteral = true, unit = unit ) } else if (type == "BinaryExpression") { return Expression( BinaryExpression.fromUnit(unit), isBinaryExpression = true, unit = unit ) } else if (type == "Identifier") { return Expression( Identifier.fromUnit(unit), isReferenceExpression = true, isIdentifier = true, unit = unit ) } else if (type == "ImportDirective") { return Expression( ImportDirective.fromUnit(unit), isIdentifier = false, unit = unit ) } else if (type == "CallExpression") { return Expression( CallExpression.fromUnit(unit), isCallExpression = true, isIdentifier = false, unit = unit ) } else if (type == "MethodInvocation") { return Expression( MethodInvocation.fromUnit(unit), isMethodInvocation = true, isIdentifier = false, unit = unit ) } else if (type == "StringTemplateEntry") { return Expression( StringTemplateEntry.fromUnit(unit), isStringTemplateEntry = true, isMethodInvocation = false, isIdentifier = false, unit = unit ) } else if (type == "SecondaryConstructor") { return Expression( ConstructorDeclaration.fromUnit(unit), isConstructorDeclaration = true, unit = unit ) } else if (type == "Argument") { val isNamed = (unit["isNamed"] ?: false) as Boolean return Expression( Argument.fromUnit(unit), isNamedExpression = isNamed, unit = unit ); } else if (type == "Column") { val isNamed = (unit["isNamed"] ?: false) as Boolean return Expression( Argument.fromUnit(unit), isNamedExpression = isNamed, unit = unit ); } return Expression( ClassDeclaration.fromUnit(unit), unit = mapOf( "type" to "e" ) ) } } } class BlockStatement(body: List, unit: Map) : Node(unit) { var body: List? = null init { this.body = body } companion object { fun fromUnit(unit: Map): BlockStatement { if (unit["type"] != "BlockStatement") { parseError(unit) } val body = mutableListOf() if (unit["type"] == "BlockStatement") { if (unit["body"].isNotEmptyCollection()) { val items = unit["body"] as List> for (item in items) { body.add(Expression.fromUnit(item)) } } } return BlockStatement(body = body, unit) } } } class EmptyFunctionBody(unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): EmptyFunctionBody { if (unit["type"] != "EmptyFunctionBody") { parseError(unit) } return EmptyFunctionBody(unit) } } } class PropertyAccess : Node { var name: String? var targetExpression: Expression? var selectorExpression: Expression? var isCascaded: Boolean var isNullAware: Boolean constructor( name: String?, targetExpression: Expression?, selectorExpression: Expression?, isCascaded: Boolean, isNullAware: Boolean, unit: Map ) : super(unit) { this.name = name this.targetExpression = targetExpression this.selectorExpression = selectorExpression this.isCascaded = isCascaded this.isNullAware = isNullAware } companion object { fun fromUnit(unit: Map): PropertyAccess { if (unit["type"] == "PropertyAccess") { val targetExpression = unit["targetExpression"]?.let { Expression.fromUnit(it as Map) } val selectorExpression = unit["selectorExpression"]?.let { Expression.fromUnit(it as Map) } return PropertyAccess( ((unit["selectorExpression"] as Map)["target"] as Map)["name"] as String, // unit["name"] as String?, targetExpression, selectorExpression, unit["isCascaded"] as? Boolean ?: false, unit["isNullAware"] as? Boolean ?: false, unit ) } parseError(unit) } } } class FieldDeclaration( name: String, isStatic: Boolean, target: Expression?, unit: Map ) : Node(unit) { var target: Expression? = null var name: String var isStatic: Boolean = false init { this.target = target this.name = name this.isStatic = isStatic } companion object { fun fromUnit(unit: Map): FieldDeclaration { if (unit["type"] != "FieldDeclaration") { return parseError(unit) } var target: Expression? = null if (unit["initializer"] != null) { target = Expression.fromUnit(unit["initializer"] as Map); } return FieldDeclaration( unit["name"] as String, false, // unit["isStatic"] as Boolean, target = target, unit = unit ) } } } class PropertyStatement( name: String, isStatic: Boolean, target: Expression?, unit: Map ) : Node(unit) { var target: Expression? = null var name: String var isStatic: Boolean = false init { this.target = target this.name = name this.isStatic = isStatic } companion object { fun fromUnit(unit: Map): PropertyStatement { if (unit["type"] != "PropertyStatement") { parseError(unit) } var target: Expression? = null if (unit["type"] == "PropertyStatement") { if (unit["initializer"] != null) { target = Expression.fromUnit(unit["initializer"] as Map); } // if (unit["parameters"].isNotEmptyMap()) { // var argument: Expression? = null // if (unit["argument"] != null) { // argument = Expression.fromUnit(unit["parameters"] as Map); // } // return PropertyStatement(argument = argument, unit = unit) // } } return PropertyStatement( unit["name"] as String, false, // unit["isStatic"] as Boolean, target = target, unit = unit ) } } } class StringLiteral(value: String?, unit: Map) : Node(unit) { var value: String? = null init { this.value = value } companion object { fun fromUnit(unit: Map): StringLiteral { if (unit["type"] != "StringLiteral") { parseError(unit) } if (unit["type"] == "StringLiteral") { return StringLiteral(value = (unit["value"].toString()), unit = unit) } return StringLiteral(value = null, unit = unit) } } } class StringTemplateEntry(value: String?, unit: Map) : Node(unit) { var value: String? = null init { this.value = value } companion object { fun fromUnit(unit: Map): StringTemplateEntry { if (unit["type"] != "StringTemplateEntry") { parseError(unit) } if (unit["type"] == "StringTemplateEntry") { return StringTemplateEntry(value = (unit["value"].toString()), unit = unit) } return StringTemplateEntry(value = null, unit = unit) } } } class ConstructorName(name: String, typeName: String?, unit: Map) : Node(unit) { val name: String = name val typeName: String? = typeName companion object { fun fromUnit(unit: Map): ConstructorName { return ConstructorName( name = unit["name"] as String, typeName = unit["typeName"] as String, unit = unit ) } private fun parseError(unit: Map): Nothing { throw IllegalArgumentException("Parse error on unit: $unit") } } } class InstanceCreationExpression( constructorName: ConstructorName?, argumentList: ArgumentList?, children: List?, unit: Map ) : Node(unit) { var constructorName: ConstructorName? = null var children: List? = null var argumentList: ArgumentList? = null init { this.constructorName = constructorName this.children = children this.argumentList = argumentList } companion object { fun fromUnit(unit: Map): InstanceCreationExpression { if (unit["type"] != "InstanceCreationExpression") { return parseError(unit) } val name = unit["constructorName"] as String val children = mutableListOf() // 处理子元素 val childrenList = unit["children"] if (childrenList is List<*> && childrenList.isNotEmpty()) { // 遍历子元素列表 for (child in childrenList) { if (child is Map<*, *>) { @Suppress("UNCHECKED_CAST") // 将每个子元素转换为Expression val childExpr = Expression.fromUnit(child as Map) children.add(childExpr) } } } return InstanceCreationExpression( ConstructorName(name, name, unit), if (unit["argumentList"] == null) null else ArgumentList.fromUnit(unit["argumentList"] as Map), children, unit = unit ) } } } class StringTemplateExpression(target: Expression?, unit: Map) : Node(unit) { var target: Expression? = null init { this.target = target } companion object { fun fromUnit(unit: Map): StringTemplateExpression { if (unit["type"] != "StringTemplateExpression") { parseError(unit) } if (unit["type"] == "StringTemplateExpression") { var target: Expression? = null if (unit["body"] != null) { target = Expression.fromUnit(unit["body"] as Map) return StringTemplateExpression( target = target, unit = unit["body"] as Map ) } } return StringTemplateExpression(target = null, unit = unit) } } } class BinaryExpression( operator: String, left: Expression, right: Expression, unit: Map ) : Node(unit) { ///运算符 /// * + /// * - /// * * /// * / /// * < /// * > /// * <= /// * >= /// * == /// * && /// * || /// * % /// * << /// * | /// * & /// * >> /// val operator: String = operator ///左操作表达式 val left: Expression = left ///右操作表达式 val right: Expression = right companion object { fun fromUnit(unit: Map): BinaryExpression { if (unit["type"] != "BinaryExpression") { parseError(unit) } if (unit["type"] == "BinaryExpression") { // return BinaryExpression(unit = unit) } return BinaryExpression( unit["operator"] as String, Expression.fromUnit(unit["left"] as Map), Expression.fromUnit(unit["right"] as Map), unit = unit ) } } } class Identifier : Node { constructor(name: String, unit: Map) : super(unit) { this.name = name } var name: String companion object { fun fromUnit(unit: Map): Identifier { if (unit["type"] == "Identifier") { return Identifier( name = (unit["name"].toString()), unit = unit ) } parseError(unit) } fun isPrivateName(name: String): Boolean { return false } } } class BooleanLiteral(value: Boolean, unit: Map) : Node(unit) { var value: Boolean = false init { this.value = value } companion object { fun fromUnit(unit: Map): BooleanLiteral { if (unit["type"] != "BOOLEAN_CONSTANT") { parseError(unit) } if (unit["type"] == "BOOLEAN_CONSTANT") { return BooleanLiteral(value = (unit["value"].toString().toBoolean()), unit = unit) } return BooleanLiteral(value = false, unit = unit) } } } class IntegerLiteral(value: Int, unit: Map) : Node(unit) { var value: Int? = 0 init { this.value = value } companion object { fun fromUnit(unit: Map): IntegerLiteral { if (unit["type"] != "INTEGER_CONSTANT") { parseError(unit) } if (unit["type"] == "INTEGER_CONSTANT") { return IntegerLiteral(value = (unit["value"].toString().toInt()), unit = unit) } return IntegerLiteral(value = 0, unit = unit) } } } class ConstantExpression(unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): ConstantExpression { if (unit["type"] != "ConstantExpression") { parseError(unit) } if (unit["type"] == "ConstantExpression") { // if (unit["parameters"].isNotEmptyMap()) { // var argument: Expression? = null // if (unit["argument"] != null) { // argument = Expression.fromUnit(unit["parameters"] as Map); // } // return PropertyStatement(argument = argument, unit = unit) // } } return ConstantExpression(unit = unit) } } } class ReturnStatement(val argument: Expression?, unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): ReturnStatement { if (unit["type"] != "ReturnStatement") { parseError(unit) } if (unit["type"] == "ReturnStatement") { var argument: Expression? = null if (unit["argument"] != null) { argument = Expression.fromUnit(unit["argument"] as Map); } return ReturnStatement(argument = argument, unit = unit) } return ReturnStatement(null, unit = unit) } } } class ClassDeclaration(members: List, name: String, unit: Map) : Node(unit) { var name: String = "" var members: List? = null init { this.members = members this.name = name } companion object { fun fromUnit(unit: Map): ClassDeclaration { if (unit["type"] != "ClassDeclaration") { parseError(unit) } val members = mutableListOf() if (unit["type"] == "ClassDeclaration") { if (unit["members"] is List<*>) { val list = unit["members"] as List> for (member in list) { members.add(Expression.fromUnit(member)) } } } return ClassDeclaration(members = members, name = (unit["name"] ?: "") as String, unit) } } } class MethodDeclaration : Node { var parameters: FormalParameterList? var name: String var isStatic: Boolean var isSetter: Boolean var bodyExpression: Expression var isAsync: Boolean constructor( parameters: FormalParameterList?, name: String, isStatic: Boolean, isSetter: Boolean, bodyExpression: Expression, isAsync: Boolean, unit: Map ) : super(unit) { this.name = name this.isStatic = isStatic this.isSetter = isSetter this.parameters = parameters this.bodyExpression = bodyExpression this.isAsync = isAsync } companion object { fun fromUnit(unit: Map): Node { if (unit["type"] != "MethodDeclaration") { parseError(unit) } var parameters: FormalParameterList? = null; if (unit["parameters"].isNotEmptyCollection()) { val any = unit["parameters"] val map = mutableMapOf() map["type"] = "ParameterList" map["parameters"] = unit["parameters"] as Any parameters = FormalParameterList.fromUnit(map); } return MethodDeclaration( parameters = parameters, unit["name"] as String, unit["isStatic"] as Boolean, unit["isSetter"] as Boolean, bodyExpression = Expression.fromUnit(unit["body"] as Map), isAsync = false, unit = unit ) } } } class VariableDeclarator : Node { var name: String var typeName: String? var init: Expression? var isStatic: Boolean var isFinal: Boolean var isConst: Boolean var isLate: Boolean var isTopLevel: Boolean constructor( name: String, typeName: String?, init: Expression?, isStatic: Boolean, isFinal: Boolean, isConst: Boolean, isLate: Boolean, isTopLevel: Boolean, unit: Map ) : super(unit) { this.name = name this.typeName = typeName this.init = init this.isStatic = isStatic this.isFinal = isFinal this.isConst = isConst this.isLate = isLate this.isTopLevel = isTopLevel } companion object { fun fromUnit(unit: Map): VariableDeclarator { if (unit["type"] == "VariableDeclarator") { val init = unit["init"]?.let { Expression.fromUnit(it as Map) } val isStatic = unit["isStatic"] as? Boolean ?: false val isTopLevel = unit["isTopLevel"] as? Boolean ?: false return VariableDeclarator( Identifier.fromUnit(unit["id"] as Map).name, unit["typeName"] as? String, init, isStatic, unit["isFinal"] as? Boolean ?: false, unit["isConst"] as? Boolean ?: false, unit["isLate"] as? Boolean ?: false, isTopLevel, unit ) } return parseError(unit) } } } //class FunctionDeclaration( // name: String, // unit: Map //) : Node(unit) { // var name: String = "" // // init { // this.name = name // } // // companion object { // fun fromUnit(unit: Map): Node { // if (unit["type"] != "FunctionDeclaration") { // parseError(unit) // } // return FunctionDeclaration( // unit["name"] as String, // unit = unit // ) // } // } //} class FormalParameterList( val parameters: List, unit: Map ) : Node(unit) { init { parameters.forEach { becomeParentOf(it) } } companion object { fun fromUnit(unit: Map): FormalParameterList { if (unit["type"] == "ParameterList") { return FormalParameterList( (unit["parameters"] as List>) .map { FormalParameter.fromUnit(it) }, unit ) } parseError(unit) } } } abstract class FormalParameter(unit: Map) : Node(unit) { abstract val name: String abstract val typeName: String? abstract val isFinal: Boolean abstract val isNamed: Boolean abstract val isPositional: Boolean abstract val isOptional: Boolean abstract val isOptionalNamed: Boolean abstract val isOptionalPositional: Boolean abstract val isRequired: Boolean abstract val isRequiredNamed: Boolean abstract val isRequiredPositional: Boolean companion object { fun fromUnit(unit: Map): FormalParameter { return when (unit["type"]) { "SimpleFormalParameter" -> SimpleFormalParameter.fromUnit(unit) "DefaultFormalParameter" -> DefaultFormalParameter.fromUnit(unit) // "FieldFormalParameter" -> FieldFormalParameter.fromUnit(unit) else -> parseError(unit) } } } } class FieldFormalParameter( name: String, typeName: String?, isFinal: Boolean, isNamed: Boolean, isPositional: Boolean, isOptional: Boolean, isOptionalNamed: Boolean, isOptionalPositional: Boolean, isRequired: Boolean, isRequiredNamed: Boolean, isRequiredPositional: Boolean, val parameters: FormalParameterList?, unit: Map ) : SimpleFormalParameter( name, typeName, isFinal, isNamed, isPositional, isOptional, isOptionalNamed, isOptionalPositional, isRequired, isRequiredNamed, isRequiredPositional, unit ) { companion object { fun fromUnit(unit: Map): FieldFormalParameter { if (unit["type"] == "FieldFormalParameter") { val parameters = unit["parameters"]?.let { FormalParameterList.fromUnit(it as Map) } val typeName = unit["typeName"]?.let { TypeName.fromUnit(it as Map).name } return FieldFormalParameter( unit["name"] as String, typeName, unit["isFinal"] as Boolean, unit["isNamed"] as Boolean, unit["isPositional"] as Boolean, unit["isOptional"] as Boolean, unit["isOptionalNamed"] as Boolean, unit["isOptionalPositional"] as Boolean, unit["isRequired"] as Boolean, unit["isRequiredNamed"] as Boolean, unit["isRequiredPositional"] as Boolean, parameters, unit ) } parseError(unit) } } } abstract class NormalFormalParameter(unit: Map) : FormalParameter(unit) open class SimpleFormalParameter( val _name: String, val _typeName: String?, val _isFinal: Boolean, val _isNamed: Boolean, val _isPositional: Boolean, val _isOptional: Boolean, val _isOptionalNamed: Boolean, val _isOptionalPositional: Boolean, val _isRequired: Boolean, val _isRequiredNamed: Boolean, val _isRequiredPositional: Boolean, unit: Map ) : NormalFormalParameter(unit) { companion object { fun fromUnit(unit: Map): SimpleFormalParameter { if (unit["type"] == "SimpleFormalParameter") { val typeName = unit["typeName"] // val typeName = unit["typeName"]?.let { TypeName.fromUnit(it as Map).name } return SimpleFormalParameter( unit["name"] as String, (typeName ?: "").toString(), unit["isFinal"] as? Boolean ?: false, unit["isNamed"] as? Boolean ?: false, unit["isPositional"] as? Boolean ?: false, unit["isOptional"] as? Boolean ?: false, unit["isOptionalNamed"] as? Boolean ?: false, unit["isOptionalPositional"] as? Boolean ?: false, unit["isRequired"] as? Boolean ?: false, unit["isRequiredNamed"] as? Boolean ?: false, unit["isRequiredPositional"] as? Boolean ?: false, unit ) } parseError(unit) } } override val isFinal: Boolean get() = _isFinal override val isNamed: Boolean get() = _isNamed override val isOptional: Boolean get() = _isOptional override val isOptionalNamed: Boolean get() = _isOptionalNamed override val isOptionalPositional: Boolean get() = _isOptionalPositional override val isPositional: Boolean get() = _isPositional override val isRequired: Boolean get() = _isRequired override val isRequiredNamed: Boolean get() = _isRequiredNamed override val isRequiredPositional: Boolean get() = _isRequiredPositional override val name: String get() = _name override val typeName: String? get() = _typeName } class TypeName( name: String, typeArguments: TypeArgumentList?, unit: Map ) : NamedType(name, typeArguments, unit) { companion object { fun fromUnit(unit: Map): TypeName { if (unit["type"] == "TypeName") { val typeArguments = unit["typeArguments"]?.let { TypeArgumentList.fromUnit(it as Map) } return TypeName( unit["name"] as String, typeArguments, unit ) } parseError(unit) } } } class TypeArgumentList : Node { val arguments: List constructor(arguments: List, unit: Map) : super(unit) { this.arguments = arguments } companion object { fun fromUnit(unit: Map): TypeArgumentList { if (unit["type"] == "TypeArgumentList") { val arguments = unit["arguments"]?.let { if (it is List<*>) { it.mapNotNull { argument -> if (argument is Map<*, *>) { TypeAnnotation.fromUnit(argument as Map) } else { null } } } else { emptyList() } } ?: emptyList() return TypeArgumentList(arguments, unit) } parseError(unit) } } } abstract class NamedType( val name: String, val typeArguments: TypeArgumentList?, unit: Map ) : TypeAnnotation(unit) { init { becomeParentOf(typeArguments) } } abstract class TypeAnnotation(unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): TypeAnnotation { val type = unit["type"] return when (type) { "TypeName" -> TypeName.fromUnit(unit) // "GenericFunctionType" -> GenericFunctionType.fromUnit(unit) else -> parseError(unit) } } } } class DefaultFormalParameter( val parameter: FormalParameter, val defaultValue: Expression?, unit: Map ) : FormalParameter(unit) { init { becomeParentOf(parameter) becomeParentOf(defaultValue) } companion object { fun fromUnit(unit: Map): DefaultFormalParameter { if (unit["type"] == "DefaultFormalParameter") { val defaultValue = unit["defaultValue"]?.let { Expression.fromUnit(it as Map) } return DefaultFormalParameter( FormalParameter.fromUnit(unit["parameter"] as Map), defaultValue, unit ) } parseError(unit) } } override val isFinal: Boolean get() = parameter.isFinal override val isNamed: Boolean get() = parameter.isNamed override val isOptional: Boolean get() = parameter.isOptional override val isOptionalNamed: Boolean get() = parameter.isOptionalNamed override val isOptionalPositional: Boolean get() = parameter.isOptionalPositional override val isPositional: Boolean get() = parameter.isPositional override val isRequired: Boolean get() = parameter.isRequired override val isRequiredNamed: Boolean get() = parameter.isRequiredNamed override val isRequiredPositional: Boolean get() = parameter.isRequiredPositional override val name: String get() = parameter.name override val typeName: String? get() = parameter.typeName } class CompilationUnit(unit: Map) : Node(unit) { var declarations: List? = null var directives: List? = null // constructor( declarations: List, directives: List, unit: Map ) : this(unit) { this.declarations = declarations this.directives = directives } // 从单元数据创建CompilationUnit实例的工厂方法 companion object { fun fromUnit(unit: Map): CompilationUnit { if (unit["type"] != "CompilationUnit") { parseError(unit) } val declarations = unit["declarations"]?.let { it as? List> } ?.map { Expression.fromUnit(it) } ?: emptyList() val directives = unit["directives"]?.let { it as? List> } ?.map { Directive.fromUnit(it) } ?: emptyList() return CompilationUnit(declarations, directives, unit) } } } class ImportDirective : NamespaceDirective { var refix: String? var name: String private constructor(uri: String, prefix: String?, name: String, unit: Map) : super( uri, unit ) { this.refix = prefix; this.name = name } companion object { fun fromUnit(unit: Map): ImportDirective { if (unit["type"] == "ImportDirective") { // val combinators = (unit["combinators"] as List>).map { Combinator.fromUnit(it as Map) } val prefix = unit["alias"] return ImportDirective( unit["importPath"] as String, prefix as String?, unit["name"] as String, unit ) } parseError(unit) } } } class CallExpression : Node { val methodName: String val target: Expression? val argumentList: ArgumentList val isCascaded: Boolean val isNullAware: Boolean private constructor( methodName: String, target: Expression?, argumentList: ArgumentList, isCascaded: Boolean, isNullAware: Boolean, unit: Map ) : super(unit) { this.methodName = methodName this.target = target this.argumentList = argumentList this.isCascaded = isCascaded this.isNullAware = isNullAware becomeParentOf(target) becomeParentOf(argumentList) } companion object { fun fromUnit(unit: Map): CallExpression { if (unit["type"] == "CallExpression") { val target = unit["target"]?.let { Expression.fromUnit(it as Map) } return CallExpression( Identifier.fromUnit(unit["methodName"] as Map).name, target, ArgumentList.fromUnit(unit["argumentList"] as Map), unit["isCascaded"] as? Boolean ?: false, unit["isNullAware"] as? Boolean ?: false, unit ) } parseError(unit) } } } class MethodInvocation : Node { val methodName: Identifier? var isStatic: Boolean = true var isSetter: Boolean = false val target: Expression? val argumentList: ArgumentList? val isCascaded: Boolean val isNullAware: Boolean private constructor( methodName: Identifier, target: Expression?, argumentList: ArgumentList?, isCascaded: Boolean, isNullAware: Boolean, unit: Map ) : super(unit) { this.methodName = methodName this.target = target this.argumentList = argumentList this.isCascaded = isCascaded this.isNullAware = isNullAware becomeParentOf(target) becomeParentOf(argumentList) } companion object { fun fromUnit(unit: Map): MethodInvocation { if (unit["type"] == "MethodInvocation") { val target = unit["target"]?.let { Expression.fromUnit(it as Map) } return MethodInvocation( // if ((unit["methodName"] as Map)["target"] == null) "" else ((unit["methodName"] as Map)["target"] as Map)["name"] as String, Identifier.fromUnit(unit["methodName"] as Map), target, if ((unit["methodName"] as Map)["argumentList"] == null) null else ArgumentList.fromUnit( (unit["methodName"] as Map)["argumentList"] as Map ), unit["isCascaded"] as? Boolean ?: false, unit["isNullAware"] as? Boolean ?: false, unit ) } parseError(unit) } } } class Argument : Node { var name: String? = null var isNamed: Boolean? = false var argument: Expression? = null private constructor( name: String?, isNamed: Boolean, argument: Expression, unit: Map ) : super(unit) { this.name = name this.isNamed = isNamed this.argument = argument } companion object { fun fromUnit(unit: Map): Argument { if (unit["type"] == "Argument") { val isNamed = (unit["isNamed"] ?: false) as Boolean val name = (unit["name"] ?: false) as String val argument = Expression.fromUnit(unit["body"] as Map) return Argument(name, isNamed, argument, unit) } parseError(unit) } } } class ArgumentList : Node { var arguments: List private constructor( arguments: List, unit: Map ) : super(unit) { this.arguments = arguments arguments?.forEach { becomeParentOf(it) } } companion object { fun fromUnit(unit: Map): ArgumentList { if (unit["type"] == "ArgumentList") { val arguments = (unit["arguments"] as List>).map { Expression.fromUnit(it as Map) } return ArgumentList(arguments, unit) } parseError(unit) } } } abstract class Combinator(unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): Combinator { val type = unit["type"] return when (type) { "HideCombinator" -> HideCombinator.fromUnit(unit) "ShowCombinator" -> ShowCombinator.fromUnit(unit) else -> parseError(unit) } } } } class ShowCombinator : Combinator { var shownNames: List private constructor(shownNames: List, unit: Map) : super(unit) { this.shownNames = shownNames shownNames.forEach { becomeParentOf(it) } } companion object { fun fromUnit(unit: Map): ShowCombinator { if (unit["type"] == "ShowCombinator") { val shownNames = (unit["shownNames"] as List>).map { Identifier.fromUnit(it as Map) } return ShowCombinator(shownNames, unit) } parseError(unit) } } } class HideCombinator : Combinator { var hiddenNames: List constructor(hiddenNames: List, unit: Map) : super(unit) { this.hiddenNames = hiddenNames hiddenNames.forEach { becomeParentOf(it) } } companion object { fun fromUnit(unit: Map): HideCombinator { if (unit["type"] == "HideCombinator") { val hiddenNames = (unit["hiddenNames"] as List>).map { Identifier.fromUnit(it as Map) } return HideCombinator(hiddenNames, unit) } parseError(unit) } } } abstract class NamespaceDirective : UriBasedDirective { constructor( uri: String, unit: Map ) : super(uri, unit) { this.uri = uri } } abstract class UriBasedDirective : Directive { var uri: String constructor( uri: String, unit: Map ) : super(unit) { this.uri = uri } } abstract class Directive(unit: Map) : Node(unit) { companion object { fun fromUnit(unit: Map): Directive { val type = unit["type"] return when (type) { "ImportDirective" -> ImportDirective.fromUnit(unit) // "PartDirective" -> PartDirective.fromUnit(unit) // "PartOfDirective" -> PartOfDirective.fromUnit(unit) // "ExportDirective" -> ExportDirective.fromUnit(unit) else -> parseError(unit) } } } } fun Any?.isNotEmptyCollection(): Boolean = this != null && this is Collection<*> && this.isNotEmpty() fun Any?.isNotEmptyMap(): Boolean = this != null && this is Map<*, *> && this.isNotEmpty() ================================================ FILE: core/src/main/java/com/aether/core/runtime/ProgramStack.kt ================================================ package com.aether.core.runtime typealias LazilyInitializer = () -> Any? class Variable( private var _value: Any?, val name: String, val isFinal: Boolean = false, val isStatic: Boolean = false, val isConst: Boolean = false, val isLate: Boolean = false ) { private var isInitialized = if (isLate && _value == null) false else true var value: kotlin.Any? get() { if (isLate && !isInitialized) { _value = (_value as LazilyInitializer).invoke() as Any? isInitialized = true } return _value!! } set(data) { value = data } // constructor(name: String, initializer: LazilyInitializer, isLate: Boolean = true) : this(null, name, isLate = isLate) { // this._value = initializer // } operator fun plus(other: Any?): Any? { return when (other) { is Variable ->{ val thisValue = value as? Comparable<*> val otherValue = other.value if (thisValue != null && otherValue != null) { thisValue.compareTo(otherValue as Nothing) } else { 0 } } is Number -> { val thisValue = value as? Number if (thisValue != null) { thisValue.toDouble() + other.toDouble() } else { null // or throw an exception if you prefer } } else -> null } } // Implement other operators similarly... override fun toString(): String { return "[Variable $value]" } override fun equals(other: kotlin.Any?): Boolean { if (this === other) return true if (other !is Variable) return false return value == other.value } override fun hashCode(): Int { return value?.hashCode() ?: 0 } } class StackScope(val name: String? = null) { private val frame = mutableMapOf() operator fun contains(key: String): Boolean = frame.containsKey(key) operator fun get(key: String): Any? = frame[key] operator fun set(key: String, value: Any?) { frame[key] = value } override fun toString(): String { return "[$name]: $frame" } } class ProgramStack(val name: String, oldStack: ProgramStack? = null) { val frames: MutableList = oldStack?.frames?.toMutableList() ?: mutableListOf() init { if (oldStack == null) { push(name = "root scope:$name") } } fun isRoot(): Boolean { return frames.size == 1 && frames.single().name == "root scope:$name" } fun length(): Int = frames.size fun push(scope: StackScope? = null, name: String? = null) { frames.add(scope ?: StackScope(name)) } fun pop(): StackScope? = frames.removeLastOrNull() fun putVariable(name: String, value: Any?) { frames.last()[name] = Variable(value, name) } fun getVariable(name: String): Variable? { return get(name) } fun putLazilyVariable(name: String, initializer: LazilyInitializer) { frames.last()[name] = Variable(_value = initializer,name = name)//todo initializer } fun put(name: String, value: Any?) { frames.last()[name] = value } inline fun get(name: String): T? { for (i in frames.indices.reversed()) { val curFrame = frames[i] if (curFrame.contains(name) && curFrame[name] is T) { @Suppress("UNCHECKED_CAST") return curFrame[name] as T } } return null } override fun toString(): String { return "Program Stack ($name)\n${frames.joinToString("\n")}" } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/ProjectHelper.kt ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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.aether.core.runtime import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.CompilerConfiguration /** * Helper that creates or uses a provided Project for psi operations. For example, finding the * PsiManager. */ object ProjectHelper { private var overriddenProject: Project? = null private val kotlinCoreEnvironment: KotlinCoreEnvironment by lazy { createCoreEnvironment() } fun getProject(): Project { return overriddenProject ?: kotlinCoreEnvironment.project } fun setProjectOverride(project: Project) { this.overriddenProject = project } private fun createCoreEnvironment(): KotlinCoreEnvironment { val disposable = Disposer.newDisposable() return KotlinCoreEnvironment.createForProduction( disposable, getConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES) } fun getConfiguration(): CompilerConfiguration { val configuration = CompilerConfiguration() configuration.put( CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false)) return configuration } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/Structs.kt ================================================ package com.aether.core.runtime import android.text.TextUtils import com.aether.core.runtime.AppContextManager.context import com.aether.core.runtime.proxy.ProxyBinding import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeComponentDescriptor2 import com.aether.core.runtime.reflectable.ComposeMirror import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.MethodMirror import org.w3c.dom.Text import kotlin.reflect.KFunction interface Present interface AstDeclaration : Present { abstract val simpleName: String abstract val qualifiedName: String abstract val owner: AstDeclaration? abstract val isPrivate: Boolean abstract val programNode: AstRuntime.ProgramNode? } interface AstObject : Present { abstract fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? = null ): Any? abstract fun invokeGetter(getterName: String): Any? abstract fun hasGetter(getterName: String): Boolean abstract fun invokeSetter(setterName: String, value: Any?): Any? abstract fun hasSetter(setterName: String): Boolean abstract fun hasRegularMethod(methodName: String): Boolean } abstract class AstType : AstDeclaration abstract class AstClass : AstType(), AstObject { abstract val superclass: AstClass? abstract val isAbstract: Boolean abstract val declarations: Map abstract val instanceFields: Map abstract val instanceGetters: Map abstract val instanceSetters: Map abstract val staticFields: Map abstract val staticGetters: Map abstract val staticSetters: Map abstract fun newInstance( constructorName: String, positionalArguments: List, namedArguments: Map? = null ): Any? abstract fun isSubclassOf(other: AstClass): Boolean abstract fun hasConstructor(constructorName: String): Boolean companion object { fun fromClass( declaration: ClassDeclaration, programNode: AstRuntime.ProgramNode ): AstClass { // 实现逻辑 return _ClassImpl.fromClass(declaration, programNode) } fun fromMirror(mirror: ComposeReflector, programNode: AstRuntime.ProgramNode): AstClass { // 实现逻辑 return _ClassMirror.fromMirror(mirror, programNode); } fun forName(className: String): AstClass? { val runtime = context.get(AstRuntime::class.java) ?: return null val clazz = runtime.getClass(className) if (clazz != null) return clazz //TODO 这里可以直接去加载反射的类。 val importDirective = runtime.getReflectClass(className) var mirror: ComposeReflector? = ProxyBinding.instance?.getProxyClassForName2(importDirective?.uri ?: "") if (mirror == null) { mirror = ProxyBinding.instance?.getProxyClassForName2(importDirective?.uri ?: "") } if (mirror != null) { return fromMirror(mirror, runtime._program) } return null } } } class _VariableImpl( name: String, typeName: String?, private val _initializer: Expression?, isPrivate: Boolean, isTopLevel: Boolean, isStatic: Boolean, isConst: Boolean, isFinal: Boolean ) : _VariableBase( name, typeName, isPrivate, isTopLevel, isStatic, isFinal, isConst ) { val initializer: Expression? get() = _initializer companion object { fun fromDeclarator( name: String, typeName: String?, _initializer: Expression?, isPrivate: Boolean = false, isTopLevel: Boolean = false, isStatic: Boolean = false, isConst: Boolean = false, isFinal: Boolean = false ): _VariableImpl { return _VariableImpl( name, typeName, _initializer, isPrivate, isTopLevel, isStatic, isConst, isFinal ) } // fun fromDeclarator(declarator: VariableDeclarator): _VariableImpl { // return _VariableImpl( // declarator.name, // declarator.typeName, // declarator.init, // Identifier.isPrivateName(declarator.name), // declarator.isTopLevel, // declarator.isStatic, // declarator.isConst, // declarator.isFinal // ) // } } } class _ClassImpl( private val _name: String, override val superclass: AstClass?, private val _staticFields: Map, private val _staticGetters: Map, private val _staticSetters: Map, val _instanceFields: Map, val _instanceGetters: Map, val _instanceSetters: Map, private val _constructors: Map, private val _node: ClassDeclaration, override val programNode: AstRuntime.ProgramNode ) : AstClass() { public lateinit var _classScope: StackScope public lateinit var runtime: AstRuntime init { val programStack = context.get(ProgramStack::class.java)!! val classScope = StackScope("$simpleName").apply { set("node", _node) } programStack.push(scope = classScope) _staticFields.values.forEach { staticField -> programStack.putLazilyVariable(staticField.simpleName) { staticField.initializer?.let { programStack.push(name = "Static field initializer") val result = executeExpression(it) programStack.pop() result } } } _staticGetters.values.forEach { method -> programStack.put(method.simpleName, method) } _classScope = programStack.pop()!! runtime = context.get(AstRuntime::class.java)!! } override val simpleName: String get() = _name override val qualifiedName: String get() = _name override val owner: AstDeclaration? get() = TODO("Not yet implemented") override val declarations: Map get() = throw NotImplementedError() override val instanceFields: Map get() = _instanceFields private var _inheritedGetters: Map? = null override val instanceGetters: Map get() { _inheritedGetters?.let { return mapOf(*_instanceGetters.toList().toTypedArray(), *it.toList().toTypedArray()) } val result = mutableMapOf().apply { superclass?.instanceGetters?.let { putAll(it) } } _inheritedGetters = result.toMap() return _instanceGetters } private var _inheritedSetters: Map? = null override val instanceSetters: Map get() { _inheritedSetters?.let { return mapOf(*_instanceSetters.toList().toTypedArray(), *it.toList().toTypedArray()) } val result = mutableMapOf().apply { superclass?.instanceSetters?.let { putAll(it) } } _inheritedSetters = result.toMap() return _instanceSetters } override val staticFields: Map get() = _staticFields override val staticGetters: Map get() = _staticGetters override val staticSetters: Map get() = _staticSetters override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { val method = _staticGetters[memberName] ?: throw NoSuchMethodError() return context.run( name = "Static invoke", overrides = mapOf( AstRuntime.ProgramNode::class.java to { programNode } ), body = { val programStack = context.get(ProgramStack::class.java)!! programStack.push(scope = _classScope) val result = AstMethod.apply2(method, positionalArguments, namedArguments) programStack.pop() (result as? Variable)?.value ?: result } ) } override fun invokeGetter(getterName: String): Any? { val programStack = context.get(ProgramStack::class.java)!! return try { programStack.push(scope = _classScope) context.run( name = "Static invokeGetter", overrides = mapOf(AstRuntime.ProgramNode::class.java to { programNode }), body = { _invokeGetter(getterName) } ) } finally { programStack.pop() } } private fun _invokeGetter(getterName: String): Any? { val programStack = context.get(ProgramStack::class.java)!! return _staticGetters[getterName]?.let { AstMethod.apply2(it, emptyList(), mutableMapOf()) } ?: _staticFields[getterName]?.let { programStack.getVariable(it.simpleName)?.value } ?: throw NoSuchMethodError("getterName=$getterName") } override fun invokeSetter(setterName: String, value: Any?): Any? { val programStack = context.get(ProgramStack::class.java)!! return try { programStack.push(scope = _classScope) context.run( name = "Static invokeSetter", overrides = mapOf(AstRuntime.ProgramNode::class.java to { programNode }), body = { _invokeSetter(setterName, value) } ) } finally { programStack.pop() } } override fun hasSetter(setterName: String): Boolean { return _staticSetters.containsKey(setterName) || _staticFields.containsKey(setterName) } private fun _invokeSetter(setterName: String, value: Any?): Any? { val programStack = context.get(ProgramStack::class.java)!! return _staticSetters[setterName]?.let { AstMethod.apply2(it, listOf(value), mapOf()) } ?: _staticFields[setterName]?.let { val variable = programStack.getVariable(it.simpleName) if (variable != null) { variable?.value = value return null; } } ?: throw NoSuchMethodError("setterName=$setterName") } override val isAbstract: Boolean get() = throw NotImplementedError() override val isPrivate: Boolean get() = throw NotImplementedError() override fun isSubclassOf(other: AstClass): Boolean { throw NotImplementedError() } override fun newInstance( constructorName: String, positionalArguments: List, namedArguments: Map? ): Any? { return context.run( name = "Constructor scope", body = { val constructor = _constructors[constructorName] ?: throw NoSuchMethodError() val programStack = context.get(ProgramStack::class.java)!! programStack.push(scope = _classScope) programStack.push(name = "Instance scope") instanceFields.values.forEach { variable -> val value = (variable as? _VariableImpl)?.initializer?.let { executeExpression(it) } programStack.putVariable(variable.simpleName, value) } instanceGetters.values.forEach { method -> programStack.put(method.simpleName, method) } val instanceScope = programStack.pop()!! lateinit var instance: _InstanceImpl _MethodImpl.readyForScopedInvoke( constructor.parameters, positionalArguments, namedArguments ) { args, namedArgs -> programStack.push(scope = instanceScope) constructor.parameters.forEachIndexed { i, param -> if (param.isField) { val field = _instanceFields[param.simpleName]!! val value = if (param.isNamed) namedArgs?.get(param.simpleName) else args[i]//param.simpleName 临时加的 programStack.putVariable( param.simpleName, value?.takeIf { field.typeName == "double" }) } } programStack.pop() instance = _InstanceImpl.build(this@_ClassImpl, instanceScope) superclass?.let { // Superclass initialization logic } programStack.push(scope = instanceScope) programStack.push(name = "Constructor body scope") val result = context.run( name = "Constructor body scope", overrides = mapOf(ThisReference::class.java to { ThisReference(instance) } ), body = { executeExpression(constructor.body) } ) programStack.pop() programStack.pop() result } instance }, overrides = mapOf( ProgramStack::class.java to { runtime.programStack }, AstRuntime::class.java to { runtime }) ) } override fun hasConstructor(constructorName: String): Boolean { return _constructors.containsKey(constructorName) } override fun hasGetter(getterName: String): Boolean { throw NotImplementedError() } override fun hasRegularMethod(methodName: String): Boolean { throw NotImplementedError() } companion object { fun fromClass( declaration: ClassDeclaration, programNode: AstRuntime.ProgramNode ): _ClassImpl { val staticFields = mutableMapOf() val staticGetters = mutableMapOf() val staticSetters = mutableMapOf() val instanceFields = mutableMapOf() val instanceGetters = mutableMapOf() val instanceSetters = mutableMapOf() val constructors = mutableMapOf() // val superclass = declaration.extendsClause?.let { // val superclassName = it.superclass // AstClass.forName(superclassName) ?: throw IllegalStateException("Unable to determine superclass: $superclassName") // } // // val mixins = mutableListOf().apply { // declaration.withClause?.mixinTypes?.forEach { mixinType -> // add(AstClass.forName(mixinType) ?: throw IllegalStateException("Unable to determine mixin: $mixinType")) // } // } declaration.members?.forEach { member -> when { member.isClassDeclaration -> { member.asClassDeclaration.members?.forEach { when { it.isMethodDeclaration -> { val method = it.asMethodExpression if (method.isStatic) { if (method.isSetter) { staticSetters[method.name] = _MethodImpl.fromMethod(method); } else { staticGetters[method.name] = _MethodImpl.fromMethod(method); } } when { // method.isSetter -> setters[method.name] = _MethodImpl.fromMethod(method) // else -> getters[method.name] = _MethodImpl.fromMethod(method) } } } } } member.isMethodDeclaration -> { val method = member.asMethodExpression if (method.isStatic) { if (method.isSetter) { staticSetters[method.name] = _MethodImpl.fromMethod(method); } else { staticGetters[method.name] = _MethodImpl.fromMethod(method); } } else { if (method.isSetter) { instanceSetters[method.name] = _MethodImpl.fromMethod(method); } else { instanceGetters[method.name] = _MethodImpl.fromMethod(method); } } } member.isConstructorDeclaration -> { val constructor = member.asConstructorDeclaration constructors[constructor.name] = _ConstructorImpl.fromConstructor(constructor) } member.isFieldDeclaration -> { val field = member.asFieldDeclaration instanceFields[field.name] = _VariableImpl.fromDeclarator( name = field.name, typeName = field.name, _initializer = field.target ) // if (field) // // fields.fields.declarationList.forEach { declarator -> // val targetMap = // if (fields.isStatic) staticFields else instanceFields // targetMap[declarator.name] = // _VariableImpl.fromDeclarator(declarator) // } } } // it.asClassDeclaration.members[0] } // declaration.members[0].asClassDeclaration.members[0] declaration.members?.forEach { member -> when { // member.isConstructorDeclaration -> { // val constructor = member.asConstructorDeclaration // constructors[constructor.name] = _ConstructorImpl.fromConstructor(constructor) // } // member.isFieldDeclaration -> { // val fields = member.asFieldDeclaration // fields.fields.declarationList.forEach { declarator -> // val targetMap = if (fields.isStatic) staticFields else instanceFields // targetMap[declarator.name] = _VariableImpl.fromDeclarator(declarator) // } // } // member.isMethodDeclaration -> { // val method = member.asMethodDeclaration // val (getters, setters) = when (method.isStatic) { // true -> staticGetters to staticSetters // false -> instanceGetters to instanceSetters // } // // when { // method.isSetter -> setters[method.name] = _MethodImpl.fromMethod(method) // else -> getters[method.name] = _MethodImpl.fromMethod(method) // } // } } } if (constructors.isEmpty()) { constructors[""] = _ConstructorImpl.defaultConstructor() } return _ClassImpl( _name = declaration.name, superclass = null, _staticFields = staticFields, _staticGetters = staticGetters, _staticSetters = staticSetters, _instanceFields = instanceFields, _instanceGetters = instanceGetters, _instanceSetters = instanceSetters, _constructors = constructors, _node = declaration, programNode = programNode, ) } } } class _InstanceImpl( private val _type: _ClassImpl, private val _instanceScope: StackScope ) : AstObject, AstInstance() { var ancestor: AstInstance? = null private set private val _behaviors = mutableListOf() init { // 初始化逻辑(如有需要) } override val type: _ClassImpl get() = _type override fun invoke( methodName: String, positionalArguments: List, namedArguments: Map? ): Any? { return context.run( name = "Instance scope", overrides = mapOf( ThisReference::class.java to { ThisReference(this) }, SuperReference::class.java to { SuperReference(ancestor) }, ProgramStack::class.java to { _type.runtime.programStack }, AstRuntime::class.java to { _type.runtime }, AstRuntime.ProgramNode::class.java to { _type.programNode } ), body = { val programStack = context.get(ProgramStack::class.java) val method = _type._instanceGetters[methodName] method?.let { programStack?.push(scope = _type._classScope) programStack?.push(scope = _instanceScope) val result = _MethodImpl.readyForScopedInvoke( it.parameters, positionalArguments, namedArguments ) { args, namedArgs -> val scope = StackScope("$methodName").apply { it.body.expression?.parent?.let { parent -> set("node", parent) } } programStack?.push(scope = scope) val executeResult = executeExpression(it.body) programStack?.pop() (executeResult as? Variable)?.value ?: executeResult } programStack?.pop() programStack?.pop() return@run result } ancestor?.takeIf { it.hasGetter(methodName) }?.let { return@run it.invoke(methodName, positionalArguments, namedArguments) } throw NoSuchMethodError("NoSuchMethodError: $methodName") } ) } override fun invokeGetter(getterName: String): Any? { return context.run( name = "Instance scope", overrides = mapOf( ThisReference::class.java to { ThisReference(this) }, SuperReference::class.java to { SuperReference(ancestor) }, ProgramStack::class.java to { _type.runtime.programStack }, AstRuntime::class.java to { _type.runtime }, AstRuntime.ProgramNode::class.java to { _type.programNode } ), body = { val programStack = context.get(ProgramStack::class.java) return@run try { programStack?.push(scope = _type._classScope) programStack?.push(scope = _instanceScope) _invokeGetter(getterName).let { (it as? Variable)?.value ?: it } } finally { programStack?.pop() programStack?.pop() } } ) } private fun _invokeGetter(getterName: String): Any? { val programStack = context.get(ProgramStack::class.java)!! _type._instanceGetters[getterName]?.takeIf { it.isGetter }?.let { method -> return _MethodImpl.readyForScopedInvoke( method.parameters, emptyList(), null ) { _, _ -> programStack.push(name = "Invoke getter $getterName") val result = executeExpression(method.body) programStack.pop() result } } _type._instanceFields[getterName]?.let { field -> return programStack.getVariable(field.simpleName) } ancestor?.takeIf { it.hasGetter(getterName) }?.let { return it.invokeGetter(getterName) } throw NoSuchMethodError("getterName=$getterName") } override fun invokeSetter(setterName: String, value: Any?): Any? { return context.run( name = "Instance scope", overrides = mapOf( ThisReference::class.java to { ThisReference(this) }, SuperReference::class.java to { SuperReference(ancestor) }, ProgramStack::class.java to { _type.runtime.programStack }, AstRuntime::class.java to { _type.runtime }, AstRuntime.ProgramNode::class.java to { _type.programNode } ), body = { val programStack = context.get(ProgramStack::class.java)!! return@run try { programStack.push(scope = _type._classScope) programStack.push(scope = _instanceScope) _invokeSetter(setterName, value) } finally { programStack.pop() programStack.pop() } } ) } override fun hasSetter(setterName: String): Boolean { return _type.instanceSetters.containsKey(setterName) || _type.instanceFields.containsKey(setterName) } private fun _invokeSetter(setterName: String, value: Any?): Any? { val programStack = context.get(ProgramStack::class.java)!! _type._instanceSetters[setterName]?.takeIf { it.isSetter }?.let { method -> return _MethodImpl.readyForScopedInvoke( method.parameters, listOf(value), null ) { _, _ -> programStack.push(name = "Invoke setter $setterName") val result = executeExpression(method.body) programStack.pop() result } } _type._instanceFields[setterName]?.let { field -> programStack.getVariable(field.simpleName)?.apply { this.value = value } return null } ancestor?.takeIf { it.hasSetter(setterName) }?.let { return it.invokeSetter(setterName, value) } throw NoSuchMethodError("setterName=$setterName") } override fun hasGetter(getterName: String): Boolean { return _type.instanceGetters.containsKey(getterName) || _type.instanceFields.containsKey(getterName) } override fun hasRegularMethod(methodName: String): Boolean { return _type.instanceGetters[methodName]?.isRegularMethod ?: false } companion object { fun build(type: _ClassImpl, scope: StackScope): _InstanceImpl { return _InstanceImpl(type, scope) } } } class _ConstructorImpl( name: String, body: Expression, parameters: List<_ParameterImpl>, isAbstract: Boolean, isSynthetic: Boolean, isGetter: Boolean, isSetter: Boolean, isStatic: Boolean, isPrivate: Boolean, isOperator: Boolean, isConstructor: Boolean, val isConstConstructor: Boolean, val isFactoryConstructor: Boolean, val isRedirectingConstructor: Boolean, val initializers: List ) : _MethodBase( _name = name, _body = body, _isAbstract = isAbstract, _isSynthetic = isSynthetic, // _isExternal = false, _parameters = parameters, // _isGetter = isGetter, // _isSetter = isSetter, _isStatic = isStatic, // _isPrivate = isPrivate, _isOperator = isOperator, _isConstructor = isConstructor ) { companion object { fun defaultConstructor(): _ConstructorImpl { return _ConstructorImpl( name = "", body = Expression.fromUnit(mapOf("type" to "EmptyFunctionBody")), parameters = emptyList(), isAbstract = false, isSynthetic = true, isGetter = false, isSetter = false, isStatic = false, isPrivate = false, isOperator = false, isConstructor = true, isConstConstructor = false, isFactoryConstructor = false, isRedirectingConstructor = false, initializers = emptyList() ) } fun fromConstructor(declaration: ConstructorDeclaration): _ConstructorImpl { val parameters = declaration.parameters.parameters.map { _ParameterImpl.fromParameter(it as FormalParameter) }.toList() return _ConstructorImpl( name = declaration.name, body = declaration.body, parameters = parameters, isAbstract = false, isSynthetic = false, isGetter = false, isSetter = false, isStatic = false, isPrivate = Identifier.isPrivateName(declaration.name), isOperator = false, isConstructor = true, isConstConstructor = declaration.isConstConstructor, isFactoryConstructor = declaration.isFactoryConstructor, isRedirectingConstructor = declaration.isRedirectingConstructor, initializers = declaration.initializers ) } } } class InstanceMirror(val composeReflector: ComposeReflector) : AstInstance() { override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { val mergedArgs = namedArguments?.toMutableMap() mergedArgs?.put("attribute",memberName) return ComposeComponentDescriptor(this.composeReflector.qualifiedName,positionalArguments,mergedArgs,null) } override fun invokeGetter(getterName: String): Any? { TODO("Not yet implemented") } override fun hasGetter(getterName: String): Boolean { TODO("Not yet implemented") } override fun invokeSetter(setterName: String, value: Any?): Any? { TODO("Not yet implemented") } override fun hasSetter(setterName: String): Boolean { TODO("Not yet implemented") } override fun hasRegularMethod(methodName: String): Boolean { TODO("Not yet implemented") } override val type: AstClass get() = TODO("Not yet implemented") } abstract class AstInstance : AstObject { abstract val type: AstClass companion object { private fun fromMirror(composeReflector: ComposeReflector): AstInstance? { return InstanceMirror(composeReflector) } fun forObject(obj: Any?, proxy: Boolean = true): AstInstance? { if (obj == null) return null if (obj is AstInstance) return obj if (obj is ComposeComponentDescriptor2) { return ComposeMirror.getReflector(obj.methodMirror?.qualifiedName ?: "") ?.let { AstInstance.fromMirror(it) } } return null } } } class ConstructorDeclaration( val name: String, val parameters: FormalParameterList, val initializers: List, val body: Expression, val isConstConstructor: Boolean, val isFactoryConstructor: Boolean, val isRedirectingConstructor: Boolean, unit: Map ) : Node(unit) { init { parameters.parent = this body.parent = this } companion object { fun fromUnit(unit: Map): ConstructorDeclaration { if (unit["type"] != "SecondaryConstructor") { parseError(unit) } val name = unit["name"] ?: "" // val name = unit["name"]?.let { // Identifier.fromUnit(it as Map).name // } ?: "" val initializers = (unit["initializers"] as? List>)?.map { Expression.fromUnit(it) }?.toList() ?: emptyList() val emptyUnit = mutableMapOf() emptyUnit["type"] = "EmptyFunctionBody" return ConstructorDeclaration( name = name as String, parameters = FormalParameterList.fromUnit( unit["parameters"] as Map ), initializers = initializers, body = if (unit["body"] != null) Expression.fromUnit(unit["body"] as Map) else Expression( EmptyFunctionBody.fromUnit(emptyUnit), isEmptyFunctionBody = true, unit = unit ), isConstConstructor = unit["isConstConstructor"] as? Boolean ?: false, isFactoryConstructor = unit["isFactoryConstructor"] as? Boolean ?: false, isRedirectingConstructor = unit["isRedirectingConstructor"] as? Boolean ?: false, unit = unit ) } } } abstract class AstVariable : AstDeclaration { abstract val type: AstType abstract override val isPrivate: Boolean abstract val isTopLevel: Boolean abstract val isStatic: Boolean abstract val isFinal: Boolean abstract val isConst: Boolean companion object { inline fun fromDeclarator(declarator: VariableDeclarator): T { // 实现逻辑 TODO("Not yet implemented") } // inline fun fromMirror(mirror: VariableMirrorBase): T { // // 实现逻辑 // TODO("Not yet implemented") // } // // fun applyTopLevelVariable(variable: AstVariable) { // val programStack = context.get() ?: return // programStack.putLazilyVariable(variable.simpleName) { // if (variable is _VariableImpl && variable.initializer != null) { // val result = executeExpression(variable.initializer!!) // result // } else { // null // } // } // } } } abstract class AstParameter : AstVariable() { abstract val isOptional: Boolean abstract val isNamed: Boolean abstract val hasDefaultValue: Boolean abstract val defaultValue: Any? companion object { // inline fun fromParameter(parameter: FormalParameter): T { // // 实现逻辑 // TODO("Not yet implemented") // } // // inline fun fromMirror(mirror: ParameterMirror): T { // // 实现逻辑 // TODO("Not yet implemented") // } } } interface AstMethod : AstDeclaration { val returnType: AstType val parameters: List<_ParameterImpl> val isStatic: Boolean val isAbstract: Boolean val isSynthetic: Boolean val isRegularMethod: Boolean val isGetter: Boolean val isSetter: Boolean val isOperator: Boolean val isConstructor: Boolean val constructorName: String companion object { // fun defaultConstructor(): AstMethod = _ConstructorImpl.defaultConstructor() // fun fromConstructor(declaration: ConstructorDeclaration): AstMethod = // _ConstructorImpl.fromConstructor(declaration) // fun fromMethod(declaration: MethodDeclaration): AstMethod = // _MethodImpl.fromMethod(declaration) fun fromFunction( declaration: MethodDeclaration, programNode: AstRuntime.ProgramNode ): AstMethod = _MethodImpl.fromFunction(declaration, programNode) // fun fromExpression(expression: MethodDeclaration): AstMethod = _MethodImpl.fromExpression(expression) fun fromMirror(mirror: KFunction<*>): AstMethod = _MethodMirror.fromMirror(mirror) fun fromMirror(mirror: MethodMirror): AstMethod = _MethodMirror.fromMirror(mirror) // fun forTopLevelFunction(name: String): AstMethod? { // val programNode = context.get() ?: return null // var function = programNode.getFunction(name) // if (function != null) { // return function // } // // val libraryMirror = ReflectionBinding.instance.reflectTopLevelInvoke(name) // if (libraryMirror != null) { // return fromMirror(libraryMirror.declarations[name] as MethodMirror) // } // return null // } // fun readyForScopedInvoke( // parameters: List<_ParameterImpl>?, // positionalArguments: List, // namedArguments: Map?, // invoke: (List, Map?) -> Any? // ): Any? = // _MethodImpl.readyForScopedInvoke(parameters, positionalArguments, namedArguments, invoke) fun apply2( method: AstMethod, positionalArguments: List, namedArguments: Map? ): Any? { if (method.isStatic) { if (method is _MethodImpl) { return _MethodImpl.readyForScopedInvoke( method.parameters, positionalArguments, namedArguments ) { args, namedArgs -> val programStack = context.get(ProgramStack::class.java) ?: return@readyForScopedInvoke null programStack.push(name = "Static function body") val result = executeExpression(method.body) programStack.pop() result } } else { // processArguments(method.parameters, positionalArguments, namedArguments) } } else { val ref = context.get(ThisReference::class.java) ?: throw IllegalStateException("Invalid ThisReference") if (ref.value is AstInstance) { val instance = ref.value return when { method.isGetter -> instance.invokeGetter(method.simpleName) method.isSetter -> instance.invokeSetter( method.simpleName, positionalArguments[0] ) else -> instance.invoke( method.simpleName, positionalArguments, namedArguments ) } } throw IllegalStateException("Invalid ThisReference") } return null } } } //abstract class AstMethod : AstDeclaration() { // // abstract val returnType: AstType // abstract val parameters: List // abstract val isStatic: Boolean // abstract val isAbstract: Boolean // abstract val isSynthetic: Boolean // abstract val isRegularMethod: Boolean // abstract val isGetter: Boolean // abstract val isSetter: Boolean // abstract val isOperator: Boolean // abstract val isConstructor: Boolean // abstract val constructorName: String // // companion object { // inline fun defaultConstructor(): T { // // 实现逻辑 // TODO("Not yet implemented") // } // //// inline fun fromConstructor(declaration: ConstructorDeclaration): T { //// // 实现逻辑 //// TODO("Not yet implemented") //// } //// //// inline fun fromMethod(declaration: MethodDeclaration): T { //// // 实现逻辑 //// TODO("Not yet implemented") //// } // // fun fromFunction( // declaration: FunctionDeclaration, // programNode: AstRuntime.ProgramNode // ): AstMethod { // return _MethodImpl() // } // // inline fun fromExpression(expression: FunctionDeclaration): T { // // 实现逻辑 // TODO("Not yet implemented") // } // //// inline fun fromMirror(mirror: MethodMirror): T { //// // 实现逻辑 //// TODO("Not yet implemented") //// } // //// fun forTopLevelFunction(name: String): AstMethod? { //// val programNode = context.get() ?: return null //// val function = programNode.getFunction(name) //// if (function != null) { //// return function //// } //// //// val libraryMirror = ReflectionBinding.instance.reflectTopLevelInvoke(name) //// if (libraryMirror != null) { //// return fromMirror(libraryMirror.declarations[name] as MethodMirror) //// } //// return null //// } // // fun readyForScopedInvoke( //// parameters: List<_ParameterImpl>?, // positionalArguments: List, // namedArguments: Map?, // invoke: (List, Map?) -> Any? // ): Any? { // // 实现逻辑 // TODO("Not yet implemented") // } // // fun apply2( // method: AstMethod, // positionalArguments: List, // namedArguments: Map? // ): Any? { // if (method.isStatic) { //// if (method is _MethodImpl) { //// return readyForScopedInvoke( //// method.parameters, //// positionalArguments, //// namedArguments //// ) { args, namedArgs -> //// val programStack = context.get()!! //// programStack.push(name = "Static function body") //// val result = executeExpression(method.body) //// programStack.pop() //// result //// } //// } else { //// processArguments(method.parameters, positionalArguments, namedArguments) //// } // } else { // val ref = context.get(ThisReference::class.java) ?: throw IllegalStateException("Invalid ThisReference") // if (ref.value is AstInstance) { // val instance = ref.value // return when { // method.isGetter -> instance.invokeGetter(method.simpleName) // method.isSetter -> instance.invokeSetter(method.simpleName, positionalArguments[0]) // else -> instance.invoke(method.simpleName, positionalArguments, namedArguments) // } // } // throw IllegalStateException("Invalid ThisReference") // } // // return null // } // } //} abstract class _MethodBase( private val _name: String, private val _body: Expression, private val _parameters: List<_ParameterImpl>, private val _isAbstract: Boolean, private val _isSynthetic: Boolean, // private val _isRegularMethod: Boolean, // private val _isGetter: Boolean, // private val _isSetter: Boolean, private val _isStatic: Boolean, // private val _isPrivate: Boolean, private val _isOperator: Boolean, private val _isConstructor: Boolean, override val programNode: AstRuntime.ProgramNode? = null ) : AstMethod { val body: Expression get() = _body override val qualifiedName: String get() = "${owner?.qualifiedName}.$simpleName" override val simpleName: String get() = if (_isConstructor) { if (_name.isEmpty()) owner.simpleName else "${owner.simpleName}.$simpleName" } else { _name } override val constructorName: String get() = if (_isConstructor) _name else "" override val isAbstract: Boolean get() = _isAbstract override val isSynthetic: Boolean get() = _isSynthetic override val isRegularMethod: Boolean get() = false override val isConstructor: Boolean get() = _isConstructor override val isGetter: Boolean get() = false override val isPrivate: Boolean get() = false override val isSetter: Boolean get() = false override val isStatic: Boolean get() = _isStatic override val owner: AstDeclaration get() = throw UnimplementedError("operator ${_name} error") // override val parameters: List<_ParameterImpl> get() = _parameters override val isOperator: Boolean get() = _isOperator override val returnType: AstType get() = throw UnimplementedError("operator ${_name} error") } public class UnimplementedError(s: String) : Throwable() { } class _MethodImpl( name: String, body: Expression, parameters: List<_ParameterImpl>, isAbstract: Boolean, isSynthetic: Boolean, // isRegularMethod: Boolean, // isGetter: Boolean, // isSetter: Boolean, isStatic: Boolean, // isPrivate: Boolean, isOperator: Boolean, isConstructor: Boolean, programNode: AstRuntime.ProgramNode? = null ) : _MethodBase( name, body, parameters, isAbstract, isSynthetic, // isRegularMethod, // isGetter, // isSetter, isStatic, // isPrivate, isOperator, isConstructor, programNode ) { companion object { fun fromExpression(expression: MethodDeclaration): AstMethod { val parameters = mutableListOf<_ParameterImpl>() if (expression.parameters?.parameters?.isNotEmpty() == true) { for (parameter in expression.parameters!!.parameters) { parameters.add(_ParameterImpl.fromParameter(parameter)) } } return _MethodImpl( name = "", body = expression.bodyExpression, parameters = parameters, isStatic = false, isAbstract = false, isOperator = false, isConstructor = false, isSynthetic = false ) } fun fromMethod(declaration: MethodDeclaration): _MethodImpl { val parameters = mutableListOf<_ParameterImpl>() // declaration.valueParameters.forEach { parameter -> // parameters.add(_ParameterImpl.fromParameter(parameter)) // } return _MethodImpl( declaration.name ?: "", declaration.bodyExpression, parameters, false, false, // !declaration.isGetter && !declaration.isSetter, // declaration.isGetter, // declaration.isSetter, true, // declaration.isPrivate, false, false, ) } fun fromFunction( declaration: MethodDeclaration, programNode: AstRuntime.ProgramNode ): _MethodImpl { val parameters = mutableListOf<_ParameterImpl>() declaration.parameters?.parameters?.forEach { parameter -> parameters.add(_ParameterImpl.fromParameter(parameter)) } return _MethodImpl( declaration.name ?: "", declaration.bodyExpression, parameters, false, false, // !declaration.isGetter && !declaration.isSetter, // declaration.isGetter, // declaration.isSetter, true, // declaration.isPrivate, false, false, programNode ) } // // fun fromExpression(expression: KtFunctionExpression): _MethodImpl { // val parameters = mutableListOf<_ParameterImpl>() // expression.valueParameters.forEach { parameter -> // parameters.add(_ParameterImpl.fromParameter(parameter)) // } // // return _MethodImpl( // "", // expression.bodyExpression, // parameters, // false, // false, // true, // false, // false, // true, // false, // false, // false // ) // } fun readyForScopedInvoke( parameters: List<_ParameterImpl>?, positionalArguments: List, namedArguments: Map?, invoke: (List, Map?) -> Any? ): Any? { val programStack = context.get(ProgramStack::class.java) ?: return null programStack.push(name = "Formal parameters scope") parameters?.forEachIndexed { index, parameter -> if (parameter.isNamed) { programStack.putVariable( parameter.simpleName, namedArguments?.get(parameter.simpleName) ) } else { programStack.putVariable( parameter.simpleName, positionalArguments.getOrNull(index) ) } } val result = invoke(positionalArguments, namedArguments) programStack.pop() return result } } } interface Reference { val value: T } class ThisReference(override val value: T) : Reference class SuperReference(override val value: T) : Reference class ProxyReference(override val value: T) : Reference class MirrorReference(override val value: T) : Reference ================================================ FILE: core/src/main/java/com/aether/core/runtime/StructsImpl.kt ================================================ package com.aether.core.runtime class StructsImpl { } abstract class _VariableBase( val _name: String, val _typeName: String?, val _isPrivate: Boolean, val _isTopLevel: Boolean, val _isStatic: Boolean, val _isFinal: Boolean, val _isConst: Boolean, override val programNode: AstRuntime.ProgramNode? = null ) : AstVariable() { override val simpleName: String get() = _name override val qualifiedName: String get() = "${owner.qualifiedName}.$simpleName" override val isPrivate: Boolean get() = _isPrivate override val isTopLevel: Boolean get() = _isTopLevel override val isStatic: Boolean get() = _isStatic override val isFinal: Boolean get() = _isFinal override val isConst: Boolean get() = _isConst override val owner: AstDeclaration get() = throw UnimplementedError("owner error") override val type: AstType get() = throw UnimplementedError("type error:${type}") val typeName: String? get() = _typeName } class VariableImpl private constructor( name: String, typeName: String?, private val _initializer: Expression?, isPrivate: Boolean, isTopLevel: Boolean, isStatic: Boolean, isConst: Boolean, isFinal: Boolean, programNode: AstRuntime.ProgramNode? = null ) : _VariableBase(name, typeName, isPrivate, isTopLevel, isStatic, isFinal, isConst, programNode) { companion object { fun fromDeclarator(declarator: VariableDeclarator): VariableImpl { return VariableImpl( declarator.name, declarator.typeName, declarator.init, Identifier.isPrivateName(declarator.name), declarator.isTopLevel, declarator.isStatic, declarator.isConst, declarator.isFinal ) } } override val owner: AstDeclaration get() = throw UnimplementedError("owner error") override val type: AstType get() = throw UnimplementedError("type error:${type}") val initializer: Expression? get() = _initializer } class _ParameterImpl private constructor( name: String, typeName: String?, isPrivate: Boolean, isTopLevel: Boolean, isStatic: Boolean, isConst: Boolean, isFinal: Boolean, private val _isNamed: Boolean, private val _isOptional: Boolean, private val _isField: Boolean, private val _defaultValue: Expression? ) : _VariableBase(name, typeName, isPrivate, isTopLevel, isStatic, isFinal, isConst){ companion object { fun fromParameter(parameter: FormalParameter): _ParameterImpl { val defaultValue: Expression? = if (parameter is DefaultFormalParameter) { parameter.defaultValue } else { null } val isField = parameter is FieldFormalParameter return _ParameterImpl( parameter.name, parameter.typeName, Identifier.isPrivateName(parameter.name), false, false, false, parameter.isFinal, parameter.isNamed, parameter.isOptional, isField, defaultValue ) } } val defaultValue: Expression? get() = _defaultValue val hasDefaultValue: Boolean get() = _defaultValue != null val isNamed: Boolean get() = _isNamed val isField: Boolean get() = _isField val isOptional: Boolean get() = _isOptional override val owner: AstDeclaration get() = throw UnimplementedError("owner error") override val type: AstType get() = throw UnimplementedError("type error:${type}") } ================================================ FILE: core/src/main/java/com/aether/core/runtime/context.kt ================================================ package com.aether.core.runtime import java.util.Collections typealias Generator = () -> Any? class ContextDependencyCycleException(cycle: List>) : Exception("Dependency cycle detected: ${cycle.joinToString(" -> ")}") const val contextKey = "context" val context2: AppContext get() = AppContextManager.context class AppContext( private var parent: AppContext?, val name: String?, private val overrides: Map, Generator>, private val fallbacks: Map, Generator> ) { private val values = mutableMapOf, Any?>() private val reentrantChecks = mutableListOf>() companion object { val root = AppContext(null, "ROOT", emptyMap(), emptyMap()) } private fun boxNull(value: Any?): Any? = value ?: BoxedNull private fun unboxNull(value: Any?): Any? = if (value == BoxedNull) null else value private fun generateIfNecessary(type: Class<*>, generators: Map, Generator>): Any? { if (!generators.containsKey(type)) { return null } return values.getOrPut(type) { val index = reentrantChecks.indexOf(type) if (index >= 0) { throw ContextDependencyCycleException(reentrantChecks.subList(index, 0)) } reentrantChecks.add(type) try { return boxNull(generators[type]?.invoke()) } finally { reentrantChecks.removeAt(reentrantChecks.lastIndex) } } } fun get(type: Class): T? { var value = generateIfNecessary(type, overrides) if (value == null && parent != null) { value = parent!!.get(type) } return unboxNull(value ?: generateIfNecessary(type, fallbacks)) as T? } fun run( name: String? = null, body: () -> Any?, overrides: Map, Generator>? = null, fallbacks: Map, Generator>? = null ): Any? { val child = AppContext( this, name, Collections.unmodifiableMap(overrides ?: emptyMap()), Collections.unmodifiableMap(fallbacks ?: emptyMap()) ) val previousContext = AppContextManager.get() child.parent = previousContext AppContextManager.set(child) try { return body() } finally { AppContextManager.set(child) } } // suspend fun run( // body: suspend () -> Any?, // name: String? = null, // overrides: Map, Generator>? = null, // fallbacks: Map, Generator>? = null // ): Any? { // val child = AppContext( // this, // name, // overrides?.toMap() ?: emptyMap(), // fallbacks?.toMap() ?: emptyMap() // ) // return withContext(currentCoroutineContext() + mapOf(contextKey to child)) { // try { // body() // } catch (e: Exception) { // val astRuntime = child.get(AstRuntime::class) // if (astRuntime != null && astRuntime.errorCallback != null) { // astRuntime.errorCallback(e, e.stackTrace) // } // throw e // } // } // } override fun toString(): String { val buf = StringBuilder() var indent = "" var ctx: AppContext? = this while (ctx != null) { buf.append("AppContext") if (ctx.name != null) { buf.append("[${ctx.name}]") } if (ctx.overrides.isNotEmpty()) { buf.append("\n$indent overrides: [${ctx.overrides.keys.joinToString(", ")}]") } if (ctx.fallbacks.isNotEmpty()) { buf.append("\n$indent fallbacks: [${ctx.fallbacks.keys.joinToString(", ")}]") } if (ctx.parent != null) { buf.append("\n$indent parent: ") } ctx = ctx.parent indent += " " } return buf.toString() } } object BoxedNull ================================================ FILE: core/src/main/java/com/aether/core/runtime/deliver/TemplateProvider.kt ================================================ package com.aether.core.runtime.deliver import com.aether.core.runtime.AstRuntime import android.util.Log import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch import java.io.File import java.util.zip.ZipFile import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button import androidx.compose.material.Card import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import com.aether.core.runtime.AppContextManager.context import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.RenderComponent /** * Arguments for a dynamic Composable */ class Arguments( val positionalArguments: List = emptyList(), val namedArguments: Map = emptyMap() ) /** * Events that can be triggered during CloudComposable lifecycle */ enum class EasyComposeEvent { LOAD_COMPLETE, LOAD_ERROR } /** * Interface for template providers */ interface TemplateProvider { val key: String fun resolve(): Flow } /** * Result of template loading */ data class TemplateResult( val programNode: AstRuntime.ProgramNode, val sourceKey: String ) /** * Network template provider */ class NetworkTemplate( private val url: String, private val fileMd5: String? = null ) : TemplateProvider { override val key: String get() = "network_$url${fileMd5?.let { "_$it" } ?: ""}" override fun resolve(): Flow { return TemplateLoader.loadFromNetwork(url, fileMd5) .flowOn(Dispatchers.IO) } } /** * Asset template provider */ class AssetTemplate( private val assetName: String ) : TemplateProvider { override val key: String get() = "asset_$assetName" override fun resolve(): Flow { return TemplateLoader.loadFromAsset(assetName) .flowOn(Dispatchers.IO) } } /** * File template provider */ class FileTemplate( private val file: File ) : TemplateProvider { override val key: String get() = "file_${file.absolutePath}" override fun resolve(): Flow { return TemplateLoader.loadFromFile(file) .flowOn(Dispatchers.IO) } } /** * Zip file template provider */ class ZipFileTemplate( private val zipFile: File ) : TemplateProvider { override val key: String get() = "zip_${zipFile.absolutePath}" override fun resolve(): Flow { return TemplateLoader.loadFromZipFile(zipFile) .flowOn(Dispatchers.IO) } } /** * Helper class for loading templates */ object TemplateLoader { fun loadFromNetwork(url: String, fileMd5: String? = null): Flow { val resultFlow = MutableStateFlow(null) try { // Download code from network and create local file val tempFile = File.createTempFile("network_template", ".kt") // For demo purposes, using placeholder content tempFile.writeText( """ @Composable fun Main() { Text("Network content from $url") } """.trimIndent() ) // Create AstRuntime from file val localFile = AstRuntime.LocalFile(tempFile) val node = localFile.createNode() resultFlow.value = TemplateResult( programNode = node, sourceKey = "network_$url${fileMd5?.let { "_$it" } ?: ""}" ) } catch (e: Exception) { throw e } return resultFlow as Flow } fun loadFromAsset(assetName: String): Flow { val resultFlow = MutableStateFlow(null) try { // val tempFile = File.createTempFile("asset_template", ".kt") // tempFile.writeText( // """ // @Composable // fun Main() { // Text("Asset content from $assetName") // } // """.trimIndent() // ) // val json = "{\n" + // " \"directives\" : [ {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.background\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"background\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.Box\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Box\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.Column\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Column\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.fillMaxWidth\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"fillMaxWidth\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.height\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"height\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.padding\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"padding\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.shape.RoundedCornerShape\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"RoundedCornerShape\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.material.Button\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Button\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.material.Text\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Text\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.runtime.Composable\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Composable\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.ui.Alignment\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Alignment\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.ui.Modifier\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Modifier\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.ui.draw.clip\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"clip\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.ui.graphics.Color\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Color\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.ui.unit.dp\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"dp\"\n" + // " } ],\n" + // " \"declarations\" : [ {\n" + // " \"type\" : \"ClassDeclaration\",\n" + // " \"name\" : \"DemoCompose\",\n" + // " \"members\" : [ {\n" + // " \"type\" : \"MethodDeclaration\",\n" + // " \"name\" : \"Main\",\n" + // " \"parameters\" : [ ],\n" + // " \"typeParameters\" : [ ],\n" + // " \"body\" : {\n" + // " \"type\" : \"BlockStatement\",\n" + // " \"body\" : [ {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Column\",\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ {\n" + // " \"type\" : \"Argument\",\n" + // " \"body\" : {\n" + // " \"type\" : \"MethodInvocation\",\n" + // " \"name\" : null,\n" + // " \"methodName\" : {\n" + // " \"type\" : \"CallExpression\",\n" + // " \"methodName\" : {\n" + // " \"type\" : \"Identifier\",\n" + // " \"name\" : \"fillMaxWidth\"\n" + // " },\n" + // " \"target\" : {\n" + // " \"type\" : \"Identifier\",\n" + // " \"name\" : \"fillMaxWidth\"\n" + // " },\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ ]\n" + // " },\n" + // " \"valueArgument\" : [ ]\n" + // " },\n" + // " \"target\" : {\n" + // " \"type\" : \"Identifier\",\n" + // " \"name\" : \"Modifier\"\n" + // " }\n" + // " }\n" + // " }, {\n" + // " \"type\" : \"Argument\",\n" + // " \"body\" : {\n" + // " \"type\" : \"MethodInvocation\",\n" + // " \"name\" : null,\n" + // " \"methodName\" : {\n" + // " \"type\" : \"Identifier\",\n" + // " \"name\" : \"CenterHorizontally\"\n" + // " },\n" + // " \"target\" : {\n" + // " \"type\" : \"Identifier\",\n" + // " \"name\" : \"Alignment\"\n" + // " }\n" + // " }\n" + // " } ]\n" + // " },\n" + // " \"valueArgument\" : [ ]\n" + // " } ]\n" + // " },\n" + // " \"isStatic\" : false,\n" + // " \"isGetter\" : true,\n" + // " \"isSetter\" : false\n" + // " } ],\n" + // " \"body\" : { }\n" + // " } ],\n" + // " \"type\" : \"CompilationUnit\"\n" + // "}" // val json = "{\"directives\":[{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.Column\",\"alias\":null,\"name\":\"Column\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.Text\",\"alias\":null,\"name\":\"Text\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.runtime.Composable\",\"alias\":null,\"name\":\"Composable\"}],\"declarations\":[{\"type\":\"ClassDeclaration\",\"name\":\"ColumComposeNameExpressText\",\"members\":[{\"type\":\"MethodDeclaration\",\"name\":\"Main\",\"parameters\":[],\"typeParameters\":[],\"body\":{\"type\":\"BlockStatement\",\"body\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":null,\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"1这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"minLines\",\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"1\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"2这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"minLines\",\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"1\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"3这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"minLines\",\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"1\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"4这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"minLines\",\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"1\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]}]}]},\"isStatic\":false,\"isGetter\":true,\"isSetter\":false}],\"body\":{}}],\"type\":\"CompilationUnit\"}" // val json = "{\"directives\":[{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.Arrangement\",\"alias\":null,\"name\":\"Arrangement\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.Column\",\"alias\":null,\"name\":\"Column\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.Spacer\",\"alias\":null,\"name\":\"Spacer\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.fillMaxSize\",\"alias\":null,\"name\":\"fillMaxSize\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.fillMaxWidth\",\"alias\":null,\"name\":\"fillMaxWidth\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.height\",\"alias\":null,\"name\":\"height\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.padding\",\"alias\":null,\"name\":\"padding\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.rememberScrollState\",\"alias\":null,\"name\":\"rememberScrollState\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.shape.RoundedCornerShape\",\"alias\":null,\"name\":\"RoundedCornerShape\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.verticalScroll\",\"alias\":null,\"name\":\"verticalScroll\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.Card\",\"alias\":null,\"name\":\"Card\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.MaterialTheme\",\"alias\":null,\"name\":\"MaterialTheme\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.Text\",\"alias\":null,\"name\":\"Text\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.runtime.Composable\",\"alias\":null,\"name\":\"Composable\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.ui.Modifier\",\"alias\":null,\"name\":\"Modifier\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.ui.graphics.Color\",\"alias\":null,\"name\":\"Color\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.ui.text.font.FontWeight\",\"alias\":null,\"name\":\"FontWeight\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.ui.unit.dp\",\"alias\":null,\"name\":\"dp\"}],\"declarations\":[{\"type\":\"ClassDeclaration\",\"name\":\"ColumArgsComposeExpressText\",\"members\":[{\"type\":\"MethodDeclaration\",\"name\":\"Main\",\"parameters\":[],\"typeParameters\":[],\"body\":{\"type\":\"BlockStatement\",\"body\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"verticalScroll\"},\"target\":{\"type\":\"Identifier\",\"name\":\"verticalScroll\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"rememberScrollState\"},\"target\":{\"type\":\"Identifier\",\"name\":\"rememberScrollState\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"target\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"16\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"target\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"verticalArrangement\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"spacedBy\"},\"target\":{\"type\":\"Identifier\",\"name\":\"spacedBy\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"10\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Arrangement\"}}}]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Card\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"height\"},\"target\":{\"type\":\"Identifier\",\"name\":\"height\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"100\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"fillMaxWidth\"},\"target\":{\"type\":\"Identifier\",\"name\":\"fillMaxWidth\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"shape\",\"body\":{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"RoundedCornerShape\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"16\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"elevation\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"4\",\"name\":\"ConstantExpression\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"backgroundColor\",\"body\":{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Color\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"0xFFE0F7FA\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]}}]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"target\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"16\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"target\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"verticalArrangement\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Center\"},\"target\":{\"type\":\"Identifier\",\"name\":\"Arrangement\"}}}]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"主标题 1\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h6\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"fontWeight\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Bold\"},\"target\":{\"type\":\"Identifier\",\"name\":\"FontWeight\"}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Spacer\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"height\"},\"target\":{\"type\":\"Identifier\",\"name\":\"height\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"4\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"副标题 1\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"body1\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"color\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Gray\"},\"target\":{\"type\":\"Identifier\",\"name\":\"Color\"}}}]},\"typeArguments\":[],\"children\":[]}]}]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Card\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"height\"},\"target\":{\"type\":\"Identifier\",\"name\":\"height\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"100\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"fillMaxWidth\"},\"target\":{\"type\":\"Identifier\",\"name\":\"fillMaxWidth\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"shape\",\"body\":{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"RoundedCornerShape\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"16\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"elevation\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"4\",\"name\":\"ConstantExpression\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"backgroundColor\",\"body\":{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Color\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"0xFFE0F7FA\",\"name\":\"ConstantExpression\"}}]},\"typeArguments\":[],\"children\":[]}}]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"target\":{\"type\":\"Identifier\",\"name\":\"padding\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"16\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"target\":{\"type\":\"Identifier\",\"name\":\"fillMaxSize\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"verticalArrangement\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Center\"},\"target\":{\"type\":\"Identifier\",\"name\":\"Arrangement\"}}}]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"主标题 2\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h6\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"fontWeight\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Bold\"},\"target\":{\"type\":\"Identifier\",\"name\":\"FontWeight\"}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Spacer\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"modifier\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"CallExpression\",\"methodName\":{\"type\":\"Identifier\",\"name\":\"height\"},\"target\":{\"type\":\"Identifier\",\"name\":\"height\"},\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":false,\"name\":null,\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"dp\"},\"target\":{\"type\":\"INTEGER_CONSTANT\",\"value\":\"4\",\"name\":\"ConstantExpression\"}}}]},\"typeArguments\":[],\"children\":[]},\"target\":{\"type\":\"Identifier\",\"name\":\"Modifier\"}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"副标题 2\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"body1\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"color\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"Gray\"},\"target\":{\"type\":\"Identifier\",\"name\":\"Color\"}}}]},\"typeArguments\":[],\"children\":[]}]}]}]}]},\"isStatic\":false,\"isGetter\":true,\"isSetter\":false}],\"body\":{}}],\"type\":\"CompilationUnit\"}" val json = obtainJson() val localFile = AstRuntime.LocalJson(json) val node = localFile.createNode() resultFlow.value = TemplateResult( programNode = node, sourceKey = "asset_$assetName" ) } catch (e: Exception) { throw e } return resultFlow as Flow } fun loadFromFile(file: File): Flow { val resultFlow = MutableStateFlow(null) try { val localFile = AstRuntime.LocalFile(file) val node = localFile.createNode() resultFlow.value = TemplateResult( programNode = node, sourceKey = "file_${file.absolutePath}" ) } catch (e: Exception) { throw e } return resultFlow as Flow } fun loadFromZipFile(zipFile: File): Flow { val resultFlow = MutableStateFlow(null) try { val extractedFile = extractMainFileFromZip(zipFile) val localFile = AstRuntime.LocalFile(extractedFile) val node = localFile.createNode() resultFlow.value = TemplateResult( programNode = node, sourceKey = "zip_${zipFile.absolutePath}" ) } catch (e: Exception) { throw e } return resultFlow as Flow } private fun extractMainFileFromZip(zipFile: File): File { ZipFile(zipFile).use { zip -> val entry = zip.entries().asSequence().firstOrNull { it.name.endsWith(".kt") && !it.isDirectory } ?: throw IllegalArgumentException("No Kotlin files found in zip") val extractedFile = File.createTempFile("extracted", ".kt") zip.getInputStream(entry).use { input -> extractedFile.outputStream().use { output -> input.copyTo(output) } } return extractedFile } } } /** * Holder for Composable content */ class ComposableHolder { var componentDescriptor: ComposeComponentDescriptor? = null } /** * Context provider for CloudComposable */ object ComposeContext { private val contextMap = mutableMapOf() fun run(name: String, body: () -> T, overrides: Map Any?> = emptyMap()): T { val savedContext = HashMap(contextMap) try { overrides.forEach { (key, provider) -> contextMap[key.toString()] = provider() ?: Any() } return body() } finally { contextMap.clear() contextMap.putAll(savedContext) } } fun get(key: Class): T? { @Suppress("UNCHECKED_CAST") return contextMap[key.toString()] as? T } } /** * View model for CloudComposable to manage state */ class CloudComposeViewModel : ViewModel() { var templateResult by mutableStateOf(null) var arguments by mutableStateOf(null) var error by mutableStateOf(null) var astRuntime by mutableStateOf(null) var composableCache by mutableStateOf<(@Composable () -> Unit)?>(null) fun loadTemplate( template: TemplateProvider, arguments: Arguments?, errorCallback: ((Throwable, Array) -> Unit)?, eventCallback: ((EasyComposeEvent) -> Unit)? ) { viewModelScope.launch { try { template.resolve() .catch { e -> error = e eventCallback?.invoke(EasyComposeEvent.LOAD_ERROR) errorCallback?.invoke(e, e.stackTrace) } .collect { result -> templateResult = result this@CloudComposeViewModel.arguments = arguments error = null composableCache = null astRuntime = AstRuntime(result.programNode) eventCallback?.invoke(EasyComposeEvent.LOAD_COMPLETE) } } catch (e: Exception) { error = e eventCallback?.invoke(EasyComposeEvent.LOAD_ERROR) errorCallback?.invoke(e, e.stackTrace) } } } fun updateArguments(arguments: Arguments?) { if (templateResult != null) { this.arguments = arguments composableCache = null } } } /** * Type for loading builder */ typealias TemplateLoadingBuilder = @Composable () -> Unit /** * Type for error builder */ typealias TemplateErrorWidgetBuilder = @Composable (Throwable, Array?) -> Unit /** * Main Composable function for dynamic UI */ @Composable fun CloudComposableFunction( template: TemplateProvider, arguments: Arguments? = null, loadingBuilder: TemplateLoadingBuilder? = null, errorBuilder: TemplateErrorWidgetBuilder? = null, errorCallback: ((Throwable, Array) -> Unit)? = null, eventCallback: ((EasyComposeEvent) -> Unit)? = null, viewModel: CloudComposeViewModel = remember { CloudComposeViewModel() } ) { // Load template when provider changes LaunchedEffect(template) { viewModel.loadTemplate(template, arguments, errorCallback, eventCallback) } // Update arguments when they change LaunchedEffect(arguments) { viewModel.updateArguments(arguments) } // Cleanup DisposableEffect(Unit) { onDispose { // Cleanup resources } } // Render appropriate content when { viewModel.error != null -> { if (errorBuilder != null) { errorBuilder(viewModel.error!!, viewModel.error!!.stackTrace) } else { DefaultErrorContent(viewModel.error!!) } } viewModel.templateResult == null -> { if (loadingBuilder != null) { loadingBuilder() } else { DefaultLoadingContent() } } else -> { if (viewModel.composableCache == null) { viewModel.composableCache = createDynamicComposable( viewModel.astRuntime!!, viewModel.arguments ) } // Use Column instead of Box to avoid BoxScope issues Text( text = "viewModel.composableCache?.invoke()...", modifier = Modifier.padding(top = 16.dp) ) Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { Column( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Button(onClick = {}) { Text("这是由云端下发资源渲染的一个动态化的页面") } Column( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Box( modifier = Modifier .fillMaxWidth() .padding(16.dp) // 设置外部边缘(padding) .clip(RoundedCornerShape(10.dp)) // 设置圆角半径为10dp .background(Color(0xFFD1EAFB)), // 设置背景颜色 contentAlignment = Alignment.Center // 将 Text 垂直和水平居中 ) { viewModel.composableCache?.invoke() } } } } } } } /** * Create a composable from AstRuntime */ private fun createDynamicComposable( runtime: AstRuntime, arguments: Arguments? ): @Composable () -> Unit { return { val holder = ComposableHolder() var descriptorState by remember { mutableStateOf(null) } // Create or retrieve the dynamic composable LaunchedEffect(runtime, arguments) { context.run( name = "CloudComposable", body = { if (runtime.hasTopLevelFunction("Main")) { // Execute main function if it exists Log.d("CloudComposable", "Executing main function") val invoke = runtime.invoke2( "Main", arguments?.positionalArguments ?: emptyList(), arguments?.namedArguments ) // Get the holder from context // 获取holder val composableHolder = context.get(ComposableHolder::class.java) if (composableHolder != null && composableHolder.componentDescriptor != null) { holder.componentDescriptor = composableHolder.componentDescriptor } else { // 创建描述符而不是直接创建Composable函数 holder.componentDescriptor = obtainDefaultCompose() } } else { // Look for composable classes // 查找Composable类 Log.d("CloudComposable", "Looking for composable classes") var foundComposable = false for (astClass in runtime.classes) { if (astClass.superclass?.simpleName == "\$ProxyComposable" || astClass.superclass?.simpleName == "\$ComposableWidget" ) { Log.d( "CloudComposable", "Found composable class: ${astClass.simpleName}" ) // 创建描述符 holder.componentDescriptor = obtainDefaultCompose() foundComposable = true break } } if (!foundComposable) { // 创建描述符 holder.componentDescriptor = obtainDefaultCompose() } } // 然后在更新时 if (holder.componentDescriptor != null) { descriptorState = holder.componentDescriptor!! } }, overrides = mapOf( ComposableHolder::class.java to { holder } ) ) } // Render the composable if (descriptorState != null) { // 使用工厂方法渲染组件 RenderComponent(descriptorState!!) } else { // 默认加载显示 Text("Loading composable content...") } } } private fun obtainDefaultCompose(): ComposeComponentDescriptor = ComposeComponentDescriptor( "androidx.compose.material.Text", null, null, null ) /** * Check if runtime has top-level function */ fun AstRuntime.hasTopLevelFunction(name: String): Boolean { return invoke2(name) != null } /** * Default loading content */ @Composable private fun DefaultLoadingContent() { Text( text = "Loading template...", modifier = Modifier.padding(top = 16.dp) ) } // ///** // * Default error content // */ @Composable private fun DefaultErrorContent(error: Throwable) { // Use a simple Text as a fallback Text( text = "Error loading template: ${error.message}", color = Color.Red, modifier = Modifier .fillMaxWidth() .padding(16.dp) ) } /** * Object to host CloudComposable extension functions */ object CloudComposable { /** * Convenience function for network templates */ @Composable fun Network( url: String, fileMd5: String? = null, arguments: Arguments? = null, loadingBuilder: TemplateLoadingBuilder? = null, errorBuilder: TemplateErrorWidgetBuilder? = null, errorCallback: ((Throwable, Array) -> Unit)? = null, eventCallback: ((EasyComposeEvent) -> Unit)? = null ) { CloudComposableFunction( template = NetworkTemplate(url, fileMd5), arguments = arguments, loadingBuilder = loadingBuilder, errorBuilder = errorBuilder, errorCallback = errorCallback, eventCallback = eventCallback ) } /** * Convenience function for asset templates */ @Composable fun Asset( assetName: String, arguments: Arguments? = null, loadingBuilder: TemplateLoadingBuilder? = null, errorBuilder: TemplateErrorWidgetBuilder? = null, errorCallback: ((Throwable, Array) -> Unit)? = null, eventCallback: ((EasyComposeEvent) -> Unit)? = null ) { CloudComposableFunction( template = AssetTemplate(assetName), arguments = arguments, loadingBuilder = loadingBuilder, errorBuilder = errorBuilder, errorCallback = errorCallback, eventCallback = eventCallback ) } /** * Convenience function for file templates */ @Composable fun File( file: File, arguments: Arguments? = null, loadingBuilder: TemplateLoadingBuilder? = null, errorBuilder: TemplateErrorWidgetBuilder? = null, errorCallback: ((Throwable, Array) -> Unit)? = null, eventCallback: ((EasyComposeEvent) -> Unit)? = null ) { CloudComposableFunction( template = FileTemplate(file), arguments = arguments, loadingBuilder = loadingBuilder, errorBuilder = errorBuilder, errorCallback = errorCallback, eventCallback = eventCallback ) } /** * Convenience function for zip file templates */ @Composable fun ZipFile( zipFile: File, arguments: Arguments? = null, loadingBuilder: TemplateLoadingBuilder? = null, errorBuilder: TemplateErrorWidgetBuilder? = null, errorCallback: ((Throwable, Array) -> Unit)? = null, eventCallback: ((EasyComposeEvent) -> Unit)? = null ) { CloudComposableFunction( template = ZipFileTemplate(zipFile), arguments = arguments, loadingBuilder = loadingBuilder, errorBuilder = errorBuilder, errorCallback = errorCallback, eventCallback = eventCallback ) } } private fun obtainJson(): String { // return "{\n" + // " \"directives\" : [ {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.foundation.layout.Column\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Column\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.material.Text\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Text\"\n" + // " }, {\n" + // " \"type\" : \"ImportDirective\",\n" + // " \"importPath\" : \"androidx.compose.runtime.Composable\",\n" + // " \"alias\" : null,\n" + // " \"name\" : \"Composable\"\n" + // " } ],\n" + // " \"declarations\" : [ {\n" + // " \"type\" : \"ClassDeclaration\",\n" + // " \"name\" : \"ColumComposeNameExpressText\",\n" + // " \"members\" : [ {\n" + // " \"type\" : \"MethodDeclaration\",\n" + // " \"name\" : \"Main\",\n" + // " \"parameters\" : [ ],\n" + // " \"typeParameters\" : [ ],\n" + // " \"body\" : {\n" + // " \"type\" : \"BlockStatement\",\n" + // " \"body\" : [ {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Column\",\n" + // " \"argumentList\" : null,\n" + // " \"typeArguments\" : [ ],\n" + // " \"children\" : [ {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Text\",\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"text\",\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateExpression\",\n" + // " \"name\" : null,\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateEntry\",\n" + // " \"body\" : null,\n" + // " \"value\" : \"1这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"\n" + // " }\n" + // " }\n" + // " }, {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"minLines\",\n" + // " \"body\" : {\n" + // " \"type\" : \"INTEGER_CONSTANT\",\n" + // " \"value\" : \"1\",\n" + // " \"name\" : \"ConstantExpression\"\n" + // " }\n" + // " } ]\n" + // " },\n" + // " \"typeArguments\" : [ ],\n" + // " \"children\" : [ ]\n" + // " }, {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Text\",\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"text\",\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateExpression\",\n" + // " \"name\" : null,\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateEntry\",\n" + // " \"body\" : null,\n" + // " \"value\" : \"2这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"\n" + // " }\n" + // " }\n" + // " }, {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"minLines\",\n" + // " \"body\" : {\n" + // " \"type\" : \"INTEGER_CONSTANT\",\n" + // " \"value\" : \"1\",\n" + // " \"name\" : \"ConstantExpression\"\n" + // " }\n" + // " } ]\n" + // " },\n" + // " \"typeArguments\" : [ ],\n" + // " \"children\" : [ ]\n" + // " }, {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Text\",\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"text\",\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateExpression\",\n" + // " \"name\" : null,\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateEntry\",\n" + // " \"body\" : null,\n" + // " \"value\" : \"3这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"\n" + // " }\n" + // " }\n" + // " }, {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"minLines\",\n" + // " \"body\" : {\n" + // " \"type\" : \"INTEGER_CONSTANT\",\n" + // " \"value\" : \"1\",\n" + // " \"name\" : \"ConstantExpression\"\n" + // " }\n" + // " } ]\n" + // " },\n" + // " \"typeArguments\" : [ ],\n" + // " \"children\" : [ ]\n" + // " }, {\n" + // " \"type\" : \"InstanceCreationExpression\",\n" + // " \"constructorName\" : \"Text\",\n" + // " \"argumentList\" : {\n" + // " \"type\" : \"ArgumentList\",\n" + // " \"arguments\" : [ {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"text\",\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateExpression\",\n" + // " \"name\" : null,\n" + // " \"body\" : {\n" + // " \"type\" : \"StringTemplateEntry\",\n" + // " \"body\" : null,\n" + // " \"value\" : \"4这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换\"\n" + // " }\n" + // " }\n" + // " }, {\n" + // " \"type\" : \"Argument\",\n" + // " \"isNamed\" : true,\n" + // " \"name\" : \"minLines\",\n" + // " \"body\" : {\n" + // " \"type\" : \"INTEGER_CONSTANT\",\n" + // " \"value\" : \"1\",\n" + // " \"name\" : \"ConstantExpression\"\n" + // " }\n" + // " } ]\n" + // " },\n" + // " \"typeArguments\" : [ ],\n" + // " \"children\" : [ ]\n" + // " } ]\n" + // " } ]\n" + // " },\n" + // " \"isStatic\" : false,\n" + // " \"isGetter\" : true,\n" + // " \"isSetter\" : false\n" + // " } ],\n" + // " \"body\" : { }\n" + // " } ],\n" + // " \"type\" : \"CompilationUnit\"\n" + // "}" return "{\"directives\":[{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.foundation.layout.Column\",\"alias\":null,\"name\":\"Column\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.MaterialTheme\",\"alias\":null,\"name\":\"MaterialTheme\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.material.Text\",\"alias\":null,\"name\":\"Text\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.runtime.Composable\",\"alias\":null,\"name\":\"Composable\"},{\"type\":\"ImportDirective\",\"importPath\":\"androidx.compose.ui.graphics.Color\",\"alias\":null,\"name\":\"Color\"}],\"declarations\":[{\"type\":\"ClassDeclaration\",\"name\":\"ColumArgsComposeExpressText\",\"members\":[{\"type\":\"MethodDeclaration\",\"name\":\"Main\",\"parameters\":[],\"typeParameters\":[],\"body\":{\"type\":\"BlockStatement\",\"body\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":null,\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"主标题 1\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h4\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"副标题 1\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h5\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]}]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"主标题 2\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h4\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"副标题 3\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h5\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]}]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Column\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[]},\"typeArguments\":[],\"children\":[{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"主标题 2\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h4\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]},{\"type\":\"InstanceCreationExpression\",\"constructorName\":\"Text\",\"argumentList\":{\"type\":\"ArgumentList\",\"arguments\":[{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"text\",\"body\":{\"type\":\"StringTemplateExpression\",\"name\":null,\"body\":{\"type\":\"StringTemplateEntry\",\"body\":null,\"value\":\"副标题 3\"}}},{\"type\":\"Argument\",\"isNamed\":true,\"name\":\"style\",\"body\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"h5\"},\"target\":{\"type\":\"MethodInvocation\",\"name\":null,\"methodName\":{\"type\":\"Identifier\",\"name\":\"typography\"},\"target\":{\"type\":\"Identifier\",\"name\":\"MaterialTheme\"}}}}]},\"typeArguments\":[],\"children\":[]}]}]}]},\"isStatic\":false,\"isGetter\":true,\"isSetter\":false}],\"body\":{}}],\"type\":\"CompilationUnit\"}" } /** * Example usage */ @Composable fun ExampleUsage() { // Column( // ) { // Text( // text = "主标题 1", // style = MaterialTheme.typography.h6, // ) // Text(text = "副标题 1", style = MaterialTheme.typography.body1, color = Color.Gray) // } val testFile = File("src/test/java/com/aether/core/compose/DemoCompose.kt") CloudComposable.Asset( assetName = "mytest", arguments = Arguments( positionalArguments = listOf(5, "a"), namedArguments = mapOf("name" to "value") ), eventCallback = { event -> when (event) { EasyComposeEvent.LOAD_COMPLETE -> Log.d("Example", "Template loaded") EasyComposeEvent.LOAD_ERROR -> Log.d("Example", "Template failed to load") } } ) } ================================================ FILE: core/src/main/java/com/aether/core/runtime/deliver/binding.kt ================================================ package com.aether.core.runtime.deliver import com.aether.core.runtime.AppContextManager.context import com.aether.core.runtime.AstMethod import com.aether.core.runtime.Expression import com.aether.core.runtime.MethodDeclaration import com.aether.core.runtime.executeExpression import com.aether.core.runtime.reflectable.ComposeComponentDescriptor // 实现 doRunBuild 方法 fun doRunBuild(func: MethodDeclaration) { val arguments = context.get(Arguments::class.java) val positionalArguments = mutableListOf() val namedArguments = mutableMapOf() if (arguments != null) { arguments.positionalArguments?.let { positionalArguments.addAll(it) } arguments.namedArguments?.let { namedArguments.putAll(it) } } val method = AstMethod.fromExpression(func) val holder = context.get(ComposableHolder::class.java)!! // 处理返回的结果 val result = AstMethod.apply2(method, positionalArguments, namedArguments) // 如果结果是 ComposeComponentDescriptor,直接设置 if (result is ComposeComponentDescriptor) { holder.componentDescriptor = result } else { // 对于其他类型的结果,创建一个默认的 Text 组件描述符 holder.componentDescriptor = obtainDefaultCompose() } } private fun obtainDefaultCompose(): ComposeComponentDescriptor = ComposeComponentDescriptor( "androidx.compose.material.Text", null, null, null ) // 实现 invokeRunMain 方法 fun invokeRunMain(expression: Any?) { val holder = context.get(ComposableHolder::class.java)!! // val result = executeExpression(expression) // 处理返回的结果 if (expression is ComposeComponentDescriptor) { holder.componentDescriptor = expression } else { // 默认情况 holder.componentDescriptor = obtainDefaultCompose() } } // 实现 invokeRunApp 方法 fun invokeRunApp(expression: Expression) { val holder = context.get(ComposableHolder::class.java)!! val result = executeExpression(expression) // 处理返回的结果 if (result is ComposeComponentDescriptor) { holder.componentDescriptor = result } else { // 默认情况 holder.componentDescriptor = obtainDefaultCompose() } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/entity/SimpleMember.kt ================================================ package com.aether.core.runtime.entity // 简单的成员表示,用于替代可能导致问题的KCallable class SimpleMember(val name: String, val modifiers: Int) { val isStatic: Boolean get() = modifiers and java.lang.reflect.Modifier.STATIC != 0 } ================================================ FILE: core/src/main/java/com/aether/core/runtime/mirror/MirrorHelper.kt ================================================ package com.aether.core.runtime.mirror import android.util.Log import androidx.compose.ui.Modifier import java.lang.reflect.Field import java.lang.reflect.Method import kotlin.reflect.KCallable import kotlin.reflect.KClass import kotlin.reflect.KFunction import kotlin.reflect.full.findAnnotation import kotlin.reflect.jvm.javaMethod object MirrorHelper { /** * 安全获取类的成员,特别处理Compose UI组件 * @param kClass 要反射的Kotlin类 * @return 成员集合,包含方法和属性 */ fun safeGetMembers(kClass: KClass<*>): Collection { return try { if (kClass.qualifiedName?.startsWith("androidx.compose") == true) { // 对于Compose类,使用Java反射获取更安全的成员列表 val javaClass = kClass.java val result = mutableListOf() // 添加方法 javaClass.declaredMethods.forEach { method -> result.add(JavaMethodAdapter(method)) } // 添加字段 javaClass.declaredFields.forEach { field -> result.add(JavaFieldAdapter(field)) } result } else { // 非Compose类使用正常的Kotlin反射 kClass.members.map { KCallableAdapter(it) } } } catch (e: Exception) { Log.e("Reflection", "Error accessing members of ${kClass.qualifiedName}", e) // 返回空列表作为后备 emptyList() } } /** * KCallable接口的统一表示 */ interface KCallableLike { val name: String val isStatic: Boolean fun call(vararg args: Any?): Any? fun hasAnnotation(annotationClass: KClass): Boolean } /** * 包装KCallable的适配器 */ class KCallableAdapter(private val callable: KCallable<*>) : KCallableLike { override val name: String = callable.name override val isStatic: Boolean get() = callable.findAnnotation() != null || (callable is KFunction<*> && callable.javaMethod?.let { java.lang.reflect.Modifier.isStatic(it.modifiers) // 明确使用完整类名 } == true) override fun call(vararg args: Any?): Any? { return callable.call(*args) } override fun hasAnnotation(annotationClass: KClass): Boolean { return callable.annotations.any { it.annotationClass == annotationClass } } } /** * Java Method的适配器 */ class JavaMethodAdapter(private val method: Method) : KCallableLike { override val name: String = method.name override val isStatic: Boolean get() = java.lang.reflect.Modifier.isStatic(method.modifiers) // 明确使用完整类名 override fun call(vararg args: Any?): Any? { val accessible = method.isAccessible try { method.isAccessible = true return method.invoke(null, *args) } finally { method.isAccessible = accessible } } override fun hasAnnotation(annotationClass: KClass): Boolean { return method.isAnnotationPresent(annotationClass.java) } } /** * Java Field的适配器 */ class JavaFieldAdapter(private val field1: Field) : KCallableLike { override val name: String = field1.name override val isStatic: Boolean get() = java.lang.reflect.Modifier.isStatic(field1.modifiers) // 明确使用完整类名 override fun call(vararg args: Any?): Any? { val accessible = field1.isAccessible try { field1.isAccessible = true return if (args.isEmpty()) { field1.get(null) } else { field1.set(null, args[0]) null } } finally { field1.isAccessible = accessible } } override fun hasAnnotation(annotationClass: KClass): Boolean { return field1.isAnnotationPresent(annotationClass.java) } } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/proxy/ProxyBinding.kt ================================================ package com.aether.core.runtime.proxy import com.aether.core.runtime.ImportDirective import com.aether.core.runtime.reflectable.ComposeMirror import com.aether.core.runtime.reflectable.ComposeReflector import java.lang.reflect.Modifier import kotlin.reflect.KClass import kotlin.reflect.full.createInstance import kotlin.reflect.jvm.javaMethod // 假设 BindingBase 是一个基础类 open class BindingBase { open fun initInstances() { println("BindingBase initInstances called") } } // ProxyBinding 类,使用继承代替 mixin class ProxyBinding : BindingBase() { companion object { private var _instance: ProxyBinding? = null // 单例访问方法 val instance: ProxyBinding? get() = _instance } override fun initInstances() { super.initInstances() _instance = this initializeReflectable() initializeProxy() } // 初始化反射相关的逻辑 private fun initializeReflectable() { println("Initializing reflectable...") } // 初始化代理相关的逻辑 private fun initializeProxy() { println("Initializing proxy...") } // 根据类型名称获取类镜像 fun getProxyClassForName2(typeName: String): ComposeReflector? { return ComposeMirror.getReflector(typeName) } // 根据类型名称获取类镜像 fun getProxyClassForName(directive: ImportDirective?): KClass<*>? { // 假设 p.data 是一个存储类型映射的全局变量 // 尝试通过反射加载类 if (directive == null) { return null } return try { //parseKtClass(directive.uri, "", ArrayList()) Class.forName(directive.uri).kotlin } catch (e: ClassNotFoundException) { println("Class not found for type: ${directive.name}") null } } fun parseKtClass(className: String, methodName: String, methodArgs: List<*>) { // 假设这是从 PSI 解析生成的 Map val parsedMap: Map = mapOf( "className" to "org.example.MyClass", "methodName" to "myMethod", "methodArgs" to listOf("arg1", "arg2") ) // // 动态加载类并调用方法 // val className = parsedMap["className"] as String // val methodName = parsedMap["methodName"] as String // val methodArgs = parsedMap["methodArgs"] as List<*> try { // 1. 动态加载类 val clazz: Class<*> = Class.forName(className) val kClass: KClass<*> = clazz.kotlin // 2. 获取目标方法 val memberFunction = kClass.members.find { it.name == methodName } ?: throw NoSuchMethodException("No such method: $methodName") // 3. 调用方法 if (memberFunction is kotlin.reflect.KFunction<*>) { // 创建实例(如果需要) val instance = if (!clazz.isInterface && !Modifier.isStatic( memberFunction.javaMethod?.modifiers ?: 0 ) ) { clazz.getDeclaredConstructor().newInstance() } else { null } // 调用方法 val result = memberFunction.call(instance, *methodArgs.toTypedArray()) println("Result of $methodName: $result") } else { throw IllegalArgumentException("$methodName is not a callable function") } } catch (e: Exception) { e.printStackTrace() } } } // 假设的全局数据源 p.data object p { val data: Map> = mapOf( "ExampleType" to ExampleType::class.java ) } // 示例类 class ExampleType fun mainTest() { // // 创建并初始化 ProxyBinding 实例 // val proxyBinding = ProxyBinding() // proxyBinding.initInstances() // // // 获取当前实例 // val currentInstance = ProxyBinding.instance // println("Current ProxyBinding instance: $currentInstance") // // // 测试 getProxyClassForName 方法 // val proxyClass = currentInstance?.getProxyClassForName("ExampleType") // println("Proxy class for 'ExampleType': $proxyClass") // // val invalidClass = currentInstance?.getProxyClassForName("InvalidType") // println("Proxy class for 'InvalidType': $invalidClass") } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ClassMirror.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable import kotlin.reflect.KClass abstract class ClassMirror : TypeMirror() { // /** // * 当前类所实现的所有接口的镜像列表。 // */ // abstract val superinterfaces: List /** * 返回当前类中显式声明的所有成员的不可变映射。 * * 包括方法、getter、setter、字段、构造函数等。 * 不包括继承来的成员。 * * 映射以简单名称为键,[DeclarationMirror] 为值。 * * 所需能力: [DeclarationsCapability] */ abstract val declarations: Map /** * 返回实例可以访问的所有成员(包括继承的)。 * * 包括方法、getter、setter。 * 字段本身不包含,但其 getter/setter 会被包含。 * * 映射以简单名称为键,[MethodMirror] 为值。 * * 所需能力: [DeclarationsCapability] */ abstract val instanceMembers: Map /** * 返回类的静态方法、getter 和 setter。 * * 映射以简单名称为键,[MethodMirror] 为值。 * * 所需能力: [DeclarationsCapability] */ abstract val staticMembers: Map /** * 调用指定名称的构造函数并返回结果。 * * @param constructorName 构造函数名(空字符串表示默认构造函数) * @param positionalArguments 位置参数列表 * @param namedArguments 命名参数映射 */ abstract fun newInstance( constructorName: String, positionalArguments: List, namedArguments: Map? = null ): Any? } /** * 表示类型相关的镜像信息。 */ abstract class TypeMirror : DeclarationMirror() { } /** * 代表方法或访问器的镜像。 */ abstract class MethodMirror : DeclarationMirror() { abstract val isStatic: Boolean @Composable abstract fun invoke(args: List?, namedArgs: Map?): Any? } data class Symbol(val name: String) typealias Type = KClass<*> ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ClassMirrorBase.kt ================================================ package com.aether.core.runtime.reflectable open class ClassMirrorBase( override val simpleName: String, override val qualifiedName: String, ) : ClassMirror(), ObjectMirror { override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { TODO("Not yet implemented") } override fun invokeGetter(getterName: String): Any? { TODO("Not yet implemented") } override fun invokeSetter(setterName: String, value: Any?): Any? { TODO("Not yet implemented") } override val declarations: Map get() = TODO("Not yet implemented") override val instanceMembers: Map get() = TODO("Not yet implemented") override val staticMembers: Map get() = TODO("Not yet implemented") override fun newInstance( constructorName: String, positionalArguments: List, namedArguments: Map? ): Any? { return null } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ComposeComponentDescriptor.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable import com.aether.core.runtime.Expression import com.aether.core.runtime.executeExpression // 定义一个描述Compose组件的类,不包含@Composable注解 class ComposeComponentDescriptor( val componentPath: String, val positionalArguments: List?, val namedArguments: Map?, val children: List? ) class ComposeComponentDescriptor2( val methodMirror: MethodMirror?, val componentPath: String, val positionalArguments: List?, val namedArguments: Map?, val children: List? = null ) // 然后在@Composable函数中使用这个描述符 @Composable fun RenderComponent(descriptor: ComposeComponentDescriptor) { ComposeComponentFactory.createComponent( descriptor.componentPath, descriptor.positionalArguments, descriptor.namedArguments, descriptor.children ) } // 然后在@Composable函数中使用这个描述符 @Composable fun RenderComponent( componentPath: String, arguments: List? ) { var mutableList = mutableListOf() val expression = arguments?.get(0) var text = "Default Text" expression?.let { text = executeExpression(expression) as String mutableList.add(text) } // ComposeComponentFactory.createComponent2( // componentPath, // mutableList // ) } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ComposeComponentRegistry.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.aether.core.runtime.Argument import com.aether.core.runtime.Expression import com.aether.core.runtime.executeExpression import com.aether.core.runtime.reflectable.widgets.ColumnMirror import com.aether.core.runtime.reflectable.widgets.MaterialThemeMirror import com.aether.core.runtime.reflectable.widgets.TextMirror import com.aether.core.runtime.reflectable.widgets.TextStyleMirror import com.aether.core.runtime.reflectable.widgets.TypographyMirror // 在你的代码中添加一个辅助类来映射Compose组件 /** * Compose组件工厂 * 提供创建Compose组件的方法 */ public object ComposeComponentFactory { private val componentFactories = mutableMapOf) -> Unit>() fun registerComponent( name: String, factory: @Composable (Map) -> Unit ) { componentFactories[name] = factory } @Composable fun createComponent2( name: String, arguments: Map = emptyMap() ) { val factory = componentFactories[name] if (factory != null) { factory(arguments) } else { // 处理未找到组件的情况 } } // 创建动态Composable组件 @Composable fun createComponent( componentPath: String?, positionalArguments: List?, namedArguments: Map?, children: List? ) { // 创建属性映射以存储解析后的参数 val props = mutableMapOf() when (componentPath) { "androidx.compose.material.Text" -> { // 设置默认值 props["modifier"] = Modifier.padding(16.dp) ComposeMirror.getReflector(componentPath)?.invoke(namedArguments) } "androidx.compose.material.MaterialTheme" -> { val mergedArgs = namedArguments?.toMutableMap() ?: mutableMapOf() // 使用反射器渲染Column ComposeMirror.getReflector(componentPath)?.invoke(mergedArgs) ?: fallbackColumn( mergedArgs, children ) } "androidx.compose.material.Typography" -> { val mergedArgs = namedArguments?.toMutableMap() ?: mutableMapOf() // 使用反射器渲染Column ComposeMirror.getReflector(componentPath)?.invoke(mergedArgs) ?: fallbackColumn( mergedArgs, children ) } "androidx.compose.foundation.layout.Column" -> { // 为Column组件添加子组件信息 val mergedArgs = namedArguments?.toMutableMap() ?: mutableMapOf() // 将子组件信息添加到参数中 mergedArgs["children"] = children // 使用反射器渲染Column ComposeMirror.getReflector(componentPath)?.invoke(mergedArgs) ?: fallbackColumn( mergedArgs, children ) } // 可以继续添加更多组件... else -> { Text("未实现的组件: $componentPath") } } } // 备用Column实现,当反射器不可用时使用 @Composable private fun fallbackColumn( args: Map, children: List? ) { // Column( // modifier = (args["modifier"] as? Modifier) ?: Modifier // .fillMaxSize() // .padding(16.dp), // verticalArrangement = (args["verticalArrangement"] as? Arrangement.Vertical) // ?: Arrangement.spacedBy(8.dp), // horizontalAlignment = (args["horizontalAlignment"] as? Alignment.Horizontal) // ?: Alignment.CenterHorizontally // ) { // // 渲染子组件 // children?.forEach { childDescriptor -> // createComponent( // childDescriptor.componentPath, // childDescriptor.positionalArguments, // childDescriptor.namedArguments, // childDescriptor.children // ) // } // } } // 注册生成的反射器的初始化函数 fun initializeComposeMirrors() { // 这里会被生成的代码调用,注册所有反射器 // 例如自动生成的TextMirror ComposeMirror.register( "androidx.compose.material.Text", TextMirror( simpleName = "Text", "androidx.compose.material.Text" ) ) ComposeMirror.register( "androidx.compose.foundation.layout.Column", ColumnMirror( simpleName = "Column", qualifiedName = "androidx.compose.foundation.layout.Column" ) ) ComposeMirror.register( "androidx.compose.material.MaterialTheme", MaterialThemeMirror( simpleName = "MaterialTheme", qualifiedName = "androidx.compose.material.MaterialTheme" ) ) ComposeMirror.register( "androidx.compose.material.Typography", TypographyMirror( simpleName = "Typography", qualifiedName = "androidx.compose.material.Typography" ) ) ComposeMirror.register( "androidx.compose.ui.text.TextStyle", TextStyleMirror( simpleName = "TextStyle", qualifiedName = "androidx.compose.ui.text.TextStyle" ) ) } private fun initReflect() { } // 注册表,用于检查组件是否可用 private val availableComponents = setOf( "androidx.compose.material.Text", "androidx.compose.material.Button", "androidx.compose.foundation.layout.Column", "androidx.compose.foundation.layout.Row", // 添加更多组件... ) // 检查组件是否可用 fun isComponentAvailable(path: String): Boolean { return availableComponents.contains(path) } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ComposeMirror.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable object ComposeMirror { private val reflectors = mutableMapOf() fun register(name: String, reflector: ComposeReflector) { reflectors[name] = reflector } fun getReflector(name: String): ComposeReflector? { return reflectors[name] } @Composable fun render(name: String, args: Map?) { reflectors[name]?.invoke(args) ?: error("No reflector found for $name") } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ComposeMirrorRuntime.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable import kotlin.reflect.KClass import kotlin.reflect.full.createInstance import kotlin.reflect.full.memberFunctions import kotlin.reflect.full.memberProperties class ComposeMirrorRuntime { private val mirrorCache = mutableMapOf() fun createMirror(clazz: KClass, params: List = emptyList()): T { val mirrorClassName = "${clazz.simpleName}Mirror" val mirrorClass = try { Class.forName("${clazz.qualifiedName}$mirrorClassName") } catch (e: ClassNotFoundException) { throw IllegalStateException("Mirror class not found for ${clazz.qualifiedName}. Make sure the class is annotated with @ComposeMirror") } val mirrorInstance = mirrorClass.getDeclaredMethod("invoke", List::class.java) .invoke(null, params) as T mirrorCache[clazz.qualifiedName!!] = mirrorInstance return mirrorInstance } fun invokeComposable(mirror: Any, functionName: String, vararg args: Any?): Any? { val clazz = mirror::class val composableFunction = clazz.memberFunctions.find { it.name == functionName } ?: throw IllegalArgumentException("No composable function named $functionName found") if (!composableFunction.annotations.any { it is Composable }) { throw IllegalArgumentException("Function $functionName is not a @Composable function") } return composableFunction.call(mirror, *args) } fun getProperty(mirror: Any, propertyName: String): Any? { val clazz = mirror::class val property = clazz.memberProperties.find { it.name == propertyName } ?: throw IllegalArgumentException("No property named $propertyName found") return property.getter.call(mirror) } fun setProperty(mirror: Any, propertyName: String, value: Any?) { val clazz = mirror::class val property = clazz.memberProperties.find { it.name == propertyName } ?: throw IllegalArgumentException("No property named $propertyName found") if (property is kotlin.reflect.KMutableProperty<*>) { property.setter.call(mirror, value) } else { throw IllegalArgumentException("Property $propertyName is not mutable") } } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ComposeReflectRuntime.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable import kotlin.reflect.KClass import kotlin.reflect.full.createInstance import kotlin.reflect.full.memberFunctions import kotlin.reflect.full.memberProperties class ComposeReflectRuntime { private val reflectCache = mutableMapOf() fun createReflect(clazz: KClass): T { val reflectClassName = "${clazz.simpleName}Reflect" val reflectClass = try { Class.forName("${clazz.qualifiedName}$reflectClassName") } catch (e: ClassNotFoundException) { throw IllegalStateException("Reflect class not found for ${clazz.qualifiedName}. Make sure the class is annotated with @ComposeReflect") } val instance = clazz.createInstance() val reflectInstance = reflectClass.getDeclaredConstructor(clazz.java) .newInstance(instance) as T reflectCache[clazz.qualifiedName!!] = reflectInstance return reflectInstance } fun invokeComposable(reflect: Any, functionName: String, vararg args: Any?): Any? { val clazz = reflect::class val reflectFunction = clazz.memberFunctions.find { it.name == "invoke$functionName" } ?: throw IllegalArgumentException("No reflectable function named $functionName found") return reflectFunction.call(reflect, *args) } fun getProperty(reflect: Any, propertyName: String): Any? { val clazz = reflect::class val property = clazz.memberProperties.find { it.name == propertyName } ?: throw IllegalArgumentException("No property named $propertyName found") return property.getter.call(reflect) } fun setProperty(reflect: Any, propertyName: String, value: Any?) { val clazz = reflect::class val property = clazz.memberProperties.find { it.name == propertyName } ?: throw IllegalArgumentException("No property named $propertyName found") if (property is kotlin.reflect.KMutableProperty<*>) { property.setter.call(reflect, value) } else { throw IllegalArgumentException("Property $propertyName is not mutable") } } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/DeclarationMirror.kt ================================================ package com.aether.core.runtime.reflectable abstract class DeclarationMirror : Mirror { /** * 返回此声明的简单名称。 * * 简单名称通常是该实体的标识符名,例如: * - 方法名 "myMethod" * - 类名 "MyClass" * - 库名 "mylibrary" */ abstract val simpleName: String /** * 返回此声明的完全限定名称。 * * 例如:库 "lib" 中的类 "MyClass" 中的方法 "myMethod" 的完全限定名为: * "lib.MyClass.myMethod" */ abstract val qualifiedName: String /** * 判断此声明是否为库私有(以 `_` 开头)。 * * 对于库本身,始终返回 false。 */ // abstract val isPrivate: Boolean /** * 判断此声明是否是顶级声明(拥有者是库)。 */ // abstract val isTopLevel: Boolean } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/MethodMirrorImpl.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable class MethodMirrorImpl(override val isStatic: Boolean, val invoke: @Composable (args: List?, namedArgs: Map?) -> Any?, override val simpleName: String, override val qualifiedName: String ) :MethodMirror() { @Composable override fun invoke( args: List?, namedArgs: Map? ): Any? { return invoke.invoke(args, namedArgs) } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/Mirror.kt ================================================ package com.aether.core.runtime.reflectable //Mirror 接口作为父接口存在。 interface Mirror { } interface ObjectMirror : Mirror { /** * 调用函数或方法 [memberName],返回结果。 * * @param memberName 方法名 * @param positionalArguments 位置参数列表 * @param namedArguments 命名参数映射(Symbol -> value) * * 实现逻辑应模拟 o.memberName(positionalArguments..., k1 = v1, ...) * 并支持访问私有成员。 */ fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? = null ): Any? /** * 调用 getter 方法并返回结果。 * * 如果是实例镜像且 [getterName] 是方法,则返回闭包。 * 如果是库镜像且 [getterName] 是顶层方法,则返回闭包。 * 如果是类镜像且 [getterName] 是静态方法,则返回闭包。 */ fun invokeGetter(getterName: String): Any? /** * 调用 setter 方法并返回结果。 * * setter 名称可以带 `=`,也可以不带,内部会自动处理。 */ fun invokeSetter(setterName: String, value: Any?): Any? } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/ParamInfo.kt ================================================ package com.aether.core.runtime.reflectable import androidx.compose.runtime.Composable // 参数信息 data class ParamInfo( val name: String, val type: String, val isOptional: Boolean ) // 组件反射接口 abstract class ComposeReflector( simpleName: String, qualifiedName: String ) : ClassMirrorBase( simpleName, qualifiedName ) { @Composable abstract fun invoke(args: Map?): Any? } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/widgets/ColumnMirror.kt ================================================ package com.aether.core.runtime.reflectable.widgets import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeComponentFactory.createComponent import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.DeclarationMirror import com.aether.core.runtime.reflectable.MethodMirror import com.aether.core.runtime.reflectable.ParamInfo class ColumnMirror( simpleName: String, qualifiedName: String ) : ComposeReflector(simpleName, qualifiedName) { override val simpleName: String = "Column" @Composable override fun invoke(args: Map?): Int { if (args == null) { Column { Text("No Column UI, please check args") } return 0 as Int } // 从参数映射中提取可选参数 val modifier = args["modifier"] as? Modifier ?: Modifier val verticalArrangement = args["verticalArrangement"] as? Arrangement.Vertical ?: Arrangement.Top val horizontalAlignment = args["horizontalAlignment"] as? Alignment.Horizontal ?: Alignment.Start // 获取内容函数 val children = args["children"] as? List // 调用实际的Column组件 Column( modifier = modifier, verticalArrangement = verticalArrangement, horizontalAlignment = horizontalAlignment ) { // 如果提供了子组件列表,则渲染它们 children?.forEach { childDescriptor -> createComponent( childDescriptor.componentPath, childDescriptor.positionalArguments, childDescriptor.namedArguments, childDescriptor.children ) } } return 1 as Int } // override val params: List = listOf( // ParamInfo( // name = "modifier", type = "androidx.compose.ui.Modifier", isOptional = true // ), ParamInfo( // name = "verticalArrangement", // type = "androidx.compose.foundation.layout.Arrangement.Vertical", // isOptional = true // ), ParamInfo( // name = "horizontalAlignment", // type = "androidx.compose.ui.Alignment.Horizontal", // isOptional = true // ), ParamInfo( // name = "content", type = "androidx.compose.runtime.Composable", isOptional = false // ) // ) // @Composable // override fun invoke(args: Map?) { // if (args == null) { // Column { // Text("No Column UI, please check args") // } // return // } // // // 从参数映射中提取可选参数 // val modifier = args["modifier"] as? Modifier ?: Modifier // val verticalArrangement = args["verticalArrangement"] as? Arrangement.Vertical ?: Arrangement.Top // val horizontalAlignment = args["horizontalAlignment"] as? Alignment.Horizontal ?: Alignment.Start // // // 获取内容函数 // val children = args["children"] as? List // // // 调用实际的Column组件 // Column( // modifier = modifier, // verticalArrangement = verticalArrangement, // horizontalAlignment = horizontalAlignment // ) { // // 如果提供了子组件列表,则渲染它们 // children?.forEach { childDescriptor -> // createComponent( // childDescriptor.componentPath, // childDescriptor.positionalArguments, // childDescriptor.namedArguments, // childDescriptor.children // ) // } // } // } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/widgets/MaterialThemeMirror.kt ================================================ package com.aether.core.runtime.reflectable.widgets import android.util.Log import androidx.compose.material.MaterialTheme import androidx.compose.material.Typography import androidx.compose.runtime.Composable import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.MethodMirror import com.aether.core.runtime.reflectable.MethodMirrorImpl class MaterialThemeMirror( simpleName: String, qualifiedName: String ) : ComposeReflector( simpleName, qualifiedName ) { private var _staticMembers: Map? = null override val staticMembers: Map get() = _staticMembers ?: run { // Create a map to store MaterialTheme's static members val result = mutableMapOf() // Add Typography property result["typography"] = MethodMirrorImpl( simpleName = "typography", qualifiedName = "androidx.compose.material.Typography", isStatic = true, invoke = { _, _ -> MaterialTheme.typography } ) // Cache and return the immutable map result.toMap().also { _staticMembers = it } } @Composable override fun invoke(args: Map?): Int? { if (args == null) { Log.e("MaterialThemeMirror", "error: args :$args") return 0 as Int } val typography = args["typography"] as? Typography val content = args["content"] as? @Composable () -> Unit // 调用实际的Text组件 MaterialTheme( content = content ?: {}, typography = typography ?: MaterialTheme.typography ) return 1 as Int } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/widgets/TextMirror.kt ================================================ package com.aether.core.runtime.reflectable.widgets import android.graphics.fonts.FontFamily import android.os.Build import android.text.TextUtils import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme.typography import androidx.compose.material.Text import androidx.compose.material.Typography import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit import com.aether.core.runtime.reflectable.ClassMirror import com.aether.core.runtime.reflectable.ClassMirrorBase import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.DeclarationMirror import com.aether.core.runtime.reflectable.MethodMirror import com.aether.core.runtime.reflectable.MethodMirrorImpl import com.aether.core.runtime.reflectable.ParamInfo import com.aether.core.runtime.reflectable.RenderComponent import java.time.format.TextStyle import kotlin.collections.set /** * 自动生成的Text组件反射包装类 */ class TextMirror( simpleName: String, qualifiedName: String ) : ComposeReflector( simpleName, qualifiedName ) { override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { return super.invoke(memberName, positionalArguments, namedArguments) } @Composable override fun invoke(args: Map?): Int { if (args == null) { Text("NO Text UI please chack args") return 0 as Int } // 从参数映射中提取必要参数 val text = args["text"] as? String ?: "" // 从参数映射中提取可选参数 val modifier = args["modifier"] as? Modifier val color = args["color"] as? Color val fontSize = args["fontSize"] as? TextUnit val fontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { args["fontFamily"] as? FontFamily } else { TODO("VERSION.SDK_INT < Q") } val textAlign = args["textAlign"] as? TextAlign val styleTemp = args["style"] val maxLines = args["maxLines"] as? Int val overflow = args["overflow"] as? androidx.compose.ui.text.style.TextOverflow val style = if (styleTemp is ComposeComponentDescriptor) { val attribute = styleTemp.namedArguments?.get("attribute") as String if (TextUtils.equals(attribute, "h6")) { typography.h6 } else if (TextUtils.equals(attribute, "h5")) { typography.h5 } else if (TextUtils.equals(attribute, "h4")) { typography.h4 } else if (TextUtils.equals(attribute, "h3")) { typography.h3 } else if (TextUtils.equals(attribute, "h2")) { typography.h2 } else if (TextUtils.equals(attribute, "h1")) { typography.h1 } else { Typography().h1 } } else { Typography().h1 } // 调用实际的Text组件 Text( text = text, // modifier = modifier ?: Modifier, color = color ?: androidx.compose.ui.graphics.Color.Unspecified, fontSize = fontSize ?: TextUnit.Unspecified, // fontFamily = fontFamily, textAlign = textAlign, style = style, // maxLines = maxLines ?: Int.MAX_VALUE, overflow = overflow ?: TextOverflow.Clip ) return 1 as Int } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/widgets/TextStyleMirror.kt ================================================ package com.aether.core.runtime.reflectable.widgets import android.util.Log import androidx.compose.material.MaterialTheme import androidx.compose.material.Typography import androidx.compose.runtime.Composable import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.MethodMirror import com.aether.core.runtime.reflectable.MethodMirrorImpl class TextStyleMirror( simpleName: String, qualifiedName: String ) : ComposeReflector( simpleName, qualifiedName ) { private var _staticMembers: Map? = null override val staticMembers: Map get() = _staticMembers ?: run { // Create a map to store MaterialTheme's static members val result = mutableMapOf() // Add Typography property result["h6"] = MethodMirrorImpl( simpleName = "h6", qualifiedName = "androidx.compose.ui.text.TextStyle", isStatic = true, invoke = { _, _ -> } ) // Cache and return the immutable map result.toMap().also { _staticMembers = it } } override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { return TextStyle( ) } @Composable override fun invoke(args: Map?): Int? { if (args == null) { Log.e("TextStyleMirror", "error: args :$args") return 0 as Int } // 调用实际的Text组件 TextStyle( ) return 1 as Int } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/reflectable/widgets/TypographyMirror.kt ================================================ package com.aether.core.runtime.reflectable.widgets import android.text.TextUtils import android.util.Log import androidx.compose.material.MaterialTheme import androidx.compose.material.Typography import androidx.compose.runtime.Composable import androidx.compose.ui.text.font.FontWeight import com.aether.core.runtime.reflectable.ComposeComponentDescriptor import com.aether.core.runtime.reflectable.ComposeComponentDescriptor2 import com.aether.core.runtime.reflectable.ComposeMirror import com.aether.core.runtime.reflectable.ComposeReflector import com.aether.core.runtime.reflectable.MethodMirror import com.aether.core.runtime.reflectable.MethodMirrorImpl class TypographyMirror( simpleName: String, qualifiedName: String ) : ComposeReflector( simpleName, qualifiedName ) { private var _staticMembers: Map? = null override val staticMembers: Map get() = _staticMembers ?: run { // Create a map to store MaterialTheme's static members val result = mutableMapOf() // Add Typography property result["h6"] = MethodMirrorImpl( simpleName = "h6", qualifiedName = "androidx.compose.ui.text.TextStyle", isStatic = true, invoke = { _, _ -> } ) // Cache and return the immutable map result.toMap().also { _staticMembers = it } } @Composable override fun invoke(args: Map?): Typography? { if (args == null) { Log.e("MaterialThemeMirror", "error: args :$args") return null } val typography = MaterialTheme.typography val attribute = args[simpleName] as String if (TextUtils.equals(attribute, "h6")) { typography.h6 }else if (TextUtils.equals(attribute, "h5")) { typography.h5 } return typography } override fun invoke( memberName: String, positionalArguments: List, namedArguments: Map? ): Any? { if (namedArguments == null) { Log.e("MaterialThemeMirror", "error: args :$namedArguments") return null } val reflector = ComposeMirror.getReflector(memberName) val typography = namedArguments["typography"] as? Typography val content = namedArguments["content"] as? @Composable () -> Unit // 调用实际的Text组件 // return MaterialTheme.typography.h6 return null } } ================================================ FILE: core/src/main/java/com/aether/core/runtime/utils/JsonReader.kt ================================================ package com.aether.core.runtime.utils import android.content.Context import android.content.res.AssetManager import org.json.JSONException import org.json.JSONObject import java.io.IOException object JsonReader { fun readJsonFromAssets(context: Context, fileName: String): JSONObject? { var json: String? = null try { val assetManager: AssetManager = context.assets val inputStream = assetManager.open(fileName) val size = inputStream.available() val buffer = ByteArray(size) inputStream.read(buffer) inputStream.close() json = String(buffer, Charsets.UTF_8) } catch (ex: IOException) { ex.printStackTrace() return null } try { return JSONObject(json) } catch (e: JSONException) { e.printStackTrace() return null } } } ================================================ FILE: core/src/main/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: core/src/main/res/drawable/ic_launcher_foreground.xml ================================================ ================================================ FILE: core/src/main/res/mipmap-anydpi/ic_launcher.xml ================================================ ================================================ FILE: core/src/main/res/mipmap-anydpi/ic_launcher_round.xml ================================================ ================================================ FILE: core/src/main/res/values/colors.xml ================================================ #FFBB86FC #FF6200EE #FF3700B3 #FF03DAC5 #FF018786 #FF000000 #FFFFFFFF ================================================ FILE: core/src/main/res/values/strings.xml ================================================ core ================================================ FILE: core/src/main/res/values/themes.xml ================================================ ================================================ FILE: core/src/main/res/values-night/themes.xml ================================================ ================================================ FILE: core/src/test/java/com/aether/core/ExampleUnitTest.kt ================================================ package com.aether.core import org.junit.Test import org.junit.Assert.* /** * Example local unit test, which will execute on the development machine (host). * * See [testing documentation](http://d.android.com/tools/testing). */ class ExampleUnitTest { @Test fun addition_isCorrect() { assertEquals(4, 2 + 2) } } ================================================ FILE: core/src/test/java/com/aether/core/compose/ColumArgsComposeExpressText.kt ================================================ package com.aether.core.compose import androidx.compose.foundation.layout.Column import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color class ColumArgsComposeExpressText { @Composable fun Main() { Column { Column( ) { Text( text = "主标题 1", style = MaterialTheme.typography.h4, ) Text( text = "副标题 1", style = MaterialTheme.typography.h5, ) } Column( ) { Text( text = "主标题 2", style = MaterialTheme.typography.h4, ) Text( text = "副标题 3", style = MaterialTheme.typography.h5, ) } Column( ) { Text( text = "主标题 2", style = MaterialTheme.typography.h4, ) Text( text = "副标题 3", style = MaterialTheme.typography.h5, ) } } } } ================================================ FILE: core/src/test/java/com/aether/core/compose/ColumComposeNameExpressText.kt ================================================ package com.aether.core.compose import androidx.compose.foundation.layout.Column import androidx.compose.material.Text import androidx.compose.runtime.Composable class ColumComposeNameExpressText { @Composable fun Main() { Column { Text( text = "1这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", minLines = 1, ) Text( text = "2这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", minLines = 1, ) Text( text = "3这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", minLines = 1, ) Text( text = "4这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", minLines = 1, ) } } } ================================================ FILE: core/src/test/java/com/aether/core/compose/DemoCompose.kt ================================================ package com.aether.core.compose import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color class DemoCompose { // @Composable // fun Main() { // Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { // Button(onClick = { }) { // Text("Click me!") // } // Column( // Modifier.fillMaxWidth(), // horizontalAlignment = Alignment.CenterHorizontally // ) { // Text("这是一个KMP加载的动态化的View") // } // } // } //} // Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { // Button(onClick = {}) { // Text("Click me!") // } // Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { // Box( // modifier = Modifier // .height(100.dp) // .fillMaxWidth() // .padding(16.dp) // 设置外部边缘(padding) // .clip(RoundedCornerShape(10.dp)) // 设置圆角半径为10dp // .background(Color(0xFFD1EAFB)), // 设置背景颜色 // contentAlignment = Alignment.Center // 将 Text 垂直和水平居中 // ) { // Text("一个标题") // } // } // } // Text("这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换") // } @Composable fun Main() { Text( "这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", color = Color.Red ) } } ================================================ FILE: core/src/test/java/com/aether/core/compose/DemoComposeColor.kt ================================================ package com.aether.core.compose import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color class DemoComposeColor { @Composable fun Main() { Text( "这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", ) } } ================================================ FILE: core/src/test/java/com/aether/core/compose/NameExpressComposeNameExpressText.kt ================================================ package com.aether.core.compose import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color class NameExpressComposeNameExpressText { @Composable fun Main() { Text( text = "text=这个一个最小试验单位的动态化卡片,它的产物来自云端打包编译,可以根据产品诉求随意替换", minLines = 1, ) } } ================================================ FILE: core/src/test/java/com/aether/core/express/ArgsComposeTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.junit.Test import java.io.File class ArgsComposeTest { @Test fun mainTest() { val localFile = AstRuntime.LocalJson(getDefaultJson()) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5, "a")) System.out.println("动态化引擎输出结果:" + test2) } @Test fun generateJson() { val targetDirectory = File("src/test/java/com/aether/core/compose/DemoComposeColor.kt") val json = AstRuntime.GeneraJson(targetDirectory).createNodeToJson() System.out.println("生成的dsl:" + json) } companion object { fun getDefaultJson(): String { return "" } } } ================================================ FILE: core/src/test/java/com/aether/core/express/ColumArgsExpressComposeTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.junit.Test import java.io.File class ColumArgsExpressComposeTest { @Test fun generateJson() { val targetDirectory = File("src/test/java/com/aether/core/compose/ColumArgsComposeExpressText.kt") val json = AstRuntime.GeneraJson(targetDirectory).createNodeToJson() System.out.println("生成的dsl:" + json) } } ================================================ FILE: core/src/test/java/com/aether/core/express/ColumExpressComposeTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.junit.Test import java.io.File class ColumExpressComposeTest { @Test fun mainTest() { val localFile = AstRuntime.LocalJson(getDefaultJson()) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5, "a")) System.out.println("动态化引擎输出结果:" + test2) } @Test fun generateJson() { val targetDirectory = File("src/test/java/com/aether/core/compose/ColumComposeNameExpressText.kt") val json = AstRuntime.GeneraJson(targetDirectory).createNodeToJson() System.out.println("生成的dsl:" + json) } companion object { fun getDefaultJson(): String { return "" } } } ================================================ FILE: core/src/test/java/com/aether/core/express/DemoEmptyFunctionExpress.kt ================================================ package com.aether.core.express object DemoEmptyFunctionExpress { /** * result =10 * result2 =10 * index = 5 */ fun test2(index: Int, item: String): Int { val a = 2 val b = 2 + index return a * b } } ================================================ FILE: core/src/test/java/com/aether/core/express/DemoFunctionExpress.kt ================================================ package com.aether.core.express import com.aether.core.express.DemoTest import com.aether.core.express.InstanceTest import org.jline.utils.Display import org.jline.utils.Log object DemoFunctionExpress { /** * result =10 * result2 =10 * index = 5 */ fun test2(index: Int, item: String): Int { val result = DemoTest.demo1Test1() val result2 = DemoTest.demo1Test2() Log.info(1,23,456) val instanceTest = InstanceTest(18) instanceTest.triggerTest() val a = 2 val b = 2 + index return a * b + result + result2 } } ================================================ FILE: core/src/test/java/com/aether/core/express/DemoTest.kt ================================================ package com.aether.core.express class DemoTest { companion object{ fun demo1Test1(): Int { return 10 } fun demo1Test2(): Int { return 10 } } fun test2(index: Int): Int { val a = 1 val b = 2 return a + b } } ================================================ FILE: core/src/test/java/com/aether/core/express/InstanceComposeTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.jline.utils.Log import org.junit.Test import java.io.File class InstanceComposeTest { @Test fun mainTest() { val localFile = AstRuntime.LocalJson(getDefaultJson()) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5, "a")) System.out.println("动态化引擎输出结果:" + test2) } @Test fun generateJson() { val targetDirectory = File("src/test/java/com/aether/core/compose/DemoCompose.kt") val json = AstRuntime.GeneraJson(targetDirectory).createNodeToJson() System.out.println("生成的dsl:" + json) } companion object { fun getDefaultJson(): String { return "{\n" + " \"directives\" : [ {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.foundation.layout.Column\",\n" + " \"alias\" : null,\n" + " \"name\" : \"Column\"\n" + " }, {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.foundation.layout.padding\",\n" + " \"alias\" : null,\n" + " \"name\" : \"padding\"\n" + " }, {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.material.Text\",\n" + " \"alias\" : null,\n" + " \"name\" : \"Text\"\n" + " }, {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.runtime.Composable\",\n" + " \"alias\" : null,\n" + " \"name\" : \"Composable\"\n" + " }, {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.ui.Modifier\",\n" + " \"alias\" : null,\n" + " \"name\" : \"Modifier\"\n" + " }, {\n" + " \"type\" : \"ImportDirective\",\n" + " \"importPath\" : \"androidx.compose.ui.unit.dp\",\n" + " \"alias\" : null,\n" + " \"name\" : \"dp\"\n" + " } ],\n" + " \"declarations\" : [ {\n" + " \"type\" : \"ClassDeclaration\",\n" + " \"name\" : \"DemoCompose\",\n" + " \"members\" : [ {\n" + " \"type\" : \"MethodDeclaration\",\n" + " \"name\" : \"Main\",\n" + " \"parameters\" : [ ],\n" + " \"typeParameters\" : [ ],\n" + " \"body\" : {\n" + " \"type\" : \"BlockStatement\",\n" + " \"body\" : [ {\n" + " \"type\" : \"InstanceCreationExpression\",\n" + " \"constructorName\" : \"Text\",\n" + " \"argumentList\" : {\n" + " \"type\" : \"ArgumentList\",\n" + " \"arguments\" : [ {\n" + " \"type\" : \"Argument\",\n" + " \"body\" : {\n" + " \"type\" : \"StringTemplateExpression\",\n" + " \"name\" : null,\n" + " \"body\" : {\n" + " \"type\" : \"StringTemplateEntry\",\n" + " \"body\" : null,\n" + " \"value\" : \"Asset content from demo\"\n" + " }\n" + " }\n" + " } ]\n" + " },\n" + " \"valueArgument\" : [ ]\n" + " } ]\n" + " },\n" + " \"isStatic\" : false,\n" + " \"isGetter\" : true,\n" + " \"isSetter\" : false\n" + " } ],\n" + " \"body\" : { }\n" + " } ],\n" + " \"type\" : \"CompilationUnit\"\n" + "}" } } } ================================================ FILE: core/src/test/java/com/aether/core/express/InstanceCreationExpressionTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.jline.utils.Log import org.junit.Test import java.io.File class InstanceCreationExpressionTest { @Test fun mainTest() { val targetDirectory = File("src/test/java/com/aether/core/express/DemoFunctionExpress.kt") val localFile = AstRuntime.LocalFile(targetDirectory) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5,"a")) System.out.println("动态化引擎输出结果:" + test2) } } ================================================ FILE: core/src/test/java/com/aether/core/express/InstanceJsonEmptyCreationExpressionTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.junit.Test class InstanceJsonEmptyCreationExpressionTest { @Test fun mainTest() { val localFile = AstRuntime.LocalJson(getDefaultJson()) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5,"a")) System.out.println("动态化引擎输出结果:" + test2) } fun getDefaultJson(): String { return "{\n" + " \"directives\" : [ ],\n" + " \"declarations\" : [ {\n" + " \"type\" : \"ClassDeclaration\",\n" + " \"name\" : \"DemoEmptyFunctionExpress\",\n" + " \"members\" : [ {\n" + " \"type\" : \"MethodDeclaration\",\n" + " \"name\" : \"test2\",\n" + " \"parameters\" : [ {\n" + " \"type\" : \"SimpleFormalParameter\",\n" + " \"name\" : \"index\",\n" + " \"typeName\" : \"Int\"\n" + " }, {\n" + " \"type\" : \"SimpleFormalParameter\",\n" + " \"name\" : \"item\",\n" + " \"typeName\" : \"String\"\n" + " } ],\n" + " \"typeParameters\" : [ ],\n" + " \"body\" : {\n" + " \"type\" : \"BlockStatement\",\n" + " \"body\" : [ {\n" + " \"type\" : \"PropertyStatement\",\n" + " \"name\" : \"a\",\n" + " \"initializer\" : {\n" + " \"type\" : \"INTEGER_CONSTANT\",\n" + " \"value\" : \"2\",\n" + " \"name\" : \"ConstantExpression\"\n" + " }\n" + " }, {\n" + " \"type\" : \"PropertyStatement\",\n" + " \"name\" : \"b\",\n" + " \"initializer\" : {\n" + " \"type\" : \"BinaryExpression\",\n" + " \"name\" : null,\n" + " \"operator\" : \"+\",\n" + " \"left\" : {\n" + " \"type\" : \"INTEGER_CONSTANT\",\n" + " \"value\" : \"2\",\n" + " \"name\" : \"ConstantExpression\"\n" + " },\n" + " \"right\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"index\"\n" + " }\n" + " }\n" + " }, {\n" + " \"type\" : \"ReturnStatement\",\n" + " \"argument\" : {\n" + " \"type\" : \"BinaryExpression\",\n" + " \"name\" : null,\n" + " \"operator\" : \"*\",\n" + " \"left\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"a\"\n" + " },\n" + " \"right\" : {\n" + " \"type\" : \"Identifier\",\n" + " \"name\" : \"b\"\n" + " }\n" + " }\n" + " } ]\n" + " },\n" + " \"isStatic\" : true,\n" + " \"isGetter\" : false,\n" + " \"isSetter\" : false\n" + " } ],\n" + " \"body\" : { }\n" + " } ],\n" + " \"type\" : \"CompilationUnit\"\n" + "}" } } ================================================ FILE: core/src/test/java/com/aether/core/express/InstanceTest.kt ================================================ package com.aether.core.express import org.jline.utils.Log class InstanceTest { private var age = 18; private val name = "zhangsan"; private val TAG = "InstanceTest"; companion object { private val name2 = "wangwu"; } constructor(age: Int) { } fun triggerTest(): Int { Log.info(TAG, ": wode :" + triggerTest2(2)) return age } fun triggerTest2(index: Int): Int { return index + 1 } } ================================================ FILE: core/src/test/java/com/aether/core/express/NameExpressComposeTest.kt ================================================ package com.aether.core.express import com.aether.core.runtime.AstRuntime import org.junit.Test import java.io.File class NameExpressComposeTest { @Test fun mainTest() { val localFile = AstRuntime.LocalJson(getDefaultJson()) val node = localFile.createNode() val runtime = AstRuntime(node); val test2 = runtime.invoke("test2", mutableListOf(5, "a")) System.out.println("动态化引擎输出结果:" + test2) } @Test fun generateJson() { val targetDirectory = File("src/test/java/com/aether/core/compose/NameExpressComposeNameExpressText.kt") val json = AstRuntime.GeneraJson(targetDirectory).createNodeToJson() System.out.println("生成的dsl:" + json) } companion object { fun getDefaultJson(): String { return "" } } } ================================================ FILE: core/src/test/java/com/aether/core/runtime/ExampleUnitTest.kt ================================================ package com.aether.core.runtime import org.junit.Test import org.junit.Assert.* /** * Example local unit test, which will execute on the development machine (host). * * See [testing documentation](http://d.android.com/tools/testing). */ class ExampleUnitTest { @Test fun addition_isCorrect() { assertEquals(4, 2 + 2) } } ================================================ FILE: gradle/libs.versions.toml ================================================ [versions] agp = "8.2.0" android-compileSdk = "34" android-minSdk = "26" android-targetSdk = "34" androidx-activityCompose = "1.8.2" androidx-appcompat = "1.7.0" androidx-constraintlayout = "2.2.1" androidx-core-ktx = "1.12.0" androidx-espresso-core = "3.6.1" androidx-lifecycle = "2.8.4" androidx-material = "1.12.0" androidx-test-junit = "1.2.1" compose-multiplatform = "1.6.0" junit = "4.13.2" kotlin = "1.8.22" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" } androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } androidLibrary = { id = "com.android.library", version.ref = "agp" } composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" } composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Mon Apr 07 01:51:47 CST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: gradle.properties ================================================ #Kotlin kotlin.code.style=official kotlin.daemon.jvmargs=-Xmx2048M #Gradle org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 #Android android.nonTransitiveRClass=true android.useAndroidX=true android.enableAapt2Daemon=false android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.mpp.androidGradlePluginCompatibility.nowarn=true ================================================ FILE: gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # 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 # # https://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. # # SPDX-License-Identifier: Apache-2.0 # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s ' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @rem SPDX-License-Identifier: Apache-2.0 @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: iosApp/Configuration/Config.xcconfig ================================================ TEAM_ID= BUNDLE_ID=org.example.project.KotlinProject APP_NAME=KotlinProject ================================================ FILE: iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json ================================================ { "colors" : [ { "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "filename" : "app-icon-1024.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: iosApp/iosApp/Assets.xcassets/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: iosApp/iosApp/ContentView.swift ================================================ import UIKit import SwiftUI import ComposeApp struct ComposeView: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIViewController { MainViewControllerKt.MainViewController() } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} } struct ContentView: View { var body: some View { ComposeView() .ignoresSafeArea(.keyboard) // Compose has own keyboard handler } } ================================================ FILE: iosApp/iosApp/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS CADisableMinimumFrameDurationOnPhone UIApplicationSceneManifest UIApplicationSupportsMultipleScenes UILaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: iosApp/iosApp/iOSApp.swift ================================================ import SwiftUI @main struct iOSApp: App { var body: some Scene { WindowGroup { ContentView() } } } ================================================ FILE: iosApp/iosApp.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 56; objects = { /* Begin PBXBuildFile section */ 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; }; 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; }; 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; }; 7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = ""; }; 7555FF7B242A565900829871 /* KotlinProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KotlinProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ B92378962B6B1156000C7307 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 058557D7273AAEEB004C7B11 /* Preview Content */ = { isa = PBXGroup; children = ( 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */, ); path = "Preview Content"; sourceTree = ""; }; 42799AB246E5F90AF97AA0EF /* Frameworks */ = { isa = PBXGroup; children = ( ); name = Frameworks; sourceTree = ""; }; 7555FF72242A565900829871 = { isa = PBXGroup; children = ( AB1DB47929225F7C00F7AF9C /* Configuration */, 7555FF7D242A565900829871 /* iosApp */, 7555FF7C242A565900829871 /* Products */, 42799AB246E5F90AF97AA0EF /* Frameworks */, ); sourceTree = ""; }; 7555FF7C242A565900829871 /* Products */ = { isa = PBXGroup; children = ( 7555FF7B242A565900829871 /* KotlinProject.app */, ); name = Products; sourceTree = ""; }; 7555FF7D242A565900829871 /* iosApp */ = { isa = PBXGroup; children = ( 058557BA273AAA24004C7B11 /* Assets.xcassets */, 7555FF82242A565900829871 /* ContentView.swift */, 7555FF8C242A565B00829871 /* Info.plist */, 2152FB032600AC8F00CF470E /* iOSApp.swift */, 058557D7273AAEEB004C7B11 /* Preview Content */, ); path = iosApp; sourceTree = ""; }; AB1DB47929225F7C00F7AF9C /* Configuration */ = { isa = PBXGroup; children = ( AB3632DC29227652001CCB65 /* Config.xcconfig */, ); path = Configuration; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7555FF7A242A565900829871 /* iosApp */ = { isa = PBXNativeTarget; buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */; buildPhases = ( F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */, 7555FF77242A565900829871 /* Sources */, B92378962B6B1156000C7307 /* Frameworks */, 7555FF79242A565900829871 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = iosApp; packageProductDependencies = ( ); productName = iosApp; productReference = 7555FF7B242A565900829871 /* KotlinProject.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7555FF73242A565900829871 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 1130; LastUpgradeCheck = 1540; ORGANIZATIONNAME = orgName; TargetAttributes = { 7555FF7A242A565900829871 = { CreatedOnToolsVersion = 11.3.1; }; }; }; buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7555FF72242A565900829871; packageReferences = ( ); productRefGroup = 7555FF7C242A565900829871 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7555FF7A242A565900829871 /* iosApp */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7555FF79242A565900829871 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */, 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Compile Kotlin Framework"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :composeApp:embedAndSignAppleFrameworkForXcode\n"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7555FF77242A565900829871 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */, 7555FF83242A565900829871 /* ContentView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7555FFA3242A565B00829871 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7555FFA4242A565B00829871 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.3; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; name = Release; }; 7555FFA6242A565B00829871 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; DEVELOPMENT_TEAM = "${TEAM_ID}"; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", ); INFOPLIST_FILE = iosApp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.3; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}"; PRODUCT_NAME = "${APP_NAME}"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 7555FFA7242A565B00829871 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; DEVELOPMENT_TEAM = "${TEAM_ID}"; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", ); INFOPLIST_FILE = iosApp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.3; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}"; PRODUCT_NAME = "${APP_NAME}"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 7555FFA3242A565B00829871 /* Debug */, 7555FFA4242A565B00829871 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 7555FFA6242A565B00829871 /* Debug */, 7555FFA7242A565B00829871 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7555FF73242A565900829871 /* Project object */; } ================================================ FILE: processor/build.gradle.kts ================================================ plugins { kotlin("jvm") id("com.google.devtools.ksp") version "1.8.22-1.0.11" } // 确保处理器可以作为工件发布 sourceSets.main { resources { srcDir("src/main/resources") } } dependencies { implementation(project(":annotations")) implementation("com.google.devtools.ksp:symbol-processing-api:1.8.22-1.0.11") implementation("com.squareup:kotlinpoet:1.14.2") implementation("com.squareup:kotlinpoet-ksp:1.14.2") } ================================================ FILE: processor/src/main/java/com/aether/processor/ComposeMirrorProcessor.kt ================================================ package com.aether.processor import com.google.devtools.ksp.processing.* import com.google.devtools.ksp.symbol.* import com.google.devtools.ksp.validate import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.ksp.writeTo class ComposeMirrorProcessor( private val codeGenerator: CodeGenerator, private val logger: KSPLogger, private val options: Map ) : SymbolProcessor { override fun process(resolver: Resolver): List { val symbols = resolver.getSymbolsWithAnnotation("com.aether.annotations.ComposeMirror") val ret = symbols.filter { !it.validate() }.toList() symbols .filter { it is KSClassDeclaration && it.validate() } .forEach { it.accept(ComposeMirrorVisitor(), Unit) } return ret } inner class ComposeMirrorVisitor : KSVisitorVoid() { override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) { val packageName = classDeclaration.packageName.asString() val className = classDeclaration.simpleName.asString() // Generate mirror class val mirrorClassName = "${className}Mirror" val fileSpec = FileSpec.builder(packageName, mirrorClassName) .addType( TypeSpec.classBuilder(mirrorClassName) .addModifiers(KModifier.PUBLIC) .addFunction( FunSpec.builder("invoke") .addModifiers(KModifier.PUBLIC) .addParameter("params", List::class.asTypeName().parameterizedBy(Any::class.asTypeName())) .returns(Any::class) .addCode(""" |return $className().apply { | params.forEachIndexed { index, param -> | when(index) { | // Add parameter assignments based on constructor parameters | } | } |} """.trimMargin()) .build() ) .build() ) .build() fileSpec.writeTo(codeGenerator, false) } } } class ComposeMirrorProcessorProvider : SymbolProcessorProvider { override fun create( environment: SymbolProcessorEnvironment ): SymbolProcessor { return ComposeMirrorProcessor( environment.codeGenerator, environment.logger, environment.options ) } } ================================================ FILE: processor/src/main/java/com/aether/processor/ComposeMirrorProcessor2.kt ================================================ package com.aether.processor import com.aether.annotations.GenerateMirror import com.google.devtools.ksp.processing.CodeGenerator import com.google.devtools.ksp.processing.Dependencies import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment import com.google.devtools.ksp.processing.SymbolProcessorProvider import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSFunctionDeclaration import com.squareup.kotlinpoet.ANY import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.LIST import com.squareup.kotlinpoet.MAP import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.STRING import com.squareup.kotlinpoet.TypeSpec class ComposeMirrorProcessor( private val codeGenerator: CodeGenerator, private val logger: KSPLogger ) : SymbolProcessor { override fun process(resolver: Resolver): List { // 查找所有标记了@GenerateMirror的符号 val symbols = resolver.getSymbolsWithAnnotation(GenerateMirror::class.qualifiedName!!) // 处理标记的函数和类 symbols.filter { it is KSFunctionDeclaration || it is KSClassDeclaration } .forEach { // processSymbol(it) } // 自动处理常用的Compose组件 processComposeComponents(resolver) return emptyList() } private fun processComposeComponents(resolver: Resolver) { // 查找Text组件的所有重载 val textFunctions = resolver.getAllFiles().flatMap { file -> file.declarations.filterIsInstance() .filter { it.simpleName.asString() == "Text" } } // 为Text组件生成反射元数据 textFunctions.forEach { generateTextMirror(it) } } private fun generateTextMirror(function: KSFunctionDeclaration) { // 分析函数参数 val params = function.parameters.map { param -> val name = param.name?.asString() ?: "" val type = param.type.resolve().declaration.qualifiedName?.asString() ?: "Any" val isOptional = param.hasDefault ParamInfo(name, type, isOptional) } // 生成Text组件的反射元数据 generateMirrorClass("Text", params) } private fun generateMirrorClass(name: String, params: List) { val fileName = "${name}Mirror" val packageName = "com.your.package.mirror.generated" val fileSpec = FileSpec.builder(packageName, fileName) .addType( TypeSpec.classBuilder(fileName) .addProperty( PropertySpec.builder("name", String::class) .initializer("\"$name\"") .build() ) .addProperty( PropertySpec.builder("params", LIST.parameterizedBy( ClassName("com.your.package.mirror", "ParamInfo") )) .initializer(buildParamsList(params)) .build() ) .addFunction( FunSpec.builder("invoke") .addParameter("args", MAP.parameterizedBy( STRING, ANY.copy(nullable = true) )) .addCode(buildInvokeCode(name, params)) .build() ) .build() ) .build() codeGenerator.createNewFile( Dependencies(false), packageName, fileName ).use { outputStream -> outputStream.writer().use { fileSpec.writeTo(it) } } } private fun buildParamsList(params: List): CodeBlock { return CodeBlock.builder() .add("listOf(\n") .indent() .apply { params.forEachIndexed { index, param -> add("ParamInfo(\n") indent() add("name = %S,\n", param.name) add("type = %S,\n", param.type) add("isOptional = %L\n", param.isOptional) unindent() add(")") if (index < params.size - 1) add(",\n") else add("\n") } } .unindent() .add(")") .build() } private fun buildInvokeCode(name: String, params: List): CodeBlock { return CodeBlock.builder() .beginControlFlow("return androidx.compose.runtime.Composable { ") .add("androidx.compose.material.Text(\n") .indent() .apply { params.forEach { param -> add("%L = args[%S] as? %L,\n", param.name, param.name, param.type.split(".").last() ) } } .unindent() .add(")\n") .endControlFlow() .build() } private data class ParamInfo( val name: String, val type: String, val isOptional: Boolean ) // 处理器提供者 class ComposeMirrorProcessorProvider2 : SymbolProcessorProvider { override fun create( environment: SymbolProcessorEnvironment ): SymbolProcessor { return ComposeMirrorProcessor( environment.codeGenerator, environment.logger ) } } } ================================================ FILE: processor/src/main/java/com/aether/processor/ComposeReflectProcessor.kt ================================================ package com.aether.processor import com.google.devtools.ksp.processing.* import com.google.devtools.ksp.symbol.* import com.google.devtools.ksp.validate import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ksp.writeTo class ComposeReflectProcessor( private val codeGenerator: CodeGenerator, private val logger: KSPLogger, private val options: Map ) : SymbolProcessor { override fun process(resolver: Resolver): List { val symbols = resolver.getSymbolsWithAnnotation("com.aether.annotations.ComposeReflect") val ret = symbols.filter { !it.validate() }.toList() symbols .filter { it is KSClassDeclaration && it.validate() } .forEach { it.accept(ComposeReflectVisitor(), Unit) } return ret } inner class ComposeReflectVisitor : KSVisitorVoid() { override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) { val packageName = classDeclaration.packageName.asString() val className = classDeclaration.simpleName.asString() // Generate reflection class val reflectClassName = "${className}Reflect" val fileSpec = FileSpec.builder(packageName, reflectClassName) .addType( TypeSpec.classBuilder(reflectClassName) .addModifiers(KModifier.PUBLIC) .primaryConstructor( FunSpec.constructorBuilder() .addParameter("instance", ClassName(packageName, className)) .build() ) .addProperty( PropertySpec.builder("instance", ClassName(packageName, className)) .initializer("instance") .build() ) .addFunctions(generateReflectFunctions(classDeclaration)) .build() ) .build() fileSpec.writeTo(codeGenerator, false) } private fun generateReflectFunctions(classDeclaration: KSClassDeclaration): List { val functions = mutableListOf() classDeclaration.declarations .filterIsInstance() .filter { it.annotations.any { ann -> ann.annotationType.resolve().declaration.qualifiedName?.asString() == "com.aether.annotations.Reflectable" } } .forEach { function -> val functionName = function.simpleName.asString() val parameters = function.parameters.map { param -> ParameterSpec.builder( param.name?.asString() ?: "param", param.type.resolve().toTypeName() ).build() } functions.add( FunSpec.builder("invoke$functionName") .addModifiers(KModifier.PUBLIC) .addParameters(parameters) .returns(Unit::class) .addCode(""" |instance.$functionName(${parameters.joinToString { it.name }}) """.trimMargin()) .build() ) } return functions } } } class ComposeReflectProcessorProvider : SymbolProcessorProvider { override fun create( environment: SymbolProcessorEnvironment ): SymbolProcessor { return ComposeReflectProcessor( environment.codeGenerator, environment.logger, environment.options ) } } ================================================ FILE: processor/src/main/java/com/aether/processor/ReflectableProcessor.kt ================================================ package com.aether.processor import com.google.devtools.ksp.processing.* import com.google.devtools.ksp.symbol.* import com.google.devtools.ksp.validate import com.aether.annotations.Reflectable class ReflectableProcessor( private val codeGenerator: CodeGenerator, private val logger: KSPLogger, private val options: Map ) : SymbolProcessor { override fun process(resolver: Resolver): List { val symbols = resolver.getSymbolsWithAnnotation(Reflectable::class.qualifiedName!!) val ret = symbols.filter { !it.validate() }.toList() symbols .filter { it is KSClassDeclaration && it.validate() } .forEach { it.accept(ReflectableVisitor(), Unit) } return ret } inner class ReflectableVisitor : KSVisitorVoid() { override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) { val packageName = classDeclaration.packageName.asString() val className = classDeclaration.simpleName.asString() // 生成反射支持代码 val file = codeGenerator.createNewFile( dependencies = Dependencies(false), packageName = packageName, fileName = "${className}Reflector" ) file.appendText(""" package $packageName import androidx.compose.runtime.Composable import com.aether.core.runtime.reflectable.ComposeComponentRegistry object ${className}Reflector { @Composable fun createInstance( name: String, arguments: Map = emptyMap() ) { when (name) { "${classDeclaration.qualifiedName?.asString()}" -> { $className() } else -> { // 处理其他情况 } } } } """.trimIndent()) file.close() } } } class ReflectableProcessorProvider : SymbolProcessorProvider { override fun create( environment: SymbolProcessorEnvironment ): SymbolProcessor { return ReflectableProcessor( environment.codeGenerator, environment.logger, environment.options ) } } ================================================ FILE: processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider ================================================ com.aether.processor.ComposeMirrorProcessorProvider ================================================ FILE: settings.gradle.kts ================================================ rootProject.name = "KotlinProject" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } } include(":composeApp") include(":core") include(":annotations") include(":processor")