diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml
index 7c0d6045..4308ca98 100644
--- a/.github/workflows/codecov.yml
+++ b/.github/workflows/codecov.yml
@@ -18,21 +18,21 @@ jobs:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
- - uses: actions/setup-java@v3
+ - uses: actions/setup-java@v4
with:
distribution: 'adopt'
- java-version: 11
+ java-version: 17
cache: gradle
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.0.5'
channel: 'stable'
- - uses: gradle/gradle-build-action@v2.4.2
+ - uses: gradle/actions/setup-gradle@v3
with:
- gradle-version: 7.4.2
+ gradle-version: 8.3
arguments: clean build koverMergedXmlReport -p "lib"
- uses: codecov/codecov-action@v2
diff --git a/.github/workflows/dokka.yml b/.github/workflows/dokka.yml
index 043eb54f..89afdbd0 100644
--- a/.github/workflows/dokka.yml
+++ b/.github/workflows/dokka.yml
@@ -19,16 +19,16 @@ jobs:
timeout-minutes: 60
steps:
- name: 'checkout source'
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: 'setup java'
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: 'adopt'
- java-version: 11
+ java-version: 17
- name: 'setup gradle'
- uses: gradle/gradle-build-action@v2.4.2
+ uses: gradle/actions/setup-gradle@v3
with:
- gradle-version: 7.4.2
+ gradle-version: 8.3
- name: 'setup flutter'
uses: subosito/flutter-action@v2
with:
diff --git a/.github/workflows/kradle.yml b/.github/workflows/kradle.yml
deleted file mode 100644
index ef4aad9f..00000000
--- a/.github/workflows/kradle.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: Publish kradle executable.
-on:
- push:
-env:
- KLUTTER_PRIVATE_USERNAME: ${{ secrets.KLUTTER_PRIVATE_USERNAME }}
- KLUTTER_PRIVATE_PASSWORD: ${{ secrets.KLUTTER_PRIVATE_PASSWORD }}
- KLUTTER_PRIVATE_URL: ${{ secrets.KLUTTER_PRIVATE_URL }}
- KLUTTER_JETBRAINS_CERTIFICATE_CHAINS: ${{ secrets.KLUTTER_JETBRAINS_CERTIFICATE_CHAINS }}
- KLUTTER_JETBRAINS_PRIVATE_KEY: ${{ secrets.KLUTTER_JETBRAINS_PRIVATE_KEY }}
- KLUTTER_JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.KLUTTER_JETBRAINS_PRIVATE_KEY_PASSWORD }}
-jobs:
- archive-build-artifacts:
- strategy:
- matrix:
- os: [macos-latest] # don't need windows anymore...? windows-latest
- runs-on: ${{ matrix.os }}
- timeout-minutes: 60
- steps:
- - name: 'checkout source'
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- - name: 'install java'
- uses: actions/setup-java@v3
- with:
- distribution: 'adopt'
- java-version: 11
- cache: gradle
- - name: 'build distribution'
- uses: gradle/gradle-build-action@v2.4.2
- with:
- gradle-version: 7.4.2
- arguments: clean build -p "lib/kradle"
- - name: 'copy jar to kradle folder'
- run: cp ./lib/kradle/build/libs/kradle-wrapper.jar kradle/lib
- - name: 'create zip file'
- uses: vimtor/action-zip@v1.1
- with:
- files: kradle
- recursive: true
- dest: kradlew.zip
- - name: 'upload kradle folder'
- uses: actions/upload-artifact@v2
- with:
- name: kradlew
- path: ${{ github.workspace }}/kradlew.zip
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 61682247..3e8b7a82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,7 +88,3 @@ hs_err_pid*
/lib-test/rune2e.properties
/lib/gradle/src/main/resources/publish.properties
/test-ksp/local.properties
-/lib/gradle/src/main/resources/kradlew
-/lib/gradle/src/main/resources/kradlew.bat
-/kradle/kradlew
-/kradle/kradlew.bat
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55cca623..01baaa49 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,13 @@
# CHANGELOG
+## v2024.1.1.beta
+- Remove kradle module from project (kradle is the default executable since [kradle](..%2Fklutter-dart%2Fkradle) 3.0.0).
+- Add support for protocol buffers.
+
## v2023.3.1.beta
-- Refactored task module to package in kore.
-- Removed task module from BOM e.a.
-- Renamed kommand to kradle.
+- Refactor task module to package in kore.
+- Remove task module from BOM e.a.
+- Rename kommand to kradle.
## v2023.2.2.beta
- Remove example/integration_test folder on project init from example app.
@@ -15,8 +19,6 @@
- Uses [klutter-dart](https://pub.dev/packages/klutter) version 1.0.0.
- Uses [klutter-dart-ui](https://pub.dev/packages/klutter_ui) version 1.0.0.
-## v2023.3.1.beta
-
## v2023.1.1.beta
- Added support for request parameters.
- Added support for streaming data from platform to ui (using EventChannel).
diff --git a/LICENSE b/LICENSE
index f7cea8cd..2628c043 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2021 - 2023 Buijs Software
+Copyright (c) 2021 - 2024 Buijs Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 8df5996f..dec0b409 100644
--- a/README.md
+++ b/README.md
@@ -2,13 +2,12 @@
[![Jetbrains Marketplace](https://img.shields.io/jetbrains/plugin/v/19846-klutter?label=Jetbrains%20Plugin)](https://plugins.jetbrains.com/plugin/19846-klutter)
[![CodeScene Code Health](https://codescene.io/projects/27235/status-badges/code-health)](https://codescene.io/projects/27235)
[![codecov](https://codecov.io/gh/buijs-dev/klutter/branch/main/graph/badge.svg)](https://codecov.io/gh/buijs-dev/klutter)
-[![GitHub](https://img.shields.io/github/license/buijs-dev/klutter?color=black&style=plastic)](https://github.com/buijs-dev/klutter/blob/main/LICENSE)
+[![GitHub](https://img.shields.io/github/license/buijs-dev/klutter?color=black)](https://github.com/buijs-dev/klutter/blob/main/LICENSE)
Klutter is a framework which interconnects Flutter and Kotlin Multiplatform.
It can be used to create Flutter plugins.
-
### Getting started
- Start a new project with the
- [Intellij](https://buijs.dev/klutter-3/) plugin
diff --git a/build.gradle.kts b/build.gradle.kts
index 4e59fc73..0c094c7d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,5 @@
plugins {
- kotlin("jvm") version "1.7.10"
+ kotlin("jvm") version "1.9.10"
}
buildscript {
@@ -13,8 +13,8 @@ buildscript {
}
dependencies {
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
- classpath("com.android.tools.build:gradle:7.2.2")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
+ classpath("com.android.tools.build:gradle:8.1.4")
}
}
diff --git a/gradle.properties b/gradle.properties
index 62f26a22..2e6f8440 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,5 +1,5 @@
org.gradle.jvmargs=-Xms3096M -Xmx8192M -Dkotlin.daemon.jvm.options\="-Xmx8192M"
kotlin.mpp.stability.nowarn=true
-android.disableAutomaticComponentCreation=true
kotlin.mpp.enableCInteropCommonization=true
-kotlin.native.cacheKind.iosArm64=none
\ No newline at end of file
+kotlin.native.cacheKind.iosArm64=none
+kotlin.stdlib.default.dependency = false
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index aa991fce..db9a6b82 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/kradle.yaml b/kradle.yaml
deleted file mode 100644
index 4640f066..00000000
--- a/kradle.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-bom-version: '2023.3.1.beta'
-flutter-version: '3.10.6'
\ No newline at end of file
diff --git a/kradle/kradlew b/kradle/kradlew
deleted file mode 100755
index b97d6a0a..00000000
--- a/kradle/kradlew
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-#
-# kradlew start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh kradlew
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and KRADLEW_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-APP_HOME=$( cd "${APP_HOME:-./}.." && pwd -P ) || exit
-
-APP_NAME="kradlew"
-APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=$APP_HOME/lib/kradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and KRADLEW_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $KRADLEW_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
-
-set -- \
- -classpath "$CLASSPATH" \
- dev.buijs.klutter.kradle.MainKt \
- "$@"
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $KRADLEW_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/kradle/kradlew.bat b/kradle/kradlew.bat
deleted file mode 100755
index f508353a..00000000
--- a/kradle/kradlew.bat
+++ /dev/null
@@ -1,88 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem kradlew startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%..
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\lib\kradle-wrapper.jar
-
-@rem Execute kradlew
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %KRADLEW_OPTS% -classpath "%CLASSPATH%" dev.buijs.klutter.kradle.MainKt %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable KRADLEW_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%KRADLEW_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/kradlew b/kradlew
deleted file mode 100755
index 134a950e..00000000
--- a/kradlew
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-#
-# kradlew start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh kradlew
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and KRADLEW_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-APP_HOME=$( cd "${APP_HOME:-./}.." && pwd -P ) || exit
-
-APP_NAME="kradlew"
-APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=./kradle/lib/kradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and KRADLEW_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $KRADLEW_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
-
-set -- \
- -classpath "$CLASSPATH" \
- dev.buijs.klutter.kradle.MainKt \
- "$@"
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $KRADLEW_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/kradlew.bat b/kradlew.bat
deleted file mode 100755
index fec2a779..00000000
--- a/kradlew.bat
+++ /dev/null
@@ -1,88 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem kradlew startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%..
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=\kradle\lib\kradle-wrapper.jar
-
-@rem Execute kradlew
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %KRADLEW_OPTS% -classpath "%CLASSPATH%" dev.buijs.klutter.kradle.MainKt %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable KRADLEW_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%KRADLEW_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/lib-build/build.gradle.kts b/lib-build/build.gradle.kts
index 23c2daa9..285c4461 100644
--- a/lib-build/build.gradle.kts
+++ b/lib-build/build.gradle.kts
@@ -1,8 +1,14 @@
plugins {
- kotlin("jvm") version "1.7.10"
+ kotlin("jvm") version "1.9.10"
id("java-gradle-plugin")
}
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
+}
+
gradlePlugin {
plugins.register("klutter") {
id = "klutter"
@@ -18,8 +24,7 @@ buildscript {
}
dependencies {
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
- classpath("com.android.tools.build:gradle:7.2.2")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
}
}
@@ -32,7 +37,7 @@ allprojects {
}
dependencies {
- implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
+ implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
implementation("org.gradle.kotlin:gradle-kotlin-dsl-plugins:2.4.0")
implementation(gradleApi())
}
\ No newline at end of file
diff --git a/lib-build/src/main/kotlin/dev/buijs/klutter/KlutterInternalPlugin.kt b/lib-build/src/main/kotlin/dev/buijs/klutter/KlutterInternalPlugin.kt
index 74b9a890..58d36206 100644
--- a/lib-build/src/main/kotlin/dev/buijs/klutter/KlutterInternalPlugin.kt
+++ b/lib-build/src/main/kotlin/dev/buijs/klutter/KlutterInternalPlugin.kt
@@ -38,7 +38,6 @@ object ProjectVersions {
val kore = versions("kore.version")
val bom = versions("bom.version")
val annotations = versions("annotations.version")
- val kradle = versions("kradle.version")
val gradle = versions("plugin.gradle.version")
val jetbrains = versions("plugin.jetbrains.version")
val kompose = versions("kompose.version")
diff --git a/lib-build/src/main/resources/publish.properties b/lib-build/src/main/resources/publish.properties
index 965edf24..bc6f13c9 100644
--- a/lib-build/src/main/resources/publish.properties
+++ b/lib-build/src/main/resources/publish.properties
@@ -1,9 +1,8 @@
-annotations.version=2023.3.1.beta
-bom.version=2023.3.1.beta
-compiler.version=2023.3.1.beta
-flutter.engine.version=2023.3.1.beta
-kompose.version=2023.3.1.beta
-kore.version=2023.3.1.beta
-kradle.version=2023.3.1.beta
-plugin.gradle.version=2023.3.1.beta
-plugin.jetbrains.version=2023.3.1.beta
\ No newline at end of file
+annotations.version=2024.1.1.beta
+bom.version=2024.1.1.beta
+compiler.version=2024.1.1.beta
+flutter.engine.version=2024.1.1.beta
+kompose.version=2024.1.1.beta
+kore.version=2024.1.1.beta
+plugin.gradle.version=2024.1.1.beta
+plugin.jetbrains.version=2024.1.1.beta
\ No newline at end of file
diff --git a/lib-build/src/main/resources/repository.properties b/lib-build/src/main/resources/repository.properties
index 104d05e7..0e8816b2 100644
--- a/lib-build/src/main/resources/repository.properties
+++ b/lib-build/src/main/resources/repository.properties
@@ -1,3 +1,3 @@
-repo.username=hi
-repo.password=hi
-repo.endpoint=hi
\ No newline at end of file
+repo.username=none
+repo.password=none
+repo.endpoint=none
\ No newline at end of file
diff --git a/lib-test/build.gradle.kts b/lib-test/build.gradle.kts
index e2ef54a3..5a112a42 100644
--- a/lib-test/build.gradle.kts
+++ b/lib-test/build.gradle.kts
@@ -8,8 +8,14 @@ plugins {
java {
withJavadocJar()
withSourcesJar()
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+}
+
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
}
sourceSets {
@@ -28,13 +34,13 @@ sourceSets {
dependencies {
//Kotlin
- implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.10")
+ implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.22")
implementation("org.jetbrains.kotlin:kotlin-compiler:1.7.10")
//Jackson for XML
- implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
- implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2")
- implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.2")
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.1")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.16.1")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1")
//Logging
implementation("org.slf4j:slf4j-api:2.0.7")
@@ -45,7 +51,7 @@ dependencies {
api(gradleTestKit())
// Spock
- api("org.codehaus.groovy:groovy-all:3.0.9")
+ api("org.codehaus.groovy:groovy-all:3.0.17")
api("org.spockframework:spock-core:2.2-M1-groovy-3.0")
// Mockingjay
diff --git a/lib-test/src/main/groovy/dev/buijs/klutter/kore/test/TestUtil.groovy b/lib-test/src/main/groovy/dev/buijs/klutter/kore/test/TestUtil.groovy
index 86542228..c52c966a 100644
--- a/lib-test/src/main/groovy/dev/buijs/klutter/kore/test/TestUtil.groovy
+++ b/lib-test/src/main/groovy/dev/buijs/klutter/kore/test/TestUtil.groovy
@@ -19,7 +19,6 @@
* SOFTWARE.
*
*/
-
package dev.buijs.klutter.kore.test
class TestUtil {
diff --git a/lib/annotations/annotations.podspec b/lib/annotations/annotations.podspec
index 4ca5521d..86723e47 100644
--- a/lib/annotations/annotations.podspec
+++ b/lib/annotations/annotations.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'annotations'
- spec.version = '2023.3.1.beta'
+ spec.version = '2024.1.1.beta'
spec.homepage = 'https://buijs.dev'
spec.source = { :http=> ''}
spec.authors = ''
@@ -22,8 +22,8 @@ Pod::Spec.new do |spec|
:execution_position => :before_compile,
:shell_path => '/bin/sh',
:script => <<-SCRIPT
- if [ "YES" = "$COCOAPODS_SKIP_KOTLIN_BUILD" ]; then
- echo "Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\""
+ if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
+ echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
exit 0
fi
set -ev
diff --git a/lib/annotations/build.gradle.kts b/lib/annotations/build.gradle.kts
index 8f1873fc..849e1cd1 100644
--- a/lib/annotations/build.gradle.kts
+++ b/lib/annotations/build.gradle.kts
@@ -1,5 +1,5 @@
plugins {
- kotlin("plugin.serialization") version "1.7.10"
+ kotlin("plugin.serialization") version "1.9.10"
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
@@ -10,16 +10,21 @@ plugins {
group = "dev.buijs.klutter"
version = dev.buijs.klutter.ProjectVersions.annotations
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
+}
+
kotlin {
- android {
+ androidTarget {
publishLibraryVariants("release", "debug")
}
jvm()
iosX64()
iosArm64()
- iosArm32()
iosSimulatorArm64()
cocoapods {
@@ -35,7 +40,7 @@ kotlin {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
}
}
@@ -56,20 +61,14 @@ kotlin {
val jvmTest by getting
val androidMain by getting
- val androidAndroidTestRelease by getting
-
- val androidTest by getting {
- dependsOn(androidAndroidTestRelease)
- }
+ val androidUnitTest by getting
- val iosArm32Main by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
- iosArm32Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
@@ -78,11 +77,12 @@ kotlin {
}
android {
+ namespace = "dev.buijs.klutter.annotations"
compileSdk = 31
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
- targetSdk = 31
+ //targetSdk = 31
}
}
@@ -110,7 +110,7 @@ publishing {
tasks.withType().configureEach {
- outputDirectory.set(buildDir.resolve("dokka"))
+ outputDirectory.set(layout.buildDirectory.dir("dokka").get().asFile)
dokkaSourceSets {
register("annotations4Jvm") {
@@ -139,13 +139,13 @@ tasks.withType().configureEach {
tasks.named("iosX64Test", org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest::class.java).configure {
// ENV VAR is set in GH where iPhone 14 is not available
if(System.getenv("KLUTTER_PRIVATE_URL") == null) {
- deviceId = "iPhone 14 Pro Max"
+ device = "iPhone 14 Pro Max"
}
}
tasks.named("iosSimulatorArm64Test", org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest::class.java).configure {
// ENV VAR is set in GH where iPhone 14 is not available
if(System.getenv("KLUTTER_PRIVATE_URL") == null) {
- deviceId = "iPhone 14 Pro Max"
+ device = "iPhone 14 Pro Max"
}
}
\ No newline at end of file
diff --git a/lib/annotations/module.md b/lib/annotations/module.md
index 2fd86a85..d95a1781 100644
--- a/lib/annotations/module.md
+++ b/lib/annotations/module.md
@@ -104,7 +104,7 @@ Also add the json dependency to the commonMain sourceset:
```kotlin
val commonMain by getting {
dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
}
}
```
diff --git a/lib/annotations/src/androidMain/AndroidManifest.xml b/lib/annotations/src/androidMain/AndroidManifest.xml
deleted file mode 100644
index a5e77f1f..00000000
--- a/lib/annotations/src/androidMain/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts
index 4e086e3c..255493bd 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -2,7 +2,7 @@ import org.jetbrains.dokka.gradle.DokkaTask
plugins {
kotlin("jvm")
- id("org.jetbrains.dokka") version "1.6.10"
+ id("org.jetbrains.dokka") version "1.9.20"
id("org.jetbrains.kotlinx.kover") version "0.5.1"
id("klutter")
}
@@ -11,6 +11,12 @@ subprojects {
plugins.apply("org.jetbrains.dokka")
}
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
+}
+
kover {
// KOVER destroys running with coverage from IDE
@@ -33,12 +39,6 @@ kover {
// a test-only module
":lib-test",
-
- // a test-only module
- ":test-integration",
-
- // for KSP testing only
- ":test-ksp",
)
}
@@ -51,7 +51,7 @@ tasks.withType().configureEach {
}
tasks.dokkaHtmlMultiModule.configure {
- outputDirectory.set(layout.buildDirectory.dir("dokkaSite").map { it.asFile })
+ outputDirectory.set(layout.buildDirectory.dir("dokkaSite"))
}
tasks.koverMergedXmlReport {
diff --git a/lib/compiler/build.gradle.kts b/lib/compiler/build.gradle.kts
index c8fb9889..5d5c5503 100644
--- a/lib/compiler/build.gradle.kts
+++ b/lib/compiler/build.gradle.kts
@@ -3,15 +3,21 @@ plugins {
id("klutter")
id("groovy")
id("maven-publish")
- id("java-library")
+ //id("java-library")
}
-java {
- withJavadocJar()
- withSourcesJar()
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
+//java {
+// withJavadocJar()
+// withSourcesJar()
+// sourceCompatibility = JavaVersion.VERSION_17
+// targetCompatibility = JavaVersion.VERSION_17
+//}
+
+//kotlin {
+// jvmToolchain {
+// languageVersion.set(JavaLanguageVersion.of(17))
+// }
+//}
sourceSets {
main {
@@ -37,14 +43,15 @@ dependencies {
// KSP for annotation scanning
implementation(kotlin("stdlib"))
- implementation("com.google.devtools.ksp:symbol-processing-api:1.8.20-1.0.11")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+ implementation("com.google.devtools.ksp:symbol-processing-api:1.9.10-1.0.13")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.6.2")
// Jackson for XML and YAML
- implementation("com.fasterxml.jackson.core:jackson-databind:2.14.2")
- implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
- implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2")
- implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.2")
+ implementation("com.fasterxml.jackson.core:jackson-databind:2.16.1")
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.1")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.16.1")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1")
// Logging
implementation("org.slf4j:slf4j-api:2.0.7")
@@ -137,6 +144,6 @@ fun Dependency.getLocalOrProjectVersion() = when(name) {
"kore" ->
dev.buijs.klutter.ProjectVersions.kore
"kotlin-stdlib" ->
- "1.7.10"
+ "1.9.22"
else -> version
}
\ No newline at end of file
diff --git a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/Processor.kt b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/Processor.kt
index 03abde6c..0cfb7dda 100644
--- a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/Processor.kt
+++ b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/Processor.kt
@@ -28,14 +28,14 @@ import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.symbol.KSAnnotated
import dev.buijs.klutter.compiler.scanner.scanForControllers
import dev.buijs.klutter.compiler.scanner.scanForResponses
+import dev.buijs.klutter.compiler.scanner.scanForResponsesProtobuf
import dev.buijs.klutter.compiler.validator.*
-import dev.buijs.klutter.compiler.validator.Invalid
-import dev.buijs.klutter.compiler.validator.InvalidSquintMessages
-import dev.buijs.klutter.compiler.validator.Valid
-import dev.buijs.klutter.compiler.validator.ValidSquintMessages
import dev.buijs.klutter.compiler.wrapper.KCLogger
import dev.buijs.klutter.kore.ast.Controller
+import dev.buijs.klutter.kore.ast.CustomType
import dev.buijs.klutter.kore.ast.SquintMessageSource
+import dev.buijs.klutter.kore.common.EitherNok
+import dev.buijs.klutter.kore.common.EitherOk
import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
import dev.buijs.klutter.kore.common.verifyExists
import dev.buijs.klutter.kore.project.*
@@ -70,6 +70,13 @@ class Processor(
private var messages: List? = null
private var controllers: List? = null
+ /**
+ * List of FQDN names for each @Response annotated class.
+ *
+ * If protobuf is NOT enabled then this list stays empty.
+ */
+ private var responseClassNames: List? = null
+
private val flutterFolder: FlutterDistributionFolderName
get() {
val os = currentOperatingSystem
@@ -90,9 +97,18 @@ class Processor(
return folder
}
+
@ExcludeFromJacocoGeneratedReport
override fun process(resolver: Resolver): List {
kcLogger = KCLogger(log, options.outputFolder)
+ kcLogger!!.logCompilerOptions(options)
+
+ responseClassNames = if(options.isProtobufEnabled) {
+ resolver.findAndValidateResponsesForProtobuf()
+ } else {
+ emptyList()
+ }
+
messages = resolver.findAndValidateMessages()
controllers = resolver.findAndValidateControllers()
generateCodeAndInstall()
@@ -101,7 +117,7 @@ class Processor(
@ExcludeFromJacocoGeneratedReport
private fun Resolver.findAndValidateMessages() =
- scanForResponses(resolver = this, outputFolder = options.outputFolder)
+ scanForResponses(resolver = this, outputFolder = options.outputFolder, isProtobufEnabled = options.isProtobufEnabled)
.validateResponses().let {
when (it) {
is ValidSquintMessages -> it.data
@@ -112,12 +128,43 @@ class Processor(
}
}
+ /**
+ * Returns the fully qualified class names of @Response annotated classes.
+ */
+ @ExcludeFromJacocoGeneratedReport
+ private fun Resolver.findAndValidateResponsesForProtobuf() =
+ scanForResponsesProtobuf(resolver = this, outputFolder = options.outputFolder)
+ .let { results ->
+ when {
+ results.any { result -> result is EitherNok } -> {
+ val warnings = results
+ .filterIsInstance>()
+ .map { it.data }
+ kcLogger?.logAnnotationScanningWarnings(warnings, "@Response")
+ null
+ }
+
+ else -> results
+ .filterIsInstance>()
+ .map { it.data }
+ }
+ }
+
@ExcludeFromJacocoGeneratedReport
private fun Resolver.findAndValidateControllers() =
scanForControllers(
resolver = this,
outputFolder = options.outputFolder,
- responses = messages?.map { it.type }?.toSet() ?: emptySet())
+ responses = messages
+ ?.map { it.type }
+ ?.toSet()
+ ?: responseClassNames
+ ?.map { CustomType(
+ className = it.substringAfterLast("."),
+ packageName = it.substringBeforeLast("."))
+ }
+ ?.toSet()
+ ?: emptySet())
.validateControllers(messages?.map { it.type } ?: emptyList()).let {
when (it) {
is Valid -> it.data
@@ -128,12 +175,19 @@ class Processor(
}
}
+
@ExcludeFromJacocoGeneratedReport
private fun generateCodeAndInstall() {
// If null then there are validation errors and code generation should be skipped
- if (messages == null || controllers == null) return
+ if (messages == null || controllers == null || responseClassNames == null) return
+
+ val responsesCount = if(messages!!.isEmpty()) {
+ responseClassNames!!.size
+ } else {
+ messages!!.size
+ }
- kcLogger?.logSquintInfo(project, messages!!.size, controllers!!.size)
+ kcLogger?.logDartCodeGenInfo(project, responsesCount, controllers!!.size)
val codegenOptions = GenerateCodeOptions(
project = project,
@@ -141,6 +195,7 @@ class Processor(
excludeArmArcFromPodspec = currentArchitecture == Architecture.X64,
controllers = controllers!!,
messages = messages!!,
+ responseClassNames = responseClassNames!!,
flutterFolder = flutterFolder,
log = { str -> kcLogger?.info("Running dart command:\n$str") })
@@ -158,11 +213,23 @@ private fun KCLogger.logAnnotationScanningWarnings(warnings: List, annot
}
@ExcludeFromJacocoGeneratedReport
-private fun KCLogger.logSquintInfo(project: Project, messageCount: Int, controllerCount: Int) {
+private fun KCLogger.logDartCodeGenInfo(project: Project, responseCount: Int, controllerCount: Int) {
info("=============================================================")
info("Generating dart code")
info("Root folder: ${project.root.folder.absolutePath}")
- info("Response count: $messageCount")
+ info("Response count: $responseCount")
info("Controller count: $controllerCount")
info("=============================================================")
+}
+
+@ExcludeFromJacocoGeneratedReport
+private fun KCLogger.logCompilerOptions(options: ProcessorOptions) {
+ info("=============================================================")
+ info("Compiler Options")
+ info("Project folder: ${options.projectFolder}")
+ info("Output folder: ${options.outputFolder}")
+ info("Flutter version: ${options.flutterVersion}")
+ info("Adapter codegen isEnabled: ${options.generateAdapters}")
+ info("Protobuf isEnabled: ${options.isProtobufEnabled}")
+ info("=============================================================")
}
\ No newline at end of file
diff --git a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/ProcessorOptions.kt b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/ProcessorOptions.kt
index f415adc8..407a3ad7 100644
--- a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/ProcessorOptions.kt
+++ b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/processor/ProcessorOptions.kt
@@ -39,17 +39,18 @@ data class ProcessorOptions(
val outputFolder: File,
val flutterVersion: String,
val generateAdapters: Boolean,
+ val isProtobufEnabled: Boolean,
)
/**
- * Possible options that can be set in the ksp DSL to configure
- * Klutter code scanning/generation.
+ * Possible options that can be set in the ksp DSL to configure Klutter code scanning/generation.
*/
internal enum class ProcessorOption(val value: String) {
PROJECT_FOLDER("klutterProjectFolder"),
OUTPUT_FOLDER("klutterOutputFolder"),
GENERATE_ADAPTERS("klutterGenerateAdapters"),
FLUTTER_SDK_VERSION("flutterVersion"),
+ PROTOBUF_ENABLED("klutterProtobufEnabled")
}
/**
@@ -84,7 +85,8 @@ internal fun processorOptions(
projectFolder = options.projectFolder(),
outputFolder = outputFolder?.let { File(it) } ?: options.outputFolder(),
generateAdapters = skipCodeGen?.let { !it } ?: options.boolean(GENERATE_ADAPTERS),
- flutterVersion = flutterOrNull ?: options.flutterVersion()
+ flutterVersion = flutterOrNull ?: options.flutterVersion(),
+ isProtobufEnabled = options.boolean(PROTOBUF_ENABLED, defaultValue = false),
).also { kcLogger?.info("Determined Processor Options: $it") }
}
@@ -142,5 +144,5 @@ private fun Map.flutterVersion(): String {
/**
* Return option argument as boolean value or default to true if not set.
*/
-private fun Map.boolean(option: ProcessorOption) =
- this[option.value]?.let { it.trim().lowercase() == "true" } ?: true
\ No newline at end of file
+private fun Map.boolean(option: ProcessorOption, defaultValue: Boolean = true) =
+ this[option.value]?.let { it.trim().lowercase() == "true" } ?: defaultValue
\ No newline at end of file
diff --git a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseOutput.kt b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseOutput.kt
index 73f1c88e..66e477bc 100644
--- a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseOutput.kt
+++ b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseOutput.kt
@@ -57,6 +57,7 @@ internal fun Either.writeOutput(
is EitherOk -> {
val file = folder.resolve("$squintJsonMetadataPrefix${data.type.className.lowercase()}.json")
file.createNewFile()
+
when (data.squintType) {
is SquintCustomType ->
file.writeText(JSON.encodeToString(data.squintType))
@@ -67,4 +68,33 @@ internal fun Either.writeOutput(
}
}
+}
+
+/**
+ * Write FQDN of Response class or error message to [outputFolder].
+ */
+internal fun Either.writeResponseFQDN(
+ outputFolder: File, count: Int
+): Either {
+
+ val folder = outputFolder
+ .resolve("response")
+ .maybeCreateFolder()
+
+ return when (this) {
+ is EitherNok -> {
+ val file = folder.resolve("${count}_invalid.txt")
+ file.createNewFile()
+ file.writeText(data)
+ Either.nok(data)
+ }
+
+ is EitherOk -> {
+ val file = folder.resolve("proto_${count}.txt")
+ file.createNewFile()
+ file.writeText(data)
+ Either.ok(data)
+ }
+ }
+
}
\ No newline at end of file
diff --git a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseScanner.kt b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseScanner.kt
index 5d3d92ec..ec248f6c 100644
--- a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseScanner.kt
+++ b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/scanner/ResponseScanner.kt
@@ -24,12 +24,12 @@ package dev.buijs.klutter.compiler.scanner
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSClassDeclaration
import dev.buijs.klutter.compiler.wrapper.*
-import dev.buijs.klutter.compiler.wrapper.KCResponse
-import dev.buijs.klutter.compiler.wrapper.toKCResponse
import dev.buijs.klutter.kore.ast.*
import dev.buijs.klutter.kore.common.Either
+import kotlinx.serialization.ExperimentalSerializationApi
import java.io.File
+
/**
* FQDN for classes annotated with @Response.
*/
@@ -39,10 +39,9 @@ private const val RESPONSE_ANNOTATION =
/**
* Get all classes with @Response annotation and convert them to [KCController].
*/
-private fun getSymbolsWithResponseAnnotation(resolver: Resolver): List =
+private fun getSymbolsWithResponseAnnotation(resolver: Resolver): List =
resolver.getSymbolsWithAnnotation(RESPONSE_ANNOTATION)
.filterIsInstance()
- .map { clazz -> clazz.toKCResponse() }
.toList()
/**
@@ -58,24 +57,59 @@ private fun getSymbolsWithResponseAnnotation(resolver: Resolver): List List = { getSymbolsWithResponseAnnotation(it) },
+ isProtobufEnabled: Boolean,
+ scanner: (resolver: Resolver) -> List = {
+ getSymbolsWithResponseAnnotation(it).map { clazz -> clazz.toKCResponse() } },
): List> =
scanner.invoke(resolver)
- .map { it.toSquintMessageSourceOrFail() }
+ .map { it.toSquintMessageSourceOrFail(isProtobufEnabled) }
.mapIndexed { index, data -> data.writeOutput(outputFolder, index) }
.toList()
-private fun KCResponse.toSquintMessageSourceOrFail()
+@JvmOverloads
+internal fun scanForResponsesProtobuf(
+ outputFolder: File,
+ resolver: Resolver,
+ scanner: (resolver: Resolver) -> List = { getSymbolsWithResponseAnnotation(it) },
+): List> =
+ scanner.invoke(resolver)
+ .map { it.toSchemaSourceOrFail() }
+ .mapIndexed { index, data -> data.writeResponseFQDN(outputFolder, index) }
+ .toList()
+
+private fun KCResponse.toSquintMessageSourceOrFail(isProtobufEnabled: Boolean)
: Either = when(this) {
is KCEnumeration -> enumeration()
- is KCMessage -> message()
+ is KCMessage -> message(isProtobufEnabled)
+}
+
+private fun KSClassDeclaration.toSchemaSourceOrFail()
+: Either {
+
+ val annotationNames = annotations
+ .map{ it.shortName.getShortName() }
+ .toList()
+
+ val isSerializableAnnotated =
+ annotationNames.contains("Serializable")
+
+ val className = "$this"
+ val packageName = packageName.asString()
+
+ if(!isSerializableAnnotated)
+ return Either.nok("Class is missing @Serializable annotation: $packageName.$className")
+
+ if(superTypes.map { it.toString() }.toList().contains("JSON"))
+ return Either.nok("Class extends JSON which is incompatible with Protobuf (remove JSON interface to fix): $packageName.$className")
+
+ return Either.ok("$packageName.$className")
}
-private fun KCMessage.message(): Either {
+private fun KCMessage.message(isProtobufEnabled: Boolean): Either {
if(!isSerializableAnnotated)
return missingSerializableAnnotation()
- if(!extendsJSON)
+ if(!extendsJSON && !isProtobufEnabled)
return doesNotExtendKlutterJSON()
val validTypeMembers = typeMembers
diff --git a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/wrapper/KCController.kt b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/wrapper/KCController.kt
index a0d73517..fc648608 100644
--- a/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/wrapper/KCController.kt
+++ b/lib/compiler/src/main/kotlin/dev/buijs/klutter/compiler/wrapper/KCController.kt
@@ -55,4 +55,35 @@ internal fun KSClassDeclaration.toKotlinClassWrapper(responses: Set = getConstructors().toList()
+
+ val controllerType = annotations
+ .filter { it.shortName.asString() == "Controller" }
+ .filter { it.arguments.isNotEmpty() }
+ .map { it.arguments.firstOrNull { arg -> arg.name?.getShortName() == "type" } }
+ .filterNotNull()
+ .map { it.value.toString() }
+ .firstOrNull { it.startsWith("dev.buijs.klutter.annotations.ControllerType.") }
+ ?.substringAfterLast("dev.buijs.klutter.annotations.ControllerType.")
+ ?: "Default"
+
+ val publisherOrNull =
+ superTypes.firstOrNull { it.toString() == "Publisher" }
+
+ return KCController(
+ hasOneConstructor = constructors.size == 1,
+ firstConstructorHasNoParameters = constructors.firstOrNull()?.parameters?.isEmpty() ?: false,
+ events = emptyList(),
+ eventErrors = emptyList(),
+ controllerType = controllerType,
+ isBroadcastController = publisherOrNull != null,
+ broadcastTypeParameterOrBlank = publisherOrNull?.resolve()?.arguments?.first()?.type?.toString() ?: "",
+ className ="$this",
+ packageName = packageName.asString())
}
\ No newline at end of file
diff --git a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/processor/ProcessorProviderSpec.groovy b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/processor/ProcessorProviderSpec.groovy
index 91587503..468ebab1 100644
--- a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/processor/ProcessorProviderSpec.groovy
+++ b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/processor/ProcessorProviderSpec.groovy
@@ -96,7 +96,7 @@ class ProcessorProviderSpec extends Specification {
and: "default kradle.yaml as generated by klutter-dart"
yaml.createNewFile()
- yaml.write("""bom-version: '2023.3.1.beta'\nflutter-version: '3.10.6'""")
+ yaml.write("""bom-version: '2023.3.1.beta'\nflutter-version: '3.10.6'\n""")
and: "default kradle.env as generated by klutter-dart"
def envFile = projectFolder.toPath().resolve("kradle.env").toFile()
@@ -126,7 +126,7 @@ class ProcessorProviderSpec extends Specification {
with(processor.options$compiler) {
it.flutterVersion == "3.10.6"
!it.generateAdapters
- //it.intelBasedBuildMachine
+ !it.protobufEnabled
it.outputFolder.absolutePath == outputFolder.absolutePath
it.projectFolder.absolutePath == projectFolder.absolutePath
}
diff --git a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ControllerScannerSpec.groovy b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ControllerScannerSpec.groovy
index 137634e3..57bec01e 100644
--- a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ControllerScannerSpec.groovy
+++ b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ControllerScannerSpec.groovy
@@ -155,7 +155,7 @@ class ControllerScannerSpec extends Specification {
it.data.class.simpleName == classType
it.data.className == "SomeClass"
it.data.packageName == "some.pack.age"
- it.data.functions.size == 1
+ it.data.functions.size() == 1
//noinspection GroovyAssignabilityCheck
it.data.functions[0] == dummyMethod
}
@@ -190,7 +190,7 @@ class ControllerScannerSpec extends Specification {
it.data.class.simpleName == classType
it.data.className == "SomeClass"
it.data.packageName == "some.pack.age"
- it.data.functions.size == 1
+ it.data.functions.size() == 1
//noinspection GroovyAssignabilityCheck
it.data.functions[0] == dummyMethod
}
diff --git a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ResponseScannerSpec.groovy b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ResponseScannerSpec.groovy
index 019453a3..1ebfcc77 100644
--- a/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ResponseScannerSpec.groovy
+++ b/lib/compiler/src/test/groovy/dev/buijs/klutter/compiler/scanner/ResponseScannerSpec.groovy
@@ -34,6 +34,7 @@ import dev.buijs.klutter.kore.common.EitherNok
import dev.buijs.klutter.kore.common.EitherOk
import kotlin.sequences.Sequence
import kotlin.sequences.SequencesKt
+import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Specification
@@ -80,7 +81,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -94,7 +95,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -108,7 +109,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -122,7 +123,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -136,7 +137,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -150,7 +151,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherOk) {
@@ -175,7 +176,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherNok) {
@@ -192,7 +193,7 @@ class ResponseScannerSpec extends Specification {
when:
def result = ResponseScannerKt
- .scanForResponses(outputFolder, resolver, {classes })
+ .scanForResponses(outputFolder, resolver, false, {classes })
then:
with(result[0] as EitherOk) {
@@ -206,6 +207,8 @@ class ResponseScannerSpec extends Specification {
}
}
+ // TODO cannot mock a sealed interface
+ @Ignore
def "When no callback is given, then default symbol-processor callback is used" () {
given:
Resolver resolver = Mock()
diff --git a/lib/gradle/build.gradle.kts b/lib/gradle/build.gradle.kts
index 72aa0806..836aada4 100644
--- a/lib/gradle/build.gradle.kts
+++ b/lib/gradle/build.gradle.kts
@@ -1,23 +1,17 @@
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+
plugins {
kotlin("jvm")
- id("com.gradle.plugin-publish") version "0.16.0"
+ id("com.gradle.plugin-publish") version "1.2.1"
+ id("com.github.johnrengelman.shadow") version "8.1.1"
id("java-gradle-plugin")
- id("java-library")
- id("maven-publish")
- // id("groovy")
+ id("groovy")
id("klutter")
}
group = "dev.buijs.klutter"
version = dev.buijs.klutter.ProjectVersions.gradle
-java {
- withJavadocJar()
- withSourcesJar()
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
sourceSets {
main {
java {
@@ -27,18 +21,21 @@ sourceSets {
test {
java {
- srcDirs("${projectDir.absolutePath}/src/test/kotlin")
+ srcDirs(
+ "${projectDir.absolutePath}/src/test/kotlin",
+ "${projectDir.absolutePath}/src/test/groovy")
}
}
}
publishing {
repositories {
+ mavenLocal()
maven {
url = dev.buijs.klutter.Repository.endpoint
credentials {
- username = dev.buijs.klutter.Repository.username
- password = dev.buijs.klutter.Repository.password
+ username = dev.buijs.klutter.Repository.username
+ password = dev.buijs.klutter.Repository.password
}
}
}
@@ -48,7 +45,7 @@ publishing {
groupId = "dev.buijs.klutter"
artifactId = "gradle"
version = dev.buijs.klutter.ProjectVersions.gradle
- artifact("$projectDir/build/libs/gradle-${dev.buijs.klutter.ProjectVersions.gradle}.jar")
+ from(components.findByName("java"))
pom {
name.set("Klutter: Gradle Plugin")
@@ -80,14 +77,8 @@ publishing {
}
}
-pluginBundle {
- website = "https://buijs.dev/klutter/"
- vcsUrl = "https://github.com/buijs-dev/klutter"
- tags = listOf("klutter", "flutter", "kotlin", "multiplatform")
-}
-
gradlePlugin {
- isAutomatedPublishing = false
+ isAutomatedPublishing = true
plugins {
create("klutterGradlePlugin") {
id = "dev.buijs.klutter"
@@ -103,13 +94,12 @@ gradlePlugin {
dependencies {
// Project
implementation(project(":lib:kore"))
- implementation(project(":lib:kradle"))
// Kotlin: Required to check if Kotlin Multiplatform plugin is applied
- implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
+ implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
// KSP Compiler plugin
- implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.8.20-1.0.11")
+ implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.9.10-1.0.13")
// Jackson XML/YAML parsing
implementation("com.fasterxml.jackson.core:jackson-databind:2.14.2")
@@ -126,7 +116,12 @@ dependencies {
}
-tasks.named("test") {
+tasks.withType {
+ archiveClassifier.set("")
+ archiveVersion.set("")
+}
+
+tasks.withType {
useJUnitPlatform()
}
diff --git a/lib/gradle/module.md b/lib/gradle/module.md
index 06f20166..abc683b4 100644
--- a/lib/gradle/module.md
+++ b/lib/gradle/module.md
@@ -7,31 +7,52 @@ Kotlin/Dart/Groovy code needed to make Flutter and KMP work together.
Important: For using and/or creating Flutter plugins with Klutter you should use the pub [plugin](https://github.com/buijs-dev/klutter-dart).
## Installation
-Preferred way of installing/using this plugin is by using the pub [plugin](https://github.com/buijs-dev/klutter-dart).
+Preferred way of installing/using this plugin is by starting a new project with one of:
+- [Intellij](https://buijs.dev/klutter-3/) plugin
+- [Android Studio](https://buijs.dev/klutter-4/) plugin
+- [Kradle](https://buijs.dev/kradle-1/) cli tool
## Tasks
-1. [klutterExcludeArchsPlatformPodspec](#Task:%20klutterExcludeArchsPlatformPodspec)
-2. [klutterGenerateAdapters](#Task:%20klutterGenerateAdapters)
+The gradle plugin defines tasks for compiling the Kotlin Multiplatform module,
+generating Dart code and more. Some tasks are executed automatically before (compiler plugin)
+and after running a gradle build.
-# Task: klutterExcludeArchsPlatformPodspec
-A Flutter app using Kotlin Multiplatform code won't run on an iOS simulator.
-There's an easy fix for that: Exclude arm64 architecture from the podspec file.
-This task does so by adding the following 2 lines of code to the KMP module .podspec file:
+1. [klutterCompileProtoSchemas](#Task:%20klutterCompileProtoSchemas)
+2. [klutterCopyAarFile](#Task:%20klutterCopyAarFile)
+3. [klutterCopyFramework](#Task:%20klutterCopyFramework)
+4. [klutterGenerateFlutterLib](#Task:%20klutterGenerateFlutterLib)
+5. [klutterGenerateProtoSchemas](#Task:%20klutterGenerateProtoSchemas)
+6. [klutterGetDartProtoc](#Task:%20klutterDartProtoc)
+7. [klutterGetKradle](#Task:%20klutterGetKradle)
+8. [klutterGetProtoc](#Task:%20klutterGetProtoc)
-```
- pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }""")
- user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }""")
-```
+# Task: klutterCompileProtoSchemas
+Compile protocol buffer schemas which generates boilerplate code for both Kotlin and Dart.
+This task does nothing when the protobuf feature is not enabled.
+
+# Task: klutterCopyAarFile
+Copy the root/platform aar file to root/android folder.
+
+# Task: klutterCopyFramework
+Copy the root/platform iOS Framework to root/ios folder.
-# Task: klutterGenerateAdapters
-The generate adapters task creates all the boilerplate code needed to make the Dart code in Flutter
-communicate with Kotlin in the Multiplatform module.
+# Task: klutterGenerateFlutterLib
+Generate the Dart library file in the root/lib folder.
-The following steps are executed to do so:
-- Scan the KMP module for annotations.
-- Convert Kotlin classes to Dart.
-- Generate a library Dart file in the root/lib folder.
-- Generate an adapter Kotlin file in the root/android folder.
-- Generate an adapter Swift file in the root/ios folder.
+# Task: klutterGenerateProtoSchemas
+Generate protocol buffer schemas which can be used by [klutterCompileProtoSchemas](#Task:%20klutterCompileProtoSchemas).
+This task does nothing when the protobuf feature is not enabled.
-The generated Dart library then gives access to any native code written in Kotlin Multiplatform.
\ No newline at end of file
+# Task: klutterGetDartProtoc
+Download the dart protobuf plugin.
+
+# Task: klutterGetKradle
+Download the kradle cli tool.
+
+# Task: klutterGetProtoc
+Download the protoc executable tool. The distribution url can be specified
+in the kradle.env file:
+
+```properties
+protoc.url=https://github.com/protocolbuffers/protobuf/releases/download/v25.3/protoc-25.3-osx-universal_binary.zip
+```
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/KlutterGradlePlugin.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/KlutterGradlePlugin.kt
index 968be132..e1726479 100644
--- a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/KlutterGradlePlugin.kt
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/KlutterGradlePlugin.kt
@@ -24,45 +24,169 @@ package dev.buijs.klutter.gradle
import com.google.devtools.ksp.gradle.KspExtension
import com.google.devtools.ksp.gradle.KspGradleSubplugin
import dev.buijs.klutter.gradle.dsl.KlutterExtension
+import dev.buijs.klutter.gradle.tasks.*
import dev.buijs.klutter.gradle.tasks.CopyAndroidAarFileGradleTask
import dev.buijs.klutter.gradle.tasks.CopyIosFrameworkGradleTask
-import dev.buijs.klutter.gradle.tasks.GetKradleTask
+import dev.buijs.klutter.gradle.tasks.GetProtocDartGradleTask
+import dev.buijs.klutter.gradle.tasks.GetProtocGradleTask
+import dev.buijs.klutter.gradle.tasks.KlutterGradleTaskName.*
import dev.buijs.klutter.kore.project.kspArgumentKlutterProjectFolder
import org.gradle.api.Plugin
import org.gradle.api.Project
-import org.gradle.api.plugins.PluginContainer
import org.gradle.api.tasks.TaskContainer
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
/**
* Gradle plugin for Klutter Framework.
+ *
+ * The plugin has extension [KlutterExtension] which can be used to configure the klutter project.
+ * See [KlutterGradleTaskName] for all available tasks. Most tasks are run automatically when executing a Gradle build.
+ * See [bindPostBuildTasks].
+ *
+ * The klutter compiler plugin is applied which handles annotation scanning, code generation and more.
*/
-class KlutterGradlePlugin: Plugin {
+class KlutterGradlePlugin : Plugin {
override fun apply(project: Project) {
with(project) {
- tasks.registerTasks()
- plugins.applyKspPlugin()
- extensions.add("klutter", KlutterExtension(project))
-
- val ext = project.extensions.getByType(KspExtension::class.java)
+ applyAndConfigureKspExtension()
+ registerTasks()
+ addKlutterExtension()
project.afterEvaluate {
- ext.arg(kspArgumentKlutterProjectFolder, project.rootDir.absolutePath)
+ configureKotlinMultiplatformExtension {
+ bindPostBuildTasks()
+ }
}
}
}
}
/**
- * Apply KSP Gradle Plugin.
+ * Add the [KlutterExtension] to the Gradle [Project].
+ */
+private fun Project.addKlutterExtension() {
+ extensions.add("klutter", KlutterExtension(project))
+}
+
+/**
+ * Apply the [KspGradleSubplugin] and add required arguments for the compiler plugin.
+ */
+private fun Project.applyAndConfigureKspExtension() {
+ plugins.apply(KspGradleSubplugin::class.java)
+ val ksp = project.extensions.getByType(KspExtension::class.java)
+ ksp.arg(kspArgumentKlutterProjectFolder, project.rootDir.absolutePath)
+}
+
+/**
+ * Add KSP generated code to the KMP source sets.
+ */
+private fun Project.configureKotlinMultiplatformExtension(
+ /**
+ * Action to invoke if the [KotlinMultiplatformExtension] is found.
+ *
+ * The [KlutterGradlePlugin] is applied to the platform module which is a KMP module
+ * and the android module which is not a KMP module. Some configuration can only be
+ * done in a KMP module, which can be configured through this closure.
+ */
+ doIfExtensionIsPresent: () -> Unit
+) {
+ // KMP
+ val kmp = try {
+ project.extensions.getByType(KotlinMultiplatformExtension::class.java)
+ } catch (_: Exception) {
+ null
+ }
+
+ if (kmp != null) {
+ kmp.sourceSets
+ .getByName("commonMain")
+ .kotlin
+ .srcDir(layout.buildDirectory.file("generated/ksp/metadata/commonMain/kotlin"))
+ doIfExtensionIsPresent()
+ }
+}
+
+/**
+ * Register Klutter tasks in the Gradle [Project].
*/
-private fun PluginContainer.applyKspPlugin() {
- apply(KspGradleSubplugin::class.java)
+private fun Project.registerTasks() {
+ tasks.registerTasks()
}
/**
- * Register the custom Klutter tasks.
+ * Register Klutter tasks in the [TaskContainer].
*/
private fun TaskContainer.registerTasks() {
- register("klutterCopyAarFile", CopyAndroidAarFileGradleTask::class.java)
- register("klutterCopyFramework", CopyIosFrameworkGradleTask::class.java)
- register("klutterGetKradle", GetKradleTask::class.java)
+ for (gradleTaskName in KlutterGradleTaskName.entries) {
+ when (gradleTaskName) {
+ GenerateProtoSchemas -> {
+ // Should be registered directly in build.gradle.kts.
+ }
+
+ CompileProtoSchemas ->
+ registerTask(gradleTaskName)
+
+ CopyAndroidAarFile ->
+ registerTask(gradleTaskName)
+
+ CopyIosFramework ->
+ registerTask(gradleTaskName)
+
+ GenerateFlutterLib ->
+ registerTask(gradleTaskName)
+
+ GetProtocDart ->
+ registerTask(gradleTaskName)
+
+ GetProtoc ->
+ registerTask(gradleTaskName)
+
+ GetKradle ->
+ registerTask(gradleTaskName)
+ }
+ }
+}
+
+private fun Project.bindPostBuildTasks() {
+ tasks.bindPostBuildTasks()
+}
+
+private fun TaskContainer.bindPostBuildTasks() {
+ val assembleXCFrameworkTaskName = "assemblePlatformReleaseXCFramework"
+
+ finalizeTaskBy("build") {
+ +assembleXCFrameworkTaskName
+ +GenerateProtoSchemas
+ +CopyAndroidAarFile
+ }
+
+ finalizeTaskBy(assembleXCFrameworkTaskName) {
+ +CopyIosFramework
+ }
+
+ finalizeTaskBy(GenerateProtoSchemas.taskName) {
+ +CompileProtoSchemas
+ }
+}
+
+private fun TaskContainer.finalizeTaskBy(
+ name: String,
+ builder: StringListBuilder.() -> Unit
+) {
+ getByName(name).setFinalizedBy(StringListBuilder().also(builder).data)
+}
+
+private class StringListBuilder {
+ val data: MutableList = mutableListOf()
+
+ operator fun String.unaryPlus() {
+ data.add(this)
+ }
+
+ operator fun KlutterGradleTaskName.unaryPlus() {
+ data.add(this.taskName)
+ }
+}
+
+private inline fun TaskContainer.registerTask(task: KlutterGradleTaskName) {
+ register(task.taskName, T::class.java)
}
\ No newline at end of file
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterExtension.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterExtension.kt
index ae7581a1..34cc0c30 100644
--- a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterExtension.kt
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterExtension.kt
@@ -22,17 +22,17 @@
@file:Suppress("unused")
package dev.buijs.klutter.gradle.dsl
+import com.google.devtools.ksp.gradle.KspExtension
import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
import org.gradle.api.Project
import org.gradle.api.tasks.Internal
import java.io.File
-import java.util.*
/**
* Glue for the DSL used in a build.gradle(.kts) file and the Klutter tasks.
*/
@Suppress("MemberVisibilityCanBePrivate")
-open class KlutterExtension(project: Project) {
+open class KlutterExtension(private val project: Project) {
private val handler = KlutterDependencyHandler(project)
@@ -43,6 +43,11 @@ open class KlutterExtension(project: Project) {
@Internal
internal var plugin: Dto? = null
+ internal val features = mutableSetOf()
+
+ internal val isProtobufEnabled: Boolean
+ get() = features.contains(KlutterFeature.PROTOBUF)
+
/**
* Configure the Gradle Plugin for a klutter plugin (consumer or producer).
*/
@@ -50,6 +55,23 @@ open class KlutterExtension(project: Project) {
plugin = KlutterPluginBuilder().apply(lambda).build()
}
+ /**
+ * Enable or disable specific klutter features.
+ *
+ * See for feature list: [KlutterFeature].
+ */
+ fun feature(name: KlutterFeature, enable: Boolean = true) {
+ if(enable) {
+ features.add(name)
+ project.extensions.getByType(KspExtension::class.java)
+ .arg("klutterProtobufEnabled", "true")
+ } else {
+ features.remove(name)
+ project.extensions.getByType(KspExtension::class.java)
+ .arg("klutterProtobufEnabled", "false")
+ }
+ }
+
/**
* Add klutter implementation dependency to this project.
*/
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterFeature.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterFeature.kt
new file mode 100644
index 00000000..fe99b2c7
--- /dev/null
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/dsl/KlutterFeature.kt
@@ -0,0 +1,10 @@
+package dev.buijs.klutter.gradle.dsl
+
+enum class KlutterFeature {
+ /**
+ * Enable the protocol buffer feature.
+ *
+ * This replaces JSON (de)serialization as communication method between Kotlin and Dart.
+ */
+ PROTOBUF
+}
\ No newline at end of file
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/AbstractTask.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/AbstractTask.kt
index c7042df6..58d8b9bc 100644
--- a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/AbstractTask.kt
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/AbstractTask.kt
@@ -23,32 +23,59 @@ package dev.buijs.klutter.gradle.tasks
import dev.buijs.klutter.gradle.dsl.KlutterExtension
import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
import dev.buijs.klutter.kore.project.Project
import dev.buijs.klutter.kore.project.plugin
-import mu.KotlinLogging
import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
-private val log = KotlinLogging.logger { }
+/**
+ * Name of a Gradle Task added by Klutter.
+ */
+enum class KlutterGradleTaskName(private val identifier: String) {
+ CopyAndroidAarFile("CopyAarFile"),
+
+ CopyIosFramework("CopyFramework"),
+
+ GenerateFlutterLib("GenerateFlutterLib"),
+
+ GenerateProtoSchemas("GenerateProtoSchemas"),
+
+ GetProtocDart("GetProtocDart"),
+
+ GetProtoc("GetProtoc"),
-internal typealias project = org.gradle.api.Project
+ GetKradle("GetKradle"),
+
+ CompileProtoSchemas("CompileProtoSchemas");
+
+ val taskName: String
+ get() = "klutter$identifier"
+
+}
/**
* Parent of all Gradle Tasks.
*/
-internal abstract class AbstractTask: DefaultTask() {
+internal abstract class AbstractTask : DefaultTask() {
- init { group = "klutter" }
+ init {
+ group = "klutter"
+ }
internal abstract fun klutterTask(): KlutterTask
+ @get:Internal
+ internal abstract val gradleTaskName: KlutterGradleTaskName
+
+ @ExcludeFromJacocoGeneratedReport(reason = "")
@TaskAction
fun execute() = klutterTask().run()
fun project(): Project {
val ext = project.klutterExtension()
val root = ext.root ?: project.rootProject.projectDir
- log.info { "Klutter Gradle configured as plugin." }
return root.plugin()
}
@@ -56,7 +83,9 @@ internal abstract class AbstractTask: DefaultTask() {
internal fun org.gradle.api.Project.klutterExtension(): KlutterExtension {
return extensions.getByName("klutter").let {
- if (it is KlutterExtension) { it } else {
+ if (it is KlutterExtension) {
+ it
+ } else {
throw IllegalStateException("klutter extension is not of the correct type")
}
}
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CodeGenTasks.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CodeGenTasks.kt
new file mode 100644
index 00000000..09fe984e
--- /dev/null
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CodeGenTasks.kt
@@ -0,0 +1,46 @@
+/* Copyright (c) 2021 - 2023 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.gradle.tasks
+
+import dev.buijs.klutter.gradle.dsl.KlutterVersion
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.tasks.codegen.GenerateFlutterLibTask
+
+/**
+ * Run the [GenerateFlutterLibTask] from Gradle.
+ */
+internal open class GenerateFlutterLibGradleTask: AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.GenerateFlutterLib
+
+ override fun klutterTask(): KlutterTask {
+ val project = project()
+ val root = project.root
+ return GenerateFlutterLibTask(
+ bomVersion = KlutterVersion.gradle,
+ pluginName = root.pluginName,
+ root = root,
+ srcFolder = root.pathToLibFolder.resolve("src")
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CopyTasks.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CopyTasks.kt
index aa4acb9d..6980f572 100644
--- a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CopyTasks.kt
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/CopyTasks.kt
@@ -27,18 +27,25 @@ import dev.buijs.klutter.kore.tasks.CopyXCFrameworkTask
/**
* Execute task [CopyAndroidAarFileGradleTask] from Gradle.
*/
-internal open class CopyAndroidAarFileGradleTask: AbstractTask() {
+internal open class CopyAndroidAarFileGradleTask : AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.CopyAndroidAarFile
+
override fun klutterTask() = CopyAarFileTask(
pathToRoot = project.rootDir,
pluginName = project.klutterExtension().plugin?.name,
)
+
}
/**
* Execute task [CopyXCFrameworkTask] from Gradle.
*/
-internal open class CopyIosFrameworkGradleTask: AbstractTask() {
- override fun klutterTask() = CopyXCFrameworkTask(
- pathToRoot = project.rootDir,
- )
+internal open class CopyIosFrameworkGradleTask : AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.CopyIosFramework
+
+ override fun klutterTask() =
+ CopyXCFrameworkTask(project.rootDir)
+
}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Get.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleGradleTask.kt
similarity index 70%
rename from lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Get.kt
rename to lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleGradleTask.kt
index ea00ad93..49775a3f 100644
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Get.kt
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleGradleTask.kt
@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
+/* Copyright (c) 2021 - 2024 Buijs Software
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,18 +19,18 @@
* SOFTWARE.
*
*/
-package dev.buijs.klutter.kradle.shared
+package dev.buijs.klutter.gradle.tasks
-import dev.buijs.klutter.kradle.command.downloadFlutterByCommand
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.tasks.GetKradleTask
-fun List.getDependency() {
- val mutable = toMutableList()
- val first = mutable.removeFirstOrNull()
- when {
- first == "flutter" ->
- mutable.downloadFlutterByCommand()
- else -> {
- println("I don't know what to get: $this")
- }
+internal open class GetKradleGradleTask: AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.GetKradle
+
+ override fun klutterTask(): KlutterTask {
+ val project = super.project()
+ return GetKradleTask(project.root.resolve("kradle").absolutePath)
}
+
}
\ No newline at end of file
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleTask.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleTask.kt
deleted file mode 100644
index 491b5cb7..00000000
--- a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/GetKradleTask.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.gradle.tasks
-
-import dev.buijs.klutter.gradle.KlutterGradlePlugin
-import dev.buijs.klutter.kore.KlutterException
-import dev.buijs.klutter.kore.KlutterTask
-import dev.buijs.klutter.kore.common.verifyExists
-import java.io.File
-import java.io.InputStream
-
-internal val kradleWrapperJar: InputStream
- get() = resourceFileOrThrow("kradle-wrapper.jar")
-
-internal val kradlew: InputStream
- get() = resourceFileOrThrow("kradlew")
-
-internal val kradlewBat: InputStream
- get() = resourceFileOrThrow("kradlew.bat")
-
-/**
- * Download Kradle CLI Tool.
- */
-internal open class GetKradleTask: AbstractTask() {
- override fun klutterTask() =
- project.rootProject.projectDir.toGetKradleTask()
-}
-
-fun File.toGetKradleTask() = object: KlutterTask {
- val dotKradle = resolve(".kradle")
- val dotKradleJar = dotKradle.resolve("kradle-wrapper.jar")
-
- override fun run() {
- dotKradle.mkdir()
- if(dotKradleJar.exists())
- dotKradleJar.delete()
-
- kradleWrapperJar.copyToFolder(
- sourceFileName = "kradle-wrapper.jar",
- targetFolder = dotKradle
- )
-
- kradlew.copyToFolder(
- sourceFileName = "kradlew",
- targetFolder = this@toGetKradleTask
- ) {
- it.setExecutable(true)
- }
-
- kradlewBat.copyToFolder(
- sourceFileName = "kradlew.bat",
- targetFolder = this@toGetKradleTask
- ) {
- it.setExecutable(true)
- }
- }
-
-}
-
-private fun resourceFileOrThrow(name: String): InputStream =
- KlutterGradlePlugin::class.java.getResourceAsStream("/$name")
- ?: throw KlutterException("Unable to find $name")
-
-private fun InputStream.copyToFolder(
- sourceFileName: String,
- targetFolder: File,
- postProcessFile: (File) -> Unit = {}
-) {
- val target = targetFolder.resolve(sourceFileName)
-
- if(target.exists())
- target.delete()
-
- use { input ->
- target.outputStream().use { output ->
- input.copyTo(output)
- }
- }
-
- target.verifyExists().let(postProcessFile)
-}
\ No newline at end of file
diff --git a/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/ProtoTasks.kt b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/ProtoTasks.kt
new file mode 100644
index 00000000..385ba1b8
--- /dev/null
+++ b/lib/gradle/src/main/kotlin/dev/buijs/klutter/gradle/tasks/ProtoTasks.kt
@@ -0,0 +1,117 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.gradle.tasks
+
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.project.protocHome
+import dev.buijs.klutter.kore.tasks.DownloadProtocTask
+import dev.buijs.klutter.kore.tasks.GetDartProtocExeTask
+import dev.buijs.klutter.kore.tasks.codegen.CompileProtoSchemaTask
+import dev.buijs.klutter.kore.tasks.codegen.GenerateProtoSchemasTask
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * Execute task [DownloadProtocTask] from Gradle.
+ */
+internal open class GetProtocGradleTask: AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.GetProtoc
+
+ override fun klutterTask(): KlutterTask =
+ DownloadProtocTask(
+ rootFolder = super.project().root.folder,
+ overwrite = false,
+ target = protocHome
+ )
+
+}
+
+/**
+ * Execute task [GetDartProtocExeTask] from Gradle.
+ */
+internal open class GetProtocDartGradleTask: AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.GetProtocDart
+
+ override fun klutterTask(): KlutterTask = GetDartProtocExeTask()
+}
+
+/**
+ * Run the [GenerateProtoSchemasTask] from Gradle.
+ *
+ * This Task should be instantiated in the build.gradle.kts File,
+ * which ensures all dependencies from the platform project
+ * are loaded in the Classloader.
+ */
+abstract class GenerateProtoSchemasGradleTask: DefaultTask() {
+
+ @get:Optional
+ @get:Input
+ abstract var classLoader: ClassLoader?
+
+ companion object {
+ /**
+ * Name of this task to be registered.
+ *
+ * See [KlutterGradleTaskName.GenerateProtoSchemas].
+ */
+ val taskName: String = KlutterGradleTaskName.GenerateProtoSchemas.taskName
+ }
+
+ @TaskAction
+ fun execute() {
+ if(classLoader == null) {
+ throw KlutterException("GenerateProtoSchemaGradleTask is missing property value 'classLoader'")
+ } else {
+ GenerateProtoSchemasTask(project.rootDir, classLoader!!).run()
+ }
+ }
+
+}
+
+/**
+ * Run [CompileProtoSchemaTask] from Gradle.
+ *
+ * This Task depends on [GetProtocDartGradleTask] and [GetProtocGradleTask]
+ * which installs the protoc toolchain for compiling schemas.
+ *
+ * This Task is finalized by [GenerateFlutterLibGradleTask],
+ * because compiling protoc schemas results in new dart classes in the ./lib folder.
+ * These new dart classes should be exported through the lib file.
+ */
+internal open class CompileProtoSchemasGradleTask: AbstractTask() {
+
+ override val gradleTaskName = KlutterGradleTaskName.CompileProtoSchemas
+
+ init {
+ super.dependsOn(KlutterGradleTaskName.GetProtocDart.taskName, KlutterGradleTaskName.GetProtoc.taskName)
+ super.finalizedBy(KlutterGradleTaskName.GenerateFlutterLib.taskName)
+ }
+
+ override fun klutterTask(): KlutterTask =
+ CompileProtoSchemaTask(super.project().root.folder)
+
+}
\ No newline at end of file
diff --git a/lib/gradle/src/main/resources/kradlew b/lib/gradle/src/main/resources/kradlew
deleted file mode 100755
index 35f8d5d0..00000000
--- a/lib/gradle/src/main/resources/kradlew
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-#
-# kradlew start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh kradlew
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and KRADLEW_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-APP_HOME=$( cd "${APP_HOME:-./}.." && pwd -P ) || exit
-
-APP_NAME="kradlew"
-APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=./.kradle/kradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and KRADLEW_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $KRADLEW_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
-
-set -- \
- -classpath "$CLASSPATH" \
- dev.buijs.klutter.kradle.MainKt \
- "$@"
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $KRADLEW_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/lib/gradle/src/main/resources/kradlew.bat b/lib/gradle/src/main/resources/kradlew.bat
deleted file mode 100755
index c95f5633..00000000
--- a/lib/gradle/src/main/resources/kradlew.bat
+++ /dev/null
@@ -1,88 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem kradlew startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%..
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and KRADLEW_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=.kradle\kradle-wrapper.jar
-
-@rem Execute kradlew
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %KRADLEW_OPTS% -classpath "%CLASSPATH%" dev.buijs.klutter.kradle.MainKt %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable KRADLEW_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%KRADLEW_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/lib/gradle/src/main/resources/publish.properties b/lib/gradle/src/main/resources/publish.properties
index 8a4cbc85..9e03950c 100644
--- a/lib/gradle/src/main/resources/publish.properties
+++ b/lib/gradle/src/main/resources/publish.properties
@@ -1,8 +1,8 @@
-annotations.version=2023.3.1.beta
-bom.version=2023.3.1.beta
-compiler.version=2023.3.1.beta
-flutter.engine.version=2023.3.1.beta
-kompose.version=2023.3.1.beta
-kore.version=2023.3.1.beta
-plugin.gradle.version=2023.3.1.beta
-plugin.jetbrains.version=2023.3.1.beta
\ No newline at end of file
+annotations.version=2024.1.1.beta
+bom.version=2024.1.1.beta
+compiler.version=2024.1.1.beta
+flutter.engine.version=2024.1.1.beta
+kompose.version=2024.1.1.beta
+kore.version=2024.1.1.beta
+plugin.gradle.version=2024.1.1.beta
+plugin.jetbrains.version=2024.1.1.bata
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterGradlePluginSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterGradlePluginSpec.groovy
index a4c718ac..2f076535 100644
--- a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterGradlePluginSpec.groovy
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterGradlePluginSpec.groovy
@@ -1,9 +1,20 @@
+//file:noinspection ConfigurationAvoidance
package dev.buijs.klutter.gradle
-import com.google.devtools.ksp.gradle.KspGradleSubplugin
+import com.google.devtools.ksp.gradle.KspExtension
+import dev.buijs.klutter.gradle.tasks.AbstractTask
+import dev.buijs.klutter.gradle.tasks.AbstractTaskKt
+import dev.buijs.klutter.gradle.tasks.KlutterGradleTaskName
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.project.RootKt
+import dev.buijs.klutter.kore.test.TestPlugin
+import org.gradle.api.NamedDomainObjectContainer
+import org.gradle.api.Project
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.api.plugins.ExtensionContainer
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import spock.lang.Specification
class KlutterGradlePluginSpec extends Specification {
@@ -11,22 +22,14 @@ class KlutterGradlePluginSpec extends Specification {
def "Verify the plugin is applied"() {
given:
- def project = ProjectBuilder.builder().build()
-
- when:
- project.extensions.add("kotlin", KotlinMultiplatformExtension.class)
- project.pluginManager.apply("dev.buijs.klutter")
-
- and:
- def plugin = project.plugins.getPlugin(KlutterGradlePlugin.class)
+ def project = getGradleProjectWithAppliedKlutterPlugin()
- then:
- plugin != null
+ expect:
+ project.plugins.getPlugin(KlutterGradlePlugin.class) != null
}
- def "Verify klutterGenerateAdapter task is created"() {
-
+ def "Verify klutter tasks are created"() {
given:
def project = ProjectBuilder.builder().build()
@@ -44,6 +47,112 @@ class KlutterGradlePluginSpec extends Specification {
and:
arr.size() != 0
+ }
+
+ def "Verify that ksp plugin is applied and configured"() {
+
+ given:
+ def project = getGradleProjectWithAppliedKlutterPlugin()
+ expect:
+ def ksp = project.extensions.getByType(KspExtension.class)
+ def args = ksp.getArguments()
+ args.containsKey(RootKt.kspArgumentKlutterProjectFolder)
}
+
+ def "Verify that ksp generated code is added to KMP sourceSets and KMP dependent tasks are added"() {
+
+ given:
+ def project = ProjectBuilder.builder().build()
+
+ and:
+ project.extensions.add("kmp", Stub(KotlinMultiplatformExtension) {
+ it.sourceSets >> Stub(NamedDomainObjectContainer) {
+ it.getByName("commonMain") >> Stub(KotlinSourceSet) {
+ it.kotlin >> Stub(SourceDirectorySet) {
+ it.srcDir(_)
+ }
+ }
+ }
+ })
+
+ and:
+ project.tasks.register("build", DummyGradleTask.class)
+ project.tasks.register("assemblePlatformReleaseXCFramework", DummyGradleTask.class)
+ project.tasks.register(KlutterGradleTaskName.GenerateProtoSchemas.taskName, DummyGradleTask.class)
+
+ when:
+ project.pluginManager.apply("dev.buijs.klutter")
+
+ and: "afterEvaluate is triggered"
+ project.getTasksByName(KlutterGradleTaskName.CopyAndroidAarFile.taskName, false)
+
+ then:
+ with(project.tasks.getByName("build") as DummyGradleTask) {
+ it.finalizers.contains("assemblePlatformReleaseXCFramework")
+ it.finalizers.contains(KlutterGradleTaskName.GenerateProtoSchemas.taskName)
+ it.finalizers.contains(KlutterGradleTaskName.CopyAndroidAarFile.taskName)
+ }
+
+ with(project.tasks.getByName("assemblePlatformReleaseXCFramework") as DummyGradleTask) {
+ it.finalizers.contains(KlutterGradleTaskName.CopyIosFramework.taskName)
+ }
+
+ with(project.tasks.getByName(KlutterGradleTaskName.GenerateProtoSchemas.taskName) as DummyGradleTask) {
+ it.finalizers.contains(KlutterGradleTaskName.CompileProtoSchemas.taskName)
+ }
+ }
+
+ def "Verify ISE is thrown if wrong class is found for klutter extension"() {
+ given:
+ def container = Stub(ExtensionContainer) {
+ it.getByName("klutter") >> "Not an extension"
+ }
+
+ def project = Stub(Project) {
+ it.extensions >> container
+ }
+
+ when:
+ AbstractTaskKt.klutterExtension(project)
+
+ then:
+ IllegalStateException ise = thrown()
+ ise.message == "klutter extension is not of the correct type"
+ }
+
+ static getGradleProjectWithAppliedKlutterPlugin() {
+ def klutterProject = new TestPlugin()
+ def project = ProjectBuilder.builder()
+ .withProjectDir(klutterProject.root)
+ .build()
+ project.pluginManager.apply("dev.buijs.klutter")
+ project.getTasks()
+ project.getTasksByName(KlutterGradleTaskName.CopyAndroidAarFile.taskName, false)
+ project
+ }
+
+ static class DummyGradleTask extends AbstractTask {
+
+ def finalizers = []
+
+ @Override
+ KlutterTask klutterTask$gradle() {
+ return new KlutterTask() {
+ @Override
+ void run() { }
+ }
+ }
+
+ @Override
+ void setFinalizedBy(Iterable> finalizedByTasks) {
+ finalizers.addAll(finalizedByTasks)
+ }
+
+ @Override
+ KlutterGradleTaskName getGradleTaskName$gradle() {
+ return null
+ }
+ }
+
}
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/DependencyUtilsSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/DependencyUtilsSpec.groovy
index d47659f0..26a853d4 100644
--- a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/DependencyUtilsSpec.groovy
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/DependencyUtilsSpec.groovy
@@ -21,7 +21,6 @@
*/
package dev.buijs.klutter.gradle.dsl
-import dev.buijs.klutter.gradle.dsl.DependencyUtilsKt
import spock.lang.Specification
import java.nio.file.Files
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterPluginDSLSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/KlutterPluginDSLSpec.groovy
similarity index 78%
rename from lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterPluginDSLSpec.groovy
rename to lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/KlutterPluginDSLSpec.groovy
index 1ff8fe83..5851a193 100644
--- a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/KlutterPluginDSLSpec.groovy
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/dsl/KlutterPluginDSLSpec.groovy
@@ -1,6 +1,5 @@
-package dev.buijs.klutter.gradle
+package dev.buijs.klutter.gradle.dsl
-import dev.buijs.klutter.gradle.dsl.KlutterPluginBuilder
import spock.lang.Specification
class KlutterPluginDSLSpec extends Specification {
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Clean.kt b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CodeGenTasksSpec.groovy
similarity index 68%
rename from lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Clean.kt
rename to lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CodeGenTasksSpec.groovy
index 52c45136..67bc7a8a 100644
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Clean.kt
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CodeGenTasksSpec.groovy
@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
+/* Copyright (c) 2021 - 2024 Buijs Software
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,20 +19,18 @@
* SOFTWARE.
*
*/
-package dev.buijs.klutter.kradle.shared
+package dev.buijs.klutter.gradle.tasks
-import dev.buijs.klutter.kore.tasks.CleanCacheTask
+import dev.buijs.klutter.kore.tasks.codegen.GenerateFlutterLibTask
+import spock.lang.Specification
-fun MutableList.clean() {
- val first = removeFirstOrNull()
- when {
- first == "cache" -> {
- println("The .kradle/cache folder will be cleaned...")
- CleanCacheTask().run()
- println("Finished .kradle/cache cleaning.")
- }
- else -> {
- println("I don't know what to clean: $this")
- }
+import static dev.buijs.klutter.gradle.tasks.TaskTestUtil.verifyTask
+
+class CodeGenTasksSpec extends Specification {
+
+ def "Verify GenerateFlutterLibGradleTask returns CopyAarFileTask"() {
+ expect:
+ verifyTask(GenerateFlutterLibGradleTask, GenerateFlutterLibTask)
}
+
}
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CopyTasksSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CopyTasksSpec.groovy
new file mode 100644
index 00000000..62c606b4
--- /dev/null
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/CopyTasksSpec.groovy
@@ -0,0 +1,43 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.gradle.tasks
+
+
+import dev.buijs.klutter.kore.tasks.CopyAarFileTask
+import dev.buijs.klutter.kore.tasks.CopyXCFrameworkTask
+import spock.lang.Specification
+
+import static dev.buijs.klutter.gradle.tasks.TaskTestUtil.verifyTask
+
+class CopyTasksSpec extends Specification {
+
+ def "Verify CopyAndroidAarFileGradleTask returns CopyAarFileTask"() {
+ expect:
+ verifyTask(CopyAndroidAarFileGradleTask, CopyAarFileTask)
+ }
+
+ def "Verify CopyIosFrameworkGradleTask returns CopyXCFrameworkTask"() {
+ expect:
+ verifyTask(CopyIosFrameworkGradleTask, CopyXCFrameworkTask)
+ }
+
+}
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleGradleTaskSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleGradleTaskSpec.groovy
new file mode 100644
index 00000000..9f357660
--- /dev/null
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleGradleTaskSpec.groovy
@@ -0,0 +1,43 @@
+/* Copyright (c) 2021 - 2022 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.gradle.tasks
+
+import spock.lang.Ignore
+import spock.lang.Specification
+
+import static dev.buijs.klutter.gradle.tasks.TaskTestUtil.getTask
+
+class GetKradleGradleTaskSpec extends Specification {
+
+ // does not work in ci yet ...
+ @Ignore
+ def "Verify getKradleTask works"() {
+ def task = getTask(GetKradleGradleTask)
+
+ when:
+ task.execute()
+
+ then: "No exception is thrown"
+ 1 == 1
+ }
+
+}
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleTaskSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleTaskSpec.groovy
deleted file mode 100644
index d042926b..00000000
--- a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/GetKradleTaskSpec.groovy
+++ /dev/null
@@ -1,30 +0,0 @@
-package dev.buijs.klutter.gradle.tasks
-
-import spock.lang.Ignore
-import spock.lang.Specification
-
-import java.nio.file.Files
-
-class GetKradleTaskSpec extends Specification {
-
- def "Verify kradlew scripts can be retrieved from resources"() {
- expect:
- GetKradleTaskKt.kradlew.available()
- GetKradleTaskKt.kradlewBat.available()
- }
-
- @Ignore // TODO get kradle from url
- def "Verify kradlew files can be copied" () {
- given:
- def root = Files.createTempDirectory("").toFile()
-
- when:
- GetKradleTaskKt.toGetKradleTask(root).run()
-
- then:
- root.toPath().resolve("kradlew").toFile().exists()
- root.toPath().resolve("kradlew.bat").toFile().exists()
- root.toPath().resolve(".kradle").resolve("kradle-wrapper.jar").toFile().exists()
- }
-
-}
\ No newline at end of file
diff --git a/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/ProtoTasksSpec.groovy b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/ProtoTasksSpec.groovy
new file mode 100644
index 00000000..c4052dae
--- /dev/null
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/ProtoTasksSpec.groovy
@@ -0,0 +1,72 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.gradle.tasks
+
+
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.tasks.DownloadProtocTask
+import dev.buijs.klutter.kore.tasks.GetDartProtocExeTask
+import dev.buijs.klutter.kore.tasks.codegen.CompileProtoSchemaTask
+import spock.lang.Specification
+
+import static dev.buijs.klutter.gradle.tasks.TaskTestUtil.getTask
+import static dev.buijs.klutter.gradle.tasks.TaskTestUtil.verifyTask
+
+class ProtoTasksSpec extends Specification {
+
+ def "Verify GetProtocGradleTask returns DownloadProtocTask"() {
+ expect:
+ verifyTask(GetProtocGradleTask, DownloadProtocTask)
+ }
+
+ def "Verify GetProtocDartGradleTask returns GetDartProtocExeTask"() {
+ expect:
+ verifyTask(GetProtocDartGradleTask, GetDartProtocExeTask)
+ }
+
+ def "Verify CompileProtoSchemasGradleTask returns GetDartProtocExeTask"() {
+ expect:
+ verifyTask(CompileProtoSchemasGradleTask, CompileProtoSchemaTask)
+ }
+
+ def "Verify GenerateProtoSchemasGradleTask throws KlutterException if classLoader variable is not set"() {
+ given:
+ def task = getTask(GenerateProtoSchemasGradleTask)
+
+ when:
+ task.execute()
+
+ then:
+ KlutterException e = thrown()
+ e.message == "GenerateProtoSchemaGradleTask is missing property value 'classLoader'"
+
+ when:
+ task.setClassLoader(this.class.classLoader)
+
+ and:
+ task.execute()
+
+ then: "No exception is thrown"
+ 1 == 1
+ }
+
+}
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/MrArg.kt b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/TaskTestUtil.groovy
similarity index 62%
rename from lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/MrArg.kt
rename to lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/TaskTestUtil.groovy
index a3cb760a..1df1b17f 100644
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/MrArg.kt
+++ b/lib/gradle/src/test/groovy/dev/buijs/klutter/gradle/tasks/TaskTestUtil.groovy
@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
+/* Copyright (c) 2021 - 2024 Buijs Software
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,19 +19,21 @@
* SOFTWARE.
*
*/
-package dev.buijs.klutter.kradle.command
+package dev.buijs.klutter.gradle.tasks
-import kotlinx.cli.ArgParser
-import kotlinx.cli.ArgType
-import kotlinx.cli.required
+import dev.buijs.klutter.gradle.KlutterGradlePluginSpec
-internal annotation class Open4Test
+class TaskTestUtil {
+ static getTask(Class> type) {
+ def project = KlutterGradlePluginSpec.gradleProjectWithAppliedKlutterPlugin
+ //noinspection ConfigurationAvoidance
+ project.task('dummy', type: type)
+ }
-internal infix fun ArgParser.required(description: String) =
- option(ArgType.String, description = description).required()
-
-internal infix fun ArgParser.optional(description: String) =
- option(ArgType.String, description = description)
-
-internal infix fun ArgParser.optionalBoolean(description: String) =
- option(ArgType.Boolean, description = description)
\ No newline at end of file
+ static verifyTask(Class> gradleTaskType, Class> klutterTaskType) {
+ def taskInstance = getTask(gradleTaskType)
+ assert taskInstance.class.superclass == gradleTaskType
+ assert taskInstance.klutterTask$gradle().class == klutterTaskType
+ true
+ }
+}
diff --git a/lib/gradle/src/test/kotlin/dev/buijs/klutter/gradle/KlutterGradlePluginTest.kt b/lib/gradle/src/test/kotlin/dev/buijs/klutter/gradle/KlutterGradlePluginTest.kt
deleted file mode 100644
index 79f92159..00000000
--- a/lib/gradle/src/test/kotlin/dev/buijs/klutter/gradle/KlutterGradlePluginTest.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-package dev.buijs.klutter.gradle
-
-import com.google.devtools.ksp.gradle.KspExtension
-import dev.buijs.klutter.gradle.dsl.KlutterExtension
-import dev.buijs.klutter.gradle.tasks.klutterExtension
-import io.kotlintest.shouldBe
-import io.kotlintest.shouldNotBe
-import io.kotlintest.specs.WordSpec
-import org.gradle.api.artifacts.dsl.DependencyHandler
-import org.gradle.api.plugins.ExtensionContainer
-import org.gradle.api.plugins.PluginContainer
-import org.gradle.api.tasks.TaskContainer
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.whenever
-import java.io.File
-import java.nio.file.Files
-import org.gradle.api.Project as GradleProject
-
-internal class KlutterGradlePluginTest: WordSpec({
-
- "Verify adapter method" should {
-
- "Throws ISE if wrong class is found" {
- val container: ExtensionContainer = mock()
- val project: GradleProject = mock()
-
- whenever(container.getByName("klutter")).thenReturn("Not an extension")
- whenever(project.extensions).thenReturn(container)
-
- try {
- project.klutterExtension()
- } catch(e: Exception) {
- e::class.java.simpleName shouldBe "IllegalStateException"
- e.message shouldBe "klutter extension is not of the correct type"
- }
-
- }
-
- "Return extension if correct class is found" {
- val extension: KlutterExtension = mock()
- val container: ExtensionContainer = mock()
- val project: GradleProject = mock()
-
- whenever(container.getByName("klutter"))
- .thenReturn(extension)
-
- whenever(project.extensions)
- .thenReturn(container)
-
- project.klutterExtension() shouldBe extension
-
- }
-
- }
-
- "Verify KlutterGradleExtension class" should {
- val temp = Files.createTempDirectory("").toFile()
- val subTemp = temp.resolve("foo")
- subTemp.mkdir()
-
- val project: org.gradle.api.Project = mock {
- whenever(it.buildDir).thenAnswer { temp }
- whenever(it.projectDir).thenAnswer { subTemp }
- }
-
- val extension = KlutterExtension(project)
-
- "All values default to null" {
- extension.root shouldBe null
- extension.plugin shouldBe null
- }
-
- "After using the plugin DSL values should be set" {
-
- extension.root = File("")
-
- extension.plugin {
- name = "With great power..."
- }
-
- extension.root shouldNotBe null
- extension.plugin shouldNotBe null
- extension.plugin!!.name shouldBe "With great power..."
- }
-
- }
-
-
- "Verify KSP extension is fed by Klutter extension through Klutter Gradle Plugin" should {
-
- // fake Gradle project
- val project: GradleProject = mock()
- val klutterScanFolder = Files.createTempDirectory("x").toFile()
- val klutterOutputFolder = Files.createTempDirectory("y").toFile()
- whenever(project.buildDir).thenReturn(klutterScanFolder)
- whenever(project.projectDir).thenReturn(klutterOutputFolder.resolve("foo"))
- whenever(project.logger).thenReturn(mock())
-
- // task container which contains the 'build' task
- val taskContainer: TaskContainer = mock()
- whenever(project.tasks).thenReturn(taskContainer)
- whenever(taskContainer.getByName("build")).thenReturn(mock())
-
- // plugin container which contains the ksp plugin
- val pluginContainer: PluginContainer = mock()
- whenever(project.plugins).thenReturn(pluginContainer)
-
- // dependency handler mock for containing the compiler-plugin dependency
- val dependencyHandler: DependencyHandler = mock()
- whenever(project.dependencies).thenReturn(dependencyHandler)
-
- // feeder!
- //val klutterExtension = KlutterExtension(project)
-
- // nomnommer!
- val kspExtension = KspExtension()
-
- val container: ExtensionContainer = mock()
- whenever(container.getByType(KspExtension::class.java)).thenReturn(kspExtension)
- whenever(project.extensions).thenReturn(container)
- }
-})
\ No newline at end of file
diff --git a/lib/jetbrains/CHANGELOG.md b/lib/jetbrains/CHANGELOG.md
index f8cd59aa..5e98f22f 100644
--- a/lib/jetbrains/CHANGELOG.md
+++ b/lib/jetbrains/CHANGELOG.md
@@ -1,4 +1,12 @@
+## [2024.1.1]
+
+### Changed
+- Uses klutter 2024.1.1.beta.
+- Uses klutter (dart) [3.0.0](https://pub.dev/packages/klutter).
+- Uses klutter_ui (dart) [1.1.0](https://pub.dev/packages/klutter_ui).
+- Add protobuf support.
+
## [2023.3.1]
### Changed
diff --git a/lib/jetbrains/build.gradle.kts b/lib/jetbrains/build.gradle.kts
index 6cd93b10..18349ab1 100644
--- a/lib/jetbrains/build.gradle.kts
+++ b/lib/jetbrains/build.gradle.kts
@@ -1,7 +1,7 @@
import org.jetbrains.changelog.date
plugins {
- id("org.jetbrains.intellij") version "1.13.3"
+ id("org.jetbrains.intellij") version "1.17.3"
id("org.jetbrains.changelog") version "2.0.0"
id("java")
id("maven-publish")
@@ -23,7 +23,7 @@ group = "dev.buijs.klutter"
version = dev.buijs.klutter.ProjectVersions.jetbrains
intellij {
- version.set("2022.3.2")
+ version.set("2023.2")
type.set("IC") // Intellij Community Edition
plugins.set(listOf("java", "com.intellij.gradle","android"))
}
@@ -51,22 +51,13 @@ changelog {
tasks {
- withType {
- sourceCompatibility = "17"
- targetCompatibility = "17"
- }
-
- withType {
- kotlinOptions.jvmTarget = "17"
- }
-
withType {
useJUnitPlatform()
}
patchPluginXml {
- sinceBuild.set("223")
- untilBuild.set("232.*")
+ sinceBuild.set("232")
+ //untilBuild.set("232.*")
}
signPlugin {
@@ -122,8 +113,8 @@ dependencies {
@Suppress("GradleDependency") // 30-07-2022 newest 3.4.2 throws exceptions
testImplementation("io.kotlintest:kotlintest-runner-junit5:3.3.0")
- testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.2")
- testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.2")
+ testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
// Plugin UI Test
testImplementation("com.intellij.remoterobot:remote-robot:$robotVersion")
diff --git a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/KlutterMetadata.kt b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/KlutterMetadata.kt
index 234542b2..4372d051 100644
--- a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/KlutterMetadata.kt
+++ b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/KlutterMetadata.kt
@@ -52,6 +52,6 @@ object KlutterBundle {
*/
@ExcludeFromJacocoGeneratedReport
object KlutterIcons {
- val logo16x16: Icon = IconLoader.getIcon("/pluginIcon16x16.png", KlutterIcons::class.java)
- val logo20x20: Icon = IconLoader.getIcon("/pluginIcon20x20.png", KlutterIcons::class.java)
+ val logo16x16: Icon = IconLoader.getIcon("/pluginIcon16x16.svg", KlutterIcons::class.java)
+ val logo20x20: Icon = IconLoader.getIcon("/pluginIcon20x20.svg", KlutterIcons::class.java)
}
\ No newline at end of file
diff --git a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectTaskFactory.kt b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectTaskFactory.kt
index db29d618..90ae37c6 100644
--- a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectTaskFactory.kt
+++ b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectTaskFactory.kt
@@ -25,8 +25,8 @@ import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
-import dev.buijs.klutter.gradle.tasks.toGetKradleTask
import dev.buijs.klutter.kore.project.*
+import dev.buijs.klutter.kore.tasks.execute
import dev.buijs.klutter.kore.tasks.executor
import dev.buijs.klutter.kore.tasks.project.*
import mu.KotlinLogging
@@ -61,15 +61,14 @@ private fun createKlutterPluginTask(
): Task.Modal {
val rootFolder = options.rootFolder.validRootFolderOrThrow()
val task = ProjectBuilderTask(options = options)
- val getKradleTask = rootFolder.toGetKradleTask()
return createKlutterTask(
pathToRoot = rootFolder,
project = project,
task = {
executor = JetbrainsExecutor()
task.run()
- getKradleTask.run()
rootFolder.moveUpFolder(options.pluginName.validPluginNameOrThrow())
+ "./gradlew klutterGetKradle -p platform" execute rootFolder
})
}
diff --git a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectWizardStep.kt b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectWizardStep.kt
index 3511e268..735253e1 100644
--- a/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectWizardStep.kt
+++ b/lib/jetbrains/src/main/kotlin/dev/buijs/klutter/jetbrains/NewProjectWizardStep.kt
@@ -45,6 +45,7 @@ import java.awt.Graphics
import javax.swing.JPanel
private val knownKlutterBOMVersions = setOf(
+ "2024.1.1.beta",
"2023.3.1.beta",
"2023.2.2.beta",
"2023.2.1.beta",
@@ -128,7 +129,7 @@ private fun newProjectPanel(data: NewProjectConfig, disposable: Disposable) = pa
indent {
row {
// KLUTTER BANNER
- cell(KlutterBanner).verticalAlign(VerticalAlign.CENTER)
+ cell(KlutterBanner).align(AlignY.CENTER)
}
val project = "Project"
@@ -138,7 +139,7 @@ private fun newProjectPanel(data: NewProjectConfig, disposable: Disposable) = pa
textField()
.bindText(data.appNameObservable)
.widthGroup(project)
- .horizontalAlign(HorizontalAlign.LEFT)
+ .align(AlignX.LEFT)
.bindValidator(disposable) { input ->
if(toPluginName(input) is EitherNok) "The Plugin Name is not valid." else null
}
@@ -149,7 +150,7 @@ private fun newProjectPanel(data: NewProjectConfig, disposable: Disposable) = pa
textField()
.bindText(data.groupNameObservable)
.widthGroup(project)
- .horizontalAlign(HorizontalAlign.LEFT)
+ .align(AlignX.LEFT)
.bindValidator(disposable) { input ->
if(toGroupName(input) is EitherNok) "The Group Name is not valid." else null
}
@@ -163,7 +164,7 @@ private fun newProjectPanel(data: NewProjectConfig, disposable: Disposable) = pa
.also { it.component.isEditable = true }
.widthGroup(dependencies)
.bindItem(data.gradleVersionObservable)
- .horizontalAlign(HorizontalAlign.LEFT)
+ .align(AlignX.LEFT)
.bindValidator(disposable, isBlocking = false) { input ->
if(knownKlutterBOMVersions.none { it == input }) "The BOM Version is unknown." else null
}
@@ -172,13 +173,13 @@ private fun newProjectPanel(data: NewProjectConfig, disposable: Disposable) = pa
comboBox(items = flutterVersionsDescending(currentOperatingSystem).map { "${it.prettyPrintedString}" })
.widthGroup(dependencies)
.bindItem(data.flutterVersionObservable)
- .horizontalAlign(HorizontalAlign.LEFT)
+ .align(AlignX.LEFT)
}
row {
checkBox("Get flutter dependencies from git.")
.widthGroup(dependencies)
.bindSelected(data.useGitForPubDependenciesObservable)
- .horizontalAlign(HorizontalAlign.LEFT)
+ .align(AlignX.LEFT)
}
row {}.comment("If enabled then all flutter dependencies are pulled from git and not pub.")
@@ -270,8 +271,4 @@ private fun observable(
// nothing
}
- override fun afterChange(listener: (T) -> Unit, parentDisposable: Disposable) {
- // nothing
- }
-
}
\ No newline at end of file
diff --git a/lib/kompose/build.gradle.kts b/lib/kompose/build.gradle.kts
index 5fb9066b..e6ad7fad 100644
--- a/lib/kompose/build.gradle.kts
+++ b/lib/kompose/build.gradle.kts
@@ -1,6 +1,5 @@
-@file:Suppress("UNUSED_VARIABLE")
plugins {
- kotlin("plugin.serialization") version "1.7.0"
+ kotlin("plugin.serialization") version "1.9.10"
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
@@ -11,16 +10,21 @@ plugins {
group = "dev.buijs.klutter"
version = dev.buijs.klutter.ProjectVersions.kompose
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
+}
+
kotlin {
- android {
+ androidTarget {
publishLibraryVariants("release", "debug")
}
jvm()
iosX64()
iosArm64()
- iosArm32()
iosSimulatorArm64()
cocoapods {
summary = "Klutter Kompose module"
@@ -35,7 +39,7 @@ kotlin {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation(project(":lib:annotations"))
}
@@ -46,14 +50,12 @@ kotlin {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
}
}
- val iosArm32Main by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
- iosArm32Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
@@ -62,7 +64,7 @@ kotlin {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("io.github.microutils:kotlin-logging-jvm:3.0.5")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
implementation(project(":lib:kore"))
implementation(project(":lib:annotations"))
}
@@ -77,11 +79,11 @@ kotlin {
}
android {
+ namespace = "dev.buijs.klutter.kompose"
compileSdk = 31
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
- targetSdk = 31
}
}
@@ -108,7 +110,7 @@ publishing {
}
tasks.withType().configureEach {
- outputDirectory.set(buildDir.resolve("dokka"))
+ outputDirectory.set(layout.buildDirectory.dir("dokka").get().asFile)
dokkaSourceSets {
register("kompose") {
diff --git a/lib/kompose/kompose.podspec b/lib/kompose/kompose.podspec
index 87c78279..a1edfea2 100644
--- a/lib/kompose/kompose.podspec
+++ b/lib/kompose/kompose.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'kompose'
- spec.version = '2023.3.1.beta'
+ spec.version = '2024.1.1.beta'
spec.homepage = 'https://buijs.dev'
spec.source = { :http=> ''}
spec.authors = ''
@@ -22,8 +22,8 @@ Pod::Spec.new do |spec|
:execution_position => :before_compile,
:shell_path => '/bin/sh',
:script => <<-SCRIPT
- if [ "YES" = "$COCOAPODS_SKIP_KOTLIN_BUILD" ]; then
- echo "Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\""
+ if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
+ echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
exit 0
fi
set -ev
diff --git a/lib/kompose/src/androidMain/AndroidManifest.xml b/lib/kompose/src/androidMain/AndroidManifest.xml
deleted file mode 100644
index c27a7462..00000000
--- a/lib/kompose/src/androidMain/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/lib/kore/build.gradle.kts b/lib/kore/build.gradle.kts
index 9f4f5c14..bcf88b96 100644
--- a/lib/kore/build.gradle.kts
+++ b/lib/kore/build.gradle.kts
@@ -1,17 +1,15 @@
plugins {
kotlin("jvm")
- kotlin("plugin.serialization") version "1.6.10"
+ kotlin("plugin.serialization") version "1.9.10"
id("klutter")
id("groovy")
id("maven-publish")
- id("java-library")
}
-java {
- withJavadocJar()
- withSourcesJar()
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+kotlin {
+ jvmToolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
}
sourceSets {
@@ -36,8 +34,9 @@ dependencies {
// KSP for annotation scanning
implementation(kotlin("stdlib"))
- implementation("com.google.devtools.ksp:symbol-processing-api:1.8.20-1.0.11")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
+ implementation("com.google.devtools.ksp:symbol-processing-api:1.9.10-1.0.13")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.6.2")
// Jackson for XML
implementation("com.fasterxml.jackson.core:jackson-databind:2.14.2")
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/ast/Type.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/ast/Type.kt
index 31ef943d..bebcc72e 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/ast/Type.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/ast/Type.kt
@@ -44,6 +44,12 @@ sealed class AbstractType {
open val className: String =
javaClass.simpleName
+
+ open val packageName: String =
+ javaClass.packageName
+
+ val fqdn: String
+ get() = "$packageName.$className"
}
/**
@@ -67,7 +73,7 @@ sealed class AbstractType {
*/
open class CustomType(
override val className: String,
- open val packageName: String? = null,
+ override val packageName: String,
val members: List = emptyList()
): AbstractType() {
@@ -91,7 +97,7 @@ open class CustomType(
override fun hashCode(): Int {
var result = className.hashCode()
- result = 31 * result + (packageName?.hashCode() ?: 0)
+ result = 31 * result + packageName.hashCode()
result = 31 * result + members.hashCode()
return result
}
@@ -119,7 +125,7 @@ open class CustomType(
*/
open class EnumType(
override val className: String,
- open val packageName: String? = null,
+ override val packageName: String ,
val values: List = emptyList(),
val valuesJSON: List = emptyList(),
): AbstractType() {
@@ -143,7 +149,7 @@ data class UndeterminedType(
*/
class NullableCustomType(
className: String,
- packageName: String? = null,
+ packageName: String,
fields: List = emptyList()
): CustomType(
className = className,
@@ -189,13 +195,13 @@ data class TypeMember(
private fun CustomType.print() = this.javaClass.simpleName +
"(className = $className, " +
- "packageName = ${packageName ?: "NOT_FOUND"}, " +
+ "packageName = $packageName, " +
"fields = ${members.map { "${it.name}: ${it.type.typeSimplename()}" }}, " +
"nullable = ${this.javaClass.interfaces.map { i -> i.simpleName }.contains(object: Nullable {}.javaClass.simpleName)})"
private fun EnumType.print() = this.javaClass.simpleName +
"(className = $className, " +
- "packageName = ${packageName ?: "NOT_FOUND"}, " +
+ "packageName = $packageName, " +
"values = $values, " +
"valuesJSON = $valuesJSON, " +
"nullable = ${this.javaClass.interfaces.map { i -> i.simpleName }.contains(object: Nullable {}.javaClass.simpleName)})"
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Config.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Config.kt
index f7347927..e058527c 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Config.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Config.kt
@@ -34,6 +34,7 @@ private val log = KotlinLogging.logger { }
@JsonPropertyOrder(
"bom-version",
"flutter-version",
+ "feature-protobuf-enabled",
"dependencies")
data class Config(
@JsonProperty("dependencies")
@@ -44,6 +45,9 @@ data class Config(
@JsonProperty("flutter-version")
val flutterVersion: String? = null,
+
+ @JsonProperty("feature-protobuf-enabled")
+ val featureProtobufEnabled: Boolean? = null,
)
@JsonInclude(JsonInclude.Include.NON_NULL)
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Environment.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Environment.kt
index a03a76de..83cfedc8 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Environment.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Environment.kt
@@ -28,6 +28,9 @@ val Version.prettyPrint: String
val isWindows: Boolean
get() = currentOperatingSystem == OperatingSystem.WINDOWS
+val isMacos: Boolean
+ get() = currentOperatingSystem == OperatingSystem.MACOS
+
/**
* Get current [OperatingSystem] from System Properties.
*
@@ -45,7 +48,17 @@ val currentOperatingSystem: OperatingSystem
}
val currentArchitecture: Architecture
- get() = """uname -m""".execute(Path.of("").toFile().absoluteFile).let { str ->
- if(str.uppercase().contains("ARM")) Architecture.ARM64 else Architecture.X64
+ get() {
+ val sysctl = "sysctl -n sysctl.proc_translated" execute currentWorkingDirectory
+ val usesRosetta = sysctl == "1"
+ val architecture = """uname -m""" execute currentWorkingDirectory
+ val archContainsARM = architecture.uppercase().contains("ARM")
+ return when {
+ usesRosetta -> Architecture.ARM64
+ archContainsARM -> Architecture.ARM64
+ else -> Architecture.X64
+ }
}
+val currentWorkingDirectory: File
+ get() = Path.of("").toFile().absoluteFile
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Project.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Project.kt
index 43ed0ac7..56a28385 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Project.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Project.kt
@@ -29,13 +29,12 @@ import java.io.File
/**
* A representation of the structure of a project made with the Klutter Framework.
* Each property of this object represents a folder containing one or more folders
- * and/or files wich are in some way used or needed by Klutter.
+ * and/or files which are in some way used or needed by Klutter.
*
* @property root is the top level of the project.
* @property ios is the folder containing the iOS frontend code, basically the iOS folder from a standard Flutter project.
* @property android is the folder containing the Android frontend code, basically the iOS folder from a standard Flutter project.
* @property platform is the folder containing the native backend code, basically a Kotlin Multiplatform library module.
- * @author Gillian Buijs
*/
data class Project(
val root: Root,
@@ -46,12 +45,23 @@ data class Project(
/**
* Path to Klutter projects cache folder which is /.kradle.
+ *
+ * @Throws [KlutterException] if it does NOT exist.
*/
val kradleHome: File
get() = File(System.getProperty("user.home"))
.verifyExists()
.resolve(".kradle")
+/**
+ * Path to Klutter projects protoc folder which is [kradleHome]/.cache/protobuf/protoc.
+ */
+val protocHome: File
+ get() = kradleHome
+ .resolve(".cache")
+ .resolve("protobuf")
+ .resolve("protoc")
+
/**
* The root/kradle.env File.
*
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Properties.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Properties.kt
index a4945936..09bbd448 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Properties.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/Properties.kt
@@ -92,6 +92,9 @@ fun findSkipCodeGenInKradleEnvOrNull(content: String?) =
}
}
+fun findProtocDownloadURLInKradleEnvOrNull(content: String?) =
+ content.findPropertyOrNull("protoc.url")
+
private fun String?.findPropertyInYamlOrNull(key: String) =
this?.let { str ->
"""$key:\s*('|")\s*([^'"]+?)\s*('|")""".toRegex().find(str)?.let { match ->
@@ -99,6 +102,13 @@ private fun String?.findPropertyInYamlOrNull(key: String) =
}
}
+private fun String?.findBooleanPropertyInYamlOrNull(key: String) =
+ this?.let { str ->
+ """$key:\s*([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])\s*""".toRegex().find(str)?.let { match ->
+ match.groupValues[1]
+ }
+ }
+
private fun String?.findPropertyOrNull(key: String) =
this?.let { str ->
"""$key=([^\n\r]+)""".toRegex().find(str)?.let { match ->
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/PubspecBuilder.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/PubspecBuilder.kt
index 41765755..16a62a32 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/PubspecBuilder.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/project/PubspecBuilder.kt
@@ -38,17 +38,17 @@ import java.io.File
/**
* The version of Klutter Gradle Executable Tool.
*/
-const val klutterBomVersion = "2023.3.1.beta"
+const val klutterBomVersion = "2024.1.1.beta"
/**
* The version of the klutter Pub Plugin.
*/
-const val klutterPubVersion = "2.0.0"
+const val klutterPubVersion = "2.1.0"
/**
* The version of the klutter-ui Pub Plugin.
*/
-const val klutterUIPubVersion = "1.0.1"
+const val klutterUIPubVersion = "1.1.0"
/**
* The version of the squint_json Pub Plugin.
@@ -66,6 +66,8 @@ val mapper = YAMLFactory.builder()
.also {
it.registerKotlinModule()
it.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
+ it.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true)
+ it.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
it.setVisibility(it.serializationConfig.defaultVisibilityChecker
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.ANY)
@@ -110,7 +112,7 @@ fun Pubspec.iosClassName(orElse: String): String {
ios == null -> {
orElse
}
- ios!!.pluginClass == null -> {
+ ios!!.pluginClass.isNullOrBlank() -> {
orElse
}
else -> {
@@ -124,7 +126,7 @@ fun Pubspec.androidClassName(orElse: String): String {
android == null -> {
orElse
}
- android!!.pluginClass == null -> {
+ android!!.pluginClass.isNullOrBlank() -> {
orElse
}
else -> {
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/CleanCacheTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/DownloadProtocTask.kt
similarity index 75%
rename from lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/CleanCacheTask.kt
rename to lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/DownloadProtocTask.kt
index 2e81934e..8dabd75f 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/CleanCacheTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/DownloadProtocTask.kt
@@ -22,15 +22,19 @@
package dev.buijs.klutter.kore.tasks
import dev.buijs.klutter.kore.KlutterTask
-import dev.buijs.klutter.kore.project.kradleHome
+import dev.buijs.klutter.kore.tasks.project.DownloadProtoc
+import java.io.File
/**
- * Task to clean the Klutter Cache Folder.
+ * Download a protoc distribution which is required to use
+ * protocol buffers in a klutter project.
*/
-class CleanCacheTask: KlutterTask {
+class DownloadProtocTask(
+ private val rootFolder: File,
+ private val overwrite: Boolean = false,
+ private val target: File
+) : KlutterTask {
override fun run() {
- kradleHome.resolve(".cache")
- .also { it.deleteRecursively() }
- .mkdir()
+ DownloadProtoc(rootFolder, overwrite, target).doAction()
}
}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/NewProject.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetDartProtocExeTask.kt
similarity index 50%
rename from lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/NewProject.kt
rename to lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetDartProtocExeTask.kt
index 11098c3a..908cff70 100644
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/NewProject.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetDartProtocExeTask.kt
@@ -19,31 +19,40 @@
* SOFTWARE.
*
*/
-package dev.buijs.klutter.kradle.shared
+package dev.buijs.klutter.kore.tasks
-import dev.buijs.klutter.kore.project.Config
-import dev.buijs.klutter.kore.project.FlutterDistributionFolderName
-import dev.buijs.klutter.kore.tasks.project.ProjectBuilderOptions
-import dev.buijs.klutter.kore.tasks.project.ProjectBuilderTask
-import dev.buijs.klutter.kore.tasks.project.*
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.maybeCreateFolder
+import dev.buijs.klutter.kore.common.verifyExists
+import dev.buijs.klutter.kore.project.kradleHome
-internal fun ProjectBuilderOptions.createNewProject() {
- println("Creating a new Klutter project...")
- ProjectBuilderTask(this).run()
- val name = pluginName.validPluginNameOrThrow()
- val root = rootFolder.validRootFolderOrThrow().resolve(name)
- listOf("klutterGetKradle").execGradleCommand(root)
- println("Finished Klutter project creation.")
-}
+/**
+ * Task to extract the dart protoc executable.
+ */
+class GetDartProtocExeTask: KlutterTask {
+
+ private val pathToExecutableFile = this::class.java.classLoader
+ .getResourceAsStream("protoc_plugin.exe")
+ ?: throw KlutterException("File protoc_plugin.exe is missing from Resources!")
+
+ override fun run() {
-internal interface NewProjectInput {
- val rootFolder: RootFolder
+ val parentFolder = kradleHome
+ .resolve(".cache")
+ .resolve("protobuf")
+ .maybeCreateFolder()
- val groupName: GroupName
+ val target = parentFolder
+ .resolve("protoc_plugin.exe")
- val pluginName: PluginName
+ if(!target.exists()) {
+ pathToExecutableFile.copyTo(target.outputStream())
+ target.setExecutable(true)
+ if(!target.canExecute())
+ throw KlutterException("Failed to make File protoc_plugin executable")
+ }
- val flutterDistributionFolderName: FlutterDistributionFolderName
+ }
- val configOrNull: Config?
}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetKradleTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetKradleTask.kt
new file mode 100644
index 00000000..98789e86
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/GetKradleTask.kt
@@ -0,0 +1,104 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.kore.tasks
+
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.verifyExists
+import dev.buijs.klutter.kore.project.*
+import dev.buijs.klutter.kore.tasks.project.DownloadFlutterTask
+import java.io.File
+import java.nio.file.Files
+
+class GetKradleTask(
+ /**
+ * Absolute path to the kradle executable file.
+ *
+ * Example: /foo/bar/my_project/kradle
+ */
+ private val pathToKradleOutput: String,
+): KlutterTask {
+ override fun run() {
+ val repository = cloneKlutterDartRepositoryToTempOrThrow()
+ val dart = findDartExecutableOrThrow()
+ val kradle = repository.resolve("bin/kradle.dart").absolutePath
+ println("$dart pub get" execute repository)
+ println("$dart compile exe $kradle -o $pathToKradleOutput" execute repository)
+ }
+}
+
+private fun cloneKlutterDartRepositoryToTempOrThrow(): File {
+ val temp = createTempDirectory()
+ cloneKlutterDartRepoTo(temp)
+ return temp.resolve("klutter-dart").verifyExists()
+}
+
+private fun createTempDirectory(): File =
+ Files.createTempDirectory("klutter").toFile().also { it.deleteOnExit() }
+
+private fun cloneKlutterDartRepoTo(directory: File) {
+ println("git clone https://github.com/buijs-dev/klutter-dart.git" execute directory)
+}
+
+/**
+ * Find a dart executable to generate the kradle executable.
+ *
+ * @throws [KlutterException] if a dart executable is not found.
+ */
+private fun findDartExecutableOrThrow(): String {
+ val cachedDartExecutableName = findDartExecutableInCacheOrNull()
+ if (cachedDartExecutableName != null) {
+ return dartExecutable(cachedDartExecutableName).absolutePath
+ }
+
+ val globalDart = findGlobalDartExecutableOrNull()
+ if (globalDart != null) {
+ return globalDart
+ }
+
+ return dartExecutable(downloadFlutterDistributionOrThrow()).absolutePath
+
+}
+
+private fun findDartExecutableInCacheOrNull(): String? {
+ val versions = compatibleFlutterVersions.keys.map { it.folderNameString.toString() }
+ val cache = kradleHome.resolve("cache").verifyExists()
+ val cachedFlutterDistributions = cache.listFiles()?.map { it.name } ?:emptyList()
+ return versions.firstOrNull { version ->
+ cachedFlutterDistributions.any { it.contains(version) }
+ }
+}
+
+private fun findGlobalDartExecutableOrNull(): String? {
+ val dartOutput = "dart" execute currentWorkingDirectory
+ val hasGlobalDart = dartOutput.contains("A command-line utility for Dart development.")
+ return if(hasGlobalDart) "dart" else null
+}
+
+private fun downloadFlutterDistributionOrThrow(): String {
+ val architecture = currentArchitecture
+ val version = flutterVersionsDescending(currentOperatingSystem)
+ .firstOrNull { it.arch == architecture }
+ ?: throw KlutterException("Could not find compatible flutter distribution")
+ DownloadFlutterTask(version).run()
+ return version.folderNameString.toString()
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/Zippie.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/Zippie.kt
index 8d2751e1..af700ade 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/Zippie.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/Zippie.kt
@@ -33,11 +33,6 @@ class Zippie(
*/
private val zipFile: File,
- /**
- * Files which should be executable after unzipping.
- */
- private val executableFiles: Set,
-
/**
* Size of the buffer to read/write data
*/
@@ -74,12 +69,6 @@ class Zippie(
}
}
- File(destFilePath).setExecutableIfApplicable()
- }
-
- private fun File.setExecutableIfApplicable() {
- if(executableFiles.contains(nameWithoutExtension)) {
- setExecutable(true)
- }
+ File(destFilePath).setExecutable(true)
}
-}
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTask.kt
new file mode 100644
index 00000000..fda3f27d
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTask.kt
@@ -0,0 +1,118 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.kore.tasks.codegen
+
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.verifyExists
+import dev.buijs.klutter.kore.project.kradleHome
+import dev.buijs.klutter.kore.tasks.executor
+import java.io.File
+
+fun GenerateCodeOptions.toCompileProtoSchemaTask() =
+ CompileProtoSchemaTask(project.root.folder)
+
+/**
+ * Generate protocol buffer schema.
+ */
+class CompileProtoSchemaTask(
+ private val rootFolder: File,
+): KlutterTask, GenerateCodeAction {
+
+ override fun run() {
+
+ val pathToBuild = rootFolder.resolve("platform/build")
+
+ val sourceFolder = pathToBuild.resolve("klutter/protoschema")
+
+ if(!sourceFolder.exists()) return
+
+ val protoc = kradleHome
+ .resolve(".cache")
+ .resolve("protobuf")
+ .resolve("protoc")
+ .resolve("bin")
+ .resolve("protoc")
+ .verifyExists()
+ .absolutePath
+
+ val destination = rootFolder
+ .resolve("lib/src")
+ .verifyExists()
+ .absolutePath
+
+ val dartExecutable = kradleHome
+ .resolve(".cache")
+ .resolve("protobuf")
+ .resolve("protoc_plugin.exe")
+ .verifyExists()
+ .absolutePath
+
+ val schemas = sourceFolder
+ .listFiles()
+ ?.map { it.absolutePath }
+ ?.toSet()
+ ?: emptySet()
+
+ val destinationFile = File(destination)
+
+ for(pathToSchemaFile in schemas) {
+ executor.execute(
+ runFrom = rootFolder,
+ command = "$protoc -I=${sourceFolder.absolutePath} --dart_out=$destination $pathToSchemaFile --plugin protoc-gen-dart=$dartExecutable")
+
+ File(pathToSchemaFile).renameProtoGeneratedFiles(destinationFile)
+ File(pathToSchemaFile).deleteObsoleteGeneratedFiles(destinationFile)
+ }
+
+ }
+
+}
+
+internal fun File.renameProtoGeneratedFiles(destination: File) = buildList {
+ val generatedFileName = nameWithoutExtension.substringAfterLast(".")
+ val generatedFile = destination.resolve("$nameWithoutExtension.pb.dart")
+ val renamedFile = destination.resolve("${generatedFileName.substringAfterLast(".")}.pb.dart")
+ generatedFile.copyTo(renamedFile)
+ generatedFile.delete()
+
+ if(renamedFile.readText().contains("class ")) {
+ add(renamedFile.verifyExists())
+ } else {
+ renamedFile.delete()
+ }
+
+ val generatedEnumFile = destination.resolve("$nameWithoutExtension.pbenum.dart")
+ val renamedEnumFile = destination.resolve("${generatedFileName.substringAfterLast(".")}.pbenum.dart")
+ generatedEnumFile.copyTo(renamedEnumFile)
+ generatedEnumFile.delete()
+
+ if(renamedEnumFile.readText().contains("class ")) {
+ add(renamedEnumFile.verifyExists())
+ } else {
+ renamedEnumFile.delete()
+ }
+}
+
+internal fun File.deleteObsoleteGeneratedFiles(destination: File) {
+ destination.resolve("$nameWithoutExtension.pbjson.dart").delete()
+ destination.resolve("$nameWithoutExtension.pbserver.dart").delete()
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateAndroidLibTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateAndroidLibTask.kt
index cc8f528c..4c9220d6 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateAndroidLibTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateAndroidLibTask.kt
@@ -28,7 +28,7 @@ import dev.buijs.klutter.kore.project.*
import dev.buijs.klutter.kore.templates.AndroidAdapter
fun GenerateCodeOptions.toGenerateAndroidLibTask() =
- GenerateAndroidLibTask(android = project.android, bindings = bindings)
+ GenerateAndroidLibTask(android = project.android, bindings = bindings, isProtobufEnabled = responseClassNames.isNotEmpty())
/**
* Generate the Android code in root/android.
@@ -36,6 +36,7 @@ fun GenerateCodeOptions.toGenerateAndroidLibTask() =
class GenerateAndroidLibTask(
private val android: Android,
private val bindings: Map>,
+ private val isProtobufEnabled: Boolean,
) : KlutterTask, GenerateCodeAction {
override fun run() {
android.pathToPlugin.maybeCreate().write(
@@ -44,6 +45,7 @@ class GenerateAndroidLibTask(
pluginPackageName = android.pluginPackageName,
methodChannels = bindings.values.flatten().filterIsInstance().map { it.name }.toSet(),
eventChannels = bindings.values.flatten().filterIsInstance().map { it.name }.toSet(),
- controllers = bindings.keys))
+ controllers = bindings.keys,
+ isProtobufEnabled = isProtobufEnabled))
}
}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeActions.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeActions.kt
index de92189d..d69da7f0 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeActions.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeActions.kt
@@ -51,6 +51,12 @@ inline fun findGenerateCodeAction(
options.toGenerateFlutterMessagesTask()
PubGetTask::class.java ->
options.toPubGetTask()
+ GenerateProtoSchemasTask::class.java ->
+ options.toGenerateProtoSchemaTask()
+ CompileProtoSchemaTask::class.java ->
+ options.toCompileProtoSchemaTask()
+ GenerateProtoExtensionsTask::class.java ->
+ options.toGenerateProtoExtensionsTask()
else -> throw KlutterException("Unknown GenerateCodeAction: ${T::class.java}")
}
@@ -58,6 +64,6 @@ fun runGenerateCodeActions(vararg action: GenerateCodeAction) {
action.toList().forEach { it.run() }
}
-sealed interface GenerateCodeAction {
+interface GenerateCodeAction {
fun run()
}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeOptions.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeOptions.kt
index c97dd13c..04786c86 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeOptions.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeOptions.kt
@@ -35,6 +35,11 @@ data class GenerateCodeOptions(
val excludeArmArcFromPodspec: Boolean,
val controllers: List,
val messages: List,
+
+ /**
+ * List of FQDN Responses for which protobuf schemas should be generated.
+ */
+ val responseClassNames: List,
val log: (String) -> Unit = { },
) {
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeTask.kt
index b9b99961..e6c66b90 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateCodeTask.kt
@@ -44,7 +44,8 @@ class GenerateCodeTask(
findGenerateCodeAction(options),
findGenerateCodeAction(options),
findGenerateCodeAction(options),
- findGenerateCodeAction(options))
+ findGenerateCodeAction(options),
+ findGenerateCodeAction(options))
}
}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterControllersTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterControllersTask.kt
index a2512245..e721b4bd 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterControllersTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterControllersTask.kt
@@ -28,7 +28,10 @@ import dev.buijs.klutter.kore.templates.flutter.*
import java.io.File
fun GenerateCodeOptions.toGenerateControllersTask() =
- GenerateFlutterControllersTask(srcFolder = flutterSrcFolder, bindings = bindings)
+ GenerateFlutterControllersTask(
+ srcFolder = flutterSrcFolder,
+ bindings = bindings,
+ isProtobufEnabled = responseClassNames.isNotEmpty())
/**
* Generate the Flutter (dart) code in root/lib folder of the plugin project.
@@ -36,6 +39,7 @@ fun GenerateCodeOptions.toGenerateControllersTask() =
class GenerateFlutterControllersTask(
private val srcFolder: File,
private val bindings: Map>,
+ private val isProtobufEnabled: Boolean,
) : KlutterTask, GenerateCodeAction {
override fun run() {
@@ -44,12 +48,14 @@ class GenerateFlutterControllersTask(
is SimpleController ->
srcFolder.writeSimpleController(
controller = controller,
- channel = channels.firstSyncChannelOrNull()!!)
+ channel = channels.firstSyncChannelOrNull()!!,
+ isProtobufEnabled = isProtobufEnabled)
is BroadcastController ->
srcFolder.writeBroadcastController(
controller = controller,
asyncChannel = channels.firstAsyncChannelOrNull()!!,
- syncChannel = channels.firstSyncChannelOrNull())
+ syncChannel = channels.firstSyncChannelOrNull(),
+ isProtobufEnabled = isProtobufEnabled)
}
}
}
@@ -65,7 +71,8 @@ private fun List.firstAsyncChannelOrNull() =
private fun File.writeBroadcastController(
controller: BroadcastController,
asyncChannel: FlutterAsyncChannel,
- syncChannel: FlutterSyncChannel?
+ syncChannel: FlutterSyncChannel?,
+ isProtobufEnabled: Boolean,
) {
val parentFolder = this
@@ -81,27 +88,30 @@ private fun File.writeBroadcastController(
dataType = controller.response))
controller.functions
- .forEach { it.writePublisherWidget(parentFolder, syncChannel!!) }
+ .forEach { it.writePublisherWidget(parentFolder, syncChannel!!, isProtobufEnabled) }
}
private fun File.writeSimpleController(
controller: SimpleController,
- channel: FlutterSyncChannel
+ channel: FlutterSyncChannel,
+ isProtobufEnabled: Boolean,
) {
val parentFolder =
resolve(controller.className.toSnakeCase())
.maybeCreateFolder()
controller.functions
- .forEach { it.writePublisherWidget(parentFolder, channel) }
+ .forEach { it.writePublisherWidget(parentFolder, channel, isProtobufEnabled) }
}
private fun Method.writePublisherWidget(
parentFolder: File,
- channel: FlutterSyncChannel
+ channel: FlutterSyncChannel,
+ isProtobufEnabled: Boolean,
) = parentFolder.resolve("${method.toSnakeCase()}.dart")
.also { it.createNewFile() }
.write(PublisherWidget(
+ isProtobufEnabled = isProtobufEnabled,
channel = channel,
event = FlutterEvent(command),
extension = FlutterExtension("${command.replaceFirstChar { it.uppercase() }}Event"),
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterLibTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterLibTask.kt
index 38d53859..9d0db1c5 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterLibTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterLibTask.kt
@@ -28,7 +28,10 @@ import dev.buijs.klutter.kore.templates.flutter.PackageLib
import java.io.File
fun GenerateCodeOptions.toGenerateFlutterLibTask() =
- GenerateFlutterLibTask(root = project.root, srcFolder = flutterSrcFolder, pluginName = pluginName)
+ GenerateFlutterLibTask(root = project.root,
+ srcFolder = flutterSrcFolder,
+ bomVersion = klutterBomVersion,
+ pluginName = pluginName)
/**
* Generate the Flutter (dart) code in root/lib folder of the plugin project.
@@ -37,13 +40,21 @@ class GenerateFlutterLibTask(
private val root: Root,
private val srcFolder: File,
private val pluginName: String,
+ private val bomVersion: String,
) : KlutterTask, GenerateCodeAction {
override fun run() {
+ // Update Klutter Gradle Plugin Version
+ root.kradleYaml.let { kradleYamlFile ->
+ kradleYamlFile.toConfigOrNull()
+ ?.copy(bomVersion = bomVersion)
+ ?.let { kradleYamlFile.writeText(mapper.writeValueAsString(it)) }
+ }
+
root.pathToLibFile.maybeCreate().write(
PackageLib(
name = pluginName,
- exports = srcFolder.walkTopDown()
+ exports = srcFolder.verifyExists().walkTopDown()
.toList()
.filter { it.isFile }
.map { it.relativeTo(srcFolder) }
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterMessagesTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterMessagesTask.kt
index 154b0b78..1176d9be 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterMessagesTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateFlutterMessagesTask.kt
@@ -29,12 +29,18 @@ import dev.buijs.klutter.kore.tasks.execute
import java.io.File
fun GenerateCodeOptions.toGenerateFlutterMessagesTask() =
- GenerateFlutterMessagesTask(
- root = project.root,
- srcFolder = flutterSrcFolder,
- flutterFolder = flutterFolder,
- messages = messages,
- log = log)
+ if(responseClassNames.isEmpty()) {
+ GenerateFlutterMessagesTask(
+ root = project.root,
+ srcFolder = flutterSrcFolder,
+ flutterFolder = flutterFolder,
+ messages = messages,
+ log = log)
+ } else {
+ object: GenerateCodeAction {
+ override fun run() { }
+ }
+ }
/**
* Generate the Flutter (dart) code in root/lib folder of the plugin project.
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateIosLibTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateIosLibTask.kt
index 92c3a528..73b8f71d 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateIosLibTask.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateIosLibTask.kt
@@ -28,7 +28,10 @@ import dev.buijs.klutter.kore.project.*
import dev.buijs.klutter.kore.templates.IosAdapter
fun GenerateCodeOptions.toGenerateIosLibTask() =
- GenerateIosLibTask(ios = project.ios, bindings = bindings)
+ GenerateIosLibTask(
+ ios = project.ios,
+ bindings = bindings,
+ isProtobufEnabled = responseClassNames.isNotEmpty())
/**
* Generate the IOS code in root/ios.
@@ -36,6 +39,7 @@ fun GenerateCodeOptions.toGenerateIosLibTask() =
class GenerateIosLibTask(
private val ios: IOS,
private val bindings: Map>,
+ private val isProtobufEnabled: Boolean,
) : KlutterTask, GenerateCodeAction {
override fun run() {
ios.pathToPlugin.maybeCreate().write(
@@ -43,6 +47,7 @@ class GenerateIosLibTask(
pluginClassName = ios.pluginClassName,
methodChannels = bindings.values.flatten().filterIsInstance().map { it.name }.toSet(),
eventChannels = bindings.values.flatten().filterIsInstance().map { it.name }.toSet(),
- controllers = bindings.keys))
+ controllers = bindings.keys,
+ isProtobufEnabled = isProtobufEnabled))
}
}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTask.kt
new file mode 100644
index 00000000..92caf0a7
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTask.kt
@@ -0,0 +1,65 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.kore.tasks.codegen
+
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.maybeCreate
+import dev.buijs.klutter.kore.common.maybeCreateFolder
+import dev.buijs.klutter.kore.common.write
+import dev.buijs.klutter.kore.templates.ProtobufExtensions
+import java.io.File
+
+const val protoGenMarker = "ProtocolBufferGenerated"
+
+fun GenerateCodeOptions.toGenerateProtoExtensionsTask() =
+ GenerateProtoExtensionsTask(project.platform.folder
+ .resolve("build")
+ .resolve("generated")
+ .resolve("ksp")
+ .resolve("metadata")
+ .resolve("commonMain")
+ .resolve("kotlin")
+ , responseClassNames)
+
+class GenerateProtoExtensionsTask(
+ private val sourceFolder: File,
+ private val responseClassNames: List,
+) : KlutterTask, GenerateCodeAction {
+ override fun run() {
+ for(fqdn in responseClassNames) {
+ val packageName = fqdn
+ .substringBeforeLast(".")
+
+ val pathToPackage = packageName
+ .replace(".", "/")
+
+ val className = fqdn.substringAfterLast(".")
+
+ sourceFolder
+ .resolve(pathToPackage)
+ .maybeCreateFolder()
+ .resolve("$protoGenMarker$className.kt")
+ .maybeCreate()
+ .write(ProtobufExtensions(packageName, className))
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoSchemasTask.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoSchemasTask.kt
new file mode 100644
index 00000000..4b3452aa
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoSchemasTask.kt
@@ -0,0 +1,119 @@
+/* Copyright (c) 2021 - 2024 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.kore.tasks.codegen
+
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.KlutterTask
+import dev.buijs.klutter.kore.common.maybeCreateFolder
+import dev.buijs.klutter.kore.common.verifyExists
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
+import java.io.File
+import java.net.URL
+import java.net.URLClassLoader
+import kotlin.reflect.full.companionObject
+import kotlin.reflect.full.companionObjectInstance
+import kotlin.reflect.full.functions
+
+/**
+ * Create an instance of [GenerateProtoSchemasTask] if the List
+ * [GenerateCodeOptions.responseClassNames] is not empty.
+ */
+fun GenerateCodeOptions.toGenerateProtoSchemaTask() =
+ if(responseClassNames.isNotEmpty()) {
+ GenerateProtoSchemasTask(project.root.folder,
+ gradleBuildInstanceClassLoader = this::class.java.classLoader)
+ } else {
+ object: GenerateCodeAction {
+ override fun run() { }
+ }
+ }
+
+
+/**
+ * Generate the protocol buffer schemas.
+ */
+class GenerateProtoSchemasTask(
+ pathToRoot: File,
+ /**
+ * Classloader instance which is retried from the Build_gradle class.
+ *
+ * Getting the Classloader through this instance is the only way to ensure
+ * all dependencies from the SourceSet are present. If any dependency is missing,
+ * then it is not possible to get the SerializationStrategy of the Serializable
+ * Response classes.
+ */
+ private val gradleBuildInstanceClassLoader: ClassLoader,
+): KlutterTask, GenerateCodeAction {
+
+ private val pathToBuild = pathToRoot.resolve("platform/build")
+
+ @OptIn(ExperimentalSerializationApi::class)
+ override fun run() {
+ val pathToSource = pathToBuild
+ .resolve("klutter/response")
+
+ if(!pathToSource.exists()) return
+
+ val pathToOutput = pathToBuild
+ .resolve("klutter/protoschema")
+ .maybeCreateFolder(clearIfExists = true)
+
+ val classNames = pathToSource
+ .listFiles { _, fn -> fn.startsWith("proto_") }
+ ?.map { it.readText() }
+ ?.toSet()
+ ?: emptySet()
+
+ val url = pathToBuild
+ .resolve("intermediates/aar_main_jar/release/classes.jar")
+ .verifyExists()
+ .toURI()
+ .toURL()
+
+ val classLoader = URLClassLoader(arrayOf(url), gradleBuildInstanceClassLoader)
+
+ for (className in classNames) {
+ val classToLoad = Class.forName(className, true, classLoader)
+
+ val companionObject = classToLoad.kotlin.companionObject
+ ?: throw KlutterException("Failed to find Companion")
+
+ val companionInstance = classToLoad.kotlin.companionObjectInstance
+ ?: throw KlutterException("Failed to find Companion Instance")
+
+ val functionEx = companionObject.functions.firstOrNull { it.name == "serializer" }
+ ?: throw KlutterException("Method 'serializer' not found in list of methods: ${companionObject.functions.map { it.name }}")
+
+ val result: KSerializer<*> = functionEx.call(companionInstance) as KSerializer<*>
+
+ val schema = ProtoBufSchemaGenerator.generateSchemaText(result.descriptor)
+
+ pathToOutput.resolve("${className.lowercase()}.proto").let { file ->
+ file.createNewFile()
+ file.writeText(schema)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadFlutter.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadFlutter.kt
index 686b50bc..10424111 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadFlutter.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadFlutter.kt
@@ -31,11 +31,6 @@ import java.nio.file.Files
internal var dryRun = false
-/**
- * Files which should be executable.
- */
-private val executableFiles = setOf("flutter", "dart", "impellerc")
-
internal fun ProjectBuilderOptions.toDowloadFlutterTask() =
DownloadFlutter(flutterDistributionString.flutterDistribution)
@@ -69,7 +64,7 @@ internal class DownloadFlutter(
// Make sure cache exists in the user home.
initKradleCache()
if(target.exists()) target.deleteRecursively()
- Zippie(zip, executableFiles).unzipTo(target.absolutePath)
+ Zippie(zip).unzipTo(target.absolutePath)
zip.deleteRecursively()
}
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadProtoc.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadProtoc.kt
new file mode 100644
index 00000000..7673cb76
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionDownloadProtoc.kt
@@ -0,0 +1,64 @@
+/* Copyright (c) 2021 - 2023 Buijs Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+package dev.buijs.klutter.kore.tasks.project
+
+import dev.buijs.klutter.kore.KlutterException
+import dev.buijs.klutter.kore.common.verifyExists
+import dev.buijs.klutter.kore.project.*
+import dev.buijs.klutter.kore.tasks.Zippie
+import java.io.*
+import java.net.URL
+import java.nio.channels.Channels
+import java.nio.file.Files
+
+internal class DownloadProtoc(
+ private val rootFolder: File,
+ private val overwrite: Boolean = false,
+ private val target: File,
+) : ProjectBuilderAction {
+ override fun doAction() {
+ if(dryRun) return
+ val path = findProtocDownloadURLInKradleEnvOrNull(rootFolder.resolve("kradle.env").verifyExists().readText())
+ if(target.exists() && !overwrite) return
+ val zip = tempZipFile
+
+ try {
+ Channels.newChannel(URL(path).openStream()).use { readableByteChannel ->
+ val fileOutputStream = FileOutputStream(zip)
+ val fileChannel = fileOutputStream.getChannel()
+ fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE)
+ }
+ } catch (e: IOException) {
+ throw KlutterException("Failed to download protoc", e)
+ }
+
+ // Make sure cache exists in the user home.
+ initKradleCache()
+ if(target.exists()) target.deleteRecursively()
+ Zippie(zip).unzipTo(target.absolutePath)
+ zip.deleteRecursively()
+ }
+
+}
+
+private val tempZipFile: File
+ get() = Files.createTempDirectory("klutter_download").toFile().resolve("protoc.zip")
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionInitKlutter.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionInitKlutter.kt
index 55cea9e7..3fe05470 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionInitKlutter.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/tasks/project/ActionInitKlutter.kt
@@ -71,20 +71,15 @@ internal class InitKlutter(
root.clearLibFolder()
root.overwriteReadmeFile()
root.copyLocalProperties()
- "$flutter pub get" execute root
- "$flutter pub get" execute exampleFolder
- "$flutter pub run klutter:producer init bom=$bomVersion flutter=$flutterSDK" execute root
- "$flutter pub run klutter:consumer init" execute exampleFolder
- "$flutter pub run klutter:consumer add lib=$name" execute exampleFolder
+ println("$flutter pub get" execute root)
+ println("$flutter pub get" execute exampleFolder)
+ println("$flutter pub run klutter:kradle init bom=$bomVersion flutter=$flutterSDK" execute root)
+ println("$flutter pub run klutter:kradle add lib=$name" execute exampleFolder)
exampleFolder.deleteIntegrationTestFolder()
- // Do not bother setting up iOS on windows
- if(isWindows) return
- exampleFolder.deleteIosPodfileLock()
- exampleFolder.deleteIosPods()
- exampleFolder.deleteRunnerXCWorkspace()
- "pod install" execute exampleFolder.resolve("ios")
- "pod update" execute exampleFolder.resolve("ios")
+ // Only setup ios on macos.
+ if(isMacos)
+ println("$flutter pub run klutter:kradle init ios=13" execute exampleFolder)
}
/**
@@ -114,18 +109,6 @@ internal class InitKlutter(
resolve("lib").listFiles()?.forEach { it.deleteRecursively() }
}
- private fun File.deleteIosPodfileLock() {
- resolve("ios").resolve("Podfile.lock").delete()
- }
-
- private fun File.deleteIosPods() {
- resolve("ios").resolve("Pods").deleteRecursively()
- }
-
- private fun File.deleteRunnerXCWorkspace() {
- resolve("ios").resolve("Runner.xcworkspace").deleteRecursively()
- }
-
/**
* Change the README content to explain Klutter plugin development.
*/
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/AndroidAdapter.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/AndroidAdapter.kt
index 8164df91..c32b6b83 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/AndroidAdapter.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/AndroidAdapter.kt
@@ -29,6 +29,7 @@ import dev.buijs.klutter.kore.common.toSnakeCase
class AndroidAdapter(
private val pluginPackageName: String,
private val pluginClassName: String,
+ private val isProtobufEnabled: Boolean,
methodChannels: Set,
eventChannels: Set,
controllers: Set,
@@ -57,7 +58,7 @@ class AndroidAdapter(
)
private val importsControllers = controllers
- .mapNotNull { controller -> controller.packageName }
+ .map { controller -> controller.packageName }
.map { "import $it.*" }
.toSet()
@@ -84,7 +85,7 @@ class AndroidAdapter(
private val methodChannelHandlerWhenClauses = controllers
.filter { it.functions.isNotEmpty() }
.flatMap { controller ->
- controller.functions.map { it.methodHandlerString(controller.instanceOrConstructor()) }
+ controller.functions.map { it.methodHandlerString(controller.instanceOrConstructor(), isProtobufEnabled) }
}.sorted()
private val methodChannelNames =
@@ -214,20 +215,21 @@ class AndroidAdapter(
}
-private fun Method.methodHandlerString(instanceOrConstuctor: String): String {
+private fun Method.methodHandlerString(instanceOrConstuctor: String, isProtobufEnabled: Boolean): String {
if(requestDataType is CustomType || requestDataType is EnumType) {
- return methodHandlerStringWithCustomTypeRequestParameter(instanceOrConstuctor)
+ return methodHandlerStringWithCustomTypeRequestParameter(instanceOrConstuctor, isProtobufEnabled)
}
val requestArgumentOrEmpty =
if(requestDataType == null) ""
else "data as ${this.requestDataType.typeSimplename(asKotlinType = true)}"
- val responseDecoderOrEmpty = when(responseDataType) {
+ val encoder = if(isProtobufEnabled) "encodeBuffer()" else "encode()"
+ val responseDecoderOrEmpty = when(this.responseDataType) {
is StandardType -> ""
- is Nullable -> "?.encode()"
- else -> ".encode()"
+ is Nullable -> "?.$encoder"
+ else -> ".$encoder"
}
val methodInvocation = "$instanceOrConstuctor.$method($requestArgumentOrEmpty)$responseDecoderOrEmpty"
@@ -247,20 +249,27 @@ private fun Method.methodHandlerString(instanceOrConstuctor: String): String {
}
-private fun Method.methodHandlerStringWithCustomTypeRequestParameter(instanceOrConstuctor: String): String {
+private fun Method.methodHandlerStringWithCustomTypeRequestParameter(instanceOrConstuctor: String, isProtobufEnabled: Boolean): String {
val requestType = requestDataType.typeSimplename(asKotlinType = true)
-
+ val encoder = if(isProtobufEnabled) "encodeBuffer()" else "encode()"
val responseDecoderOrEmpty = when(this.responseDataType) {
is StandardType -> ""
- is Nullable -> "?.encode()"
- else -> ".encode()"
+ is Nullable -> "?.$encoder"
+ else -> ".$encoder"
}
val methodInvocation = "$instanceOrConstuctor.$method(kJson)$responseDecoderOrEmpty"
+
+ val decoder = if(isProtobufEnabled) {
+ "data.decodeBuffer<$requestType>()"
+ } else {
+ "data.decode() as $requestType?"
+ }
+
return if(responseDataType is UnitType) {
"""
| "$command" -> {
- | val kJson: $requestType? = data.decode() as $requestType?
+ | val kJson: $requestType? = $decoder
| if(kJson != null) {
| $methodInvocation
| }
@@ -270,7 +279,7 @@ private fun Method.methodHandlerStringWithCustomTypeRequestParameter(instanceOrC
} else
"""
| "$command" -> {
- | val kJson: $requestType? = data.decode() as $requestType?
+ | val kJson: $requestType? = $decoder
| if(kJson != null) {
| result.success($methodInvocation)
| } else {
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/IosAdapter.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/IosAdapter.kt
index 808120b8..95643266 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/IosAdapter.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/IosAdapter.kt
@@ -29,6 +29,7 @@ import dev.buijs.klutter.kore.common.toSnakeCase
class IosAdapter(
private val pluginClassName: String,
+ private val isProtobufEnabled: Boolean,
methodChannels: Set,
eventChannels: Set,
controllers: Set,
@@ -68,7 +69,7 @@ class IosAdapter(
""" case "${it.className.toSnakeCase()}":""",
" ${it.instanceOrConstructor()}.receiveBroadcastIOS().collect(",
" onEach: { value in",
- " eventSink(${it.response.responseDecoder()})",
+ " eventSink(${it.response.responseEncoder()})",
" },",
" onCompletion: { error in",
""" eventSink("ERROR: \("error")")""",
@@ -156,11 +157,11 @@ class IosAdapter(
private fun Method.methodHandlerString(instanceOrConstuctor: String): List {
val method = method.replace("(context)", """(context: "")""")
- val responseDecoder =
- responseDataType.responseDecoder()
+ val responseEncoder =
+ responseDataType.responseEncoder()
if(this.requestDataType != null) {
- return methodHandlerWithArgument(instanceOrConstuctor, responseDecoder)
+ return methodHandlerWithArgument(instanceOrConstuctor, responseEncoder)
}
if(this.responseDataType is UnitType) {
@@ -171,7 +172,9 @@ class IosAdapter(
listOf(
"""| func ${command}(data: Any?, result: @escaping FlutterResult) {
| $instanceOrConstuctor.${method.removeSuffix("()")} { maybeData, error in
- | if let value = maybeData { result($responseDecoder) }
+ | if let value = maybeData {
+ | $responseEncoder
+ | }
|
| if let failure = error { result(failure) }
| }
@@ -182,7 +185,7 @@ class IosAdapter(
listOf(
"""| func ${command}(data: Any?, result: @escaping FlutterResult) {
| let value = $instanceOrConstuctor.$method()
- | result($responseDecoder)
+ | $responseEncoder
| }
|
""".trimMargin())
@@ -212,23 +215,44 @@ class IosAdapter(
}
}
- private fun Method.methodHandlerWithArgument(instanceOrConstuctor: String, responseDecoder: String): List {
- val requestDecoder = when(requestDataType) {
- is StringType -> "TypeHandlerKt.stringOrNull(data: data)"
- is IntType -> "TypeHandlerKt.intOrNull(data: data)"
- is DoubleType -> "TypeHandlerKt.intOrNull(data: data)"
- is BooleanType -> "TypeHandlerKt.booleanOrNull(data: data)"
- is LongType -> "TypeHandlerKt.intOrNull(data: data)"
- is ByteArrayType -> "TypeHandlerKt.byteArrayOrNull(data: data)"
- is IntArrayType -> "TypeHandlerKt.intArrayOrNull(data: data)"
- is LongArrayType -> "TypeHandlerKt.longArrayOrNull(data: data)"
- is FloatArrayType -> "TypeHandlerKt.floatArrayOrNull(data: data)"
- is DoubleArrayType -> "TypeHandlerKt.doubleArrayOrNull(data: data)"
- is ListType -> "TypeHandlerKt.listOrNull(data: data)"
- is MapType -> "TypeHandlerKt.mapOrNull(data: data)"
- is CustomType -> "TypeHandlerKt.deserialize(data)"
- is EnumType -> "TypeHandlerKt.deserialize(data)"
- else -> throw KlutterException("Found unsupported request Type: $requestDataType")
+ private fun Method.methodHandlerWithArgument(instanceOrConstuctor: String, responseEncoder: String): List {
+
+ var requiresBytesDecoding = false
+
+ val requestDecoder = if(isProtobufEnabled) {
+ when(requestDataType) {
+ is StringType -> "TypeHandlerKt.stringOrNull(data: data)"
+ is IntType -> "TypeHandlerKt.intOrNull(data: data)"
+ is DoubleType -> "TypeHandlerKt.intOrNull(data: data)"
+ is BooleanType -> "TypeHandlerKt.booleanOrNull(data: data)"
+ is LongType -> "TypeHandlerKt.intOrNull(data: data)"
+ is IntArrayType -> "TypeHandlerKt.intArrayOrNull(data: data)"
+ is LongArrayType -> "TypeHandlerKt.longArrayOrNull(data: data)"
+ is FloatArrayType -> "TypeHandlerKt.floatArrayOrNull(data: data)"
+ is DoubleArrayType -> "TypeHandlerKt.doubleArrayOrNull(data: data)"
+ else -> {
+ requiresBytesDecoding = true
+ "TypeHandlerKt.byteArrayOrNull(data: data)"
+ }
+ }
+ } else {
+ when(requestDataType) {
+ is StringType -> "TypeHandlerKt.stringOrNull(data: data)"
+ is IntType -> "TypeHandlerKt.intOrNull(data: data)"
+ is DoubleType -> "TypeHandlerKt.intOrNull(data: data)"
+ is BooleanType -> "TypeHandlerKt.booleanOrNull(data: data)"
+ is LongType -> "TypeHandlerKt.intOrNull(data: data)"
+ is ByteArrayType -> "TypeHandlerKt.byteArrayOrNull(data: data)"
+ is IntArrayType -> "TypeHandlerKt.intArrayOrNull(data: data)"
+ is LongArrayType -> "TypeHandlerKt.longArrayOrNull(data: data)"
+ is FloatArrayType -> "TypeHandlerKt.floatArrayOrNull(data: data)"
+ is DoubleArrayType -> "TypeHandlerKt.doubleArrayOrNull(data: data)"
+ is ListType -> "TypeHandlerKt.listOrNull(data: data)"
+ is MapType -> "TypeHandlerKt.mapOrNull(data: data)"
+ is CustomType -> "TypeHandlerKt.deserialize(data)"
+ is EnumType -> "TypeHandlerKt.deserialize(data)"
+ else -> throw KlutterException("Found unsupported request Type: $requestDataType")
+ }
}
val swiftRequestDataType = when(requestDataType) {
@@ -294,7 +318,14 @@ class IosAdapter(
lines.add(" } else {")
- val dataOrNull = "(dataOrNull $swiftRequestDataType)"
+ if(requiresBytesDecoding)
+ lines.add("let data = ProtocolBufferGenerated${requestDataType.className}Kt.decodeByteArrayTo${requestDataType.className}(byteArray: dataOrNull!)")
+
+ val dataOrNull = if(requiresBytesDecoding) {
+ "(data $swiftRequestDataType)"
+ } else {
+ "(dataOrNull $swiftRequestDataType)"
+ }
if(async) {
if(responseDataType is UnitType) {
@@ -304,7 +335,7 @@ class IosAdapter(
lines.add(" }")
} else {
lines.add(" $instanceOrConstuctor.$method($requestParameterName: $dataOrNull) { maybeData, error in")
- lines.add(" if let value = maybeData { result($responseDecoder) }")
+ lines.add(" if let value = maybeData { $responseEncoder }")
lines.add(" if let failure = error { result(failure) }")
lines.add(" }")
}
@@ -327,10 +358,19 @@ class IosAdapter(
else -> "${className}()"
}
- private fun AbstractType.responseDecoder(): String {
- return when (this) {
- is StandardType -> "value"
- else -> "TypeHandlerKt.encode(value)"
+ private fun AbstractType.responseEncoder(): String {
+ return when {
+ this is StandardType -> "result(value)"
+ isProtobufEnabled ->
+ """|let bytes = value.encode${className}ToByteArray()
+ | var array = [UInt8]()
+ | var iterator = bytes.iterator()
+ | while iterator.hasNext() {
+ | array.append(UInt8(iterator.nextByte()))
+ | }
+ | result(FlutterStandardTypedData(bytes: Data(array)))
+ """.trimMargin()
+ else -> "result(TypeHandlerKt.encode(value))"
}
}
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/ProtobufExtensions.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/ProtobufExtensions.kt
new file mode 100644
index 00000000..1c64ba58
--- /dev/null
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/ProtobufExtensions.kt
@@ -0,0 +1,25 @@
+package dev.buijs.klutter.kore.templates
+
+import dev.buijs.klutter.kore.KlutterPrinter
+
+class ProtobufExtensions(
+ private val packageName: String,
+ private val className: String,
+): KlutterPrinter {
+
+ override fun print(): String = """|package $packageName
+|
+|import kotlinx.serialization.ExperimentalSerializationApi
+|import kotlinx.serialization.decodeFromByteArray
+|import kotlinx.serialization.encodeToByteArray
+|import kotlinx.serialization.protobuf.ProtoBuf
+|
+|@OptIn(ExperimentalSerializationApi::class)
+|fun $className.encode${className}ToByteArray(): ByteArray =
+| ProtoBuf.encodeToByteArray(this)
+|
+|@OptIn(ExperimentalSerializationApi::class)
+|fun decodeByteArrayTo$className(byteArray: ByteArray): $className =
+| ProtoBuf.decodeFromByteArray(byteArray)""".trimMargin()
+
+}
\ No newline at end of file
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PublisherWidget.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PublisherWidget.kt
index ad4f881a..5c3a7470 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PublisherWidget.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PublisherWidget.kt
@@ -99,16 +99,30 @@ fun PublisherWidget.createPrinter(): KlutterPrinter {
val requiresResponseDecoder =
responseType.dataType !is StandardType
- val requestEncoderOrBlank = when(requestType?.dataType) {
- is CustomType -> {
- "encode: (dynamic data) => (data as ${requestType.dataType.className}).toJson,"
- }
+ val requestEncoderOrBlank = if(isProtobufEnabled) {
+ when(requestType?.dataType) {
+ is CustomType -> {
+ "encodeBuffer: (dynamic data) => (data as ${requestType.dataType.className}).writeToBuffer(),"
+ }
+
+ is EnumType -> {
+ "encodeBuffer: (dynamic data) => Uint8List.fromList([(data as ${responseType.dataType.className}).value]),"
+ }
- is EnumType -> {
- "encode: (dynamic data) => (data as ${requestType.dataType.className}).toJsonValue,"
+ else -> ""
}
+ } else {
+ when(requestType?.dataType) {
+ is CustomType -> {
+ "encode: (dynamic data) => (data as ${requestType.dataType.className}).toJson,"
+ }
- else -> ""
+ is EnumType -> {
+ "encode: (dynamic data) => (data as ${requestType.dataType.className}).toJsonValue,"
+ }
+
+ else -> ""
+ }
}
val template = buildString {
@@ -121,21 +135,37 @@ fun PublisherWidget.createPrinter(): KlutterPrinter {
)
if(requiresRequestEncoder) {
- append(
- """
+ if(isProtobufEnabled) {
+ if(requestType?.dataType is EnumType) {
+ append("import '../${requestType.dartType.toSnakeCase().replace("_", "")}.pbenum.dart';")
+ } else {
+ append("import '../${requestType?.dartType?.toSnakeCase()?.replace("_", "")}.pb.dart';")
+ }
+ } else {
+ append(
+ """
|import '../${requestType?.dartType?.toSnakeCase()}_dataclass.dart';
|import '../${requestType?.dartType?.toSnakeCase()}_extensions.dart';
"""
- )
+ )
+ }
}
if(requiresResponseDecoder) {
- append(
- """
+ if(isProtobufEnabled) {
+ if(responseType.dataType is EnumType) {
+ append("import '../${responseType.dartType.toSnakeCase().replace("_", "")}.pbenum.dart';")
+ } else {
+ append("import '../${responseType.dartType.toSnakeCase().replace("_", "")}.pb.dart';")
+ }
+ } else {
+ append(
+ """
|import '../${responseType.dartType.toSnakeCase()}_dataclass.dart';
|import '../${responseType.dartType.toSnakeCase()}_extensions.dart';
"""
- )
+ )
+ }
}
append(
@@ -172,7 +202,15 @@ fun PublisherWidget.createPrinter(): KlutterPrinter {
}
if(requiresResponseDecoder) {
- append("decode: (String json) => json.to${responseType.dataType.className},")
+ if(isProtobufEnabled) {
+ if(responseType.dataType is EnumType) {
+ append("decodeBuffer: (List buffer) => ${responseType.dataType.className}.valueOf(buffer[0])!,")
+ } else {
+ append("decodeBuffer: (List buffer) => ${responseType.dataType.className}.fromBuffer(buffer),")
+ }
+ } else {
+ append("decode: (String json) => json.to${responseType.dataType.className},")
+ }
}
append("""
@@ -211,7 +249,15 @@ fun PublisherWidget.createPrinter(): KlutterPrinter {
}
if(requiresResponseDecoder) {
- append("decode: (String json) => json.to${responseType.dataType.className},")
+ if(isProtobufEnabled) {
+ if(responseType.dataType is EnumType) {
+ append("decodeBuffer: (List buffer) => ${responseType.dataType.className}.valueOf(buffer[0])!,")
+ } else {
+ append("decodeBuffer: (List buffer) => ${responseType.dataType.className}.fromBuffer(buffer),")
+ }
+ } else {
+ append("decode: (String json) => json.to${responseType.dataType.className},")
+ }
}
append("""
@@ -282,6 +328,8 @@ data class PublisherWidget(
* ```
*/
val method: FlutterMethod,
+
+ val isProtobufEnabled: Boolean,
)
/**
diff --git a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PubspecYaml.kt b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PubspecYaml.kt
index 84de77ce..e8c722db 100644
--- a/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PubspecYaml.kt
+++ b/lib/kore/src/main/kotlin/dev/buijs/klutter/kore/templates/flutter/PubspecYaml.kt
@@ -69,6 +69,8 @@ fun createRootPubspecYamlWriter(
appendLine("")
appendDependency(config?.dependencies?.klutterUI ?: klutterUIPubVersion, name = "klutter_ui")
appendLine("")
+ appendLine("")
+ appendLine(" protobuf: ^3.1.0")
appendLine("dev_dependencies:")
appendDependency(config?.dependencies?.klutter ?: klutterPubVersion, name = "klutter")
appendLine("")
diff --git a/lib/kore/src/main/resources/protoc_plugin.exe b/lib/kore/src/main/resources/protoc_plugin.exe
new file mode 100755
index 00000000..8dc564dc
Binary files /dev/null and b/lib/kore/src/main/resources/protoc_plugin.exe differ
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Build.kt b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/GetDartProtocExeTaskSpec.groovy
similarity index 77%
rename from lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Build.kt
rename to lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/GetDartProtocExeTaskSpec.groovy
index f27f571b..8751f4ff 100644
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/Build.kt
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/GetDartProtocExeTaskSpec.groovy
@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
+/* Copyright (c) 2021 - 2022 Buijs Software
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,12 +19,16 @@
* SOFTWARE.
*
*/
-package dev.buijs.klutter.kradle.shared
+package dev.buijs.klutter.kore.tasks
-import java.io.File
-fun build(currentFolder: File) {
- println("Let's build something great!")
- listOf("clean", "build", "-p", "platform").execGradleCommand(currentFolder)
- println("Finished project build.")
+import spock.lang.Specification
+
+class GetDartProtocExeTaskSpec extends Specification {
+
+ def "Verify protoc_plugin executable can be loaded from resources"() {
+ expect:
+ new GetDartProtocExeTask() != null
+ }
+
}
\ No newline at end of file
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTaskSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTaskSpec.groovy
new file mode 100644
index 00000000..4011360a
--- /dev/null
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/CompileProtoSchemaTaskSpec.groovy
@@ -0,0 +1,72 @@
+package dev.buijs.klutter.kore.tasks.codegen
+
+import spock.lang.Specification
+
+import java.nio.file.Files
+
+class CompileProtoSchemaTaskSpec extends Specification {
+
+ def "Verify generated proto files are renamed correctly"() {
+ given:
+ def destination = Files.createTempDirectory("").toFile()
+ def schemaFile = destination.toPath().resolve("foo.bar.someclass.proto").toFile()
+ schemaFile.createNewFile()
+ def classInput = destination.toPath().resolve("foo.bar.someclass.pb.dart").toFile()
+ classInput.createNewFile()
+ classInput.write("class SomeClass")
+ def enumInput = destination.toPath().resolve("foo.bar.someclass.pbenum.dart").toFile()
+ enumInput.createNewFile()
+ enumInput.write("class SomeClass")
+
+ expect:
+ with(CompileProtoSchemaTaskKt.renameProtoGeneratedFiles(schemaFile, destination)) {
+ it.size() == 2
+ it.any { it.name.contains("someclass.pb.dart")}
+ it.any { it.name.contains("someclass.pbenum.dart")}
+ }
+ }
+
+ def "Verify generated files that have no class definition are deleted"() {
+ given:
+ def destination = Files.createTempDirectory("").toFile()
+ def schemaFile = destination.toPath().resolve("foo.bar.someclass.proto").toFile()
+ schemaFile.createNewFile()
+ def classInput = destination.toPath().resolve("foo.bar.someclass.pb.dart").toFile()
+ classInput.createNewFile()
+ classInput.write("class SomeClass")
+ def enumInput = destination.toPath().resolve("foo.bar.someclass.pbenum.dart").toFile()
+ enumInput.createNewFile()
+ enumInput.write("// Comments BLA BLA")
+
+ expect:
+ with(CompileProtoSchemaTaskKt.renameProtoGeneratedFiles(schemaFile, destination)) {
+ it.size() == 1
+ it[0].name.contains("someclass.pb.dart")
+ }
+
+ }
+
+ def "Verify generated files that are obsolete are deleted"() {
+ given:
+ def destination = Files.createTempDirectory("").toFile()
+ def schemaFile = destination.toPath().resolve("foo.bar.someclass.proto").toFile()
+ schemaFile.createNewFile()
+ def pbjsonFile = destination.toPath().resolve("foo.bar.someclass.pbjson.dart").toFile()
+ pbjsonFile.createNewFile()
+ def pbserverFile = destination.toPath().resolve("foo.bar.someclass.pbserver.dart").toFile()
+ pbserverFile.createNewFile()
+
+ and:
+ pbjsonFile.exists()
+ pbserverFile.exists()
+
+ when:
+ CompileProtoSchemaTaskKt.deleteObsoleteGeneratedFiles(schemaFile, destination)
+
+ then:
+ !pbjsonFile.exists()
+ !pbserverFile.exists()
+
+ }
+
+}
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTaskSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTaskSpec.groovy
new file mode 100644
index 00000000..19d98c6f
--- /dev/null
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/codegen/GenerateProtoExtensionsTaskSpec.groovy
@@ -0,0 +1,40 @@
+package dev.buijs.klutter.kore.tasks.codegen
+
+import spock.lang.Specification
+
+import java.nio.file.Files
+
+class GenerateProtoExtensionsTaskSpec extends Specification {
+
+ def "Verify protobuf extension methods are generated correctly"() {
+
+ given:
+ def source = Files.createTempDirectory("").toFile()
+ def kotlin = source.toPath().resolve("com/example/my_plugin/platform").toFile()
+ kotlin.mkdirs()
+
+ when:
+ new GenerateProtoExtensionsTask(source, ["com.example.my_plugin.platform.MyGreeting"]).run()
+
+ then:
+ def generatedFile = kotlin.toPath().resolve("${GenerateProtoExtensionsTaskKt.protoGenMarker}MyGreeting.kt").toFile()
+ generatedFile.exists()
+ println(generatedFile.text)
+ generatedFile.text == """package com.example.my_plugin.platform
+
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.decodeFromByteArray
+import kotlinx.serialization.encodeToByteArray
+import kotlinx.serialization.protobuf.ProtoBuf
+
+@OptIn(ExperimentalSerializationApi::class)
+fun MyGreeting.encodeMyGreetingToByteArray(): ByteArray =
+ ProtoBuf.encodeToByteArray(this)
+
+@OptIn(ExperimentalSerializationApi::class)
+fun decodeByteArrayToMyGreeting(byteArray: ByteArray): MyGreeting =
+ ProtoBuf.decodeFromByteArray(byteArray)"""
+
+ }
+
+}
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ActionInitKlutterSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ActionInitKlutterSpec.groovy
index 445b9de9..33518b73 100644
--- a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ActionInitKlutterSpec.groovy
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ActionInitKlutterSpec.groovy
@@ -76,7 +76,7 @@ class ActionInitKlutterSpec extends Specification {
def setupSpec() {
validRootFolder = Either.ok(root)
validPluginName = Either.ok(pluginName)
- config = new Config(new Dependencies(), "2023.x.y", null)
+ config = new Config(new Dependencies(), "2023.x.y", null, null)
klutterYaml = root.toPath().resolve("my_plugin/kradle.yaml").toFile()
plugin.mkdirs()
example.mkdirs()
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/GenerateCodeTaskSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/GenerateCodeTaskSpec.groovy
index 73a11b0a..8d79d629 100644
--- a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/GenerateCodeTaskSpec.groovy
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/GenerateCodeTaskSpec.groovy
@@ -21,29 +21,13 @@
*/
package dev.buijs.klutter.kore.tasks.project
-import dev.buijs.klutter.kore.ast.Controller
-import dev.buijs.klutter.kore.ast.CustomType
-import dev.buijs.klutter.kore.ast.Method
-import dev.buijs.klutter.kore.ast.RequestScopedBroadcastController
-import dev.buijs.klutter.kore.ast.RequestScopedSimpleController
-import dev.buijs.klutter.kore.ast.SingletonBroadcastController
-import dev.buijs.klutter.kore.ast.SingletonSimpleController
-import dev.buijs.klutter.kore.ast.SquintCustomType
-import dev.buijs.klutter.kore.ast.SquintCustomTypeMember
-import dev.buijs.klutter.kore.ast.SquintMessageSource
-import dev.buijs.klutter.kore.ast.StringType
-import dev.buijs.klutter.kore.ast.TypeMember
-import dev.buijs.klutter.kore.ast.UnitType
+import dev.buijs.klutter.kore.ast.*
import dev.buijs.klutter.kore.common.Either
-import dev.buijs.klutter.kore.project.FlutterDistributionFolderName
-import dev.buijs.klutter.kore.project.FlutterDistributionKt
import dev.buijs.klutter.kore.project.ProjectKt
import dev.buijs.klutter.kore.project.PubspecBuilder
import dev.buijs.klutter.kore.tasks.ExecutorKt
import dev.buijs.klutter.kore.tasks.codegen.GenerateCodeOptions
import dev.buijs.klutter.kore.tasks.codegen.GenerateCodeTaskKt
-import dev.buijs.klutter.kore.tasks.project.ActionDownloadFlutterKt
-import dev.buijs.klutter.kore.tasks.project.ProjectBuilderTask
import spock.lang.Shared
import spock.lang.Specification
@@ -107,13 +91,16 @@ class GenerateCodeTaskSpec extends Specification {
def flutterPubGet = flutterExe + " pub get"
@Shared
- def klutterProducerInit = flutterExe + " pub run klutter:producer init bom=2023.3.1.beta flutter=3.0.5.macos.arm64"
+ def klutterProducerInit = flutterExe + " pub run klutter:kradle init bom=2024.1.1.beta flutter=3.0.5.macos.arm64"
@Shared
- def klutterConsumerInit = flutterExe + " pub run klutter:consumer init"
+ def klutterConsumerInit = flutterExe + " pub run klutter:kradle init"
@Shared
- def klutterConsumerAdd = flutterExe + " pub run klutter:consumer add lib=my_awesome_plugin"
+ def klutterConsumerInitIOS = flutterExe + " pub run klutter:kradle init ios=13"
+
+ @Shared
+ def klutterConsumerAdd = flutterExe + " pub run klutter:kradle add lib=my_awesome_plugin"
@Shared
def iosPodUpdate = "pod update"
@@ -183,6 +170,7 @@ class GenerateCodeTaskSpec extends Specification {
executor.putExpectation(pathToPlugin, klutterProducerInit)
executor.putExpectation(pathToExample, klutterConsumerInit)
executor.putExpectation(pathToExample, klutterConsumerAdd)
+ executor.putExpectation(pathToExample, klutterConsumerInitIOS)
executor.putExpectation(pathToExampleIos, iosPodUpdate)
executor.putExpectation(pathToExampleIos, iosPodInstall)
sut.run()
@@ -224,6 +212,7 @@ class GenerateCodeTaskSpec extends Specification {
def project = ProjectKt.plugin(pathToPlugin)
def pubspec = PubspecBuilder.toPubspec(rootPubspecYamlFile)
def srcFolder = project.root.pathToLibFolder.toPath().resolve("src")
+ Path.of(pathToPlugin).resolve("platform/src/commonMain").toFile().mkdirs()
and:
executor.putExpectation(pathToPlugin, flutterExe + " pub get")
@@ -244,7 +233,7 @@ class GenerateCodeTaskSpec extends Specification {
and:
GenerateCodeTaskKt.toGenerateCodeTask(new GenerateCodeOptions(
- project, pubspec, "3.0.5.macos.arm64", false, controllers, messages, { println("$it") })).run()
+ project, pubspec, "3.0.5.macos.arm64", false, controllers, messages, [],{ println("$it") })).run()
then:
def flutterLib = project.root.pathToLibFile
@@ -283,9 +272,9 @@ dependencies:
sdk: flutter
squint_json: ^0.1.2
- klutter_ui: ^1.0.1
+ klutter_ui: ^1.1.0
dev_dependencies:
- klutter: ^2.0.0
+ klutter: ^2.1.0
flutter:
plugin:
platforms:
@@ -311,13 +300,13 @@ dependencies:
my_awesome_plugin:
path: ../
- klutter_ui: ^1.0.1
+ klutter_ui: ^1.1.0
squint_json: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
- klutter: ^2.0.0
+ klutter: ^2.1.0
flutter:
uses-material-design: true
"""
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ProjectBuilderTaskSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ProjectBuilderTaskSpec.groovy
index a0e9ff75..c089c364 100644
--- a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ProjectBuilderTaskSpec.groovy
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/tasks/project/ProjectBuilderTaskSpec.groovy
@@ -23,10 +23,8 @@ package dev.buijs.klutter.kore.tasks.project
import dev.buijs.klutter.kore.common.Either
import dev.buijs.klutter.kore.project.ProjectKt
-import dev.buijs.klutter.kore.test.TestUtil
-import dev.buijs.klutter.kore.tasks.Executor
import dev.buijs.klutter.kore.tasks.ExecutorKt
-import dev.buijs.klutter.kore.tasks.project.ProjectBuilderTask
+import dev.buijs.klutter.kore.test.TestUtil
import spock.lang.Shared
import spock.lang.Specification
@@ -86,13 +84,16 @@ class ProjectBuilderTaskSpec extends Specification {
def flutterPubGet = flutterExe + " pub get"
@Shared
- def klutterProducerInit = flutterExe + " pub run klutter:producer init bom=2023.3.1.beta flutter=3.0.5.macos.arm64"
+ def klutterProducerInit = flutterExe + " pub run klutter:kradle init bom=2024.1.1.beta flutter=3.0.5.macos.arm64"
+
+ @Shared
+ def klutterConsumerInit = flutterExe + " pub run klutter:kradle init"
@Shared
- def klutterConsumerInit = flutterExe + " pub run klutter:consumer init"
+ def klutterConsumerInitIOS = flutterExe + " pub run klutter:kradle init ios=13"
@Shared
- def klutterConsumerAdd = flutterExe + " pub run klutter:consumer add lib=my_awesome_plugin"
+ def klutterConsumerAdd = flutterExe + " pub run klutter:kradle add lib=my_awesome_plugin"
@Shared
def iosPodUpdate = "pod update"
@@ -128,6 +129,7 @@ class ProjectBuilderTaskSpec extends Specification {
executor.putExpectation(pathToExample, flutterPubGet)
executor.putExpectation(pathToPlugin, klutterProducerInit)
executor.putExpectation(pathToExample, klutterConsumerInit)
+ executor.putExpectation(pathToExample, klutterConsumerInitIOS)
executor.putExpectation(pathToExample, klutterConsumerAdd)
executor.putExpectation(pathToExampleIos, iosPodUpdate)
executor.putExpectation(pathToExampleIos, iosPodInstall)
@@ -208,9 +210,10 @@ class ProjectBuilderTaskSpec extends Specification {
sdk: flutter
squint_json: ^0.1.2
- klutter_ui: ^1.0.1
+ klutter_ui: ^1.1.0
+ protobuf: ^3.1.0
dev_dependencies:
- klutter: ^2.0.0
+ klutter: ^2.1.0
flutter:
plugin:
platforms:
@@ -237,13 +240,13 @@ class ProjectBuilderTaskSpec extends Specification {
my_awesome_plugin:
path: ../
- klutter_ui: ^1.0.1
+ klutter_ui: ^1.1.0
squint_json: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
- klutter: ^2.0.0
+ klutter: ^2.1.0
flutter:
uses-material-design: true
"""
@@ -264,13 +267,13 @@ class ProjectBuilderTaskSpec extends Specification {
my_awesome_plugin:
path: ../
- klutter_ui: ^1.0.1
+ klutter_ui: ^1.1.0
squint_json: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
- klutter: ^2.0.0
+ klutter: ^2.1.0
flutter:
uses-material-design: true
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/AndroidAdapterSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/AndroidAdapterSpec.groovy
index f23cf25b..e9ce2f52 100644
--- a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/AndroidAdapterSpec.groovy
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/AndroidAdapterSpec.groovy
@@ -302,7 +302,7 @@ class SuperPlugin: FlutterPlugin, MethodCallHandler, StreamHandler, ActivityAwar
def "Verify emptySet is used when there are no method channels"() {
given:
- def adapter = new AndroidAdapter("", "", Set.of(), Set.of(), Set.of())
+ def adapter = new AndroidAdapter("", "", false, Set.of(), Set.of(), Set.of())
expect:
with(adapter.print()) { content ->
@@ -315,7 +315,7 @@ class SuperPlugin: FlutterPlugin, MethodCallHandler, StreamHandler, ActivityAwar
given:
def methodReturningVoid = createMethod(new StringType(), new UnitType())
def controllerWithMethod = new SingletonSimpleController("foo.bar", "MySingleton", [methodReturningVoid])
- def adapter = new AndroidAdapter("", "", Set.of("foo/bar"), Set.of(), Set.of(controllerWithMethod))
+ def adapter = new AndroidAdapter("", "", false,Set.of("foo/bar"), Set.of(), Set.of(controllerWithMethod))
expect:
with(adapter.print()) { content ->
@@ -402,6 +402,7 @@ class SuperPlugin: FlutterPlugin, MethodCallHandler, StreamHandler, ActivityAwar
new AndroidAdapter(
packageName,
pluginName,
+ false,
channels,
streams,
controllers
diff --git a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/flutter/PublisherWidgetSpec.groovy b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/flutter/PublisherWidgetSpec.groovy
index 0668e869..356e3dd7 100644
--- a/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/flutter/PublisherWidgetSpec.groovy
+++ b/lib/kore/src/test/groovy/dev/buijs/klutter/kore/template/flutter/PublisherWidgetSpec.groovy
@@ -38,7 +38,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
null,
new FlutterMessageType(new StringType()),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
@@ -53,7 +54,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
null,
new FlutterMessageType(new CustomType("MyType", "foo.example", [])),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
@@ -68,7 +70,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
new FlutterMessageType(new StringType()),
new FlutterMessageType(new StringType()),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
@@ -83,7 +86,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
new FlutterMessageType(new CustomType("MyType", "foo.example", [])),
new FlutterMessageType(new CustomType("MyOtherType", "foo.example", [])),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
@@ -98,7 +102,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
new FlutterMessageType(new StringType()),
new FlutterMessageType(new CustomType("MyType", "foo.example", [])),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
@@ -113,7 +118,8 @@ class PublisherWidgetSpec extends Specification {
new FlutterExtension("SayWhatNow"),
new FlutterMessageType(new CustomType("MyType", "foo.example", [])),
new FlutterMessageType(new StringType()),
- new FlutterMethod("getSayWhat")
+ new FlutterMethod("getSayWhat"),
+ false
)
expect:
diff --git a/lib/kradle/build.gradle.kts b/lib/kradle/build.gradle.kts
deleted file mode 100644
index 8cf2db56..00000000
--- a/lib/kradle/build.gradle.kts
+++ /dev/null
@@ -1,96 +0,0 @@
-@file:Suppress("VulnerableLibrariesLocal")
-plugins {
- kotlin("jvm")
- id("klutter")
- id("groovy")
- id("org.jetbrains.kotlin.plugin.allopen") version "1.8.21"
-}
-
-group = "dev.buijs.klutter"
-
-allOpen {
- annotation("dev.buijs.klutter.kradle.Open4Test")
-}
-
-java {
- withJavadocJar()
- withSourcesJar()
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
-sourceSets {
- main {
- java {
- srcDirs("${projectDir.absolutePath}/src/main/kotlin")
- }
- }
-
- test {
- java {
- srcDirs(
- "${projectDir.absolutePath}/src/test/kotlin",
- "${projectDir.absolutePath}/src/test/groovy"
- )
- }
-
- }
-}
-
-dependencies {
- // Klutter
- implementation(project(":lib:kore"))
-
- // CLI
- implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.5")
- implementation("com.github.kotlin-inquirer:kotlin-inquirer:0.1.0")
-
- // Logging
- implementation("org.slf4j:slf4j-api:2.0.7")
- implementation("io.github.microutils:kotlin-logging:3.0.5")
-
- // Test
- testImplementation("io.kotlintest:kotlintest-runner-junit5:3.4.2")
-
- // T-t-t-t-testing !
- testImplementation(project(":lib-test"))
- testImplementation("org.spockframework:spock-core")
-}
-
-tasks.withType {
- useJUnitPlatform()
-}
-
-tasks.withType {
- applicationName = "kradlew"
-}
-
-tasks.register("kradleWrapperJar", Jar::class) {
- archiveBaseName.set("${project.name}-wrapper")
- duplicatesStrategy = DuplicatesStrategy.EXCLUDE
-
- manifest {
- attributes["Main-Class"] = "dev.buijs.klutter.kradle.MainKt"
- }
-
- from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
- with(tasks.jar.get() as CopySpec)
-}
-
-tasks.register("copyKradleWrapperJarToRoot", Copy::class) {
- from(project.projectDir.resolve("build/libs/kradle-wrapper.jar"))
- into(project.rootProject.rootDir.resolve("kradle/lib"))
-}
-
-tasks.register("copyKradleWrapperJarToResources", Copy::class) {
- from(project.projectDir.resolve("build/libs/kradle-wrapper.jar"))
- into(project.projectDir.resolve("src/main/resources"))
-}
-
-tasks.named("build") {
- setFinalizedBy(setOf("kradleWrapperJar"))
-}
-
-tasks.named("kradleWrapperJar") {
- setFinalizedBy(setOf("copyKradleWrapperJarToRoot", "copyKradleWrapperJarToResources"))
-}
\ No newline at end of file
diff --git a/lib/kradle/module.md b/lib/kradle/module.md
deleted file mode 100644
index 048bcafe..00000000
--- a/lib/kradle/module.md
+++ /dev/null
@@ -1,138 +0,0 @@
-# Kradle
-
-Executable tool to create a new independent [Klutter](https://github.com/buijs-dev/klutter) project.
-Create a new project with the click of a button without having any frameworks installed (including Flutter).
-
-Kradle can be used on any platform using the kraldew or kradlew.bat script.
-Running your Gradle and/or Flutter commands through the kradle-wrapper
-ensures you use the correct versions for these libraries. You can send commands
-through the kradle-wrapper directly or use the interactive wizard to configure.
-
-## Commands
-- [kradle](#kradle)
-- [gradle](#gradle)
-- [flutter](#flutter)
-
-### Kradle
-Kradle commands:
-- build
-- [clean](#clean)
-- [create](#create)
-- [get](#get)
-
-#### Build
-Build the iOS and Android artifacts and generate all boilerplate code.
-
-> Build is always required to run the app on a device when changes are done in the platform module.
-
-Example:
-```shell
-./kradlew build
-```
-
-#### Clean
-Options:
-- [cache](#cache)
-
-##### Cache
-Remove all files and/or folders from the kradle cache folder.
-The cache folder is by default set to user.home/.kradle/cache.
-It can be overwritten by setting the cache property in kradle.env.
-The kradle.env is stored next to the kradlew scripts.
-
-Default kradle.env cache setting:
-```properties
-cache={{system.user.home}}/.kradle/cache/
-```
-
-Example command:
-```shell
-./kradlew clean cache
-```
-
-#### Create
-Create a new Klutter project.
-
-Required arguments:
-- root: The root folder of the project.
-- name: The name of the project (and subsequently the Flutter plugin).
-- group: The group/organisation name of the project.
-- flutter: The Flutter distribution to use.
-
-Example:
-```shell
-./kradlew create --root "./" --name "my_plugin" --group "com.example" --flutter "3.10.6.macos.arm64"
-```
-
-##### Config (Optional)
-Path to config yaml. This yaml can be used to configure project versions and dependencies.
-
-Example yaml:
-```yaml
-bom-version: "2023.3.1.beta"
-flutter-version: "3.10.6"
-dependencies:
- klutter: "2.0.0"
- klutter_ui: "1.0.1"
- squint: "0.1.2"
- embedded:
- - "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0"
-```
-
-Example command:
-```shell
-./kradlew create --config "./foo/bar/kradle.yaml" --root "./" --name "my_plugin" --group "com.example" --flutter "3.10.6.macos.arm64"
-```
-
-#### Get
-Get project dependencies and store them in the kradle cache.
-Options:
-- [flutter](#get-flutter)
-
-##### Get Flutter
-Get a Flutter distribution which is compatible with Klutter.
-Options:
-- [dist](#Dist)
-- [overwrite](#Overwrite)
-
-###### Dist
-The distribution to download in format major.minor.patch.platform.architecture.
-
-Example command:
-```shell
-./kradlew get flutter --dist "3.10.6.windows.x64"
-```
-
-###### Overwrite
-Overwrite any existing distribution if present.
-
-Example which overwrites any existing distribution:
-```shell
-./kradlew get flutter --dist "3.10.6.windows.x64" --overwrite
-```
-
-### Gradle
-Gradle commands can be executed by using the -g argument.
-
-```shell
-# Run gradle clean build in the folder /platform.
-./kradlew -g clean build -p "platform"
-```
-
-### Flutter
-Flutter commands can be executed by using the -f argument.
-
-```shell
-# Run flutter doctor command.
-./kradlew -f doctor
-```
-
-## Wizard
-When no argument is given then the interactive wizard is started.
-
-```shell
-./kradlew
-```
-
-
-// TODO wizard UI options etc.
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/Main.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/Main.kt
deleted file mode 100644
index 92b1d9ef..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/Main.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle
-
-import dev.buijs.klutter.kore.project.klutterBomVersion
-import dev.buijs.klutter.kradle.command.getNewProjectOptions
-import dev.buijs.klutter.kradle.shared.*
-import dev.buijs.klutter.kradle.shared.createNewProject
-import dev.buijs.klutter.kradle.shared.execFlutterCommand
-import dev.buijs.klutter.kradle.shared.execGradleCommand
-import dev.buijs.klutter.kradle.wizard.mrWizard
-import java.nio.file.Paths
-
-fun main(args: Array) {
- println("""
- ════════════════════════════════════════════
- KRADLE (v$klutterBomVersion)
- ════════════════════════════════════════════
- """)
-
- val currentFolder = Paths.get("").toAbsolutePath().toFile()
-
- val first: (Array) -> MutableList = {
- args.toMutableList().also { it.removeFirst() }
- }
-
- when {
- args.isEmpty() -> mrWizard.runWizard(currentFolder)
-
- args.firstOrNull() == "-g" ->
- first(args).execGradleCommand(currentFolder)
-
- args.firstOrNull() == "-f" ->
- first(args).execFlutterCommand(currentFolder)
-
- args.firstOrNull() == "build" ->
- build(currentFolder)
-
- args.firstOrNull() == "clean" ->
- first(args).clean()
-
- args.firstOrNull() == "create" ->
- first(args).getNewProjectOptions().createNewProject()
-
- args.firstOrNull() == "get" ->
- first(args).getDependency()
-
- else -> println("I don't know what to do. Please try again!")
- }
-
-}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/GetFlutterCommand.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/GetFlutterCommand.kt
deleted file mode 100644
index d81e0022..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/GetFlutterCommand.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.command
-
-import dev.buijs.klutter.kore.project.*
-import dev.buijs.klutter.kore.tasks.project.DownloadFlutterTask
-import kotlinx.cli.ArgParser
-
-private const val distributionDescription = "Flutter distribution in format major.minor.patch.platform.architecture (example: 3.0.5.windows.x64)."
-
-private const val forceDescription = "Set to true to delete existing Flutter distribution."
-
-internal fun List.downloadFlutterByCommand() =
- toTypedArray().downloadFlutterByCommand()
-
-internal fun Array.downloadFlutterByCommand() =
- GetFlutterCommand(parser = ArgParser("klutter"), args = this).downloadOrFail()
-
-private fun GetFlutterCommand.downloadOrFail() {
- val version = flutterDistribution
- val overwrite = overwriteExistingDistribution
- println("Will download Flutter ${version.prettyPrintedString}")
- if(overwrite) {
- println("Will delete existing Flutter ${version.prettyPrintedString} if present")
- } else {
- println("Will abort if Flutter ${version.prettyPrintedString} is present")
- }
- DownloadFlutterTask(flutterDistribution, overwriteExistingDistribution).run()
- println("Finished get command")
-}
-
-private class GetFlutterCommand(parser: ArgParser, args: Array) {
-
- private val dist by parser required distributionDescription
-
- private val overwrite by parser optionalBoolean forceDescription
-
- init {
- parser.parse(args)
- }
-
- val flutterDistribution: FlutterDistribution
- get() = FlutterDistributionFolderName(dist).flutterDistribution
-
- val overwriteExistingDistribution: Boolean
- get() = overwrite ?: false
-
-}
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/NewProjectCommand.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/NewProjectCommand.kt
deleted file mode 100644
index e525e910..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/command/NewProjectCommand.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.command
-
-import dev.buijs.klutter.kore.project.*
-import dev.buijs.klutter.kore.tasks.project.*
-import dev.buijs.klutter.kradle.shared.NewProjectInput
-import kotlinx.cli.ArgParser
-import java.io.File
-
-private const val rootDescription = "Path to root folder"
-
-private const val groupDescription = "Groupname (organisation)"
-
-private const val nameDescription = "Name of app (plugin)"
-
-private const val configDescription = "Path to kradle.yaml"
-
-private const val flutterDescription = "Flutter SDK version (format: major.minor.patch.platform.architecture, example: 3.10.6.macos.arm64)"
-
-internal fun List.getNewProjectOptions(): ProjectBuilderOptions =
- toTypedArray().getNewProjectOptions()
-
-internal fun Array.getNewProjectOptions(): ProjectBuilderOptions =
- NewProjectCommand(parser = ArgParser("klutter"), args = this).toProjectBuilderOptions()
-
-private fun NewProjectCommand.toProjectBuilderOptions(): ProjectBuilderOptions =
- ProjectBuilderOptions(
- rootFolder = rootFolder,
- groupName = groupName,
- pluginName = pluginName,
- flutterDistributionString = flutterDistributionFolderName,
- config = configOrNull)
-
-private class NewProjectCommand(parser: ArgParser, args: Array): NewProjectInput {
-
- private val root by parser required rootDescription
-
- private val name by parser required nameDescription
-
- private val group by parser required groupDescription
-
- private val flutter by parser required flutterDescription
-
- private val config by parser optional configDescription
-
- init {
- parser.parse(args)
- }
-
- override val rootFolder: RootFolder
- get() = toRootFolder(root)
-
- override val groupName: GroupName
- get() = toGroupName(group)
-
- override val pluginName: PluginName
- get() = toPluginName(name)
-
- override val flutterDistributionFolderName: FlutterDistributionFolderName
- get() = FlutterDistributionFolderName(flutter)
-
- override val configOrNull: Config?
- get() = config?.let { File(it).toConfigOrNull() }
-
-}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecFlutterCommand.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecFlutterCommand.kt
deleted file mode 100644
index b405b077..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecFlutterCommand.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.shared
-
-import dev.buijs.klutter.kore.KlutterException
-import dev.buijs.klutter.kore.project.*
-import dev.buijs.klutter.kore.tasks.finish
-import java.io.File
-
-internal fun List.execFlutterCommand(currentFolder: File): String =
- toTypedArray().execFlutterCommand(currentFolder)
-
-internal fun Array.execFlutterCommand(currentFolder: File): String {
- val flutter = findFlutterDistributionOrThrow(currentFolder)
- return this.let { args ->
- ProcessBuilder()
- .command(buildList {
- if(isWindows) {
- add("cmd.exe")
- add("/c")
- }
-
- add(flutter)
- addAll(args)
- })
- .directory(currentFolder)
- .inheritIO()
- .start()
- .finish(30L)
- }
-}
-
-private fun findFlutterDistributionOrThrow(currentFolder: File): String {
- val version = currentFolder
- .resolve("kradle.yaml")
- .resolveProjectPropertiesOrThrow()
- .resolveSystemPropertiesOrThrow()
- .readText()
- .let { findFlutterVersionInKradleYamlOrNull(it) }
- ?.let { version ->
- version.split(".").let { parts ->
- Version(parts[0].toInt(), parts[1].toInt(), parts[2].toInt())
- }
- } ?: throw KlutterException("Failed to determine Flutter version from kradle.yaml")
-
- val distribution = FlutterDistributionFolderName("${version.prettyPrint}.${currentOperatingSystem.value}.${currentArchitecture.name}")
- return flutterExecutable(distribution).absolutePath
-}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecGradleCommand.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecGradleCommand.kt
deleted file mode 100644
index c0b11e90..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/shared/ExecGradleCommand.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.shared
-
-import dev.buijs.klutter.kore.project.isWindows
-import dev.buijs.klutter.kore.tasks.finish
-import java.io.File
-
-internal fun List.execGradleCommand(currentFolder: File): String =
- toTypedArray().execGradleCommand(currentFolder)
-
-internal fun Array.execGradleCommand(currentFolder: File): String = this.let { args ->
- ProcessBuilder()
- .command(buildList {
- if(isWindows) {
- add("cmd.exe")
- add("/c")
- }
-
- add(currentFolder.resolve("gradlew").absolutePath)
- addAll(args)
- })
- .directory(currentFolder)
- .inheritIO()
- .start()
- .finish(30L)
-}
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/GetFlutterWizard.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/GetFlutterWizard.kt
deleted file mode 100644
index 48cf1c94..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/GetFlutterWizard.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.wizard
-
-import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
-import dev.buijs.klutter.kore.project.*
-import dev.buijs.klutter.kore.tasks.project.DownloadFlutterTask
-import java.io.File
-import java.nio.file.Paths
-import kotlin.io.path.absolutePathString
-
-@ExcludeFromJacocoGeneratedReport
-internal fun getFlutterWizard() {
- val distribution = askForFlutterVersion().let { version ->
- PrettyPrintedFlutterDistribution(version).flutterDistribution
- }
-
- val target = askForDownloadFolder()
-
- val overwrite = mrWizard.promptConfirm(
- message = "Delete the existing SDK distribution if it exists?",
- default = false)
- println("Downloading Flutter SDK...")
- DownloadFlutterTask(distribution, overwrite, target).run()
- println("Finished!")
-}
-
-private fun askForDownloadFolder(): File? {
- val cache = "Default cache"
- val other = "Other (specify)"
- val cacheOrOther = mrWizard.promptList(
- hint = "press Enter to pick",
- message = "Where to store the Flutter SDK distribution?",
- choices = listOf(cache, other))
-
- /**
- * Return null if cache is to be used,
- * so that DownloadFlutterTask automatically uses its default configuration.
- */
- if(cacheOrOther == cache) return null
-
- var file: File
- do {
- val path = mrWizard.promptInput(
- message = "Please specify a download folder.",
- default = Paths.get("").absolutePathString())
- file = File(path)
- } while(!file.exists())
- return file
-}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/MrWizard.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/MrWizard.kt
deleted file mode 100644
index fa72941d..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/MrWizard.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.wizard
-
-import com.github.kinquirer.KInquirer
-import com.github.kinquirer.components.promptConfirm
-import com.github.kinquirer.components.promptInput
-import com.github.kinquirer.components.promptList
-import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
-import dev.buijs.klutter.kradle.command.Open4Test
-import dev.buijs.klutter.kradle.shared.build
-import dev.buijs.klutter.kradle.shared.clean
-import dev.buijs.klutter.kradle.shared.createNewProject
-import java.io.File
-
-internal var mrWizard: Wizard = MrWizard()
-
-@Open4Test
-@ExcludeFromJacocoGeneratedReport(
- reason = "KInquirer can't be mocked/stubbed")
-internal open class MrWizard(private val inquirer: KInquirer = KInquirer): Wizard {
- override fun promptInput(message: String, default: String) =
- inquirer.promptInput(message = message, default = default)
-
- override fun promptConfirm(message: String, default: Boolean) =
- inquirer.promptConfirm(message = message, default = default)
-
- override fun promptList(hint: String, message: String, choices: List) =
- inquirer.promptList(hint = hint, message = message, choices = choices)
-
-}
-
-internal interface Wizard {
- fun promptInput(message: String, default: String): String
-
- fun promptConfirm(message: String, default: Boolean): Boolean
-
- fun promptList(hint: String, message: String, choices: List): String
-
- fun runWizard(currentFolder: File) {
- var chosen: WizardAction
- do {
- chosen = askForWizardAction()
- chosen.action(currentFolder)
- } while(chosen != WizardAction.EXIT)
- }
-
- fun askForWizardAction(): WizardAction {
- val chosen: String = promptList(
- hint = "press Enter to pick",
- message = "What do you want to do?",
- choices = WizardAction.values().map { it.prettyPrinted })
- return WizardAction.values().first { it.prettyPrinted == chosen }
- }
-}
-
-internal enum class WizardAction(val prettyPrinted: String, val action: (currentFolder: File) -> Unit) {
- NEW_PROJECT(
- prettyPrinted = "New: Project",
- action = { getNewProjectOptionsByUserInput().confirmNewProjectOptions()?.createNewProject() }),
- GET_FLUTTER_SDK(
- prettyPrinted = "Download: Flutter SDK",
- action = { getFlutterWizard() }),
- CLEAN_CACHE(
- prettyPrinted = "Clean: Klutter Cache",
- action = { mutableListOf("cache").clean() }),
- BUILD_APP(
- prettyPrinted = "Build: App",
- action = { folder -> build(folder) }),
- EXIT(
- prettyPrinted = "Exit",
- action = { })
-}
\ No newline at end of file
diff --git a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/NewProjectWizard.kt b/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/NewProjectWizard.kt
deleted file mode 100644
index 0acc605f..00000000
--- a/lib/kradle/src/main/kotlin/dev/buijs/klutter/kradle/wizard/NewProjectWizard.kt
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle.wizard
-
-import dev.buijs.klutter.kore.common.EitherNok
-import dev.buijs.klutter.kore.common.EitherOk
-import dev.buijs.klutter.kore.common.ExcludeFromJacocoGeneratedReport
-import dev.buijs.klutter.kore.project.*
-import dev.buijs.klutter.kore.tasks.project.*
-import dev.buijs.klutter.kradle.shared.NewProjectInput
-import java.io.File
-import java.nio.file.Path
-import java.nio.file.Paths
-import kotlin.io.path.absolutePathString
-
-private const val groupMessage = "Enter Groupname (organisation):"
-
-private const val groupDefault = "com.example"
-
-private const val nameMessage = "Enter Plugin name:"
-
-private const val nameDefault = "my_plugin"
-
-private const val createProjectInCurrentFolderMessage = "Create project in current folder?"
-
-private const val createProjectInCurrentFolderDefault = true
-
-private const val projectFolderPathMessage = "Enter path where to create the project:"
-
-private const val projectFolderPathDefault = ""
-
-@ExcludeFromJacocoGeneratedReport
-internal fun getNewProjectOptionsByUserInput(): ProjectBuilderOptions =
- NewProjectWizard().toProjectBuilderOptions()
-
-internal fun ProjectBuilderOptions.confirmNewProjectOptions(): ProjectBuilderOptions? {
- println(" Confirm project details")
- println(" - Plugin Name: ${pluginName.validPluginNameOrThrow()}")
- println(" - Group Name: ${groupName.validPluginNameOrThrow()}")
- println(" - Flutter: $flutterDistributionString")
- println(" - Dependencies:")
- println(" - klutter: ${config?.dependencies?.klutter ?: klutterPubVersion}")
- println(" - klutter_ui: ${config?.dependencies?.klutterUI ?: klutterUIPubVersion}")
- println(" - squint_json: ${config?.dependencies?.squint ?: squintPubVersion}")
- println(" - bom: ${config?.bomVersion ?: klutterBomVersion}")
- println("")
- val confirmed = mrWizard.promptConfirm(message = "Create project?", default = true)
- return if(confirmed) this else null
-}
-
-internal class NewProjectWizard(
- override val rootFolder: RootFolder =
- RootFolderQuestion().ask(),
-
- override val groupName: GroupName =
- toGroupName(askForGroupName()),
-
- override val pluginName: PluginName =
- toPluginName(askForPluginName()),
-
- private val prettyPrintedFlutterDistribution: String =
- askForFlutterVersion(),
-
- override val configOrNull: Config? =
- askForConfig(),
-
- ) : NewProjectInput {
- override val flutterDistributionFolderName: FlutterDistributionFolderName
- get() = PrettyPrintedFlutterDistribution(prettyPrintedFlutterDistribution).flutterDistribution.folderNameString
-}
-
-private fun NewProjectWizard.toProjectBuilderOptions(): ProjectBuilderOptions =
- ProjectBuilderOptions(
- rootFolder = rootFolder,
- groupName = groupName,
- pluginName = pluginName,
- flutterDistributionString = flutterDistributionFolderName,
- config = configOrNull)
-
-private fun askForGroupName(): String =
- mrWizard.promptInput(message = groupMessage, default = groupDefault)
-
-private fun askForPluginName(): String =
- mrWizard.promptInput(message = nameMessage, default = nameDefault)
-
-private class RootFolderQuestion {
- private var rootFolder: RootFolder? = null
-
- fun ask(): RootFolder {
- rootFolder = toRootFolder(askForRootFolder())
- if(rootFolder is EitherOk)
- return rootFolder!!
-
- if(rootFolder is EitherNok)
- println((rootFolder as EitherNok).data)
-
- return ask()
- }
-}
-
-private fun askForRootFolder(): String {
- val useCurrentFolder = mrWizard.promptConfirm(
- message = createProjectInCurrentFolderMessage,
- default = createProjectInCurrentFolderDefault
- )
-
- if(useCurrentFolder)
- return Path.of("").absolutePathString()
-
- return mrWizard.promptInput(
- message = projectFolderPathMessage,
- default = Paths.get(projectFolderPathDefault).absolutePathString())
-}
-
-private fun askForConfig(): Config? {
- val useConfig = mrWizard.promptConfirm(
- message = "Configure dependencies?",
- default = false)
-
- if(!useConfig) return null
-
- val klutter = askForSource(
- name = "klutter",
- stableVersion = klutterPubVersion,
- gitUrl = "https://github.com/buijs-dev/klutter-dart.git@develop")
-
- val klutterUI = askForSource(
- name = "klutter_ui",
- stableVersion = klutterUIPubVersion,
- gitUrl = "https://github.com/buijs-dev/klutter-dart-ui.git@develop")
-
- val squint = askForSource(
- name = "squint_json",
- stableVersion = squintPubVersion,
- gitUrl = "https://github.com/buijs-dev/squint.git@develop")
-
- val bomVersion = askForKlutterGradleBomVersion()
-
- return Config(
- bomVersion = bomVersion,
- dependencies = Dependencies(
- klutter = klutter,
- klutterUI = klutterUI,
- squint = squint))
-}
-
-internal fun askForFlutterVersion(): String =
- mrWizard.promptList(
- hint = "press Enter to pick",
- message = "Select Flutter SDK version:",
- choices = flutterVersionsDescending(currentOperatingSystem).map { "${it.prettyPrintedString}" })
-
-private fun askForSource(name: String, stableVersion: String, gitUrl: String): String {
- val git = "Git@Develop"
- val pub = "Pub@^$stableVersion"
- val chosen = mrWizard.promptList(
- hint = "press Enter to pick",
- message = "Get $name source from:",
- choices = listOf(git, pub, "Local"))
- return when {
- chosen.startsWith(git) -> gitUrl
- chosen.startsWith("Local") -> "local@${askForPathToLocal(name = name)}"
- else -> stableVersion
- }
-}
-
-private fun askForPathToLocal(name: String): String = mrWizard.promptInput(
- message = "Enter path to $name (dart) library:",
- default = Paths.get("").absolutePathString())
-
-private fun askForKlutterGradleBomVersion(): String = mrWizard.promptInput(
- message = "Enter bill-of-materials version:",
- default = klutterBomVersion)
\ No newline at end of file
diff --git a/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/ByCommandSpec.groovy b/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/ByCommandSpec.groovy
deleted file mode 100644
index a23b0b5d..00000000
--- a/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/ByCommandSpec.groovy
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-package dev.buijs.klutter.kradle
-
-import dev.buijs.klutter.kradle.command.NewProjectCommandKt
-import spock.lang.Shared
-import spock.lang.Specification
-
-import java.nio.file.Files
-
-class ByCommandSpec extends Specification {
-
- @Shared
- File rootFolder = Files.createTempDirectory("").toFile()
-
- @Shared
- File flutterSDK = rootFolder.toPath().resolve("flutter").toFile()
-
- @Shared
- File configYaml = rootFolder.toPath().resolve("kradle.yaml").toFile()
-
- @Shared
- String overrideBomVersion = "9999.1.1.zeta"
-
- def setupSpec() {
- flutterSDK.mkdir()
- configYaml.createNewFile()
- configYaml.write("""
-bom-version: $overrideBomVersion
-""")
- }
-
- def "Verify specifying only required args returns ProjectBuilderOptions"() {
- given:
- def command = [
- "--root", rootFolder.path,
- "--group", "com.example",
- "--name", "my_awesome_plugin",
- "--flutter", "3.0.5.windows.X64",
- ]
-
- when:
- def options = NewProjectCommandKt.getNewProjectOptions(command)
-
- then:
- options.pluginName.data == "my_awesome_plugin"
- options.groupName.data == "com.example"
- options.rootFolder.data == rootFolder
- options.config == null
- }
-
- def "When config is specified and the File exists then ProjectBuilderOptions contains config"() {
- given:
- def command = [
- "--root", rootFolder.path, "" +
- "--group", "com.example",
- "--name", "my_awesome_plugin",
- "--flutter", "3.0.5.windows.X64",
- "--config", configYaml.absolutePath
- ]
-
- when:
- def options = NewProjectCommandKt.getNewProjectOptions(command)
-
- then:
- options.pluginName.data == "my_awesome_plugin"
- options.groupName.data == "com.example"
- options.rootFolder.data == rootFolder
- options.config != null
- options.config.bomVersion == overrideBomVersion
- }
-
-}
diff --git a/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/NewProjectWizardSpec.groovy b/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/NewProjectWizardSpec.groovy
deleted file mode 100644
index d0e1b024..00000000
--- a/lib/kradle/src/test/groovy/dev/buijs/klutter/kradle/NewProjectWizardSpec.groovy
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Copyright (c) 2021 - 2023 Buijs Software
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-//file:noinspection GroovyAssignabilityCheck
-package dev.buijs.klutter.kradle
-
-import dev.buijs.klutter.kore.project.PubspecBuilder
-import dev.buijs.klutter.kradle.wizard.MrWizard
-import dev.buijs.klutter.kradle.wizard.MrWizardKt
-import dev.buijs.klutter.kradle.wizard.NewProjectWizard
-import dev.buijs.klutter.kradle.wizard.NewProjectWizardKt
-import dev.buijs.klutter.kradle.wizard.Wizard
-import spock.lang.Shared
-import spock.lang.Specification
-import spock.lang.Stepwise
-
-import java.nio.file.Files
-
-@Stepwise
-class NewProjectWizardSpec extends Specification {
-
- @Shared
- File folder = Files.createTempDirectory("").toFile()
-
- def "Verify wizard asks for all required fields"() {
- given:
- def mrWizard = Stub(Wizard)
- MrWizardKt.mrWizard = mrWizard
-
- and: "ask for rootFolder"
- mrWizard.promptConfirm("Create project in current folder?", _) >> false
- mrWizard.promptInput("Enter path where to create the project:", _) >> folder.path
-
- and: "ask for groupName"
- mrWizard.promptInput("Enter Groupname (organisation):", _) >> "foo.boo.yay"
-
- and: "ask for pluginName"
- mrWizard.promptInput("Enter Plugin name:", _) >> "dummy_plugin"
-
- and: "ask for flutterPath"
- mrWizard.promptList(
- "press Enter to pick",
- "Select Flutter SDK version:",
- _
- ) >> "3.0.5 (macos ARM64)"
-
- and: "ask for configOrNull"
- mrWizard.promptConfirm("Configure dependencies?", _) >> false
-
- and: "ask for confirmation"
- mrWizard.promptConfirm("Create project?", _) >> true
-
- when:
- def options = NewProjectWizardKt.toProjectBuilderOptions(new NewProjectWizard())
-
- then:
- options != null
- }
-
- def "When specified RootFolder does NOT exist then MrWizard asks again"() {
- given:
- def index = 0
- def folders = ["doesNotExist", folder.path]
- def mrWizard = Mock(MrWizard) {
- 2 * it.promptInput("Enter path where to create the project:", _) >> {
- def rootFolder = folders[index]
- index+=1
- rootFolder
- }
- }
-
- and: "ask for groupName"
- mrWizard.promptInput("Enter Groupname (organisation):", _) >> "foo.boo.yay"
-
- and: "ask for pluginName"
- mrWizard.promptInput("Enter Plugin name:", _) >> "dummy_plugin"
-
- and: "ask for flutterPath"
- mrWizard.promptList(
- "press Enter to pick",
- "Select Flutter SDK version:",
- _
- ) >> "3.0.5 (macos ARM64)"
-
- and: "ask for configOrNull"
- mrWizard.promptConfirm("Configure dependencies?", _) >> false
-
- and:
- MrWizardKt.mrWizard = mrWizard
-
- and: "ask for rootFolder"
- mrWizard.promptConfirm("Create project in current folder?", _) >> false
-
- when:
- def options = NewProjectWizardKt.toProjectBuilderOptions(new NewProjectWizard())
-
- then:
- options != null
- }
-
- def "Verify wizard asks for all dependencies"() {
- given:
- def mrWizard = Mock(MrWizard)
- MrWizardKt.mrWizard = mrWizard
-
- and: "ask for rootFolder"
- mrWizard.promptConfirm("Create project in current folder?", _) >> false
- mrWizard.promptInput("Enter path where to create the project:", _) >> folder.path
-
- and: "ask for groupName"
- mrWizard.promptInput("Enter Groupname (organisation):", _) >> "foo.boo.yay"
-
- and: "ask for pluginName"
- mrWizard.promptInput("Enter Plugin name:", _) >> "dummy_plugin"
-
- and: "ask for flutterPath"
- mrWizard.promptList(
- "press Enter to pick",
- "Select Flutter SDK version:",
- _
- ) >> "3.0.5 (macos ARM64)"
-
- and: "ask for configOrNull"
- mrWizard.promptConfirm("Configure dependencies?", _) >> true
-
- and: "ask for squint_json"
- mrWizard.promptList(
- "press Enter to pick",
- "Get squint_json source from:",
- _
- ) >> "Git@Develop"
-
- and: "ask for klutter_ui"
- mrWizard.promptList(
- "press Enter to pick",
- "Get klutter_ui source from:",
- _
- ) >> "Local"
-
- and: "ask for klutter_ui local path"
- mrWizard.promptInput("Enter path to klutter_ui (dart) library:", _) >> null
-
- and: "ask for klutter"
- mrWizard.promptList(
- "press Enter to pick",
- "Get klutter source from:",
- _
- ) >> "Pub@^${PubspecBuilder.klutterPubVersion}"
-
- and: "ask for bom-version"
- mrWizard.promptInput("Enter bill-of-materials version:", _) >> "9999.x.y.z"
-
- when:
- def options = NewProjectWizardKt.toProjectBuilderOptions(new NewProjectWizard())
-
- then:
- options != null
- }
-}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 15cc610c..cee3413d 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -5,9 +5,8 @@ include(":lib:compiler")
include(":lib:gradle")
include(":lib:jetbrains")
include(":lib:kompose")
-include(":lib:kradle")
include(":lib:kore")
// Internal Testing library
include(":lib-test")
// Internal build properties
-includeBuild("lib-build")
+includeBuild("lib-build")
\ No newline at end of file
diff --git a/tools/build_publish_kore.compiler.gradle.sh b/tools/build_publish_kore.compiler.gradle.sh
new file mode 100644
index 00000000..2eaba630
--- /dev/null
+++ b/tools/build_publish_kore.compiler.gradle.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#stop script on failure
+set -e
+
+cd ".."
+
+echo " ____________
+< Publishing Klutter modules >
+ ------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||"
+
+./gradlew clean build -p "lib/kore"
+./gradlew clean build -p "lib/compiler"
+./gradlew clean build -p "lib/gradle"
+./gradlew publishToMavenLocal -p "lib/kore"
+./gradlew publishToMavenLocal -p "lib/compiler"
+./gradlew publishToMavenLocal -p "lib/gradle"
diff --git a/tools/kommand_build.sh b/tools/kommand_build.sh
deleted file mode 100644
index b7d38f7b..00000000
--- a/tools/kommand_build.sh
+++ /dev/null
@@ -1 +0,0 @@
-./gradlew clean distZip -p "./../lib/kommand"
\ No newline at end of file
diff --git a/tools/kommand_build_run.sh b/tools/kommand_build_run.sh
deleted file mode 100644
index 142739b3..00000000
--- a/tools/kommand_build_run.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-./gradlew clean distZip -p "./../lib/kradle"
-unzip ./../lib/kradle/build/distributions/kradle.zip -d ./build
-./build/kradle/bin/kradlew
\ No newline at end of file