浏览代码

embedded ksp

milan jurkulák 2 年之前
父节点
当前提交
b2648d4cac
共有 70 个文件被更改,包括 1358 次插入 和 291 次删除
  1. 0 21
      annotations/build.gradle.kts
  2. 17 2
      app/build.gradle.kts
  3. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt
  4. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt
  5. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt
  6. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt
  7. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt
  8. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt
  9. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt
  10. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/GalleryScreen.kt
  11. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt
  12. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/LoadingScreen.kt
  13. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt
  14. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/SplashScreen.kt
  15. 2 0
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/WebScreen.kt
  16. 3 2
      app/src/main/res/drawable/shape_circle.xml
  17. 3 2
      app/src/main/res/drawable/shape_round_square.xml
  18. 3 2
      app/src/main/res/layout/widget_loading_layout.xml
  19. 8 9
      app/src/main/res/values/strings.xml
  20. 3 2
      app/src/main/res/xml/main_app_widget_info.xml
  21. 62 2
      build.gradle.kts
  22. 35 8
      buildSrc/build.gradle.kts
  23. 1 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateAndroidUnitTest.kt
  24. 2 2
      buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateScreenShot.kt
  25. 1 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateUnitTest.kt
  26. 13 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/EnumConvertible.kt
  27. 1 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/base/BaseTask.kt
  28. 4 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/custom/TestCaseGeneratorTask.kt
  29. 1 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/custom/unittest/WorkerImpl.kt
  30. 2 2
      buildSrc/src/main/kotlin/org/mjdev/gradle/custom/unittest/makers/ClassMakerImpl.kt
  31. 25 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/DependencyHandlerScopeExt.kt
  32. 19 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/KSClassDeclarationExt.kt
  33. 19 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/KSFileExt.kt
  34. 15 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/OtherExt.kt
  35. 20 4
      buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/ProjectExt.kt
  36. 13 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/base/IProcessor.kt
  37. 1 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/base/ITestBuilder.kt
  38. 4 4
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/builders/PaparazziTestBuilder.kt
  39. 18 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/data/ProcessedEnumConvertible.kt
  40. 56 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/generators/EnumConvertibleGenerator.kt
  41. 38 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/log/LoggerKsp.kt
  42. 55 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/enums/EnumConvertibleProcessor.kt
  43. 18 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/enums/EnumConvertibleProcessorProvider.kt
  44. 61 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/screenshots/ScreenshotProcessor.kt
  45. 4 3
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/screenshots/ScreenshotProcessorProvider.kt
  46. 40 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/visitors/EnumConvertibleVisitor.kt
  47. 43 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/visitors/ScreenShotsVisitor.kt
  48. 42 22
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/AppPlugin.kt
  49. 15 5
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/LibPlugin.kt
  50. 4 2
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/config/AppConfig.kt
  51. 3 0
      buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/config/LibConfig.kt
  52. 1 3
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/CheckNewLibsTask.kt
  53. 2 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/InAppInfoCreateTask.kt
  54. 2 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ReleaseNotesCreateTask.kt
  55. 78 42
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/TestClassesGeneratorTask.kt
  56. 0 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/WebServiceCreateTask.kt
  57. 0 1
      buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ZipReleaseCreateTask.kt
  58. 493 0
      documentation/release-notes-1.3.1.md
  59. 21 13
      gradle.properties
  60. 29 9
      gradle/libs.versions.toml
  61. 9 1
      gradle/wrapper/gradle-wrapper.properties
  62. 0 23
      processor/build.gradle.kts
  63. 0 76
      processor/src/main/kotlin/org/mjdev/processor/Processor.kt
  64. 0 9
      processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
  65. 12 6
      settings.gradle.kts
  66. 二进制
      sources/annotations.zip
  67. 二进制
      sources/processor.zip
  68. 9 1
      tvlib/build.gradle.kts
  69. 2 1
      tvlib/src/main/AndroidManifest.xml
  70. 2 2
      tvlib/src/main/res/values/colors.xml

+ 0 - 21
annotations/build.gradle.kts

@@ -1,21 +0,0 @@
-/*
- *  Copyright (c) Milan Jurkulák 2024.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-plugins {
-    id("org.jetbrains.kotlin.jvm")
-    id("kotlin")
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_17
-    targetCompatibility = JavaVersion.VERSION_17
-}
-
-dependencies {
-    implementation(libs.kotlin.stdlib.jdk8)
-}

+ 17 - 2
app/build.gradle.kts

@@ -8,15 +8,30 @@
 
 import org.mjdev.gradle.extensions.isAndroidStudio
 
-
 plugins {
-    id("AppPlugin")
+    AppPlugin
 }
 
 appConfig {
     namespace = "org.mjdev.tvapp"
     description = "Smart TV android app for any android device"
+
+    autoCorrectCode = true
+    ignoreCodeFailures = isAndroidStudio
+
     createDocumentation = !isAndroidStudio
+    reportUndocumentedFiles = !isAndroidStudio
+    failOnDocumentationWarning = false
+
+    createReleaseNotes = !isAndroidStudio
+    createZipRelease = !isAndroidStudio
+
+    createWebApp = !isAndroidStudio
+    createWebSiteFromGit = false
+
+    renameApkOutputByAppID = false
+    createInfoClass = false
+    launcherIconByBuildType = false
 
     // todo
     default {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt

@@ -26,6 +26,7 @@ import org.mjdev.tvlib.interfaces.ItemPhoto
 import org.mjdev.tvlib.interfaces.ItemVideo
 import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvlib.navigation.NavHostControllerEx
+import org.mjdev.gradle.annotations.CreateScreenShot
 import java.net.URL
 
 @Suppress("PreviewShouldNotBeCalledRecursively")
@@ -33,6 +34,7 @@ class IPTVActivity : TvActivity() {
 
     override val backgroundColor: Color = Color.Black
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Compose() = super.Compose()

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt

@@ -9,6 +9,7 @@
 package org.mjdev.tvapp.activity
 
 import androidx.compose.runtime.Composable
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.ui.screens.MainScreen
 import org.mjdev.tvapp.ui.screens.SplashScreen
 import org.mjdev.tvlib.activity.TvActivity
@@ -20,6 +21,7 @@ import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 @Suppress("PreviewShouldNotBeCalledRecursively")
 class MainActivity : TvActivity() {
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Compose() = super.Compose()

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt

@@ -11,6 +11,7 @@ package org.mjdev.tvapp.activity
 import android.content.Intent
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.ui.screens.WebScreen
 import org.mjdev.tvlib.activity.TvActivity
 import org.mjdev.tvlib.annotations.Previews
@@ -25,6 +26,7 @@ class WebActivity : TvActivity() {
 
     override val backgroundColor: Color = Color.Black
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Compose() = super.Compose()

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt

@@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
@@ -37,6 +38,7 @@ class AboutPage : Page() {
     override val title: Int = R.string.title_about
     override val icon: ImageVector = Icons.Default.Info
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt

@@ -26,6 +26,7 @@ import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.BuildConfig
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.activity.IPTVActivity
@@ -59,6 +60,7 @@ class MainPage : Page() {
     override val title: Int = R.string.title_home
     override val icon: ImageVector = Icons.Default.Home
 
+    @CreateScreenShot
     @SuppressLint("OpaqueUnitKey")
     @Previews
     @Composable

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt

@@ -23,6 +23,7 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
@@ -34,6 +35,7 @@ class PluginsPage : Page() {
     override val title: Int = R.string.title_plugins
     override val icon: ImageVector = Icons.Default.SettingsInputComponent
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt

@@ -23,6 +23,7 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
@@ -35,6 +36,7 @@ class SubscriptionPage : Page() {
     override val title: Int = R.string.title_subscription
     override val icon: ImageVector = Icons.Default.ShoppingCart
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/GalleryScreen.kt

@@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
 import androidx.navigation.navArgument
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.app.Application
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSyncUntilGone
@@ -48,6 +49,7 @@ class GalleryScreen : Screen() {
         }
     )
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt

@@ -20,6 +20,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalContext
 import androidx.media3.common.MediaItem
 import androidx.navigation.navArgument
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.app.Application
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSyncUntilGone
@@ -52,6 +53,7 @@ class IPTVScreen : Screen() {
         }
     )
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/LoadingScreen.kt

@@ -16,6 +16,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.screen.Screen
@@ -29,6 +30,7 @@ class LoadingScreen : Screen() {
     override val immersive: Boolean = true
     override val showOnce: Boolean = true
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt

@@ -12,6 +12,7 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Home
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.vector.ImageVector
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.ui.pages.AboutPage
 import org.mjdev.tvapp.ui.pages.MainPage
@@ -39,6 +40,7 @@ class MainScreen : ScreenWithPages() {
         page(AboutPage(), menuGravity = Bottom)
     }
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() = super.Content()

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/SplashScreen.kt

@@ -30,6 +30,7 @@ import com.airbnb.lottie.compose.animateLottieCompositionAsState
 import com.airbnb.lottie.compose.rememberLottieComposition
 import com.google.accompanist.permissions.ExperimentalPermissionsApi
 import kotlinx.coroutines.delay
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
@@ -46,6 +47,7 @@ class SplashScreen : Screen() {
     override val immersive: Boolean = true
 
     @OptIn(ExperimentalPermissionsApi::class)
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 2 - 0
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/WebScreen.kt

@@ -16,6 +16,7 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.navigation.navArgument
+import org.mjdev.gradle.annotations.CreateScreenShot
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.sync.SyncAdapter.Companion.pauseSyncUntilGone
 import org.mjdev.tvlib.annotations.Previews
@@ -39,6 +40,7 @@ class WebScreen : Screen() {
         }
     )
 
+    @CreateScreenShot
     @Previews
     @Composable
     override fun Content() {

+ 3 - 2
app/src/main/res/drawable/shape_circle.xml

@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~  Copyright (c) Milan Jurkulák 2023.
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com
   ~  e: mj@mjdev.org

+ 3 - 2
app/src/main/res/drawable/shape_round_square.xml

@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~  Copyright (c) Milan Jurkulák 2023.
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com
   ~  e: mj@mjdev.org

+ 3 - 2
app/src/main/res/layout/widget_loading_layout.xml

@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~  Copyright (c) Milan Jurkulák 2023.
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com
   ~  e: mj@mjdev.org

+ 8 - 9
app/src/main/res/values/strings.xml

@@ -1,12 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-/*
- * Copyright (c) Milan Jurkulák 2023.
- * Contact:
- * e: mimoccc@gmail.com
- * e: mj@mjdev.org
- * w: https://mjdev.org
- */
--->
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  Copyright (c) Milan Jurkulák 2024.
+  ~  Contact:
+  ~  e: mimoccc@gmail.com
+  ~  e: mj@mjdev.org
+  ~  w: https://mjdev.org
+  -->
 <resources>
 
 <!--    <string name="app_name" translatable="false">TVApp</string>-->

+ 3 - 2
app/src/main/res/xml/main_app_widget_info.xml

@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~  Copyright (c) Milan Jurkulák 2023.
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com
   ~  e: mj@mjdev.org

