Serialization plugin GSK build

Fixed issue when serialDesc property getter was generated, but backing field not.

Respect @Serializable(with=...) on property

Calling 3-arg readElementValue for support of custom contexts

Ability to nest context-based serializer

Migration to 1.2-Beta2

Use polymorphicSerializer prior to default

Don't use polymorphic serializers for all java classes

Docs and maven project update

Remove plugin runtime dependency on stdlib
This commit is contained in:
Leonid Startsev
2017-10-06 17:52:46 +03:00
parent 8a250b07df
commit f42767fcc2
21 changed files with 133 additions and 437 deletions
+2
View File
@@ -88,6 +88,7 @@ val commonLocalDataDir = "$rootDir/local"
val ideaSandboxDir = "$commonLocalDataDir/ideaSandbox" val ideaSandboxDir = "$commonLocalDataDir/ideaSandbox"
val ideaUltimateSandboxDir = "$commonLocalDataDir/ideaUltimateSandbox" val ideaUltimateSandboxDir = "$commonLocalDataDir/ideaUltimateSandbox"
val ideaPluginDir = "$distDir/artifacts/ideaPlugin/Kotlin" val ideaPluginDir = "$distDir/artifacts/ideaPlugin/Kotlin"
val serialPluginDir = "$distDir/artifacts/Serialization"
val ideaUltimatePluginDir = "$distDir/artifacts/ideaUltimatePlugin/Kotlin" val ideaUltimatePluginDir = "$distDir/artifacts/ideaUltimatePlugin/Kotlin"
val cidrPluginDir = "$distDir/artifacts/cidrPlugin/Kotlin" val cidrPluginDir = "$distDir/artifacts/cidrPlugin/Kotlin"
@@ -98,6 +99,7 @@ extra["commonLocalDataDir"] = project.file(commonLocalDataDir)
extra["ideaSandboxDir"] = project.file(ideaSandboxDir) extra["ideaSandboxDir"] = project.file(ideaSandboxDir)
extra["ideaUltimateSandboxDir"] = project.file(ideaUltimateSandboxDir) extra["ideaUltimateSandboxDir"] = project.file(ideaUltimateSandboxDir)
extra["ideaPluginDir"] = project.file(ideaPluginDir) extra["ideaPluginDir"] = project.file(ideaPluginDir)
extra["serialPluginDir"] = project.file(serialPluginDir)
extra["ideaUltimatePluginDir"] = project.file(ideaUltimatePluginDir) extra["ideaUltimatePluginDir"] = project.file(ideaUltimatePluginDir)
extra["cidrPluginDir"] = project.file(cidrPluginDir) extra["cidrPluginDir"] = project.file(cidrPluginDir)
extra["isSonatypeRelease"] = false extra["isSonatypeRelease"] = false
+3 -2
View File
@@ -11,7 +11,7 @@ dependencies {
compileOnly(project(":idea:idea-jvm")) compileOnly(project(":idea:idea-jvm"))
compile(intellijDep()) compile(intellijDep())
runtimeOnly(files(toolsJar())) runtimeOnly(files(toolsJar()))
} }
@@ -19,5 +19,6 @@ val ideaPluginDir: File by rootProject.extra
val ideaSandboxDir: File by rootProject.extra val ideaSandboxDir: File by rootProject.extra
runIdeTask("runIde", ideaPluginDir, ideaSandboxDir) { runIdeTask("runIde", ideaPluginDir, ideaSandboxDir) {
dependsOn(":dist", ":ideaPlugin") // TODO: add serialization plugin to pluginDir
dependsOn(":dist", ":ideaPlugin", ":kotlinx-serialization-compiler-plugin:dist")
} }
@@ -11,14 +11,13 @@
<serialization.maven.plugin.resources>${basedir}/src/main/resources</serialization.maven.plugin.resources> <serialization.maven.plugin.resources>${basedir}/src/main/resources</serialization.maven.plugin.resources>
<serialization.target-src>${basedir}/target/src/main/kotlin</serialization.target-src> <serialization.target-src>${basedir}/target/src/main/kotlin</serialization.target-src>
<serialization.target-resources>${basedir}/target/resource</serialization.target-resources> <serialization.target-resources>${basedir}/target/resource</serialization.target-resources>
<kotlin.version>1.1-SNAPSHOT</kotlin.version> <kotlin.version>1.2-SNAPSHOT</kotlin.version>
</properties> </properties>
<groupId>org.jetbrains.kotlinx</groupId> <groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-maven-serialization-plugin</artifactId> <artifactId>kotlinx-maven-serialization-plugin</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>0.1.1</version> <version>0.2</version>
<description>Serialization plugin for Maven</description> <description>Serialization plugin for Maven</description>
<repositories> <repositories>
@@ -33,6 +32,7 @@
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId> <artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version> <version>${kotlin.version}</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
@@ -2,12 +2,16 @@ plugins {
id "com.jfrog.bintray" version "1.7.3" id "com.jfrog.bintray" version "1.7.3"
} }
group = 'org.jetbrains.kotlinx'
version = '0.1.1'
apply plugin: 'kotlin' apply plugin: 'kotlin'
configureJvmProject(project) configureJvmProject(project)
configurePublishing(project)
group = 'org.jetbrains.kotlinx'
version = '0.2'
if (!project.hasProperty("deploy")) {
version = "$version-SNAPSHOT"
}
compileJava { compileJava {
sourceCompatibility = 1.8 sourceCompatibility = 1.8
@@ -24,55 +28,35 @@ repositories {
dependencies { dependencies {
compileOnly project(':kotlin-gradle-plugin-api') compileOnly project(':kotlin-gradle-plugin-api')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compileOnly project(':kotlin-stdlib')
compile "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlin_version" compileOnly project(path: ':kotlin-compiler-embeddable', configuration: 'runtimeJar')
compileOnly project(':kotlin-allopen-compiler-plugin')
compileOnly 'org.jetbrains.kotlin:gradle-api:1.6' compileOnly 'org.jetbrains.kotlin:gradle-api:1.6'
} }
def originalSrc = "$kotlin_root/plugins/kotlin-serialization/kotlin-serialization-compiler/src" evaluationDependsOn(":kotlinx-serialization-compiler-plugin")
def targetSrc = file("$buildDir/kotlin-serialization-target-src")
task preprocessSources(type: Copy) {
from originalSrc
into targetSrc
filter { it.replaceAll('(?<!\\.)com\\.intellij', 'org.jetbrains.kotlin.com.intellij') }
}
sourceSets.main.java.srcDirs += targetSrc
compileKotlin.dependsOn preprocessSources
jar { jar {
from(targetSrc) { include("META-INF/**") } from(project(":kotlinx-serialization-compiler-plugin").sourceSets.main.output.classesDirs)
from(project(":kotlinx-serialization-compiler-plugin").sourceSets.main.output.resourcesDir)
manifestAttributes(manifest, project)
} }
apply plugin: 'maven-publish' ArtifactsKt.runtimeJar(project, EmbeddableKt.rewriteDepsToShadedCompiler(project, jar, {}), {})
task sourceJar(type: Jar, dependsOn: classes) { artifacts {
classifier 'sources' archives sourcesJar
from sourceSets.main.allSource archives javadocJar
}
publishing {
publications {
mavenProject(MavenPublication) {
from components.java
groupId project.group
artifactId project.name
version project.version
artifact sourceJar {
classifier "sources"
}
}
}
} }
bintray { bintray {
user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
publications = ['mavenProject'] configurations = ['archives']
if (!project.hasProperty("deploy")) {
dryRun = true
}
pkg { pkg {
repo = 'kotlinx' repo = 'kotlinx'
name = 'kotlinx.serialization.plugin' name = 'kotlinx.serialization.plugin'
@@ -1,30 +1,38 @@
# Kotlin serialization IDEA plugin # Kotlin serialization IDEA plugin
Kotlin serialization plugin consists of three parts: a gradle compiler plugin, an IntelliJ plugin and a runtime library. Kotlin serialization plugin consists of three parts: a compiler plugin, an IntelliJ plugin and a runtime library.
This is the IDEA plugin. Gradle plugin can be found in `libraries` folder. This is the IDEA plugin. Gradle and Maven plugins can be found in `libraries` folder.
Please note that this plugin currently works only for highlighting and resolving symbols, and it doesn't work with embedded IDEA compiler. Please note that this plugin currently works only for highlighting and resolving symbols, and it doesn't work with embedded IDEA compiler.
To build any project with serialization within IDEA, you'll need to delegate all build actions to gradle: To build any project with serialization within IDEA, you'll need to delegate all build actions to gradle:
`File - Settings - Build, Execution, Deployment - Build Tools - Gradle - Runner -` tick `Delegate IDE build/run actions to gradle`. `File - Settings - Build, Execution, Deployment - Build Tools - Gradle - Runner -` tick `Delegate IDE build/run actions to gradle`.
Maven and IntelliJ projects currently are not supported. IntelliJ projects currently are not supported.
Compiler plugins are uploaded on bintray: https://bintray.com/kotlin/kotlinx/kotlinx.serialization.plugin
## Building and usage ## Building and usage
### Prerequisites: ### Prerequisites:
Before all, follow the instructions from root README.md to download dependencies and build Kotlin compiler. (`ant -f update_dependencies.xml && ant dist`) Before all, follow the instructions from root README.md to download dependencies and build Kotlin compiler. (`ant -f update_dependencies.xml && ./gradlew dist`)
**Plugin works only with IntelliJIDEA 2017.2 and higher.** **Plugin works only with IntelliJIDEA 2017.2 and higher.**
Make sure you have latest dev version of Kotlin plugin installed: Make sure you have latest dev version of Kotlin plugin installed.
Open `Settings - Plugins - Browse Repositories... - Manage repositories` and add `https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_master_CompilerAndPlugin_NoTests/.lastSuccessful/updatePlugins-IJ2017.2.xml`.
Update Kotlin plugin from new repository.
### With gradle: ### With gradle:
Run `./gradlew buildPlugin`. Run `./gradlew :kotlinx-serialization-compiler-plugin:dist`.
In IDEA, open `Settings - Plugins - Install plugin from disk...` and choose `build/distributions/Kotlin-serialization-0.1-SNAPSHOT.zip` In IDEA, open `Settings - Plugins - Install plugin from disk...` and choose `$kotlin_root/dist/artifacts/Serialization/lib/kotlinx-serialization-compiler-plugin.jar`
### From within IDE (for development): ### From within IDE (for development):
Open whole Kotlin project. Choose run configuration `IDEA` and run it. You'll get a fresh copy of IDEA with Kotlin and Kotlin-serialization plugins built from sources. Run `./gradlew runIde` You'll get a fresh copy of IDEA with Kotlin and Kotlin-serialization plugins built from sources.
## Building gradle plugin
Run `./gradlew :kotlinx-gradle-serialization-plugin:install`
## Building maven plugin
Go to `$kotlin_root/libraries/tools/kotlin-maven-serialization`. Run `mvn install`
@@ -1,65 +0,0 @@
buildscript {
ext {
kotlin_root = file("$rootDir/../../..")
distDir = file("$kotlin_root/dist")
bootstrapCompilerFile = file("$distDir/kotlin-compiler-for-maven.jar")
kotlin_version = "1.1.3"
}
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
}
}
plugins {
id "org.jetbrains.intellij" version "0.2.15"
}
group 'org.jetbrains.kotlinx'
version '0.1-SNAPSHOT'
apply plugin: 'kotlin'
apply plugin: 'maven-publish'
repositories {
mavenCentral()
}
dependencies {
compileOnly "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
compileOnly files(bootstrapCompilerFile.toString())
}
sourceSets {
main {
java {
srcDir 'src'
}
}
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile) {
compilerJarFile = bootstrapCompilerFile
}
jar {
from ('./src') {
include 'META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar'
include 'META-INF/plugin.xml'
}
}
apply plugin: 'org.jetbrains.intellij'
intellij {
if (findProperty("noIdeaSDK") == null) {
localPath "$kotlin_root/ideaSDK"
}
pluginName 'Kotlin-serialization'
downloadSources false
}
@@ -0,0 +1,35 @@
description = "Kotlin Serialization Compiler Plugin"
apply { plugin("kotlin") }
dependencies {
compileOnly(ideaSdkCoreDeps("intellij-core"))
compileOnly(project(":compiler:plugin-api"))
compileOnly(project(":compiler:frontend"))
compileOnly(project(":compiler:backend"))
compileOnly(project(":js:js.frontend"))
compileOnly(project(":js:js.translator"))
runtime(projectRuntimeJar(":kotlin-compiler"))
runtime(projectDist(":kotlin-stdlib"))
// val compileOnly by configurations
// val runtime by configurations
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
val jar = runtimeJar {
from(fileTree("$projectDir/src")) { include("META-INF/**") }
}
val serialPluginDir: File by rootProject.extra
dist(targetDir = File(serialPluginDir,"lib"), targetName = the<BasePluginConvention>().archivesBaseName.removePrefix("kotlin-") + ".jar")
ideaPlugin {
from(jar)
rename("^kotlin-", "")
}
@@ -1,6 +0,0 @@
#Mon Jul 31 13:14:07 MSK 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
@@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_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 "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# 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
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@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 init
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 init
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
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="plugin-api" scope="PROVIDED" />
<orderEntry type="module" module-name="frontend" scope="PROVIDED" />
<orderEntry type="module" module-name="frontend.java" scope="PROVIDED" />
<orderEntry type="module" module-name="util" scope="PROVIDED" />
<orderEntry type="module" module-name="backend" scope="PROVIDED" />
<orderEntry type="module" module-name="js.translator" scope="PROVIDED" />
</component>
</module>
@@ -1 +0,0 @@
rootProject.name='serialization-plugin'
@@ -38,10 +38,10 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
fun generate() { fun generate() {
check(properties.isExternallySerializable) { "Class ${serializableDescriptor.name} is not externally serializable" } check(properties.isExternallySerializable) { "Class ${serializableDescriptor.name} is not externally serializable" }
generateSerializableClassPropertyIfNeeded() val prop = generateSerializableClassPropertyIfNeeded()
val save = generateSaveIfNeeded() val save = generateSaveIfNeeded()
val load = generateLoadIfNeeded() val load = generateLoadIfNeeded()
if (save || load) if (save || load || prop)
generateSerialDesc() generateSerialDesc()
} }
@@ -55,10 +55,11 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
protected abstract fun generateLoad(function: FunctionDescriptor) protected abstract fun generateLoad(function: FunctionDescriptor)
private fun generateSerializableClassPropertyIfNeeded() { private fun generateSerializableClassPropertyIfNeeded(): Boolean {
val property = serialDescPropertyDescriptor val property = serialDescPropertyDescriptor
?: return ?: return false
generateSerializableClassProperty(property) generateSerializableClassProperty(property)
return true
} }
private fun generateSaveIfNeeded(): Boolean { private fun generateSaveIfNeeded(): Boolean {
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.containsTypeProjectionsInTopLevelArguments import org.jetbrains.kotlin.types.typeUtil.containsTypeProjectionsInTopLevelArguments
import org.jetbrains.kotlin.types.typeUtil.isBoolean import org.jetbrains.kotlin.types.typeUtil.isBoolean
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
@@ -52,12 +53,12 @@ fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
KotlinBuiltIns.isUnit(T) -> SerialTypeInfo(property, "Unit", unit = true) KotlinBuiltIns.isUnit(T) -> SerialTypeInfo(property, "Unit", unit = true)
KotlinBuiltIns.isPrimitiveArray(T) -> TODO("primitive arrays are not supported yet") KotlinBuiltIns.isPrimitiveArray(T) -> TODO("primitive arrays are not supported yet")
KotlinBuiltIns.isNonPrimitiveArray(T.toClassDescriptor!!) -> { KotlinBuiltIns.isNonPrimitiveArray(T.toClassDescriptor!!) -> {
val serializer = property.serializer?.toClassDescriptor ?: val serializer = property.serializableWith?.toClassDescriptor ?:
property.module.findClassAcrossModuleDependencies(referenceArraySerializerId) property.module.findClassAcrossModuleDependencies(referenceArraySerializerId)
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer) SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
} }
T.toClassDescriptor?.kind == ClassKind.ENUM_CLASS -> { T.toClassDescriptor?.kind == ClassKind.ENUM_CLASS -> {
val serializer = property.serializer?.toClassDescriptor ?: val serializer = property.serializableWith?.toClassDescriptor ?:
property.module.findClassAcrossModuleDependencies(enumSerializerId) property.module.findClassAcrossModuleDependencies(enumSerializerId)
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer) SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
} }
@@ -73,6 +74,7 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer ?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
?: findEnumTypeSerializer(module, kType) ?: findEnumTypeSerializer(module, kType)
?: module.findClassAcrossModuleDependencies(contextSerializerId)
} }
fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? { fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
@@ -105,7 +107,7 @@ fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDe
fun KotlinType.requiresPolymorphism(): Boolean { fun KotlinType.requiresPolymorphism(): Boolean {
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|| this.toClassDescriptor?.modality == Modality.OPEN || (this.toClassDescriptor?.modality == Modality.OPEN && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|| this.containsTypeProjectionsInTopLevelArguments() // List<*> || this.containsTypeProjectionsInTopLevelArguments() // List<*>
} }
@@ -35,6 +35,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCod
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
@@ -158,7 +159,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
return getQualifiedClassReferenceName(serializerClass) return getQualifiedClassReferenceName(serializerClass)
} }
else { else {
var args = if (serializerClass.classId == enumSerializerId) var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
listOf(createGetKClassExpression(kType.toClassDescriptor!!)) listOf(createGetKClassExpression(kType.toClassDescriptor!!))
else kType.arguments.map { else kType.arguments.map {
val argSer = findTypeSerializer(module, it.type) ?: return null val argSer = findTypeSerializer(module, it.type) ?: return null
@@ -166,7 +167,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
if (it.type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr if (it.type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr
} }
if (serializerClass.classId == referenceArraySerializerId) if (serializerClass.classId == referenceArraySerializerId)
args = listOf(createGetKClassExpression(kType.arguments[0].type.toClassDescriptor!!)) + args args = listOf(createGetKClassExpression(kType.arguments[0].type.toClassDescriptor!!)) + args
return JsNew(getQualifiedClassReferenceName(serializerClass), args) return JsNew(getQualifiedClassReferenceName(serializerClass), args)
} }
} }
@@ -215,7 +216,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
JsInvocation(JsNameRef(readElementF, inputVar), serialClassDescRef) JsInvocation(JsNameRef(readElementF, inputVar), serialClassDescRef)
).makeStmt() ).makeStmt()
// switch(index) // switch(index)
jsSwitch (indexVar) { jsSwitch(indexVar) {
// -2: readAll = true // -2: readAll = true
case(JsIntLiteral(-2)) { case(JsIntLiteral(-2)) {
+JsAstUtils.assignment( +JsAstUtils.assignment(
@@ -230,12 +231,15 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val sti = getSerialTypeInfo(property) val sti = getSerialTypeInfo(property)
val innerSerial = if (sti.serializer == null) null else serializerInstance(sti.serializer, property.module, property.type) val innerSerial = if (sti.serializer == null) null else serializerInstance(sti.serializer, property.module, property.type)
val call = if (innerSerial == null) { val call = if (innerSerial == null) {
val unknownSer = (sti.elementMethodPrefix.isEmpty())
val readFunc = val readFunc =
inputClass.getFuncDesc("read${sti.elementMethodPrefix}ElementValue").single() inputClass.getFuncDesc("read${sti.elementMethodPrefix}ElementValue")
// if readElementValue, must have 3 parameters, if readXXXElementValue - 2
.single { !unknownSer || (it is FunctionDescriptor && it.valueParameters.size == 3) }
.let { context.getNameForDescriptor(it) } .let { context.getNameForDescriptor(it) }
JsInvocation(JsNameRef(readFunc, inputVar), val readArgs = mutableListOf(serialClassDescRef, JsIntLiteral(i))
serialClassDescRef, if (unknownSer) readArgs.add(createGetKClassExpression(property.type.toClassDescriptor!!))
JsIntLiteral(i)) JsInvocation(JsNameRef(readFunc, inputVar), readArgs)
} }
else { else {
val readFunc = val readFunc =
@@ -262,7 +266,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
if (KotlinBuiltIns.isCharOrNullableChar(property.type)) { if (KotlinBuiltIns.isCharOrNullableChar(property.type)) {
+JsAstUtils.assignment( +JsAstUtils.assignment(
localProps[i], localProps[i],
TranslationUtils.coerce(context, localProps[i], TranslationUtils.getReturnTypeForCoercion(property.descriptor.getter!!)) TranslationUtils.coerce(context, localProps[i], context.currentModule.builtIns.charType)
).makeStmt() ).makeStmt()
} }
@@ -298,6 +302,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
).makeStmt() ).makeStmt()
// deserialization constructor call // deserialization constructor call
// todo: external deserialization with primary constructor and setters calls after resolution of KT-11586
val constrDesc = KSerializerDescriptorResolver.createLoadConstructorDescriptor(serializableDescriptor, context.bindingContext()) val constrDesc = KSerializerDescriptorResolver.createLoadConstructorDescriptor(serializableDescriptor, context.bindingContext())
val constrRef = context.getInnerNameForDescriptor(constrDesc).makeRef() val constrRef = context.getInnerNameForDescriptor(constrDesc).makeRef()
val args: MutableList<JsExpression> = mutableListOf(bitMasks[0]) val args: MutableList<JsExpression> = mutableListOf(bitMasks[0])
@@ -31,10 +31,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInf
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findEnumTypeSerializer import org.jetbrains.kotlinx.serialization.compiler.backend.common.findEnumTypeSerializer
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findPolymorphicSerializer import org.jetbrains.kotlinx.serialization.compiler.backend.common.findPolymorphicSerializer
import org.jetbrains.kotlinx.serialization.compiler.backend.common.requiresPolymorphism import org.jetbrains.kotlinx.serialization.compiler.backend.common.requiresPolymorphism
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperty import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.internalPackageFqName
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
import org.jetbrains.kotlinx.serialization.compiler.resolve.typeSerializer
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -113,8 +110,9 @@ internal fun ImplementationBodyCodegen.generateMethod(function: FunctionDescript
internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier("EnumSerializer")) internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier("EnumSerializer"))
internal val polymorphicSerializerId = ClassId(internalPackageFqName, Name.identifier("PolymorphicSerializer")) internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier("PolymorphicSerializer"))
internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer")) internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer"))
internal val contextSerializerId = ClassId(packageFqName, Name.identifier("ContextSerializer"))
// returns false is property should not use serializer // returns false is property should not use serializer
internal fun InstructionAdapter.stackValueSerializerInstance(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo): Boolean { internal fun InstructionAdapter.stackValueSerializerInstance(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo): Boolean {
@@ -150,7 +148,7 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
// instantiate all arg serializers on stack // instantiate all arg serializers on stack
val signature = StringBuilder("(") val signature = StringBuilder("(")
when (serializer.classId) { when (serializer.classId) {
enumSerializerId -> { enumSerializerId, contextSerializerId -> {
// a special way to instantiate enum -- need a enum KClass reference // a special way to instantiate enum -- need a enum KClass reference
aconst(codegen.typeMapper.mapType(kType)) aconst(codegen.typeMapper.mapType(kType))
AsmUtil.wrapJavaClassIntoKClass(this) AsmUtil.wrapJavaClassIntoKClass(this)
@@ -202,7 +200,7 @@ fun getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialType
} }
ARRAY -> { ARRAY -> {
// check for explicit serialization annotation on this property // check for explicit serialization annotation on this property
var serializer = property.serializer.toClassDescriptor var serializer = property.serializableWith.toClassDescriptor
if (serializer == null) { if (serializer == null) {
// no explicit serializer for this property. Select strategy by element type // no explicit serializer for this property. Select strategy by element type
when (type.elementType.sort) { when (type.elementType.sort) {
@@ -224,7 +222,8 @@ fun getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialType
return JVMSerialTypeInfo(property, Type.getType("Lkotlin/Unit;"), "Unit", unit = true) return JVMSerialTypeInfo(property, Type.getType("Lkotlin/Unit;"), "Unit", unit = true)
// todo: more efficient enum support here, but only for enums that don't define custom serializer // todo: more efficient enum support here, but only for enums that don't define custom serializer
// otherwise, it is a serializer for some other type // otherwise, it is a serializer for some other type
val serializer = findTypeSerializer(property.module, property.type, type) val serializer = property.serializableWith?.toClassDescriptor
?: findTypeSerializer(property.module, property.type, type)
return JVMSerialTypeInfo(property, Type.getType("Ljava/lang/Object;"), return JVMSerialTypeInfo(property, Type.getType("Ljava/lang/Object;"),
if (property.type.isMarkedNullable) "Nullable" else "", serializer) if (property.type.isMarkedNullable) "Nullable" else "", serializer)
} }
@@ -237,6 +236,7 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType, asmType: Typ
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
?: findStandardAsmTypeSerializer(module, asmType) // otherwise see if there is a standard serializer ?: findStandardAsmTypeSerializer(module, asmType) // otherwise see if there is a standard serializer
?: findEnumTypeSerializer(module, kType) ?: findEnumTypeSerializer(module, kType)
?: module.findClassAcrossModuleDependencies(contextSerializerId)
} }
fun findStandardAsmTypeSerializer(module: ModuleDescriptor, asmType: Type): ClassDescriptor? { fun findStandardAsmTypeSerializer(module: ModuleDescriptor, asmType: Type): ClassDescriptor? {
@@ -16,13 +16,11 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.jvm package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.CompilationException import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
@@ -238,10 +236,16 @@ class SerializerCodegenImpl(
val sti = getSerialTypeInfo(property, propertyType) val sti = getSerialTypeInfo(property, propertyType)
val useSerializer = stackValueSerializerInstance(codegen, sti) val useSerializer = stackValueSerializerInstance(codegen, sti)
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
if (unknownSer) {
aconst(codegen.typeMapper.mapType(property.type))
AsmUtil.wrapJavaClassIntoKClass(this)
}
invokevirtual(kInputType.internalName, invokevirtual(kInputType.internalName,
"read" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue", "read" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
"(" + descType.descriptor + "I" + "(" + descType.descriptor + "I" +
(if (useSerializer) kSerialLoaderType.descriptor else "") (if (useSerializer) kSerialLoaderType.descriptor else "")
+ (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "")
+ ")" + (if (sti.unit) "V" else sti.type.descriptor), false) + ")" + (if (sti.unit) "V" else sti.type.descriptor), false)
if (sti.unit) { if (sti.unit) {
StackValue.putUnitInstance(this) StackValue.putUnitInstance(this)
@@ -128,15 +128,8 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
} }
// serializer that was declared for this specific type or annotation from a class declaration // serializer that was declared for this specific type or annotation from a class declaration
val KotlinType?.typeSerializer: KotlinType? val KotlinType.typeSerializer: KotlinType?
get() = this?.let { get() = this.annotations.serializableWith ?: (this.toClassDescriptor).classSerializer
// serializer annotation on this type or from a class
return it.annotations.serializableWith ?: (it.toClassDescriptor).classSerializer
}
// serializer that was declared specifically for this property via its own annotation or via annotation on its type
val PropertyDescriptor.propertySerializer: KotlinType?
get() = annotations.serializableWith ?: type.typeSerializer
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? { fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
@@ -23,7 +23,7 @@ class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructor
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString() val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
val type = descriptor.type val type = descriptor.type
val module = descriptor.module val module = descriptor.module
val serializer = descriptor.propertySerializer val serializableWith = descriptor.annotations.serializableWith
val optional = descriptor.annotations.serialOptional val optional = descriptor.annotations.serialOptional
val transient = descriptor.annotations.serialTransient val transient = descriptor.annotations.serialTransient
val annotations = descriptor.annotations val annotations = descriptor.annotations
+7 -1
View File
@@ -180,7 +180,10 @@ include ":kotlin-build-common",
':kotlin-gradle-plugin:plugin-marker', ':kotlin-gradle-plugin:plugin-marker',
':kotlin-allopen:plugin-marker', ':kotlin-allopen:plugin-marker',
':kotlin-noarg:plugin-marker', ':kotlin-noarg:plugin-marker',
":test-instrumenter" ":test-instrumenter",
":kotlinx-serialization-compiler-plugin",
":kotlinx-gradle-serialization-plugin"
def isTeamcityBuild = hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null def isTeamcityBuild = hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
def includeUltimate = hasProperty("intellijUltimateEnabled") && intellijUltimateEnabled != 'false' def includeUltimate = hasProperty("intellijUltimateEnabled") && intellijUltimateEnabled != 'false'
@@ -294,3 +297,6 @@ project(':libraries:kotlin-prepush-hook').projectDir = "$rootDir/libraries/tools
project(':kotlin-gradle-plugin:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-gradle-plugin/plugin-marker") project(':kotlin-gradle-plugin:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-gradle-plugin/plugin-marker")
project(':kotlin-allopen:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-allopen/plugin-marker") project(':kotlin-allopen:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-allopen/plugin-marker")
project(':kotlin-noarg:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-noarg/plugin-marker") project(':kotlin-noarg:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-noarg/plugin-marker")
project(':kotlinx-serialization-compiler-plugin').projectDir = file("$rootDir/plugins/kotlin-serialization/kotlin-serialization-compiler")
project(':kotlinx-gradle-serialization-plugin').projectDir = file("$rootDir/libraries/tools/kotlin-serialization")