+ 62 - 2
build.gradle.kts

@@ -6,11 +6,14 @@
  *  w: https://mjdev.org
  */
 
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 plugins {
-    alias(libs.plugins.gradle.devtools.google.ksp) apply false
+    alias(libs.plugins.gradle.ksp) apply false
     alias(libs.plugins.gradle.ktlint) apply false
     alias(libs.plugins.gradle.versions) apply true
     alias(libs.plugins.gradle.catalogs.update) apply true
+    alias(libs.plugins.compose.screenshot) apply false
 }
 
 buildscript {
@@ -32,7 +35,7 @@ buildscript {
         classpath(libs.gradle.kotlinter)
         classpath(libs.gradle.dokka.plugin)
         classpath(libs.gradle.markdown.plugin)
-        classpath(libs.gradle.ospackage.plugin)
+//        classpath(libs.gradle.ospackage.plugin)
     }
 
     configurations.classpath {
@@ -62,3 +65,60 @@ versionCatalogUpdate {
 tasks.register<Delete>("clean") {
     delete(rootProject.layout.buildDirectory)
 }
+
+subprojects {
+    pluginManager.withPlugin("java") {
+        configure<JavaPluginExtension> {
+            toolchain {
+                languageVersion.set(JavaLanguageVersion.of(17))
+            }
+        }
+
+        tasks.withType<JavaCompile>().configureEach {
+            options.release.set(8)
+        }
+    }
+
+    pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
+        tasks.withType<KotlinCompile>().configureEach {
+            compilerOptions {
+//                jvmTarget.set(17)
+                progressiveMode.set(true)
+            }
+        }
+    }
+
+    if (JavaVersion.current() >= JavaVersion.VERSION_16) {
+        tasks.withType<Test>().configureEach {
+            jvmArgs(
+                "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+                "--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+            )
+        }
+    }
+
+//    pluginManager.withPlugin("com.vanniktech.maven.publish") {
+//        apply(plugin = "org.jetbrains.dokka")
+//
+//        tasks.withType<DokkaTask>().configureEach {
+//            outputDirectory.set(rootDir.resolve("../docs/0.x"))
+//            dokkaSourceSets.configureEach {
+//                skipDeprecated.set(true)
+//            }
+//        }
+
+//        configure<MavenPublishBaseExtension> {
+//            publishToMavenCentral(automaticRelease = true)
+//            signAllPublications()
+//        }
+//    }
+
+}

+ 35 - 8
buildSrc/build.gradle.kts

@@ -6,8 +6,9 @@
  *  w: https://mjdev.org
  */
 
-@Suppress("DEPRECATION", "JcenterRepositoryObsolete")
 repositories {
+    //noinspection JcenterRepositoryObsolete
+    @Suppress("DEPRECATION")
     jcenter()
     google()
     mavenCentral()
@@ -16,19 +17,19 @@ repositories {
     maven(url = "https://plugins.gradle.org/m2/")
     maven(url = "https://oss.sonatype.org/content/repositories/public")
     maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
-    maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt"))
 }
 
 plugins {
     `kotlin-dsl`
-//    id("org.jetbrains.reflekt") version "1.5.30"
 }
 
 dependencies {
     implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
+
     implementation(gradleApi())
     implementation(gradleKotlinDsl())
-    implementation(kotlin("reflect"))
+
+    implementation(libs.kotlin.reflect)
     implementation(libs.gradle.api)
     implementation(libs.gradle)
     implementation(libs.gradle.kotlin.plugin)
@@ -47,15 +48,22 @@ dependencies {
     implementation(libs.kotlin.mockito)
     implementation(libs.junit)
     implementation(libs.kotlin.compose.compiler)
-    implementation(libs.symbol.processing.api)
-//    implementation(libs.kotlin.reflekt.dsl)
-//    implementation(libs.symbol.processing.embeddable)
+
+    implementation(libs.ksp)
+    implementation(libs.ksp.api)
+    implementation(libs.ksp.commonDeps)
+    implementation(libs.ksp.aaEmbeddable)
+    implementation(libs.aalto.xml)
+
+//    implementation(libs.classgraph)
+
 //    implementation(libs.apk.parser)
 //    implementation(libs.gradle.docker.plugin)
 //    implementation(libs.korim.jvm)
 //    implementation(libs.photofilter)
 //    implementation(libs.dependency.analysis.gradle.plugin)
 //    implementation(libs.google.api.services.androidpublisher)
+
 //    implementation(libs.ini4j)
 }
 
@@ -74,4 +82,23 @@ gradlePlugin {
             implementationClass = "org.mjdev.gradle.plugin.LibPlugin"
         }
     }
-}
+}
+
+tasks {
+    val sourcesJar by creating(Jar::class) {
+        dependsOn(JavaPlugin.CLASSES_TASK_NAME)
+        archiveClassifier = "sources"
+        from(java.sourceSets["main"].allSource)
+    }
+
+    val javadocJar by creating(Jar::class) {
+        dependsOn(JavaPlugin.JAVADOC_TASK_NAME)
+        archiveClassifier = "javadoc"
+        from(java.docsDir)
+    }
+
+    artifacts {
+        add("archives", sourcesJar)
+        add("archives", javadocJar)
+    }
+}

+ 1 - 1
annotations/src/main/kotlin/org/mjdev/annotations/CreateAndroidUnitTest.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateAndroidUnitTest.kt

@@ -6,7 +6,7 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.annotations
+package org.mjdev.gradle.annotations
 
 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
 annotation class CreateAndroidUnitTest

+ 2 - 2
annotations/src/main/kotlin/org/mjdev/annotations/CreateScreenShot.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateScreenShot.kt

@@ -6,7 +6,7 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.annotations
+package org.mjdev.gradle.annotations
 
-@Target(AnnotationTarget.FUNCTION)
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
 annotation class CreateScreenShot

+ 1 - 1
annotations/src/main/kotlin/org/mjdev/annotations/CreateUnitTest.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/CreateUnitTest.kt

@@ -6,7 +6,7 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.annotations
+package org.mjdev.gradle.annotations
 
 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
 annotation class CreateUnitTest

+ 13 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/annotations/EnumConvertible.kt

@@ -0,0 +1,13 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.annotations
+
+@Target(AnnotationTarget.CLASS)
+@Retention(AnnotationRetention.SOURCE)
+annotation class EnumConvertible

+ 1 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/base/BaseTask.kt

@@ -63,7 +63,7 @@ abstract class BaseTask : DefaultTask() {
             .toURL()
 
     @get:Internal
-    val restDependencies
+    val resDependencies
         get() = variant
             .getCompileClasspath(null)
             .files

+ 4 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/custom/TestCaseGeneratorTask.kt

@@ -15,7 +15,10 @@ import org.mjdev.gradle.custom.unittest.WorkerImpl
 abstract class TestCaseGeneratorTask : BaseTask() {
 
     private val urls
-        get() = restDependencies + javaCompiledClasses + kotlinCompiledClasses
+        get() = mutableListOf(
+            javaCompiledClasses,
+            kotlinCompiledClasses,
+        ).apply { addAll(resDependencies) }
 
     private val sourceDirectoryList
         get() = listOf(

+ 1 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/custom/unittest/WorkerImpl.kt

@@ -17,7 +17,7 @@ import org.mjdev.gradle.custom.unittest.writers.TestFileWriterImpl
 import java.net.URL
 
 internal class WorkerImpl(
-    private val urls: Array<URL>,
+    private val urls: List<URL>,
     private val sourceDirectoryList: List<String>,
     private val exclude: List<String>,
     private val filePathHelper: FilePathHelper = FilePathHelperImpl(sourceDirectoryList, exclude),

+ 2 - 2
buildSrc/src/main/kotlin/org/mjdev/gradle/custom/unittest/makers/ClassMakerImpl.kt

@@ -24,7 +24,7 @@ import java.nio.file.Path
 
 @Suppress("PrivatePropertyName")
 internal class ClassMakerImpl(
-    private var urls: Array<URL>
+    private var urls: List<URL>
 ) : ClassMaker {
     private val ANDROID_DIRECTORY = "ANDROID_SDK_DIRECTORY"
     private val ANDROID_JAR = "android.jar"
@@ -56,7 +56,7 @@ internal class ClassMakerImpl(
             val ANDROID = URL(FILE_URL_PREFIX + SDKLocation + DIRECTORY_SEPARATOR + ANDROID_JAR)
             urls += ANDROID
         }
-        classloader = URLClassLoader(urls, Thread.currentThread().contextClassLoader)
+        classloader = URLClassLoader(urls.toTypedArray(), Thread.currentThread().contextClassLoader)
     }
 
     override fun makeClass(path: Path): Class<*>? = runCatching {

+ 25 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/DependencyHandlerScopeExt.kt

@@ -19,6 +19,25 @@ private const val DEBUG_IMPLEMENTATION = "debugImplementation"
 private const val ANDROID_TEST_IMPLEMENTATION = "androidTestImplementation"
 private const val TEST_IMPLEMENTATION = "testImplementation"
 private const val KSP_IMPLEMENTATION = "ksp"
+private const val COMPILE = "compile"
+
+fun DependencyHandlerScope.compile(
+    dependency: Provider<MinimalExternalModuleDependency>
+) {
+    add(COMPILE, dependency.get())
+}
+
+fun DependencyHandlerScope.compile(
+    dependency: Dependency
+) {
+    add(COMPILE, dependency)
+}
+
+fun DependencyHandlerScope.compile(
+    dependency: ExternalModuleDependencyFactory.DependencyNotationSupplier
+) {
+    add(COMPILE, dependency.asProvider().get())
+}
 
 fun DependencyHandlerScope.implementation(
     dependency: Provider<MinimalExternalModuleDependency>
@@ -38,6 +57,12 @@ fun DependencyHandlerScope.implementation(
     add(IMPLEMENTATION, dependency)
 }
 
+fun DependencyHandlerScope.implementation(
+    dependency: Any
+) {
+    add(IMPLEMENTATION, dependency)
+}
+
 fun DependencyHandlerScope.debugImplementation(
     dependency: Provider<MinimalExternalModuleDependency>
 ) {

+ 19 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/KSClassDeclarationExt.kt

@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.extensions
+
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+
+fun KSClassDeclaration.extractKeyName(): String? = primaryConstructor
+    ?.parameters
+    ?.first()
+    ?.type
+    ?.resolve()
+    ?.declaration
+    ?.simpleName?.asString()

+ 19 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/KSFileExt.kt

@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.extensions
+
+import com.google.devtools.ksp.symbol.KSFile
+import java.io.File
+
+val KSFile.projectDir: File
+    get() = File(filePath).let {
+        var ff = it
+        while (ff.name != "src") ff = ff.parentFile
+        ff.parentFile
+    }

+ 15 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/OtherExt.kt

@@ -8,7 +8,9 @@
 
 package org.mjdev.gradle.extensions
 
+import org.gradle.api.initialization.Settings
 import org.gradle.api.Project
+import org.gradle.api.plugins.ExtensionAware
 import java.lang.reflect.Modifier
 import java.util.Locale
 
@@ -86,4 +88,16 @@ fun parseDouble(value: Any): Double? = when (value) {
     is CharSequence -> value.toString().toDoubleOrNull()
     is Number -> value.toDouble()
     else -> null
-}
+}
+
+//fun <T : ExtensionAware> T.ifCi(action: T.() -> Unit) {
+//    if (ci) {
+//        action()
+//    }
+//}
+
+//fun <T : ExtensionAware> T.ifLocal(action: T.() -> Unit) {
+//    if (!ci) {
+//        action()
+//    }
+//}

+ 20 - 4
buildSrc/src/main/kotlin/org/mjdev/gradle/extensions/ProjectExt.kt

@@ -22,6 +22,7 @@ import org.gradle.api.GradleException
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.Task
+import org.gradle.api.file.ConfigurableFileCollection
 import org.gradle.api.logging.Logger
 import org.gradle.api.logging.Logging
 import org.gradle.api.plugins.ExtraPropertiesExtension
@@ -30,7 +31,6 @@ import org.gradle.api.tasks.SourceSet
 import org.gradle.api.tasks.SourceSet.MAIN_SOURCE_SET_NAME
 import org.gradle.api.tasks.SourceSet.TEST_SOURCE_SET_NAME
 import org.gradle.api.tasks.SourceSetContainer
-import org.gradle.internal.impldep.jakarta.xml.bind.DatatypeConverter.parseBoolean
 import org.gradle.kotlin.dsl.extra
 import org.gradle.kotlin.dsl.findByType
 import org.gradle.kotlin.dsl.the
@@ -162,6 +162,18 @@ val Project.androidComponents: AndroidComponentsExtension<*, *, *>
 val Project.buildDirectory: File
     get() = layout.buildDirectory.asFile.get()
 
+val Project.generatedDir: File
+    get() = buildDirectory.resolve("generated")
+
+val Project.generatedResDir: File
+    get() = buildDirectory.resolve("generated").resolve("res")
+
+val Project.generatedKspDir: File
+    get() = buildDirectory.resolve("generated").resolve("ksp")
+
+val Project.generatedKspCachesDir: File
+    get() = buildDirectory.resolve("kspCaches")
+
 val Project.sourceSets
     get() = properties["sourceSets"] as SourceSetContainer
 
@@ -216,6 +228,10 @@ val Project.log: Logger
 //    })
 //}
 
+fun Project.addSourceFiles(files: ConfigurableFileCollection) {
+    mainSourceSet?.compileClasspath?.plus(files)
+}
+
 fun Project.loadRootPropertiesFile(
     path: String,
     exposeToExtra: Boolean = true
@@ -279,8 +295,8 @@ inline fun <reified T : Task> Project.registerTask(
     fn: T.() -> Unit = {}
 ): T {
     val taskName = name ?: T::class.java.simpleName
-            .replace("Task", "")
-            .unCapitalize()
+        .replace("Task", "")
+        .unCapitalize()
     tasks.register(taskName, T::class.java)
     return tasks.findByName(taskName).let { task ->
         task as T
@@ -292,7 +308,7 @@ inline fun <reified T : Task> Project.registerTask(
 inline fun <reified T : Plugin<Project>> Project.applyPlugin(): T =
     plugins.apply(T::class.java)
 
-fun <T:Plugin<Project>> Project.applyPlugin(type: KClass<T>): T =
+fun <T : Plugin<Project>> Project.applyPlugin(type: KClass<T>): T =
     plugins.apply(type.java)
 
 fun Project.applyPlugin(type: Provider<PluginDependency>) =

+ 13 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/base/IProcessor.kt

@@ -0,0 +1,13 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.base
+
+interface  IProcessor {
+    fun addBuilder(builder: ITestBuilder)
+}

+ 1 - 1
processor/src/main/kotlin/org/mjdev/processor/base/ITestBuilder.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/base/ITestBuilder.kt

@@ -6,7 +6,7 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.processor.base
+package org.mjdev.gradle.ksp.base
 
 import com.google.devtools.ksp.processing.CodeGenerator
 import java.io.File

+ 4 - 4
processor/src/main/kotlin/org/mjdev/processor/builders/PaparazziTestBuilder.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/builders/PaparazziTestBuilder.kt

@@ -6,15 +6,15 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.processor.builders
+package org.mjdev.gradle.ksp.builders
 
 import com.google.devtools.ksp.processing.CodeGenerator
 import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration
-import org.mjdev.processor.base.ITestBuilder
-import org.mjdev.processor.base.ITestBuilder.Companion.file
-import org.mjdev.processor.base.ITestBuilder.Companion.fileFromPackageName
 import java.io.File
+import org.mjdev.gradle.ksp.base.ITestBuilder
+import org.mjdev.gradle.ksp.base.ITestBuilder.Companion.fileFromPackageName
+import org.mjdev.gradle.ksp.base.ITestBuilder.Companion.file
 
 class PaparazziTestBuilder(
     private val projectDir: File

+ 18 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/data/ProcessedEnumConvertible.kt

@@ -0,0 +1,18 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.data
+
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+
+data class ProcessedEnumConvertible(
+    val packageName: String,
+    val className: String,
+    val keyName: String?,
+    val classDeclaration: KSClassDeclaration
+)

+ 56 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/generators/EnumConvertibleGenerator.kt

@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.generators;
+
+import com.google.devtools.ksp.processing.CodeGenerator
+import com.google.devtools.ksp.processing.Dependencies
+import org.mjdev.gradle.ksp.data.ProcessedEnumConvertible
+import java.io.OutputStream
+
+class EnumConvertibleGenerator(
+    private val codeGenerator: CodeGenerator
+) {
+
+    fun generate(
+        processedEnumConvertible: ProcessedEnumConvertible
+    ) = with(processedEnumConvertible) {
+        // Generate file and declare its dependencies
+        val mapperFile: OutputStream = codeGenerator.createNewFile(
+            dependencies = Dependencies(
+                aggregating = true,
+                sources = arrayOf(classDeclaration.containingFile!!)
+            ),
+            packageName = packageName,
+            fileName = "${className}Mapper",
+            extensionName = "kt"
+        )
+        val sourceCode = buildConvertibleMapperSource(
+            packageName = processedEnumConvertible.packageName,
+            className = processedEnumConvertible.className,
+            keyName = processedEnumConvertible.keyName
+        ).toByteArray()
+        mapperFile.write(sourceCode)
+        mapperFile.close()
+    }
+
+    private fun buildConvertibleMapperSource(
+        packageName: String,
+        className: String,
+        keyName: String?
+    ): String = """
+            |package $packageName
+            |
+            |object ${className}Mapper {
+            |    
+            |    fun from(${keyName}: String?): ${className}? = values().find {
+            |        it.value.equals(${keyName}, ignoreCase = true)
+            |    }
+            |}
+        """.trimMargin()
+}

+ 38 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/log/LoggerKsp.kt

@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.log
+
+import com.google.devtools.ksp.processing.KSPLogger
+import com.google.devtools.ksp.symbol.KSNode
+import org.gradle.api.logging.Logger
+
+class LoggerKsp(
+    val log :  Logger
+) : KSPLogger {
+    override fun error(message: String, symbol: KSNode?) {
+        log.error(message, symbol)
+    }
+
+    override fun exception(e: Throwable) {
+        log.error(e.message)
+    }
+
+    override fun info(message: String, symbol: KSNode?) {
+        log.info(message, symbol)
+    }
+
+    override fun logging(message: String, symbol: KSNode?) {
+        log.lifecycle(message, symbol)
+    }
+
+    override fun warn(message: String, symbol: KSNode?) {
+        log.warn(message, symbol)
+    }
+
+}

+ 55 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/enums/EnumConvertibleProcessor.kt

@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.processor.enums
+
+import com.google.devtools.ksp.processing.CodeGenerator
+import com.google.devtools.ksp.processing.Resolver
+import com.google.devtools.ksp.processing.SymbolProcessor
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.validate
+import org.mjdev.gradle.ksp.data.ProcessedEnumConvertible
+import org.mjdev.gradle.ksp.visitors.EnumConvertibleVisitor
+import org.mjdev.gradle.ksp.generators.EnumConvertibleGenerator
+import org.mjdev.gradle.annotations.EnumConvertible
+
+class EnumConvertibleProcessor(codeGenerator: CodeGenerator) : SymbolProcessor {
+    private val enumConvertibleExtGenerator by lazy {
+        EnumConvertibleGenerator(codeGenerator = codeGenerator)
+    }
+    private val processedEnumConvertibles by lazy {
+        mutableListOf<ProcessedEnumConvertible>()
+    }
+    private val enumConvertibleVisitor by lazy {
+        EnumConvertibleVisitor(
+            processedEnumConvertibles = processedEnumConvertibles
+        )
+    }
+
+    override fun process(resolver: Resolver): List<KSAnnotated> {
+        val symbols = resolver.getSymbolsWithAnnotation(
+            annotationName = EnumConvertible::class.java.name
+        )
+        symbols
+            .filterIsInstance<KSClassDeclaration>()
+            .filter { kSClassDeclaration ->
+                kSClassDeclaration.validate()
+            }
+            .forEach { kSClassDeclaration ->
+                kSClassDeclaration.accept(enumConvertibleVisitor, Unit)
+            }
+        return emptyList()
+    }
+
+    override fun finish() {
+        processedEnumConvertibles.forEach {
+            enumConvertibleExtGenerator.generate(processedEnumConvertible = it)
+        }
+    }
+}

+ 18 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/enums/EnumConvertibleProcessorProvider.kt

@@ -0,0 +1,18 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.processor.enums
+
+import com.google.devtools.ksp.processing.SymbolProcessor
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
+import com.google.devtools.ksp.processing.SymbolProcessorProvider
+
+class EnumConvertibleProcessorProvider : SymbolProcessorProvider {
+    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor =
+        EnumConvertibleProcessor(codeGenerator = environment.codeGenerator)
+}

+ 61 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/screenshots/ScreenshotProcessor.kt

@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.processor.screenshots
+
+import com.google.devtools.ksp.processing.CodeGenerator
+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.symbol.KSAnnotated
+
+import com.google.devtools.ksp.validate
+import org.mjdev.gradle.ksp.base.ITestBuilder
+import org.mjdev.gradle.ksp.base.IProcessor
+import org.mjdev.gradle.ksp.visitors.ScreenShotsVisitor
+import org.mjdev.gradle.annotations.CreateScreenShot
+
+@Suppress("unused")
+class ScreenshotProcessor(
+    private val codeGenerator: CodeGenerator,
+    private val logger: KSPLogger,
+    private val options: Map<String, String>
+) : SymbolProcessor, IProcessor {
+
+    private val screenShotAnnotation = CreateScreenShot::class.java.canonicalName
+
+    private val builders = mutableListOf<ITestBuilder>()
+
+    override fun addBuilder(builder: ITestBuilder) {
+        builders.add(builder)
+    }
+
+    override fun process(resolver: Resolver): List<KSAnnotated> {
+        println("Processor for KSP starts to process annotations: $screenShotAnnotation")
+        val screenshots : Sequence<KSAnnotated> = try {
+            resolver.getSymbolsWithAnnotation(screenShotAnnotation)
+        } catch (t:Throwable) {
+            logger.error(t.message ?: "unknown error to get annotation.", null)
+            emptySequence()
+        }
+        if (!screenshots.iterator().hasNext()) {
+            return emptyList()
+        }
+        screenshots.forEach {
+            it.accept(ScreenShotsVisitor(this), Unit)
+        }
+        val unableToProcess = screenshots.filterNot {
+            it.validate()
+        }.toList()
+        builders.forEach { builder ->
+            builder.build(codeGenerator)
+        }
+        return unableToProcess
+    }
+
+}

+ 4 - 3
processor/src/main/kotlin/org/mjdev/processor/ProcessorProvider.kt → buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/processor/screenshots/ScreenshotProcessorProvider.kt

@@ -6,16 +6,17 @@
  *  w: https://mjdev.org
  */
 
-package org.mjdev.processor
+package org.mjdev.gradle.ksp.processor.screenshots
 
 import com.google.devtools.ksp.processing.SymbolProcessor
 import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
 import com.google.devtools.ksp.processing.SymbolProcessorProvider
 
-class ProcessorProvider : SymbolProcessorProvider {
+class ScreenshotProcessorProvider : SymbolProcessorProvider {
 
     override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
-        return Processor(
+        println("Processor for KSP created")
+        return ScreenshotProcessor(
             environment.codeGenerator,
             environment.logger,
             environment.options

+ 40 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/visitors/EnumConvertibleVisitor.kt

@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.visitors
+
+import com.google.devtools.ksp.symbol.ClassKind
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.symbol.KSVisitorVoid
+
+import org.mjdev.gradle.ksp.data.ProcessedEnumConvertible
+import org.mjdev.gradle.annotations.EnumConvertible
+import org.mjdev.gradle.extensions.extractKeyName
+
+class EnumConvertibleVisitor(
+    private val processedEnumConvertibles: MutableList<ProcessedEnumConvertible>
+) : KSVisitorVoid() {
+
+    private val enumConvertibleAnnotation = EnumConvertible::class.simpleName
+
+    override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
+        if (classDeclaration.classKind != ClassKind.ENUM_CLASS) {
+            throw IllegalStateException(
+                "$enumConvertibleAnnotation can be used only in an enum class."
+            )
+        }
+        val processedEnumConvertible = ProcessedEnumConvertible(
+            packageName = classDeclaration.packageName.asString(),
+            className = classDeclaration.simpleName.asString(),
+            keyName =  classDeclaration.extractKeyName(),
+            classDeclaration = classDeclaration
+        )
+        processedEnumConvertibles.add(processedEnumConvertible)
+    }
+
+}

+ 43 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/ksp/visitors/ScreenShotsVisitor.kt

@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.gradle.ksp.visitors
+
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration
+import com.google.devtools.ksp.symbol.KSVisitorVoid
+import org.mjdev.gradle.ksp.base.IProcessor
+import org.mjdev.gradle.ksp.builders.PaparazziTestBuilder
+import org.mjdev.gradle.extensions.projectDir
+
+class ScreenShotsVisitor(
+    private val processor: IProcessor
+) : KSVisitorVoid() {
+
+    override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
+        val file = function.containingFile
+        if (file != null) {
+            PaparazziTestBuilder(file.projectDir).fileName(file.fileName)
+                .packageName(file.packageName.asString()).function(function).also {
+                    processor.addBuilder(it)
+                }
+        }
+    }
+
+    override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
+        // todo
+//            val file = classDeclaration.containingFile
+//            if (file != null) {
+//                PaparazziTestBuilder(file.projectDir).fileName(file.fileName)
+//                    .packageName(file.packageName.asString()).function(classDeclaration).also {
+//                        addBuilder(it)
+//                    }
+//            }
+    }
+
+}

+ 42 - 22
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/AppPlugin.kt

@@ -16,7 +16,6 @@ import org.gradle.api.Project
 import org.gradle.api.artifacts.dsl.LockMode
 import org.gradle.kotlin.dsl.configure
 import org.gradle.kotlin.dsl.dependencies
-import org.gradle.kotlin.dsl.project
 import org.jetbrains.dokka.Platform
 import org.jmailen.gradle.kotlinter.KotlinterExtension
 import org.jmailen.gradle.kotlinter.KotlinterPlugin
@@ -46,6 +45,7 @@ import org.mjdev.gradle.extensions.projectName
 import org.mjdev.gradle.extensions.registerTask
 import org.mjdev.gradle.extensions.releaseNotesCreateTask
 import org.mjdev.gradle.extensions.runAfterAssembleTask
+import org.mjdev.gradle.extensions.runBeforeAssemble
 import org.mjdev.gradle.extensions.setSigningConfigs
 import org.mjdev.gradle.extensions.stringRes
 import org.mjdev.gradle.extensions.testImplementation
@@ -55,10 +55,12 @@ import org.mjdev.gradle.extensions.versionName
 import org.mjdev.gradle.extensions.webServiceCreateTask
 import org.mjdev.gradle.extensions.zipReleaseCreateTask
 import org.mjdev.gradle.plugin.config.AppConfig
+import org.mjdev.gradle.plugin.config.LibConfig
 import org.mjdev.gradle.tasks.CheckNewLibsTask
 import org.mjdev.gradle.tasks.CleanProjectTask
 import org.mjdev.gradle.tasks.CreatePropsTask
 import org.mjdev.gradle.tasks.ReleaseNotesCreateTask
+import org.mjdev.gradle.tasks.TestClassesGeneratorTask
 import org.mjdev.gradle.tasks.WebServiceCreateTask
 import org.mjdev.gradle.tasks.ZipReleaseCreateTask
 
@@ -76,7 +78,6 @@ class AppPlugin : BasePlugin() {
         applyPlugin(libs.plugins.gradle.dokka)
         applyPlugin(libs.plugins.kotlin.compose.compiler)
         applyPlugin(libs.plugins.gradle.paparazzi.plugin)
-//        applyPlugin(libs.plugins.kotlin.reflekt)
         applyPlugin<MarkdownPlugin>()
         applyPlugin<DetektPlugin>()
         applyPlugin<KotlinterPlugin>()
@@ -92,6 +93,7 @@ class AppPlugin : BasePlugin() {
         registerTask<ReleaseNotesCreateTask>()
         registerTask<WebServiceCreateTask>()
         registerTask<ZipReleaseCreateTask>()
+        registerTask<TestClassesGeneratorTask>()
         configure<ApplicationExtension> {
             namespace = appConfig.namespace
             compileSdk = AppConfig.compileSdk
@@ -114,9 +116,14 @@ class AppPlugin : BasePlugin() {
                 applicationId = appConfig.namespace
                 minSdk = AppConfig.minSdk
                 targetSdk = AppConfig.compileSdk
+//                buildToolsVersion = AppConfig.buildToolsVersion
                 versionCode = project.versionCode
                 versionName = project.versionName
                 multiDexEnabled = AppConfig.multiDexEnabled
+                vectorDrawables {
+                    useSupportLibrary = false
+                    generatedDensities()
+                }
                 // todo : move
                 buildConfigString(
                     "IPTV_API_URL" to "https://iptv-org.github.io/api/",
@@ -178,7 +185,9 @@ class AppPlugin : BasePlugin() {
                 }
             }
             sourceSets {
-                getByName("main") { jniLibs.srcDirs() }
+                getByName("main") {
+                    jniLibs.srcDirs()
+                }
             }
             lint {
                 checkReleaseBuilds = true
@@ -201,6 +210,8 @@ class AppPlugin : BasePlugin() {
                 if (appConfig.autoCorrectCode) {
                     mustRunAfter(assembleTasks)
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             dokkaTask {
@@ -222,6 +233,8 @@ class AppPlugin : BasePlugin() {
                 }
                 if (appConfig.createDocumentation) {
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             markDownToHtmlTask {
@@ -250,6 +263,8 @@ class AppPlugin : BasePlugin() {
             releaseNotesCreateTask {
                 if (appConfig.createReleaseNotes) {
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             webServiceCreateTask {
@@ -261,24 +276,28 @@ class AppPlugin : BasePlugin() {
                 serviceLicense = ""
                 if (appConfig.createWebApp) {
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             zipReleaseCreateTask {
                 // todo files here
                 if (appConfig.createZipRelease) {
                     runAfterAssembleTask()
-                }
-                if (appConfig.createReleaseNotes) {
-                    mustRunAfter(releaseNotesCreateTask())
-                }
-                if (appConfig.createWebApp) {
-                    mustRunAfter(webServiceCreateTask())
-                }
-                if (appConfig.createDocumentation) {
-                    mustRunAfter(dokkaTask())
-                }
-                if (appConfig.autoCorrectCode) {
-                    mustRunAfter(detektTask())
+                    if (appConfig.createReleaseNotes) {
+                        mustRunAfter(releaseNotesCreateTask())
+                    }
+                    if (appConfig.createWebApp) {
+                        mustRunAfter(webServiceCreateTask())
+                    }
+                    if (appConfig.createDocumentation) {
+                        mustRunAfter(dokkaTask())
+                    }
+                    if (appConfig.autoCorrectCode) {
+                        mustRunAfter(detektTask())
+                    }
+                } else {
+                    enabled = false
                 }
             }
             kotlinCompileOptions {
@@ -314,6 +333,7 @@ class AppPlugin : BasePlugin() {
         }
         dependencies {
             implementation(project(mapOf("path" to ":tvlib")))
+            implementation(files("$rootDir/buildSrc/build/libs/buildSrc.jar"))
             // compose
             implementation(platform(libs.androidx.compose.bom))
             implementation(libs.androidx.compose.ui.tooling)
@@ -404,18 +424,18 @@ class AppPlugin : BasePlugin() {
             implementation(libs.androidx.glance.appwidget)
             implementation(libs.androidx.glance.material)
             implementation(libs.androidx.glance.material3)
-            // test
-            testImplementation(libs.junit)
-            androidTestImplementation(libs.androidx.junit)
-            androidTestImplementation(libs.androidx.espresso.core)
             // anr
             implementation(libs.anrwatchdog)
-            // own ksp
-            implementation(project(":annotations"))
-            ksp(project(":processor"))
             // oauth
 //            implementation(libs.auth0)
 //            implementation(libs.android.jwtdecode)
+            // test
+            testImplementation(libs.junit)
+            androidTestImplementation(libs.androidx.junit)
+            androidTestImplementation(libs.androidx.espresso.core)
+            // own ksp
+//            implementation(project(":annotations"))
+//            ksp(project(":processor"))
         }
     }
 }

+ 15 - 5
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/LibPlugin.kt

@@ -13,9 +13,9 @@ import io.gitlab.arturbosch.detekt.DetektPlugin
 import io.gitlab.arturbosch.detekt.extensions.DetektExtension
 import org.gradle.api.Project
 import org.gradle.api.artifacts.dsl.LockMode
+import org.gradle.kotlin.dsl.PluginDependenciesSpecScope
 import org.gradle.kotlin.dsl.configure
 import org.gradle.kotlin.dsl.dependencies
-import org.gradle.kotlin.dsl.project
 import org.jetbrains.dokka.Platform
 import org.jmailen.gradle.kotlinter.KotlinterExtension
 import org.jmailen.gradle.kotlinter.KotlinterPlugin
@@ -36,9 +36,11 @@ import org.mjdev.gradle.extensions.loadRootPropertiesFile
 import org.mjdev.gradle.extensions.projectName
 import org.mjdev.gradle.extensions.registerTask
 import org.mjdev.gradle.extensions.runAfterAssembleTask
+import org.mjdev.gradle.extensions.runBeforeAssemble
 import org.mjdev.gradle.extensions.testImplementation
 import org.mjdev.gradle.plugin.config.LibConfig
 import org.mjdev.gradle.tasks.CreatePropsTask
+import org.mjdev.gradle.tasks.TestClassesGeneratorTask
 
 @Suppress("UnstableApiUsage")
 class LibPlugin : BasePlugin() {
@@ -50,18 +52,17 @@ class LibPlugin : BasePlugin() {
         applyPlugin(libs.plugins.kotlin.android)
         applyPlugin(libs.plugins.kotlin.parcelize)
         applyPlugin(libs.plugins.google.devtools.ksp)
-        applyPlugin(libs.plugins.google.devtools.ksp)
         applyPlugin(libs.plugins.objectbox)
         applyPlugin(libs.plugins.gradle.dokka)
         applyPlugin(libs.plugins.kotlin.compose.compiler)
         applyPlugin(libs.plugins.gradle.paparazzi.plugin)
-//        applyPlugin(libs.plugins.kotlin.reflekt)
         applyPlugin<DetektPlugin>()
         applyPlugin<KotlinterPlugin>()
         registerTask<CreatePropsTask> {
             propsFilePath = LibConfig.configPropertiesFile
             propsClass = LibConfig::class.java
         }
+        registerTask<TestClassesGeneratorTask>()
         configure<LibraryExtension> {
             namespace = libConfig.namespace
             compileSdk = LibConfig.compileSdk
@@ -79,6 +80,11 @@ class LibPlugin : BasePlugin() {
             defaultConfig {
                 minSdk = LibConfig.minSdk
                 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+//                buildToolsVersion = LibConfig.buildToolsVersion
+                vectorDrawables {
+                    useSupportLibrary = false
+                    generatedDensities()
+                }
             }
             packaging.resources.excludes.addAll(LibConfig.projectExcludes)
             buildTypes {
@@ -124,6 +130,8 @@ class LibPlugin : BasePlugin() {
             detektTask {
                 if (libConfig.autoCorrectCode) {
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             dokkaTask {
@@ -145,6 +153,8 @@ class LibPlugin : BasePlugin() {
                 }
                 if (libConfig.createDocumentation) {
                     runAfterAssembleTask()
+                } else {
+                    enabled = false
                 }
             }
             kotlinCompileOptions {
@@ -169,6 +179,7 @@ class LibPlugin : BasePlugin() {
             lockMode.set(LockMode.STRICT)
         }
         dependencies {
+            implementation(files("$rootDir/buildSrc/build/libs/buildSrc.jar"))
             // core
             implementation(libs.androidx.ktx)
             implementation(libs.kotlinx.coroutines.android)
@@ -276,8 +287,7 @@ class LibPlugin : BasePlugin() {
             // anr
             implementation(libs.anrwatchdog)
             // own ksp
-            implementation(project(":annotations"))
-            ksp(project(":processor"))
+//            ksp(project(":processor"))
             // oauth
 //            implementation(libs.auth0)
 //            implementation(libs.android.jwtdecode)

+ 4 - 2
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/config/AppConfig.kt

@@ -12,10 +12,10 @@ import org.gradle.api.JavaVersion
 import org.mjdev.gradle.extensions.toHashMap
 import org.mjdev.gradle.plugin.config.base.BuildConfigs
 
-@Suppress("unused")
+@Suppress("unused", "ConstPropertyName")
 open class AppConfig : BuildConfigs() {
     open var namespace = "org.mjdev.tvapp"
-    open var description = ""
+    open var description = "Android tv and streaming application for any android lollipop+ device"
 
     open var autoCorrectCode = true
     open var ignoreCodeFailures = true
@@ -53,6 +53,8 @@ open class AppConfig : BuildConfigs() {
         const val compileSdk = 34
         const val minSdk = 21
 
+//        const val buildToolsVersion = "34.0.0-rc3"
+
         const val jacocoVersion = "0.8.8"
 
         const val multiDexEnabled = true

+ 3 - 0
buildSrc/src/main/kotlin/org/mjdev/gradle/plugin/config/LibConfig.kt

@@ -12,6 +12,7 @@ import org.gradle.api.JavaVersion
 import org.mjdev.gradle.extensions.toHashMap
 import org.mjdev.gradle.plugin.config.base.BuildConfigs
 
+@Suppress("ConstPropertyName")
 open class LibConfig : BuildConfigs() {
     open var namespace = "org.mjdev.tvlib"
     open var description = "Smart TV android app lib for android applications running on any android device"
@@ -42,6 +43,8 @@ open class LibConfig : BuildConfigs() {
         const val compileSdk = 34
         const val minSdk = 21
 
+//        const val buildToolsVersion = "34.0.0-rc3"
+
         const val jacocoVersion = "0.8.8"
 
         val javaVersion = JavaVersion.VERSION_17

+ 1 - 3
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/CheckNewLibsTask.kt

@@ -14,8 +14,6 @@ import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.Optional
 import org.gradle.internal.impldep.org.tomlj.Toml
 import org.mjdev.gradle.base.BaseTask
-import org.mjdev.gradle.extensions.buildDirectory
-import org.mjdev.gradle.extensions.println
 import org.mjdev.gradle.extensions.writeToFile
 import org.xml.sax.InputSource
 import java.io.FileReader
@@ -106,7 +104,7 @@ open class CheckNewLibsTask : BaseTask() {
                     newLibs.forEach { line -> appendLine(" - $line") }
                 }
                 if (missingLibs.size > 0) {
-                    println("* Missing version.ref - Need to check manually")
+                    appendLine("* Missing version.ref - Need to check manually")
                     missingLibs.forEach { line -> appendLine(" - $line") }
                 }
             }

+ 2 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/InAppInfoCreateTask.kt

@@ -16,6 +16,7 @@ import java.io.File
 import org.mjdev.gradle.base.BaseTask
 import org.mjdev.gradle.extensions.write
 import org.mjdev.gradle.extensions.registerSourceDirectory
+import org.mjdev.gradle.extensions.println
 
 open class InAppInfoCreateTask : BaseTask() {
 
@@ -49,7 +50,7 @@ open class InAppInfoCreateTask : BaseTask() {
                 }
             }
         }.write(srcOutputDir) {
-            println("> Writing generated file: ${srcOutputDir}/${this.name}.kt")
+            println("Writing generated file: ${srcOutputDir}/${this.name}.kt")
         }
     }
 

+ 2 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ReleaseNotesCreateTask.kt

@@ -18,6 +18,7 @@ import org.mjdev.gradle.extensions.writeText
 import java.io.File
 import java.util.Date
 import java.util.Locale
+import org.mjdev.gradle.extensions.println
 
 open class ReleaseNotesCreateTask : BaseTask() {
 
@@ -82,7 +83,7 @@ open class ReleaseNotesCreateTask : BaseTask() {
             }
         }.toString().let { text ->
             outputFiles.forEach { of ->
-                println("> Creating release file: ${of.absolutePath}")
+                println("Creating release file: ${of.absolutePath}")
                 of.writeText(text)
             }
         }

+ 78 - 42
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/TestClassesGeneratorTask.kt

@@ -8,29 +8,20 @@
 
 package org.mjdev.gradle.tasks
 
-//import com.google.devtools.ksp.impl.CommandLineKSPLogger
-//import com.google.devtools.ksp.impl.KotlinSymbolProcessing
-//import com.google.devtools.ksp.processing.KSPJvmConfig
-//import com.google.devtools.ksp.processor.AbstractTestProcessor
-//import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
-//import org.jetbrains.kotlin.cli.jvm.config.javaSourceRoots
-//import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
-//import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
-//import org.jetbrains.kotlin.config.JVMConfigurationKeys
-//import org.jetbrains.kotlin.config.languageVersionSettings
-//import org.jetbrains.kotlin.test.compileJavaFiles
-//import org.jetbrains.kotlin.test.kotlinPathsForDistDirectoryForTests
-//import org.jetbrains.kotlin.test.model.FrontendKinds
-//import org.jetbrains.kotlin.test.model.TestModule
-//import org.jetbrains.kotlin.test.services.JUnit5Assertions
-//import org.jetbrains.kotlin.test.services.TestServices
-//import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
-//import org.jetbrains.kotlin.test.services.isKtFile
-//import org.jetbrains.kotlin.test.util.KtTestUtil
-//import org.jetbrains.kotlin.utils.PathUtil
+import com.google.devtools.ksp.impl.KotlinSymbolProcessing
+import com.google.devtools.ksp.processing.KSPJvmConfig
+import com.google.devtools.ksp.processing.SymbolProcessorProvider
+import org.gradle.api.Project
 import org.mjdev.gradle.base.BaseTask
-import org.mjdev.gradle.extensions.allFiles
-import org.mjdev.gradle.extensions.file
+import org.mjdev.gradle.extensions.buildDirectory
+import org.mjdev.gradle.extensions.generatedKspDir
+import org.mjdev.gradle.extensions.generatedKspCachesDir
+import org.mjdev.gradle.extensions.generatedResDir
+import org.gradle.api.JavaVersion
+import org.mjdev.gradle.extensions.println
+import org.mjdev.gradle.extensions.runBeforeAssemble
+import org.mjdev.gradle.ksp.log.LoggerKsp
+import org.mjdev.gradle.ksp.processor.screenshots.ScreenshotProcessorProvider
 
 @Suppress("unused")
 open class TestClassesGeneratorTask : BaseTask() {
@@ -44,13 +35,11 @@ open class TestClassesGeneratorTask : BaseTask() {
     //  --data '<Replace this with a json request body as needed>' \
     //  https://api-beta.copilot.com/v1/<Replace this with a resource>
 
-    private val subprojects = project.rootProject.subprojects
+    private val generatedDir
+        get() = project.buildDirectory.resolve("generated")
 
-    private val fileMap = subprojects.associateWith { p ->
-        p.file("src").file("main").allFiles("kt")
-    }
-
-//    private val worker = GithubClassWorker()
+    //    private val worker = GithubClassWorker()
+    private val screenshotKSPProvider by lazy { ScreenshotProcessorProvider() }
 
     init {
         group = "mjdev"
@@ -71,10 +60,10 @@ open class TestClassesGeneratorTask : BaseTask() {
 //    @Suppress("SpellCheckingInspection")
 //    private fun makeTestFile(
 //        srcFile: File,
-//        destfile: File
+//        destFile: File
 //    ) {
 //        worker.makeTestClass(srcFile).also { createdClass ->
-//            createdClass?.writeTo(destfile)
+//            createdClass?.writeTo(destFile)
 //        }
 //    }
 
@@ -89,21 +78,68 @@ open class TestClassesGeneratorTask : BaseTask() {
 //    }
 
     override fun onClean() {
+//        val pkg = project.packageName
+//        val annotation = CreateScreenShot::class.java.canonicalName
+//        ClassGraph()
+//            .verbose()
+//            .enableAllInfo()
+//            .enableClassInfo()
+//            .enableFieldInfo()
+//            .enableMethodInfo()
+//            .enableAnnotationInfo()
+//            .ignoreClassVisibility()
+//            .ignoreFieldVisibility()
+//            .ignoreMethodVisibility()
+//            .acceptPackages(pkg)
+//            .scan().use { scanResult ->
+//                scanResult.getClassesWithAnnotation(annotation).forEach { classInfo ->
+//                    val annotationInfo = classInfo.getAnnotationInfo(annotation)
+//                    val paramValues: List<AnnotationParameterValue> = annotationInfo.parameterValues
+//                    val ann = paramValues[0].value as String
+//                    println("${classInfo.name} is annotated with $ann")
+//                }
+//            }
+//        processKsp(project, screenshotKSPProvider)
     }
 
     override fun onAssemble() {
-//        val kspConfig = KSPJvmConfig.Builder().apply {
-//             All configurations happen here.
-//        }.build()
-//        val exitCode = KotlinSymbolProcessing(kspConfig, listOfProcessors, kspLoggerImpl).execute()
-//        println("> Got files:")
-//        fileMap.keys.forEach { project ->
-//            val files = fileMap[project] ?: emptyList()
-//            files.forEach { file ->
-//                println("> ${project.name} > $file")
-//                createTestFile(project, file)
-//            }
-//        }
+        processKsp(project, screenshotKSPProvider)
+    }
+
+    private fun processKsp(
+        project: Project,
+        processorProvider: SymbolProcessorProvider
+    ) {
+        println("processing symbols for : ${project.name}")
+        KotlinSymbolProcessing(
+            KSPJvmConfig.Builder().apply {
+                moduleName = project.projectDir.name
+                projectBaseDir = project.projectDir
+                outputBaseDir = project.projectDir
+                sourceRoots = listOf(project.projectDir)
+                javaOutputDir = project.generatedKspDir
+                kotlinOutputDir = project.generatedKspDir
+                cachesDir = project.generatedKspCachesDir
+                classOutputDir = project.generatedKspDir
+                resourceOutputDir = project.generatedResDir
+                jvmTarget = JavaVersion.VERSION_17.toString()
+                incremental = false
+                incrementalLog = false
+                allWarningsAsErrors = true
+                mapAnnotationArgumentsInJava = false
+                languageVersion = "2.0.0"
+                apiVersion = "1.0.22"
+                modifiedSources = emptyList()
+                removedSources = emptyList()
+                changedClasses = emptyList()
+                processorOptions = emptyMap()
+                commonSourceRoots = emptyList()
+            }.build(),
+            listOf(processorProvider),
+            LoggerKsp(logger)
+        ).execute().let { code ->
+            println("Kotlin processor ends with exit code: $code")
+        }
     }
 
 }

+ 0 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/WebServiceCreateTask.kt

@@ -9,7 +9,6 @@
 package org.mjdev.gradle.tasks
 
 import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.TaskAction
 import org.mjdev.gradle.base.BaseTask
 import org.mjdev.gradle.extensions.file
 import org.mjdev.gradle.extensions.writeText

+ 0 - 1
buildSrc/src/main/kotlin/org/mjdev/gradle/tasks/ZipReleaseCreateTask.kt

@@ -9,7 +9,6 @@
 package org.mjdev.gradle.tasks
 
 import org.mjdev.gradle.base.BaseTask
-import org.mjdev.gradle.extensions.projectVersion
 import org.mjdev.gradle.extensions.zipArchive
 
 open class ZipReleaseCreateTask : BaseTask() {

+ 493 - 0
documentation/release-notes-1.3.1.md

@@ -0,0 +1,493 @@
+## Release notes 1.0.0 - 28. 6. 2024, 23:18:07
+
+* 26.06.2024
+
+* [milan jurkulák] : testing base 
+
+* 14.06.2024
+
+* [milan jurkulák] : kodein improvements 
+* [milan jurkulák] : kodein improvements 
+* [milan jurkulák] : kodein improvements 
+* [milan jurkulák] : kodein improvements 
+* [milan jurkulák] : code cleanup 
+* [milan jurkulák] : code cleanup 
+
+* 13.06.2024
+
+* [milan jurkulák] : tv lib update 
+* [milan jurkulák] : dagger removal, kodein pre-implementation  
+
+* 22.05.2024
+
+* [milan jurkulák] : update libs  update libs 
+
+* 20.05.2024
+
+* [milan jurkulák] : kapt removal 
+* [milan jurkulák] : new compose & kotlin 2 
+
+* 02.05.2024
+
+* [milan jurkulák] : documentation update 
+* [milan jurkulák] : documentation update 
+* [milan jurkulák] : documentation update 
+* [milan jurkulák] : build script update 
+* [milan jurkulák] : download button 
+* [milan jurkulák] : download button 
+* [milan jurkulák] : update documentations 
+* [milan jurkulák] : update documentations 
+* [milan jurkulák] : update documentations 
+* [milan jurkulák] : update documentations 
+* [milan jurkulák] : update actions 
+* [milan jurkulák] : update actions 
+* [milan jurkulák] : documentation 
+* [milan jurkulák] : documentation 
+* [milan jurkulák] : documentation 
+* [milan jurkulák] : documentation 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : action update  
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : dockerfile 
+* [milan jurkulák] : generated files removal 
+* [milan jurkulák] : generated files removal 
+* [milan jurkulák] : generated files removal 
+* [milan jurkulák] : generated files removal 
+* [milan jurkulák] : generated files removal 
+* [milan jurkulák] : code improvements 
+
+* 01.05.2024
+
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+
+* 30.04.2024
+
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+
+* 29.04.2024
+
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+
+* 28.04.2024
+
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements 
+* [milan jurkulák] : code improvements  code improvements  code improvements 
+
+* 15.02.2024
+
+* [milan jurkulak] : code improvements 
+
+* 08.02.2024
+
+* [milan jurkulak] : code improvements 
+
+* 07.02.2024
+
+* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements 
+
+* 09.01.2024
+
+* [milan jurkulak] : number digits 
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : background changes 
+
+* 05.01.2024
+
+* [milan jurkulak] : code improvements  
+* [milan jurkulak] : webview fetcher  web scrapper webview  web scrapper webview 
+
+* 27.12.2023
+
+* [milan jurkulak] : build release fix 
+* [milan jurkulak] : scrapper improvements 
+* [milan jurkulak] : scrapper improvements  scrapper improvements  scrapper improvements  scrapper improvements 
+
+* 26.12.2023
+
+* [milan jurkulak] : config field fix / proguard fix 
+* [milan jurkulak] : build improvements 
+
+* 21.12.2023
+
+* [milan jurkulak] : scrapper base  scrapper base 
+* [milan jurkulak] : navigation improvements 
+
+* 19.12.2023
+
+* [milan jurkulak] : navigation improvements / need more improvements 
+
+* 06.12.2023
+
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : code improvements 
+
+* 05.12.2023
+
+* [milan jurkulak] : scroll improvements 
+* [milan jurkulak] : update fix 
+* [milan jurkulak] : update fix 
+
+* 04.12.2023
+
+* [milan jurkulak] : update fix 
+* [milan jurkulak] : update fix 
+* [milan jurkulak] : app bump 
+* [milan jurkulak] : merge remote-tracking branch 'origin/main' 
+* [milan jurkulák] : delete .github/workflows/codeql.yml
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements 
+* [milan jurkulak] : glide album art 
+* [milan jurkulak] : web scrapper pre-implement  web scrapper pre-implement 
+
+* 16.10.2023
+
+* [milan jurkulak] : images glide 
+
+* 12.10.2023
+
+* [milan jurkulak] : libraries versions bump 
+* [milan jurkulak] : theme dynamic & payments preimplementation 
+
+* 06.10.2023
+
+* [milan jurkulak] : image caching improvement 
+
+* 05.10.2023
+
+* [milan jurkulak] : minify temporary removal 
+* [milan jurkulak] : code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements  code improvements 
+
+* 30.09.2023
+
+* [milan jurkulak] : merge remote-tracking branch 'origin/main' 
+* [milan jurkulak] : code cleanup 
+* [milan jurkulak] : image loader improvements 
+
+* 29.09.2023
+
+* [milan jurkulák] : codeql.yml
+* [milan jurkulak] : remembers 
+
+* 27.09.2023
+
+* [milan jurkulak] : test component 
+* [milan jurkulak] : app updater 
+* [milan jurkulak] : html scrapper 
+* [milan jurkulak] : design improvement 
+
+* 21.08.2023
+
+* [milan jurkulak] : sync improvement 
+
+* 20.08.2023
+
+* [milan jurkulak] : play next on error preimplementation 
+* [milan jurkulak] : sync improvement 
+* [milan jurkulak] : network check improvement 
+* [milan jurkulak] : mobile apps fix 
+* [milan jurkulak] : app updater preimplement  app updater  app updater  app updater 
+* [milan jurkulak] : messages, resources 
+* [milan jurkulak] : code coments 
+
+* 19.08.2023
+
+* [milan jurkulak] : mediaitem uri fix 
+* [milan jurkulak] : mediaitem uri fix 
+* [milan jurkulak] : design improvements  design improvements  design improvements 
+* [milan jurkulak] : media player improvements 
+* [milan jurkulak] : nav controller fix 
+* [milan jurkulak] : lifecycle fix 
+
+* 18.08.2023
+
+* [milan jurkulak] : caching cursor fixes 
+
+* 11.08.2023
+
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : notification importance change 
+* [milan jurkulak] : player improvements  player improvements 
+
+* 10.08.2023
+
+* [milan jurkulak] : gridviews preimplementation  
+* [milan jurkulak] : media session  media session 
+* [milan jurkulak] : audio focus 
+* [milan jurkulak] : graphic resources & widget prepare 
+* [milan jurkulak] : mediaplayer widget preimplementation 
+* [milan jurkulak] : mediaplayer lifecycle / performance 
+* [milan jurkulak] : media state fixes 
+* [milan jurkulak] : audio preview fixes 
+
+* 09.08.2023
+
+* [milan jurkulak] : playernotificationmanager preimplementation (mobile) 
+* [milan jurkulak] : code cleanup 
+* [milan jurkulak] : sync improvements 
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : design fixes 
+* [milan jurkulak] : performance improvements  
+* [milan jurkulak] : sanwitch lib for removing bpt 
+
+* 08.08.2023
+
+* [milan jurkulak] : audio player preview dailymotion 
+* [milan jurkulak] : config changes preparation 
+* [milan jurkulak] : exoplayer transparency 
+* [milan jurkulak] : padding fix main screen 
+* [milan jurkulak] : download video for audio files, preimplementation 
+* [milan jurkulak] : design improvements  design improvements  design improvements  design improvements  design improvements  design improvements 
+
+* 07.08.2023
+
+* [milan jurkulak] : navigation padding 
+* [milan jurkulak] : gallery double tap 
+* [milan jurkulak] : gallery selection fix 
+* [milan jurkulak] : code cleanup & improvements 
+* [milan jurkulak] : page improvements 
+* [milan jurkulak] : focus fixes  
+* [milan jurkulak] : design fixes  design fixes 
+* [milan jurkulak] : carousel reimplementation 
+* [milan jurkulak] : carousel reimplementation 
+* [milan jurkulak] : activity lifecycle improvements 
+* [milan jurkulak] : image cache improvements 
+* [milan jurkulak] : manifest fixes 
+* [milan jurkulak] : cursor improvements 
+* [milan jurkulak] : anr fixes 
+
+* 06.08.2023
+
+* [milan jurkulak] : code fixes 
+* [milan jurkulak] : coil improvements 
+* [milan jurkulak] : caching album art data 
+* [milan jurkulak] : placeholder improvement 
+* [milan jurkulak] : webview fixes 
+* [milan jurkulak] : album art downloader cover art improvement 
+* [milan jurkulak] : album art downloader cover art 
+* [milan jurkulak] : gallery custom overlay support 
+* [milan jurkulak] : web client user agent 
+* [milan jurkulak] : carousel fixes 
+* [milan jurkulak] : swipe gestures for big carousel & gallery 
+* [milan jurkulak] : swipe gestures for big carousel & gallery 
+* [milan jurkulak] : code cleanup 
+* [milan jurkulak] : icon change 
+* [milan jurkulak] : item info improvement 
+* [milan jurkulak] : item info improvement 
+* [milan jurkulak] : code clean 
+* [milan jurkulak] : storage permissions fix 
+* [milan jurkulak] : detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements  detail improvements 
+
+* 04.08.2023
+
+* [milan jurkulak] : library update post fixes 
+* [milan jurkulak] : agp upgrade  agp upgrade 
+
+* 03.08.2023
+
+* [milan jurkulak] : oauth preimplementation 
+* [milan jurkulak] : library update 
+
+* 02.08.2023
+
+* [milan jurkulak] : detail screen improvements  detail screen improvements  detail screen improvements 
+* [milan jurkulak] : player improvements 
+* [milan jurkulak] : settings preimlplementation 
+* [milan jurkulak] : album art for coil 
+* [milan jurkulak] : mobile navigation modal 
+
+* 01.08.2023
+
+* [milan jurkulak] : player improvements & detail improvements 
+* [milan jurkulak] : code improvements  code improvements  code improvements 
+* [milan jurkulak] : better navigation prepare  better navigation prepare 
+* [milan jurkulak] : main page improvements 
+* [milan jurkulak] : portrait / landscape mode 
+
+* 23.07.2023
+
+* [milan jurkulak] : code improvements for preview 
+* [milan jurkulak] : repos refactor 
+
+* 22.07.2023
+
+* [milan jurkulak] : data fixes 
+* [milan jurkulak] : design improvements 
+* [milan jurkulak] : iptv categories 
+* [milan jurkulak] : iptv 
+* [milan jurkulak] : media player controls  media player controls 
+
+* 21.07.2023
+
+* [milan jurkulak] : pages improvement 
+* [milan jurkulak] : lottie support 
+
+* 18.07.2023
+
+* [milan jurkulak] : code move / anr reporting 
+* [milan jurkulak] : libs update 
+* [milan jurkulak] : new screenshots 
+* [milan jurkulak] : libs ver. upgrade 
+* [milan jurkulak] : media player controls 
+* [milan jurkulak] : xml layout component 
+* [milan jurkulak] : anr spy 
+* [milan jurkulak] : photo improvements 
+
+* 12.07.2023
+
+* [milan jurkulak] : photo improvements 
+* [milan jurkulak] : photo detail fix 
+* [milan jurkulak] : launcher add 
+* [milan jurkulak] : performance fix 
+* [milan jurkulak] : app manager fix / removal of itself from list 
+* [milan jurkulak] : photo item tablet fix 
+* [milan jurkulak] : card text focus background 
+* [milan jurkulak] : fading background 
+* [milan jurkulak] : readme update 
+* [milan jurkulak] : temporary dokka disablement & code cleanup 
+* [milan jurkulak] : items improve 
+* [milan jurkulak] : library pre-implementation 
+* [milan jurkulak] : tablet photos cursor fix 
+* [milan jurkulak] : tablet screen padding fix 
+* [milan jurkulak] : tablet background fix 
+* [milan jurkulak] : cursor sort order  cursor sort order 
+* [milan jurkulak] : carousel finalization 
+* [milan jurkulak] : featured items #1 
+* [milan jurkulak] : tv pager fix #1 
+* [milan jurkulak] : performance improvements 
+
+* 11.07.2023
+
+* [milan jurkulak] : pager animation 
+* [milan jurkulak] : image load improvement 
+* [milan jurkulak] : cursor row scroll improvement 
+* [milan jurkulak] : cursor row scroll improvement 
+* [milan jurkulak] : cursor improvement  cursor improvement 
+* [milan jurkulak] : permissions pre-implementation  permissions fix 
+
+* 10.07.2023
+
+* [milan jurkulak] : code cleanup 
+* [milan jurkulak] : lifecycle preimplementation 
+* [milan jurkulak] : net state improvements 
+* [milan jurkulak] : gui improvements 
+* [milan jurkulak] : cursor rows improvement 
+* [milan jurkulak] : columns fix for older devices 
+* [milan jurkulak] : one line text in cards 
+* [milan jurkulak] : recompose fixes  recompose fixes #2  recompose fixes #4 
+* [milan jurkulak] : recompose debugging 
+* [milan jurkulak] : custom adapter and custom rows  custom adapter and custom rows  coil more sources  scroll horizontal lists  scroll horizontal lists  scroll horizontal lists  scroll horizontal lists  details  details  details 
+
+* 07.07.2023
+
+* [milan jurkulak] : themes preimplementation 
+* [milan jurkulak] : paging preimplementation 
+* [milan jurkulak] : design improvements 
+
+* 02.07.2023
+
+* [milan jurkulak] : design improvements 
+* [milan jurkulak] : design improvements 
+* [milan jurkulak] : responsive design improvements 
+* [milan jurkulak] : contentpadding badge fix 
+* [milan jurkulak] : touch event fix 
+* [milan jurkulak] : card aspect fix 
+* [milan jurkulak] : page focus 
+* [milan jurkulak] : focusing fix, final 
+* [milan jurkulak] : carousel fix 
+* [milan jurkulak] : focusing fix 
+
+* 01.07.2023
+
+* [milan jurkulak] : gui improvements 
+* [milan jurkulak] : navigation code cleanup 
+* [milan jurkulak] : ui improvements 
+
+* 30.06.2023
+
+* [milan jurkulak] : touch handling  
+* [milan jurkulak] : navigation improvements 
+* [milan jurkulak] : ui improvements ui improvements ui improvements #1 
+* [milan jurkulak] : code cleanup 
+* [milan jurkulak] : pager preimplementation 
+* [milan jurkulak] : merge branch 'page1' into main
+
+* 29.06.2023
+
+* [milan jurkulak] : ui improvements 
+* [milan jurkulak] : code improvements 
+* [milan jurkulak] : code improvements 
+
+* 28.06.2023
+
+* [milan jurkulak] : caching fix 
+* [milan jurkulak] : pager implementation 
+* [milan jurkulak] : merge branch 'old_working' into main
+* [milan jurkulak] : previews improvement/components 
+
+* 27.06.2023
+
+* [milan jurkulak] : screens improvement 
+* [milan jurkulak] : network state fixes 
+* [milan jurkulak] : design fixes tabs  design fixes tabs 
+* [milan jurkulak] : design fixes header 
+* [milan jurkulak] : pager preimplementation 
+
+* 26.06.2023
+
+* [milan jurkulak] : repo clean 
+* [milan jurkulak] : ignore update 
+* [milan jurkulak] : ignore update 
+* [milan jurkulak] : documentation index  ignore update 
+* [milan jurkulak] : carousel touchable implementation 
+* [milan jurkulak] : code clean / icons for screens  media player fix  splash screen menu removal  delete .gradle directory delete .idea directory create security.md design improvements  git ignore items update  git ignore items update 
+* [milan] : create security.md
+* [milan] : delete .idea directory
+* [milan] : delete .gradle directory
+* [milan jurkulak] : splash screen menu removal 
+* [milan jurkulak] : media player fix 
+
+* 25.06.2023
+
+* [milan jurkulak] : code clean / icons for screens 
+* [milan jurkulak] : initial commit 

+ 21 - 13
gradle.properties

@@ -6,22 +6,30 @@
 #  w: https://mjdev.org
 #
 org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
-android.useAndroidX=true
-kotlin.code.style=official
-android.nonTransitiveRClass=true
 org.gradle.unsafe.configuration-cache=false
-android.suppressUnsupportedCompileSdk=34
-android.nonFinalResIds=true
+#org.gradle.warning.mode=all
+# test launcher api
 gradle.testLauncherAPI.enabled=false
-kotlin.mpp.androidSourceSetLayoutVersion=2
-kotlin.mpp.applyDefaultHierarchyTemplate=false
-createReports=true
-systemProp.javax.xml.accessExternalDTD=http
-systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
+# kapt settings
 kapt.use.worker.api=false
 kapt.incremental.apt=false
+kapt.include.compile.classpath=false
+# ksp2 settings
+ksp.useKSP2=true
+systemProp.kct.test.useKsp2=true
+# kotlin settings
+kotlin.code.style=official
+kotlin.incremental=false
+kotlin.mpp.androidSourceSetLayoutVersion=2
+kotlin.mpp.applyDefaultHierarchyTemplate=false
+# android settings
+android.useAndroidX=true
+android.nonTransitiveRClass=true
+android.suppressUnsupportedCompileSdk=34
+android.nonFinalResIds=true
 android.enableJetifier=true
 android.jetifier.ignorelist=android-base-common,common
-#org.gradle.warning.mode=all
-#kotlin.experimental.tryK2=true
-ksp.useKSP2=true
+android.experimental.enableScreenshotTest=true
+#
+#createReports=true
+#

+ 29 - 9
gradle/libs.versions.toml

@@ -13,7 +13,7 @@ androidx-espresso-core = "3.5.1"
 androidx-exifinterface = "1.3.7"
 androidx-foundation = "1.6.8"
 androidx-glance-appwidget = "1.1.0"
-androidx-junit = "1.1.5"
+androidx-junit = "1.2.1"
 androidx-ktx = "1.13.1"
 androidx-lifecycle-viewmodel-compose = "2.8.2"
 androidx-material-icons-extended = "1.6.8"
@@ -39,7 +39,7 @@ dokka-gradle-plugin = "1.9.20"
 google-api-services-androidpublisher = "v3-rev41-1.25.0"
 gradle = "8.4.2"
 gradle-docker-plugin = "9.4.0"
-gradleOspackagePlugin = "9.1.1"
+#gradleOspackagePlugin = "9.1.1"
 ini4j = "0.5.4"
 #
 javapoet = "1.13.0"
@@ -75,7 +75,9 @@ kodein-di = "7.22.0"
 gradle-catalogs-update = "0.8.4"
 gradle-versions = "0.51.0"
 ktlint = "11.3.2"
-gradle-devtools-google-ksp = "2.0.0-1.0.21"
+ksp = "2.0.0-1.0.22"
+compose-screenshot="0.0.1-alpha02"
+idea = "242.8057"
 # libraries ########################################################################################
 [libraries]
 ####################################################################################################
@@ -161,7 +163,7 @@ gradle-kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", v
 gradle-kotlinter = { module = "org.jmailen.gradle:kotlinter-gradle", version.ref = "kotlinter-gradle" }
 gradle-markdown-plugin = { module = "org.kordamp.gradle:markdown-gradle-plugin", version.ref = "markdownGradlePlugin" }
 gradle-objectbox-plugin = { module = "io.objectbox:objectbox-gradle-plugin", version.ref = "objectbox-gradle-plugin" }
-gradle-ospackage-plugin = { module = "com.netflix.nebula:gradle-ospackage-plugin", version.ref = "gradleOspackagePlugin" }
+#gradle-ospackage-plugin = { module = "com.netflix.nebula:gradle-ospackage-plugin", version.ref = "gradleOspackagePlugin" }
 gradle-paparazzi-plugin = { module = "app.cash.paparazzi:paparazzi-gradle-plugin", version.ref = "paparazzi-gradle-plugin" }
 gradle-tools-r8 = { module = "com.android.tools:r8", version.ref = "r8" }
 #
@@ -196,13 +198,28 @@ retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converte
 retrofit2-kotlin-coroutines-adapter = { module = "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter", version.ref = "retrofit2-kotlin-coroutines-adapter" }
 sandwich = { module = "com.github.skydoves:sandwich", version.ref = "sandwich" }
 sandwich-retrofit = { module = "com.github.skydoves:sandwich-retrofit", version.ref = "sandwich" }
-symbol-processing-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "gradle-devtools-google-ksp" }
-#symbol-processing-embeddable = { module = "com.google.devtools.ksp:symbol-processing-aa-embeddable", version.ref = "gradle-devtools-google-ksp" }
+#
+ksp = { module = "com.google.devtools.ksp:symbol-processing", version.ref = "ksp" }
+ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }
+ksp-aaEmbeddable = { module = "com.google.devtools.ksp:symbol-processing-aa-embeddable", version.ref = "ksp" }
+ksp-commonDeps = { module = "com.google.devtools.ksp:symbol-processing-common-deps", version.ref = "ksp" }
+#
 timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
 zxing-core = { module = "com.google.zxing:core", version.ref = "zxing-core" }
 kotlin-compose-compiler = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
 kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
-kotlin-reflekt-dsl = { module = "org.jetbrains.reflekt:reflekt-dsl", version.ref = "kotlin" }
+#
+autoService = "com.google.auto.service:auto-service-annotations:1.1.1"
+autoService-ksp = "dev.zacsweers.autoservice:auto-service-ksp:1.2.0"
+classgraph = "io.github.classgraph:classgraph:4.8.174"
+intellij-core = { module = "com.jetbrains.intellij.platform:core", version.ref = "idea" }
+intellij-util = { module = "com.jetbrains.intellij.platform:util", version.ref = "idea" }
+kotlin-compilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" }
+kotlin-annotationProcessingEmbeddable = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable", version.ref = "kotlin" }
+kotlin-kapt4 = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-compiler", version.ref = "kotlin" }
+kotlin-scriptingCompiler = { module = "org.jetbrains.kotlin:kotlin-scripting-compiler", version.ref = "kotlin" }
+kotlin-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
+aalto-xml={ module="com.fasterxml:aalto-xml" , version="1.3.1"} # todo
 #
 #classpath("org.jetbrains.kotlin:kotlin-scripting-jsr223:1.9.22")
 #classpath("org.jetbrains.kotlin:kotlin-scripting-common:1.9.22")
@@ -218,7 +235,7 @@ kotlin-reflekt-dsl = { module = "org.jetbrains.reflekt:reflekt-dsl", version.ref
 android-application = { id = "com.android.application", version.ref = "gradle" }
 android-library = { id = "com.android.library", version.ref = "gradle" }
 gradle-catalogs-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "gradle-catalogs-update" }
-gradle-devtools-google-ksp = { id = "com.google.devtools.ksp", version.ref = "gradle-devtools-google-ksp" }
+gradle-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
 gradle-ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
 # todo ktorfit https://foso.github.io/Ktorfit/
 #gradle-ktorfit = "de.jensklingenberg.ktorfit:1.10.2"
@@ -227,9 +244,12 @@ gradle-versions = { id = "com.github.ben-manes.versions", version.ref = "gradle-
 kotlin-compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
 kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
 kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
-kotlin-reflekt = { id = "org.jetbrains.reflekt", version.ref = "kotlin" }
 gradle-dokka = { id = "org.jetbrains.dokka" }
 objectbox = { id = "io.objectbox" }
 google-devtools-ksp = { id = "com.google.devtools.ksp" }
 gradle-paparazzi-plugin = { id = "app.cash.paparazzi" }
+compose-screenshot = { id = "com.android.compose.screenshot", version.ref = "compose-screenshot"}
+buildconfig = { id = "com.github.gmazzo.buildconfig", version = "3.1.0" }
+kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
+mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.29.0" }
 ####################################################################################################

+ 9 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,14 @@
+#
+#  Copyright (c) Milan Jurkulák 2024.
+#  Contact:
+#  e: mimoccc@gmail.com
+#  e: mj@mjdev.org
+#  w: https://mjdev.org
+#
+
 #Mon May 20 13:58:31 CEST 2024
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists

+ 0 - 23
processor/build.gradle.kts

@@ -1,23 +0,0 @@
-/*
- *  Copyright (c) Milan Jurkulák 2024.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-plugins {
-    id("org.jetbrains.kotlin.jvm")
-    id("kotlin")
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_17
-    targetCompatibility = JavaVersion.VERSION_17
-}
-
-dependencies {
-    implementation(project(":annotations"))
-    implementation(libs.kotlin.stdlib.jdk8)
-    implementation(libs.symbol.processing.api)
-}

+ 0 - 76
processor/src/main/kotlin/org/mjdev/processor/Processor.kt

@@ -1,76 +0,0 @@
-/*
- *  Copyright (c) Milan Jurkulák 2024.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-package org.mjdev.processor
-
-import com.google.devtools.ksp.processing.CodeGenerator
-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.symbol.KSAnnotated
-import com.google.devtools.ksp.symbol.KSFile
-import com.google.devtools.ksp.symbol.KSFunctionDeclaration
-import com.google.devtools.ksp.symbol.KSVisitorVoid
-import com.google.devtools.ksp.validate
-import org.mjdev.annotations.CreateScreenShot
-import org.mjdev.processor.base.ITestBuilder
-import org.mjdev.processor.builders.PaparazziTestBuilder
-import java.io.File
-
-@Suppress("unused")
-class Processor(
-    private val codeGenerator: CodeGenerator,
-    private val logger: KSPLogger,
-    private val options: Map<String, String>
-) : SymbolProcessor {
-
-    private val builders = mutableListOf<ITestBuilder>()
-
-    fun addBuilder(builder: ITestBuilder) {
-        builders.add(builder)
-    }
-
-    override fun process(resolver: Resolver): List<KSAnnotated> {
-        val screenshots = resolver.getSymbolsWithAnnotation(CreateScreenShot::class.qualifiedName!!)
-        if (!screenshots.iterator().hasNext()) {
-            return emptyList()
-        }
-        screenshots.forEach {
-            it.accept(ScreenShotsVisitor(), Unit)
-        }
-        val unableToProcess = screenshots.filterNot {
-            it.validate()
-        }.toList()
-        builders.forEach { builder ->
-            builder.build(codeGenerator)
-        }
-        return unableToProcess
-    }
-
-    inner class ScreenShotsVisitor : KSVisitorVoid() {
-
-        override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
-            val file = function.containingFile
-            if (file != null) {
-                PaparazziTestBuilder(file.projectDir).fileName(file.fileName)
-                    .packageName(file.packageName.asString()).function(function).also {
-                        addBuilder(it)
-                    }
-            }
-        }
-
-        private val KSFile.projectDir: File
-            get() = File(filePath).let {
-                var ff = it
-                while (ff.name != "src") ff = ff.parentFile
-                ff.parentFile
-            }
-
-    }
-
-}

+ 0 - 9
processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider

@@ -1,9 +0,0 @@
-#
-#  Copyright (c) Milan Jurkulák 2024.
-#  Contact:
-#  e: mimoccc@gmail.com
-#  e: mj@mjdev.org
-#  w: https://mjdev.org
-#
-
-org.mjdev.processor.ProcessorProvider

+ 12 - 6
settings.gradle.kts

@@ -37,10 +37,16 @@ dependencyResolutionManagement {
     }
 }
 
-rootProject.name = "TvApp"
-
-include(":annotations")
-include(":processor")
+fun Settings.includeAllModules() {
+    rootDir.walk().maxDepth(1).filter { file ->
+        val isBuildSrc = file.name == "buildSrc"
+        val isDirectory = file.isDirectory
+        val hasBuildScriptFile = file.resolve("build.gradle.kts").exists()
+        !isBuildSrc && isDirectory && hasBuildScriptFile
+    }.forEach {
+        include(":${it.name}")
+    }
+}
 
-include(":app")
-include(":tvlib")
+rootProject.name = "TvApp"
+includeAllModules()

二进制
sources/annotations.zip


二进制
sources/processor.zip


+ 9 - 1
tvlib/build.gradle.kts

@@ -9,11 +9,19 @@
 import org.mjdev.gradle.extensions.isAndroidStudio
 
 plugins {
-    id("LibPlugin")
+    LibPlugin
 }
 
 libConfig {
     namespace = "org.mjdev.tvlib"
     description = "Smart TV android app lib for android applications running on any android device"
+
+    autoCorrectCode = true
+    ignoreCodeFailures = true
+
     createDocumentation = !isAndroidStudio
+    reportUndocumentedFiles = !isAndroidStudio
+    failOnDocumentationWarning = false
+
+    minify = false
 }

+ 2 - 1
tvlib/src/main/AndroidManifest.xml

@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com

+ 2 - 2
tvlib/src/main/res/values/colors.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~  Copyright (c) Milan Jurkulák 2023.
+  ~  Copyright (c) Milan Jurkulák 2024.
   ~  Contact:
   ~  e: mimoccc@gmail.com
   ~  e: mj@mjdev.org
@@ -11,4 +11,4 @@
     <color name="white">#ffffffff</color>
     <color name="dark_gray">#ff444444</color>
     <color name="transparent">#00000000</color>
-</resources>
+</resources>