mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[workspace model] IDEA-297350 Remove old gradle modules
GitOrigin-RevId: 0a7a8b7032ee8ca24345599d8cdd7b5eaae4a9d3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0895a246f8
commit
95d8f4d808
@@ -1,42 +0,0 @@
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@@ -1,42 +0,0 @@
|
||||
plugins {
|
||||
id("maven-publish")
|
||||
// Java support
|
||||
id("java")
|
||||
// Kotlin support
|
||||
id("org.jetbrains.kotlin.jvm") version "1.8.0"
|
||||
}
|
||||
|
||||
group = "com.jetbrains.intellij.platform"
|
||||
version = "0.0.4"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = uri("https://www.jetbrains.com/intellij-repository/releases")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://packages.jetbrains.team/maven/p/ide-accessibility-assistant/codegen-test")
|
||||
credentials {
|
||||
username = System.getProperty("intellij.workspace.codegen.repository.user")
|
||||
password = System.getProperty("intellij.workspace.codegen.repository.password")
|
||||
}
|
||||
}
|
||||
}
|
||||
publications {
|
||||
register("mavenJava", MavenPublication::class) {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains:annotations:24.0.0")
|
||||
implementation("com.jetbrains.intellij.platform:workspace-model-storage:223.8836.34")
|
||||
}
|
||||
Binary file not shown.
-6
@@ -1,6 +0,0 @@
|
||||
#Fri Mar 10 15:23:48 AMT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
-234
@@ -1,234 +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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/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="Gradle"
|
||||
APP_BASE_NAME=${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='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
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 GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_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 -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -1,89 +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 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 Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "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%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="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,2 +0,0 @@
|
||||
rootProject.name = "workspace-model-codegen"
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.annotations
|
||||
|
||||
@Target(
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.FUNCTION
|
||||
)
|
||||
annotation class Cached
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.annotations
|
||||
|
||||
/**
|
||||
* Name property values acts as implicit field of parent object.
|
||||
*
|
||||
* By setting name of some object, you are actually declare implicit field
|
||||
* of parent object with same name and this object as value.
|
||||
*/
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class Name
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.annotations
|
||||
|
||||
annotation class Parent
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
interface CompiledObjModule : ObjModule {
|
||||
fun objClass(typeId: Int): ObjClass<*>
|
||||
fun <T : Obj, V> extField(receiver: ObjClass<*>, name: String, default: T.() -> V): ExtProperty<T, V>
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
interface Obj {
|
||||
val objType: ObjType<*>
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutable, possibly not fully initialized [Obj].
|
||||
*
|
||||
* Implementation of that interface is generated by the Deft compiler,
|
||||
* inside each [Obj]. It will contain `var`s for all final fields.
|
||||
*
|
||||
* [ObjBuilder] inherits all corresponding builders of [Obj] supertypes.
|
||||
*
|
||||
* Doesn't have `var`s for open field, as open setters contravariance
|
||||
* contradicts open getter invariance. [ObjFinalBuilder] contains rest fields,
|
||||
* but **not** inherits supertypes Builders.
|
||||
*/
|
||||
interface ObjBuilder<T : Obj> : Obj {
|
||||
val isInitialized: Boolean
|
||||
|
||||
fun isInitialized(field: OwnProperty<T, *>): Boolean
|
||||
fun isInitialized(field: ExtProperty<T, *>): Boolean
|
||||
|
||||
fun <V> setValue(field: OwnProperty<T, V>, value: V)
|
||||
fun <V> setValue(field: ExtProperty<T, V>, value: V)
|
||||
fun <V : Obj> setValue(type: ObjClass<V>, value: V)
|
||||
|
||||
fun remove(field: ExtProperty<T, *>): Boolean
|
||||
fun remove(type: ObjClass<*>): Boolean
|
||||
|
||||
fun build(): T
|
||||
}
|
||||
|
||||
/**
|
||||
* See [ObjBuilder].
|
||||
*
|
||||
* Contains rest open fields, and not inherits supertypes Builders
|
||||
* (as open setters contravariance contradicts open getter invariance).
|
||||
*/
|
||||
interface ObjFinalBuilder<T : Obj> : ObjBuilder<T>
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.annotations.Name
|
||||
import org.jetbrains.deft.annotations.Child
|
||||
|
||||
interface ObjModule : Obj {
|
||||
@Name
|
||||
val name: String
|
||||
|
||||
val moduleId: Id
|
||||
get() = Id(name)
|
||||
|
||||
val dependencies: List<ObjModule>
|
||||
|
||||
val types: List<@Child ObjClass<*>>
|
||||
|
||||
val extensions: List<@Child ExtProperty<*, *>>
|
||||
|
||||
/**
|
||||
* Example: `org.jetbrains.deft.obj.intellijWs`
|
||||
* will be parsed as:
|
||||
* - `org.jetbrains.deft.obj.intellijWs` package
|
||||
* - `org.jetbrains.deft.obj.intellijWs.IntellijWs` object name
|
||||
**/
|
||||
@JvmInline
|
||||
value class Id(private val notation: String) {
|
||||
private val javaPackage: String
|
||||
get() = notation
|
||||
|
||||
private val objName: String
|
||||
get() = notation.substringAfterLast(".")
|
||||
.replaceFirstChar { it.titlecaseChar() }
|
||||
|
||||
val objFqn: String
|
||||
get() = "$javaPackage.$objName"
|
||||
|
||||
fun check() {
|
||||
check(objName.first().isUpperCase()) {
|
||||
"`$notation` should be an id notation like `org.jetbrains.deft.obj.IntellijWs`.\n" +
|
||||
"Will be parsed as:\n" +
|
||||
"- `org.jetbrains.deft.obj.intellijWs` package\n" +
|
||||
"- `IntellijWs` object name"
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = "ObjModule.Id($notation)"
|
||||
}
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.annotations.Name
|
||||
import com.intellij.workspaceModel.codegen.deft.annotations.Parent
|
||||
|
||||
/**
|
||||
* Same as [kotlin.reflect.KProperty]
|
||||
*/
|
||||
interface ObjProperty<T : Obj, V> : Obj {
|
||||
val suspend: Boolean
|
||||
|
||||
val open: Boolean
|
||||
|
||||
val mutable: Boolean
|
||||
|
||||
val receiver: ObjClass<T>
|
||||
|
||||
@Name
|
||||
val name: String
|
||||
|
||||
val valueType: ValueType<V>
|
||||
|
||||
val valueKind: ValueKind
|
||||
|
||||
sealed interface ValueKind {
|
||||
object Plain : ValueKind
|
||||
class Computable(val expression: String) : ValueKind
|
||||
class WithDefault(val value: String) : ValueKind
|
||||
}
|
||||
|
||||
////// Kotlin DSL
|
||||
|
||||
val content: Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as [kotlin.reflect.KProperty1]
|
||||
*/
|
||||
interface OwnProperty<T : Obj, V> : ObjProperty<T, V> {
|
||||
@Parent
|
||||
override val receiver: ObjClass<T>
|
||||
|
||||
val constructorParameter: Boolean
|
||||
|
||||
val classLocalId: Int
|
||||
|
||||
val isKey: Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as [kotlin.reflect.KProperty1]
|
||||
*/
|
||||
interface ExtProperty<T : Obj, V> : ObjProperty<T, V> {
|
||||
@Parent
|
||||
val module: ObjModule
|
||||
|
||||
override val receiver: ObjClass<T>
|
||||
|
||||
val moduleLocalId: Int
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.annotations.Cached
|
||||
import com.intellij.workspaceModel.codegen.deft.annotations.Parent
|
||||
import org.jetbrains.deft.annotations.Child
|
||||
|
||||
interface ObjType<T> : Obj {
|
||||
val classifier: ObjType<T>
|
||||
|
||||
val arguments: List<ObjType<*>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes parameterized type of [Objects][Obj].
|
||||
*
|
||||
* Read first: "Values, References and Objects" in [Obj] docs.
|
||||
*
|
||||
* For implementation simplicity, [ObjClass] is used to define both [ObjClass]
|
||||
* itself and [asStructure], even when you need [asStructure] only.
|
||||
*
|
||||
* Objects can have [own][OwnProperty] and [extension][ExtProperty] fields.
|
||||
*/
|
||||
interface ObjClass<T : Obj> : ObjType<T> {
|
||||
val typeParameters: List<@Child TypeParameter>
|
||||
|
||||
val superTypes: List<ObjType<*>>
|
||||
|
||||
@Parent
|
||||
val module: ObjModule
|
||||
|
||||
val name: String
|
||||
|
||||
val openness: Openness
|
||||
|
||||
enum class Openness(
|
||||
val instantiatable: Boolean = false,
|
||||
val extendable: Boolean = false,
|
||||
val openHierarchy: Boolean = extendable
|
||||
) {
|
||||
/** Single instance */
|
||||
`const`,
|
||||
|
||||
/** Can't be extended */
|
||||
`final`(instantiatable = true),
|
||||
|
||||
/** Should be extended (can't be instantiated directly) */
|
||||
`abstract`(extendable = true),
|
||||
|
||||
/** Should be extended with sealed hierarchy */
|
||||
`enum`(extendable = true, openHierarchy = false),
|
||||
|
||||
/** Can be extended and can be instantiated */
|
||||
`open`(instantiatable = true, extendable = true)
|
||||
}
|
||||
|
||||
val fields: List<@Child OwnProperty<T, *>>
|
||||
|
||||
val parentField: OwnProperty<T, *>?
|
||||
|
||||
val nameField: OwnProperty<T, *>?
|
||||
|
||||
val fieldsByName: Map<String, OwnProperty<in T, *>>
|
||||
@Cached get() = fields.associateBy { it.name }
|
||||
|
||||
val fieldsByLocalId: Map<Int, OwnProperty<in T, *>>
|
||||
@Cached get() = fields.associateBy { it.classLocalId }
|
||||
|
||||
val asStructure: ValueType.Structure<T>
|
||||
@Cached get() = ValueType.Structure(fields.mapTo(mutableListOf()) { it.valueType })
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
interface TypeParameter : Obj {
|
||||
val name: String
|
||||
val lowerBound: ObjType<*>
|
||||
}
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.deft.meta
|
||||
|
||||
/**
|
||||
* [ValueType] is used to describe the set of suitable values.
|
||||
*/
|
||||
sealed class ValueType<T> {
|
||||
sealed class Primitive<T> : ValueType<T>()
|
||||
|
||||
/**
|
||||
* `true` or `false`. Actually, the shorthand for `OneOf(Const(true), Const(false))`.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Boolean] and Java primitive `boolean` ([java.lang.Boolean])
|
||||
*/
|
||||
object Boolean : Primitive<kotlin.Boolean>()
|
||||
|
||||
/**
|
||||
* 8-bit signed integer with the least significant bit.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Byte] and Java primitive `byte`([java.lang.Byte]).
|
||||
*/
|
||||
object Byte : Primitive<kotlin.Byte>()
|
||||
|
||||
/**
|
||||
* 16-bit signed, big endian integer with the least significant bit.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Short] and Java primitive `short`([java.lang.Short]).
|
||||
*/
|
||||
object Short : Primitive<kotlin.Short>()
|
||||
|
||||
/**
|
||||
* 32-bit signed, big endian integer with the least significant bit.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Int] and Java primitive `int`([java.lang.Integer])
|
||||
*/
|
||||
object Int : Primitive<kotlin.Int>()
|
||||
|
||||
/**
|
||||
* 64-bit signed, big endian integer with the least significant bit.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Long] and Java primitive `long`([java.lang.Long])
|
||||
*/
|
||||
object Long : Primitive<kotlin.Long>()
|
||||
|
||||
/**
|
||||
* Represents a double-precision 32-bit [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) floating point number.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Float] and Java primitive `float`([java.lang.Float])
|
||||
*/
|
||||
object Float : Primitive<kotlin.Float>()
|
||||
|
||||
/**
|
||||
* Represents a double-precision 64-bit [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) floating point number.
|
||||
*
|
||||
* Same as Kotlin [kotlin.Double] and Java primitive `double`([java.lang.Double])
|
||||
*/
|
||||
object Double : Primitive<kotlin.Double>()
|
||||
|
||||
/**
|
||||
* 8-bit unsigned integer.
|
||||
*
|
||||
* Same as Kotlin [UByte]. Not available in Java.
|
||||
*/
|
||||
object UByte : Primitive<kotlin.UByte>()
|
||||
|
||||
/**
|
||||
* 16-bit unsigned, big endian integer.
|
||||
*
|
||||
* Same as Kotlin [UShort]. Not available in Java.
|
||||
*/
|
||||
object UShort : Primitive<kotlin.UShort>()
|
||||
|
||||
/**
|
||||
* 32-bit unsigned, big endian integer.
|
||||
*
|
||||
* Same as Kotlin [UInt]. Not available in Java.
|
||||
*/
|
||||
object UInt : Primitive<kotlin.UInt>()
|
||||
|
||||
/**
|
||||
* 64-bit unsigned, big endian integer.
|
||||
*
|
||||
* Same as Kotlin [ULong]. Not available in Java.
|
||||
*/
|
||||
object ULong : Primitive<kotlin.ULong>()
|
||||
|
||||
/**
|
||||
* 16-bit Unicode character encoded by [UShort].
|
||||
*
|
||||
* Same as Kotlin [kotlin.Char] and Java [java.lang.Character]
|
||||
*/
|
||||
object Char : Primitive<kotlin.Char>()
|
||||
|
||||
/**
|
||||
* Behaves as [List] of [Char].
|
||||
*
|
||||
* Unlike all other [ValueType]s, requires decoding on read and encoding on write,
|
||||
* thus should be cached on client side. The actual binary representation is
|
||||
* implementation detail.
|
||||
*
|
||||
* Translated to [kotlin.String] and Java [java.lang.String].
|
||||
*/
|
||||
object String : Primitive<kotlin.String>()
|
||||
|
||||
/**
|
||||
* Polymorphic reference to [Obj] of [target] [ObjClass].
|
||||
**/
|
||||
data class ObjRef<T : Obj>(
|
||||
val child: kotlin.Boolean,
|
||||
val target: ObjClass<T>
|
||||
) : ValueType<T>()
|
||||
|
||||
sealed class JvmClass<T>(
|
||||
val javaClassName: kotlin.String,
|
||||
val javaSuperClasses: kotlin.collections.List<kotlin.String>,
|
||||
) : ValueType<T>()
|
||||
|
||||
class DataClass<T>(
|
||||
javaClassName: kotlin.String,
|
||||
javaSuperClasses: kotlin.collections.List<kotlin.String>,
|
||||
val properties: kotlin.collections.List<DataClassProperty>
|
||||
) : JvmClass<T>(javaClassName, javaSuperClasses)
|
||||
|
||||
data class DataClassProperty(val name: kotlin.String, val type: ValueType<*>)
|
||||
|
||||
class SealedClass<T>(
|
||||
javaClassName: kotlin.String,
|
||||
javaSuperClasses: kotlin.collections.List<kotlin.String>,
|
||||
val subclasses: kotlin.collections.List<JvmClass<*>>
|
||||
) : JvmClass<T>(javaClassName, javaSuperClasses)
|
||||
|
||||
class Blob<T>(
|
||||
javaClassName: kotlin.String,
|
||||
javaSuperClasses: kotlin.collections.List<kotlin.String>,
|
||||
) : JvmClass<T>(javaClassName, javaSuperClasses)
|
||||
|
||||
class Enum<T>(
|
||||
javaClassName: kotlin.String,
|
||||
) : JvmClass<T>(javaClassName, emptyList())
|
||||
|
||||
class Object<T>(
|
||||
javaClassName: kotlin.String,
|
||||
javaSuperClasses: kotlin.collections.List<kotlin.String>,
|
||||
) : JvmClass<T>(javaClassName, javaSuperClasses)
|
||||
|
||||
/**
|
||||
* Tuple of fields with fixed [ValueType]s.
|
||||
*
|
||||
* [Structure] is [ValueType] itself, thus can be nested (but without recursion)
|
||||
* and compared by value.
|
||||
*
|
||||
* Use [ObjClass] to define your own structure.
|
||||
*
|
||||
* Read "Values, References and Objects" in [Obj] to understand differences
|
||||
* between [ValueType] (which [Structure] is) and [ObjClass].
|
||||
*
|
||||
* Unlike [ObjProperty], [Structure] fields are not nominal.
|
||||
* Thus, two structures with same set of field types considered equal.
|
||||
*/
|
||||
data class Structure<T>(val fields: kotlin.collections.List<ValueType<*>>) : ValueType<T>()
|
||||
|
||||
sealed class Collection<E, T : kotlin.collections.Collection<E>> : ValueType<T>() {
|
||||
abstract val elementType: ValueType<E>
|
||||
}
|
||||
|
||||
data class List<T>(override val elementType: ValueType<T>) : Collection<T, kotlin.collections.List<T>>()
|
||||
data class Set<T>(override val elementType: ValueType<T>) : Collection<T, kotlin.collections.Set<T>>()
|
||||
|
||||
data class Map<K, V>(
|
||||
val keyType: ValueType<K>,
|
||||
val valueType: ValueType<V>
|
||||
) : ValueType<Map<K, V>>()
|
||||
|
||||
data class Optional<T>(val type: ValueType<T>) : ValueType<T?>()
|
||||
|
||||
/**
|
||||
* Any possible value.
|
||||
* Valid inside [ValueRef] only.
|
||||
*
|
||||
* Logical representation: [AnyOf]`(...all value kinds)`.
|
||||
*/
|
||||
object Any : ValueType<kotlin.Any>()
|
||||
|
||||
/**
|
||||
* Nothing has no possible values.
|
||||
* Used to denote [Optional] values.
|
||||
*
|
||||
* Logical representation: [Both]`(...all value kinds, except Any)`.
|
||||
*/
|
||||
object Nothing : ValueType<kotlin.Nothing>()
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
/**
|
||||
* Contains interfaces which describe structure of {@link com.intellij.workspaceModel.storage.WorkspaceEntity workspace entities}.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
package com.intellij.workspaceModel.codegen.deft.meta;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.engine
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.*
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntity
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntityWithSymbolicId
|
||||
|
||||
val SKIPPED_TYPES: Set<String> = setOfNotNull(WorkspaceEntity::class.simpleName,
|
||||
WorkspaceEntity.Builder::class.simpleName,
|
||||
WorkspaceEntityWithSymbolicId::class.simpleName)
|
||||
interface CodeGenerator {
|
||||
fun generate(module: CompiledObjModule): GenerationResult
|
||||
}
|
||||
|
||||
class GenerationResult(val generatedCode: List<GeneratedCode>, val problems: List<GenerationProblem>)
|
||||
|
||||
class GenerationProblem(
|
||||
val message: String,
|
||||
val level: Level,
|
||||
val location: ProblemLocation
|
||||
) {
|
||||
enum class Level { ERROR, WARNING }
|
||||
}
|
||||
|
||||
sealed interface ProblemLocation {
|
||||
val objModule: ObjModule
|
||||
|
||||
class Class(val objClass: ObjClass<*>) : ProblemLocation {
|
||||
override val objModule: ObjModule
|
||||
get() = objClass.module
|
||||
|
||||
override fun toString(): String = objClass.name
|
||||
}
|
||||
class Property(val property: ObjProperty<*, *>) : ProblemLocation {
|
||||
override val objModule: ObjModule
|
||||
get() = when (property) {
|
||||
is ExtProperty<*, *> -> property.module
|
||||
else -> property.receiver.module
|
||||
}
|
||||
|
||||
override fun toString(): String = property.toString()
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratedCode(
|
||||
val target: ObjClass<*>,
|
||||
val builderInterface: String,
|
||||
val companionObject: String,
|
||||
val topLevelCode: String?,
|
||||
val implementationClass: String?
|
||||
)
|
||||
@@ -1,42 +0,0 @@
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@@ -1,43 +0,0 @@
|
||||
plugins {
|
||||
id("maven-publish")
|
||||
// Java support
|
||||
id("java")
|
||||
// Kotlin support
|
||||
id("org.jetbrains.kotlin.jvm") version "1.8.0"
|
||||
}
|
||||
|
||||
group = "com.jetbrains.intellij.platform"
|
||||
version = "0.0.6"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = uri("https://www.jetbrains.com/intellij-repository/releases")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://www.jetbrains.com/intellij-repository/nightly")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("https://packages.jetbrains.team/maven/p/ide-accessibility-assistant/codegen-test")
|
||||
credentials {
|
||||
username = System.getProperty("intellij.workspace.codegen.repository.user")
|
||||
password = System.getProperty("intellij.workspace.codegen.repository.password")
|
||||
}
|
||||
}
|
||||
}
|
||||
publications {
|
||||
register("mavenJava", MavenPublication::class) {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("com.jetbrains.intellij.platform:workspace-model-codegen:LATEST-TRUNK-SNAPSHOT")
|
||||
implementation("com.jetbrains.intellij.platform:workspace-model-storage:223.8836.34")
|
||||
}
|
||||
Binary file not shown.
-6
@@ -1,6 +0,0 @@
|
||||
#Fri Mar 10 15:27:35 AMT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
-234
@@ -1,234 +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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/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="Gradle"
|
||||
APP_BASE_NAME=${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='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
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 GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_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 -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -1,89 +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 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 Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "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%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="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,2 +0,0 @@
|
||||
rootProject.name = "workspace-model-codegen-impl"
|
||||
|
||||
-343
@@ -1,343 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.OwnProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.javaType
|
||||
import com.intellij.workspaceModel.codegen.writer.LinesBuilder
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
|
||||
class InterfaceTraverser {
|
||||
fun traverse(myInterface: ObjClass<*>, visitor: InterfaceVisitor): Boolean {
|
||||
for (field in myInterface.fields) {
|
||||
val res = traverseField(field, visitor, field.name)
|
||||
if (!res) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun traverseField(field: OwnProperty<*, *>, visitor: InterfaceVisitor, varName: String): Boolean {
|
||||
return traverseType(field.valueType, visitor, varName)
|
||||
}
|
||||
|
||||
private fun traverseType(type: ValueType<*>, visitor: InterfaceVisitor, varName: String): Boolean {
|
||||
when (type) {
|
||||
is ValueType.Boolean -> return visitor.visitBoolean(varName)
|
||||
is ValueType.Int -> return visitor.visitInt(varName)
|
||||
is ValueType.String -> return visitor.visitString(varName)
|
||||
is ValueType.Collection<*, *> -> {
|
||||
val itemVarName = "_$varName"
|
||||
val shouldProcessList = visitor.visitListStart(varName, itemVarName, type.elementType)
|
||||
if (!shouldProcessList) return false
|
||||
val traversingResult = traverseType(type.elementType, visitor, itemVarName)
|
||||
return visitor.visitListEnd(varName, itemVarName, traversingResult, type.elementType)
|
||||
}
|
||||
|
||||
is ValueType.Map<*, *> -> {
|
||||
val keyVarName = "key_$varName"
|
||||
val valueVarName = "value_$varName"
|
||||
val shouldProcessMap = visitor.visitMapStart(varName, keyVarName, valueVarName, type.keyType, type.valueType)
|
||||
if (!shouldProcessMap) return false
|
||||
|
||||
val keyTraverseResult = traverseType(type.keyType, visitor, keyVarName)
|
||||
val valueTraverseResult = traverseType(type.valueType, visitor, valueVarName)
|
||||
|
||||
return visitor.visitMapEnd(varName, keyVarName, valueVarName, type.keyType, type.valueType,
|
||||
keyTraverseResult && valueTraverseResult)
|
||||
}
|
||||
is ValueType.Optional<*> -> {
|
||||
val notNullVarName = "_$varName"
|
||||
var continueProcess = visitor.visitOptionalStart(varName, notNullVarName, type.type)
|
||||
if (!continueProcess) return false
|
||||
|
||||
continueProcess = traverseType(type.type, visitor, notNullVarName)
|
||||
return visitor.visitOptionalEnd(varName, notNullVarName, type.type, continueProcess)
|
||||
}
|
||||
is ValueType.Blob<*> -> {
|
||||
return visitor.visitUnknownBlob(varName, type.javaClassName)
|
||||
/*
|
||||
|
||||
|
||||
var process = visitor.visitKnownBlobStart(varName, type.javaSimpleName)
|
||||
if (!process) return false
|
||||
|
||||
process = traverse(foundType, visitor)
|
||||
return visitor.visitKnownBlobFinish(varName, type.javaSimpleName, process)
|
||||
*/
|
||||
}
|
||||
is ValueType.DataClass<*> -> {
|
||||
var process = visitor.visitDataClassStart(varName, type)
|
||||
if (!process) return false
|
||||
|
||||
//process = traverse(type, visitor)
|
||||
return visitor.visitDataClassEnd(varName, type, process)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class DeserializationVisitor(linesBuilder: LinesBuilder) : InterfaceVisitor {
|
||||
private val builders: ArrayDeque<LinesBuilder> = ArrayDeque<LinesBuilder>().also { it.add(linesBuilder) }
|
||||
private val builder: LinesBuilder
|
||||
get() = builders.last()
|
||||
|
||||
private var countersCounter = 0
|
||||
|
||||
override fun visitBoolean(varName: String): Boolean {
|
||||
builder.line("$varName = de.readBoolean()")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitInt(varName: String): Boolean {
|
||||
builder.line("$varName = de.readInt()")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitString(varName: String): Boolean {
|
||||
builder.line("$varName = de.readString()")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitListStart(varName: String, itemVarName: String, listArgumentType: ValueType<*>): Boolean {
|
||||
if (listArgumentType.isRefType()) return true
|
||||
|
||||
val sub = LinesBuilder(StringBuilder(), builder.indentLevel + 1)
|
||||
builders.add(sub)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitListEnd(varName: String, itemVarName: String, traverseResult: Boolean, listArgumentType: ValueType<*>): Boolean {
|
||||
if (listArgumentType.isRefType()) return true
|
||||
|
||||
val myInListBuilder = builders.removeLast()
|
||||
if (myInListBuilder.result.isNotBlank()) {
|
||||
val varCounter = "counter" + counter()
|
||||
val varCollector = "collector" + counter()
|
||||
builder.line("val $varCounter = de.readInt()")
|
||||
builder.line("val $varCollector = ArrayList<${listArgumentType.javaType}>()")
|
||||
builder.line("var $itemVarName: ${listArgumentType.javaType}")
|
||||
builder.line("repeat($varCounter) {")
|
||||
myInListBuilder.line("$varCollector.add($itemVarName)")
|
||||
builder.result.append(myInListBuilder.result)
|
||||
builder.line("}")
|
||||
builder.line("$varName = $varCollector")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitMapStart(varName: String,
|
||||
keyVarName: String,
|
||||
valueVarName: String,
|
||||
keyType: ValueType<*>,
|
||||
valueType: ValueType<*>): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitMapEnd(varName: String,
|
||||
keyVarName: String,
|
||||
valueVarName: String,
|
||||
keyType: ValueType<*>,
|
||||
valueType: ValueType<*>,
|
||||
traverseResult: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitOptionalStart(varName: String, notNullVarName: String, type: ValueType<*>): Boolean {
|
||||
if (type.isRefType()) return true
|
||||
|
||||
val sub = LinesBuilder(StringBuilder(), builder.indentLevel + 1)
|
||||
builders.add(sub)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitOptionalEnd(varName: String, notNullVarName: String, type: ValueType<*>, traverseResult: Boolean): Boolean {
|
||||
if (type.isRefType()) return true
|
||||
|
||||
val popLast = builders.removeLast()
|
||||
builder.section("if (de.acceptNull())") {
|
||||
line("$varName = null")
|
||||
}
|
||||
builder.section("else") {
|
||||
if (popLast.result.isNotBlank()) {
|
||||
line("val $notNullVarName: ${type.javaType}")
|
||||
result.append(popLast.result)
|
||||
line("$varName = $notNullVarName")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitUnknownBlob(varName: String, javaSimpleName: String): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitKnownBlobStart(varName: String, javaSimpleName: String): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitKnownBlobFinish(varName: String, javaSimpleName: String, traverseResult: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitDataClassStart(varName: String, dataClass: ValueType.DataClass<*>): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun visitDataClassEnd(varName: String, dataClass: ValueType.DataClass<*>, traverseResult: Boolean): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
private fun counter(): Int {
|
||||
return countersCounter++
|
||||
}
|
||||
}
|
||||
|
||||
class SerializatorVisitor private constructor(private val linesBuilder: ArrayDeque<LinesBuilder>) : InterfaceVisitor {
|
||||
|
||||
constructor(linesBuilder: LinesBuilder) : this(ArrayDeque<LinesBuilder>().also { it.add(linesBuilder) })
|
||||
|
||||
val builder: LinesBuilder
|
||||
get() = linesBuilder.last()
|
||||
|
||||
override fun visitBoolean(varName: String): Boolean {
|
||||
builder.line("ser.saveBoolean($varName)")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitInt(varName: String): Boolean {
|
||||
builder.line("ser.saveInt($varName)")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitString(varName: String): Boolean {
|
||||
builder.line("ser.saveString($varName)")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitListStart(varName: String, itemVarName: String, listArgumentType: ValueType<*>): Boolean {
|
||||
if (listArgumentType.isRefType()) return true
|
||||
|
||||
val sub = LinesBuilder(StringBuilder(), builder.indentLevel + 1)
|
||||
linesBuilder.add(sub)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitListEnd(varName: String, itemVarName: String, traverseResult: Boolean, listArgumentType: ValueType<*>): Boolean {
|
||||
if (listArgumentType.isRefType()) return true
|
||||
|
||||
val myInListBuilder = linesBuilder.removeLast()
|
||||
if (myInListBuilder.result.isNotBlank()) {
|
||||
builder.line("ser.saveInt($varName.size)")
|
||||
builder.line("for ($itemVarName in $varName) {")
|
||||
builder.result.append(myInListBuilder.result)
|
||||
builder.line("}")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitMapStart(varName: String,
|
||||
keyVarName: String,
|
||||
valueVarName: String,
|
||||
keyType: ValueType<*>,
|
||||
valueType: ValueType<*>): Boolean {
|
||||
if (keyType.isRefType() || valueType.isRefType()) return true
|
||||
|
||||
val sub = LinesBuilder(StringBuilder(), builder.indentLevel + 1)
|
||||
linesBuilder.add(sub)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitMapEnd(varName: String,
|
||||
keyVarName: String,
|
||||
valueVarName: String,
|
||||
keyType: ValueType<*>,
|
||||
valueType: ValueType<*>,
|
||||
traverseResult: Boolean): Boolean {
|
||||
if (keyType.isRefType() || valueType.isRefType()) return true
|
||||
|
||||
val inMapBuilder = linesBuilder.removeLast()
|
||||
if (inMapBuilder.result.isNotBlank()) {
|
||||
builder.line("ser.saveInt($varName.size)")
|
||||
builder.line("for (($keyVarName, $valueVarName) in $varName) {")
|
||||
builder.result.append(inMapBuilder.result)
|
||||
builder.line("}")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitOptionalStart(varName: String, notNullVarName: String, type: ValueType<*>): Boolean {
|
||||
if (type.isRefType()) return true
|
||||
|
||||
val sub = LinesBuilder(StringBuilder(), builder.indentLevel + 1)
|
||||
linesBuilder.add(sub)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitOptionalEnd(varName: String, notNullVarName: String, type: ValueType<*>, traverseResult: Boolean): Boolean {
|
||||
if (type.isRefType()) return true
|
||||
|
||||
val inMapBuilder = linesBuilder.removeLast()
|
||||
if (inMapBuilder.result.isNotBlank()) {
|
||||
builder.line("val $notNullVarName = $varName")
|
||||
builder.line("if ($notNullVarName != null) {")
|
||||
builder.result.append(inMapBuilder.result)
|
||||
builder.line("} else {")
|
||||
builder.line(" ser.saveNull()")
|
||||
builder.line("}")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitUnknownBlob(varName: String, javaSimpleName: String): Boolean {
|
||||
if (javaSimpleName == "EntitySource") return true
|
||||
builder.line("ser.saveBlob($varName, \"$javaSimpleName\")")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitKnownBlobStart(varName: String, javaSimpleName: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitKnownBlobFinish(varName: String, javaSimpleName: String, traverseResult: Boolean): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitDataClassStart(varName: String, dataClass: ValueType.DataClass<*>): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun visitDataClassEnd(varName: String, dataClass: ValueType.DataClass<*>, traverseResult: Boolean): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
interface InterfaceVisitor {
|
||||
fun visitBoolean(varName: String): Boolean
|
||||
fun visitInt(varName: String): Boolean
|
||||
fun visitString(varName: String): Boolean
|
||||
|
||||
fun visitListStart(varName: String, itemVarName: String, listArgumentType: ValueType<*>): Boolean
|
||||
fun visitListEnd(varName: String, itemVarName: String, traverseResult: Boolean, listArgumentType: ValueType<*>): Boolean
|
||||
|
||||
fun visitMapStart(varName: String, keyVarName: String, valueVarName: String, keyType: ValueType<*>, valueType: ValueType<*>): Boolean
|
||||
fun visitMapEnd(varName: String,
|
||||
keyVarName: String,
|
||||
valueVarName: String,
|
||||
keyType: ValueType<*>,
|
||||
valueType: ValueType<*>,
|
||||
traverseResult: Boolean): Boolean
|
||||
|
||||
fun visitOptionalStart(varName: String, notNullVarName: String, type: ValueType<*>): Boolean
|
||||
fun visitOptionalEnd(varName: String, notNullVarName: String, type: ValueType<*>, traverseResult: Boolean): Boolean
|
||||
|
||||
fun visitUnknownBlob(varName: String, javaSimpleName: String): Boolean
|
||||
fun visitKnownBlobStart(varName: String, javaSimpleName: String): Boolean
|
||||
fun visitKnownBlobFinish(varName: String, javaSimpleName: String, traverseResult: Boolean): Boolean
|
||||
|
||||
fun visitDataClassStart(varName: String, dataClass: ValueType.DataClass<*>): Boolean
|
||||
fun visitDataClassEnd(varName: String, dataClass: ValueType.DataClass<*>, traverseResult: Boolean): Boolean
|
||||
}
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.engine.impl
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import com.intellij.workspaceModel.codegen.engine.CodeGenerator
|
||||
import com.intellij.workspaceModel.codegen.engine.GeneratedCode
|
||||
import com.intellij.workspaceModel.codegen.engine.GenerationProblem
|
||||
import com.intellij.workspaceModel.codegen.engine.GenerationResult
|
||||
import com.intellij.workspaceModel.codegen.writer.generateBuilderCode
|
||||
import com.intellij.workspaceModel.codegen.writer.generateCompanionObject
|
||||
import com.intellij.workspaceModel.codegen.writer.generateExtensionCode
|
||||
import com.intellij.workspaceModel.codegen.writer.implWsCode
|
||||
|
||||
class CodeGeneratorImpl : CodeGenerator {
|
||||
override fun generate(module: CompiledObjModule): GenerationResult {
|
||||
val problems = ArrayList<GenerationProblem>()
|
||||
val reporter = ProblemReporter { problems.add(it) }
|
||||
val objClassToBuilderInterface = module.types.associateWith {
|
||||
val builderInterface = it.generateBuilderCode(reporter)
|
||||
builderInterface
|
||||
}
|
||||
// If there is at least one error, report them and stop any further calculations and
|
||||
if (problems.any { it.level == GenerationProblem.Level.ERROR }) {
|
||||
return GenerationResult(emptyList(), problems)
|
||||
}
|
||||
|
||||
val code = objClassToBuilderInterface.map { (objClass, builderInterface) ->
|
||||
GeneratedCode(
|
||||
target = objClass,
|
||||
builderInterface = builderInterface,
|
||||
companionObject = objClass.generateCompanionObject(),
|
||||
topLevelCode = objClass.generateExtensionCode(),
|
||||
implementationClass = objClass.implWsCode()
|
||||
)
|
||||
}
|
||||
return GenerationResult(code, problems)
|
||||
}
|
||||
}
|
||||
|
||||
fun interface ProblemReporter {
|
||||
fun reportProblem(problem: GenerationProblem)
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
class LinesBuilder(
|
||||
val result: StringBuilder,
|
||||
val indentLevel: Int,
|
||||
val indentSize: Int = 4
|
||||
) {
|
||||
var first = true
|
||||
|
||||
fun line(str: String = "") {
|
||||
lineNoNl(str)
|
||||
result.append('\n')
|
||||
}
|
||||
|
||||
fun lineNoNl(str: String) {
|
||||
if (first) {
|
||||
first = false
|
||||
}
|
||||
|
||||
result.append(" ".repeat(indentLevel * indentSize))
|
||||
result.append(str)
|
||||
}
|
||||
|
||||
fun <T> list(c: Collection<T>, f: T.() -> String = { "$this" }) {
|
||||
c.forEach {
|
||||
line(it.f())
|
||||
}
|
||||
}
|
||||
|
||||
fun section(s: LinesBuilder.() -> Unit) {
|
||||
LinesBuilder(result, indentLevel + 1, indentSize).s()
|
||||
}
|
||||
|
||||
fun section(head: String, s: LinesBuilder.() -> Unit) {
|
||||
lineNoNl(head)
|
||||
val sub = LinesBuilder(result, indentLevel+1, indentSize)
|
||||
sub.result.append(" {\n")
|
||||
sub.s()
|
||||
line("}")
|
||||
}
|
||||
|
||||
fun sectionNoBrackets(head: String, s: LinesBuilder.() -> Unit) {
|
||||
lineNoNl(head)
|
||||
val sub = LinesBuilder(result, indentLevel+1, indentSize)
|
||||
sub.result.append("\n")
|
||||
sub.s()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun lines(level: Int = 0, lines: LinesBuilder.() -> Unit): String {
|
||||
val result = StringBuilder()
|
||||
LinesBuilder(result, level).lines()
|
||||
return result.toString()
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.storage.EntityStorage
|
||||
import com.intellij.workspaceModel.storage.MutableEntityStorage
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntity
|
||||
import com.intellij.workspaceModel.storage.impl.ConnectionId
|
||||
import com.intellij.workspaceModel.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.jvm.javaMethod
|
||||
|
||||
private const val fqnEscape = "#uC03o#"
|
||||
|
||||
fun fqn(function: KProperty1<KClass<*>, Collection<Any>>): QualifiedName = function.fqn
|
||||
fun fqn1(function: KFunction3<EntityStorage, ConnectionId, WorkspaceEntity, WorkspaceEntity?>): QualifiedName = function.fqn
|
||||
fun fqn2(function: KFunction3<EntityStorage, ConnectionId, WorkspaceEntity, Sequence<Any>>): QualifiedName = function.fqn
|
||||
fun fqn3(function: KFunction4<EntityStorage, ConnectionId, WorkspaceEntity, WorkspaceEntity?, Unit>): QualifiedName = function.fqn
|
||||
fun fqn4(function: KFunction4<EntityStorage, ConnectionId, WorkspaceEntity, List<WorkspaceEntity>, Unit>): QualifiedName = function.fqn
|
||||
fun fqn5(function: KFunction4<EntityStorage, ConnectionId, WorkspaceEntity, Sequence<WorkspaceEntity>, Unit>): QualifiedName = function.fqn
|
||||
fun fqn6(function: KFunction2<ModifiableWorkspaceEntityBase<*, *>, MutableEntityStorage, Unit>): QualifiedName = function.fqn
|
||||
fun fqn7(function: KFunction1<Collection<*>, Collection<*>>): QualifiedName = function.fqn
|
||||
|
||||
private val KProperty<*>.fqn: QualifiedName
|
||||
get() {
|
||||
val declaringClass = this.getter.javaMethod?.declaringClass ?: return "".toQualifiedName()
|
||||
return fqn(declaringClass.packageName, this.name)
|
||||
}
|
||||
|
||||
private val KFunction<*>.fqn: QualifiedName
|
||||
get() {
|
||||
val declaringClass = this.javaMethod?.declaringClass ?: return "".toQualifiedName()
|
||||
return fqn(declaringClass.packageName, this.name)
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class QualifiedName(val encodedString: String) {
|
||||
override fun toString(): String {
|
||||
return encodedString
|
||||
}
|
||||
|
||||
val decoded: String
|
||||
get() = encodedString.removePrefix(fqnEscape).substringBefore("#").replace("@@", ".")
|
||||
fun appendInner(innerClassPath: String): QualifiedName = QualifiedName("$encodedString.$innerClassPath")
|
||||
fun appendSuffix(suffix: String): QualifiedName = QualifiedName("$encodedString$suffix")
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary string for adding to imports
|
||||
*/
|
||||
fun fqn(packageName: String?, name: String): QualifiedName {
|
||||
if (packageName.isNullOrEmpty()) return QualifiedName(name)
|
||||
|
||||
val outerClassName = name.substringBefore(".")
|
||||
return QualifiedName("$fqnEscape$packageName@@$outerClassName#$name")
|
||||
}
|
||||
|
||||
fun String.toQualifiedName(): QualifiedName {
|
||||
val classNameMatch = Regex("\\.[A-Z]").find(this) ?: return QualifiedName(this)
|
||||
return fqn(substring(0, classNameMatch.range.first), substring(classNameMatch.range.last))
|
||||
}
|
||||
|
||||
val KClass<*>.fqn: QualifiedName
|
||||
get() = java.fqn
|
||||
|
||||
val Class<*>.fqn: QualifiedName
|
||||
get() {
|
||||
val name = name
|
||||
val packageName = name.substringBeforeLast(".")
|
||||
val className = name.substringAfterLast(".")
|
||||
.replace('$', '.')
|
||||
|
||||
if (className.contains(".")) {
|
||||
val outerClassName = className.substringBefore(".")
|
||||
val innerClassPath = className.substringAfter(".")
|
||||
return fqn(packageName, outerClassName).appendInner(innerClassPath)
|
||||
}
|
||||
else {
|
||||
return fqn(packageName, className)
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
|
||||
val ObjClass<*>.javaFullName: QualifiedName
|
||||
get() = fqn(module.name, name)
|
||||
|
||||
val ObjClass<*>.javaBuilderName: String
|
||||
get() = "$name.Builder"
|
||||
|
||||
val ObjClass<*>.javaImplName: String
|
||||
get() = "${name.replace(".", "")}Impl"
|
||||
|
||||
val ObjClass<*>.javaImplBuilderName
|
||||
get() = "${javaImplName}.Builder"
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.codegen.writer.classes.*
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.OwnProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.engine.GenerationProblem
|
||||
import com.intellij.workspaceModel.codegen.engine.ProblemLocation
|
||||
import com.intellij.workspaceModel.codegen.engine.SKIPPED_TYPES
|
||||
import com.intellij.workspaceModel.codegen.engine.impl.ProblemReporter
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.javaMutableType
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.javaType
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.wsCode
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn7
|
||||
import com.intellij.workspaceModel.codegen.writer.lines
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.storage.*
|
||||
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceList
|
||||
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceSet
|
||||
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
|
||||
import org.jetbrains.deft.ObjBuilder
|
||||
import org.jetbrains.deft.Type
|
||||
|
||||
fun ObjClass<*>.generateBuilderCode(reporter: ProblemReporter): String = lines {
|
||||
checkSuperTypes(this@generateBuilderCode, reporter)
|
||||
checkSymbolicId(this@generateBuilderCode, reporter)
|
||||
line("@${GeneratedCodeApiVersion::class.fqn}(${CodeGeneratorVersions.API_VERSION})")
|
||||
val (typeParameter, typeDeclaration) =
|
||||
if (openness.extendable) "T" to "<T: $javaFullName>" else javaFullName to ""
|
||||
val superBuilders = superTypes.filterIsInstance<ObjClass<*>>().filter { !it.isStandardInterface }.joinToString {
|
||||
", ${it.name}.Builder<$typeParameter>"
|
||||
}
|
||||
val header = "interface Builder$typeDeclaration: $javaFullName$superBuilders, ${WorkspaceEntity.Builder::class.fqn}<$typeParameter>, ${ObjBuilder::class.fqn}<$typeParameter>"
|
||||
|
||||
section(header) {
|
||||
list(allFields.noSymbolicId()) {
|
||||
checkProperty(this, reporter)
|
||||
wsBuilderApi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkSuperTypes(objClass: ObjClass<*>, reporter: ProblemReporter) {
|
||||
objClass.superTypes.filterIsInstance<ObjClass<*>>().forEach {superClass ->
|
||||
if (!superClass.openness.extendable) {
|
||||
reporter.reportProblem(GenerationProblem("Class '${superClass.name}' cannot be extended", GenerationProblem.Level.ERROR,
|
||||
ProblemLocation.Class(objClass)))
|
||||
}
|
||||
else if (!superClass.openness.openHierarchy && superClass.module != objClass.module) {
|
||||
reporter.reportProblem(GenerationProblem("Class '${superClass.name}' cannot be extended from other modules",
|
||||
GenerationProblem.Level.ERROR, ProblemLocation.Class(objClass)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSymbolicId(objClass: ObjClass<*>, reporter: ProblemReporter) {
|
||||
if (!objClass.isEntityWithSymbolicId) return
|
||||
if (objClass.openness == ObjClass.Openness.abstract) return
|
||||
if (objClass.fields.none { it.name == "symbolicId" }) {
|
||||
reporter.reportProblem(GenerationProblem("Class extends '${WorkspaceEntityWithSymbolicId::class.simpleName}' but " +
|
||||
"doesn't override 'WorkspaceEntityWithSymbolicId.getSymbolicId' property",
|
||||
GenerationProblem.Level.ERROR, ProblemLocation.Class(objClass)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkProperty(objProperty: ObjProperty<*, *>, reporter: ProblemReporter) {
|
||||
checkInheritance(objProperty, reporter)
|
||||
checkAllImmutable(objProperty, reporter)
|
||||
checkPropertyType(objProperty, reporter)
|
||||
}
|
||||
|
||||
fun checkInheritance(objProperty: ObjProperty<*, *>, reporter: ProblemReporter) {
|
||||
objProperty.receiver.allSuperClasses.mapNotNull { it.fieldsByName[objProperty.name] }.forEach { overriddenField ->
|
||||
if (!overriddenField.open) {
|
||||
reporter.reportProblem(
|
||||
GenerationProblem("Property '${overriddenField.receiver.name}::${overriddenField.name}' cannot be overridden",
|
||||
GenerationProblem.Level.ERROR, ProblemLocation.Property(objProperty)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyType(objProperty: ObjProperty<*, *>, reporter: ProblemReporter) {
|
||||
val errorMessage = when (val type = objProperty.valueType) {
|
||||
is ValueType.ObjRef<*> -> {
|
||||
if (type.child) "Child references should always be nullable"
|
||||
else null
|
||||
}
|
||||
else -> checkType(type)
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
reporter.reportProblem(GenerationProblem(errorMessage, GenerationProblem.Level.ERROR, ProblemLocation.Property(objProperty)))
|
||||
}
|
||||
}
|
||||
|
||||
fun checkAllImmutable(objProperty: ObjProperty<*, *>, reporter: ProblemReporter) {
|
||||
if (objProperty.mutable) {
|
||||
reporter.reportProblem(GenerationProblem("An immutable interface can't contain mutable properties", GenerationProblem.Level.ERROR, ProblemLocation.Property(objProperty)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkType(type: ValueType<*>): String? = when (type) {
|
||||
is ValueType.Optional -> when (type.type) {
|
||||
is ValueType.List<*> -> "Optional lists aren't supported"
|
||||
is ValueType.Set<*> -> "Optional sets aren't supported"
|
||||
else -> checkType(type.type)
|
||||
}
|
||||
is ValueType.Set<*> -> {
|
||||
if (type.elementType.isRefType()) {
|
||||
"Set of references isn't supported"
|
||||
}
|
||||
else checkType(type.elementType)
|
||||
}
|
||||
is ValueType.Map<*, *> -> {
|
||||
checkType(type.keyType) ?: checkType(type.valueType)
|
||||
}
|
||||
is ValueType.Blob<*> -> {
|
||||
if (!keepUnknownFields && type.javaClassName !in knownInterfaces) {
|
||||
"Unsupported type '${type.javaClassName}'"
|
||||
}
|
||||
else null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
private val keepUnknownFields: Boolean
|
||||
get() = java.lang.Boolean.getBoolean("workspace.model.generator.keep.unknown.fields")
|
||||
|
||||
private val knownInterfaces = setOf(
|
||||
VirtualFileUrl::class.qualifiedName!!,
|
||||
EntitySource::class.qualifiedName!!,
|
||||
SymbolicEntityId::class.qualifiedName!!,
|
||||
)
|
||||
|
||||
fun ObjClass<*>.generateCompanionObject(): String = lines {
|
||||
val builderGeneric = if (openness.extendable) "<$javaFullName>" else ""
|
||||
val companionObjectHeader = buildString {
|
||||
append("companion object: ${Type::class.fqn}<$javaFullName, Builder$builderGeneric>(")
|
||||
val base = superTypes.filterIsInstance<ObjClass<*>>().firstOrNull()
|
||||
if (base != null && base.name !in SKIPPED_TYPES)
|
||||
append(base.javaFullName)
|
||||
append(")")
|
||||
}
|
||||
val mandatoryFields = allFields.mandatoryFields()
|
||||
if (mandatoryFields.isNotEmpty()) {
|
||||
val fields = mandatoryFields.joinToString { "${it.name}: ${it.valueType.javaType}" }
|
||||
section(companionObjectHeader) {
|
||||
line("@${JvmOverloads::class.fqn}")
|
||||
line("@${JvmStatic::class.fqn}")
|
||||
line("@${JvmName::class.fqn}(\"create\")")
|
||||
section("operator fun invoke($fields, init: (Builder$builderGeneric.() -> Unit)? = null): $javaFullName") {
|
||||
line("val builder = builder()")
|
||||
list(mandatoryFields) {
|
||||
if (this.valueType is ValueType.Set<*> && !this.valueType.isRefType()) {
|
||||
"builder.$name = $name.${fqn7(Collection<*>::toMutableWorkspaceSet)}()"
|
||||
} else if (this.valueType is ValueType.List<*> && !this.valueType.isRefType()) {
|
||||
"builder.$name = $name.${fqn7(Collection<*>::toMutableWorkspaceList)}()"
|
||||
} else {
|
||||
"builder.$name = $name"
|
||||
}
|
||||
}
|
||||
line("init?.invoke(builder)")
|
||||
line("return builder")
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
section(companionObjectHeader) {
|
||||
line("@${JvmOverloads::class.fqn}")
|
||||
line("@${JvmStatic::class.fqn}")
|
||||
line("@${JvmName::class.fqn}(\"create\")")
|
||||
section("operator fun invoke(init: (Builder$builderGeneric.() -> Unit)? = null): $javaFullName") {
|
||||
line("val builder = builder()")
|
||||
line("init?.invoke(builder)")
|
||||
line("return builder")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun List<OwnProperty<*, *>>.mandatoryFields(): List<ObjProperty<*, *>> {
|
||||
var fields = this.noRefs().noOptional().noSymbolicId().noDefaultValue()
|
||||
if (fields.isNotEmpty()) {
|
||||
fields = fields.noEntitySource() + fields.single { it.name == "entitySource" }
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
fun ObjClass<*>.generateExtensionCode(): String? {
|
||||
val fields = module.extensions.filter { it.receiver == this || it.receiver.module != module && it.valueType.isRefType() && it.valueType.getRefType().target == this }
|
||||
if (openness.extendable && fields.isEmpty()) return null
|
||||
|
||||
return lines {
|
||||
if (!openness.extendable) {
|
||||
line("fun ${MutableEntityStorage::class.fqn}.modifyEntity(entity: $name, modification: $name.Builder.() -> Unit) = modifyEntity($name.Builder::class.java, entity, modification)")
|
||||
}
|
||||
fields.sortedWith(compareBy({ it.receiver.name }, { it.name })).forEach { line(it.wsCode) }
|
||||
}
|
||||
}
|
||||
|
||||
val ObjProperty<*, *>.wsBuilderApi: String
|
||||
get() {
|
||||
val returnType = if (valueType is ValueType.Collection<*, *> && !valueType.isRefType()) valueType.javaMutableType else valueType.javaType
|
||||
return "override var $javaName: $returnType"
|
||||
}
|
||||
|
||||
-316
@@ -1,316 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer.classes
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.javaMutableType
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.LinesBuilder
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn
|
||||
import com.intellij.workspaceModel.codegen.writer.lines
|
||||
import com.intellij.workspaceModel.codegen.writer.toQualifiedName
|
||||
import com.intellij.workspaceModel.codegen.writer.allFields
|
||||
import com.intellij.workspaceModel.storage.SymbolicEntityId
|
||||
import com.intellij.workspaceModel.storage.impl.indices.WorkspaceMutableIndex
|
||||
|
||||
internal fun ObjClass<*>.softLinksCode(context: LinesBuilder, hasSoftLinks: Boolean) {
|
||||
context.conditionalLine({ hasSoftLinks }, "override fun getLinks(): Set<${SymbolicEntityId::class.fqn}<*>>") {
|
||||
line("val result = HashSet<${SymbolicEntityId::class.fqn}<*>>()")
|
||||
operate(this) { line("result.add($it)") }
|
||||
line("return result")
|
||||
}
|
||||
|
||||
context.conditionalLine(
|
||||
{ hasSoftLinks },
|
||||
"override fun index(index: ${WorkspaceMutableIndex::class.fqn}<${SymbolicEntityId::class.fqn}<*>>)"
|
||||
) {
|
||||
operate(this) { line("index.index(this, $it)") }
|
||||
}
|
||||
|
||||
context.conditionalLine(
|
||||
{ hasSoftLinks },
|
||||
"override fun updateLinksIndex(prev: Set<${SymbolicEntityId::class.fqn}<*>>, index: ${WorkspaceMutableIndex::class.fqn}<${SymbolicEntityId::class.fqn}<*>>)"
|
||||
) {
|
||||
line("// TODO verify logic")
|
||||
line("val mutablePreviousSet = HashSet(prev)")
|
||||
operate(this) {
|
||||
line("val removedItem_${it.clean()} = mutablePreviousSet.remove($it)")
|
||||
section("if (!removedItem_${it.clean()})") {
|
||||
line("index.index(this, $it)")
|
||||
}
|
||||
}
|
||||
section("for (removed in mutablePreviousSet)") {
|
||||
line("index.remove(this, removed)")
|
||||
}
|
||||
}
|
||||
|
||||
context.conditionalLine(
|
||||
{ hasSoftLinks },
|
||||
"override fun updateLink(oldLink: ${SymbolicEntityId::class.fqn}<*>, newLink: ${SymbolicEntityId::class.fqn}<*>): Boolean"
|
||||
) {
|
||||
line("var changed = false")
|
||||
operateUpdateLink(this)
|
||||
line("return changed")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ObjClass<*>.hasSoftLinks(): Boolean {
|
||||
return fields.noSymbolicId().noRefs().any { field ->
|
||||
field.hasSoftLinks()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ObjProperty<*, *>.hasSoftLinks(): Boolean {
|
||||
if (name == "symbolicId") return false
|
||||
return valueType.hasSoftLinks()
|
||||
}
|
||||
|
||||
internal fun ValueType<*>.hasSoftLinks(): Boolean = when (this) {
|
||||
is ValueType.Blob -> isSymbolicId
|
||||
is ValueType.Collection<*, *> -> elementType.hasSoftLinks()
|
||||
is ValueType.Optional<*> -> type.hasSoftLinks()
|
||||
is ValueType.SealedClass<*> -> isSymbolicId || subclasses.any { it.hasSoftLinks() }
|
||||
is ValueType.DataClass<*> -> isSymbolicId || properties.any { it.type.hasSoftLinks() }
|
||||
else -> false
|
||||
}
|
||||
|
||||
val ValueType.JvmClass<*>.isSymbolicId: Boolean
|
||||
get() = SymbolicEntityId::class.java.name in javaSuperClasses
|
||||
|
||||
private fun ObjClass<*>.operate(
|
||||
context: LinesBuilder,
|
||||
operation: LinesBuilder.(String) -> Unit
|
||||
) {
|
||||
allFields.noSymbolicId().noRefs().forEach { field ->
|
||||
field.valueType.operate(field.name, context, operation)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ValueType<*>.operate(
|
||||
varName: String,
|
||||
context: LinesBuilder,
|
||||
operation: LinesBuilder.(String) -> Unit,
|
||||
generateNewName: Boolean = true,
|
||||
) {
|
||||
when (this) {
|
||||
is ValueType.JvmClass -> {
|
||||
when {
|
||||
isSymbolicId -> context.operation(varName)
|
||||
this is ValueType.SealedClass<*> -> processSealedClass(this, varName, context, operation, generateNewName)
|
||||
this is ValueType.DataClass<*> -> processDataClassProperties(varName, context, properties, operation)
|
||||
}
|
||||
}
|
||||
is ValueType.Collection<*, *> -> {
|
||||
val elementType = elementType
|
||||
|
||||
context.section("for (item in ${varName})") {
|
||||
elementType.operate("item", this@section, operation, false)
|
||||
}
|
||||
}
|
||||
is ValueType.Optional<*> -> {
|
||||
if (type is ValueType.JvmClass && (type as ValueType.JvmClass<*>).isSymbolicId) {
|
||||
context.line("val optionalLink_${varName.clean()} = $varName")
|
||||
context.`if`("optionalLink_${varName.clean()} != null") label@{
|
||||
type.operate("optionalLink_${varName.clean()}", this@label, operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun processDataClassProperties(varName: String,
|
||||
context: LinesBuilder,
|
||||
dataClassProperties: List<ValueType.DataClassProperty>,
|
||||
operation: LinesBuilder.(String) -> Unit) {
|
||||
for (property in dataClassProperties) {
|
||||
property.type.operate("$varName.${property.name}", context, operation)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processSealedClass(thisClass: ValueType.SealedClass<*>,
|
||||
varName: String,
|
||||
context: LinesBuilder,
|
||||
operation: LinesBuilder.(String) -> Unit,
|
||||
generateNewName: Boolean = true) {
|
||||
val newVarName = if (generateNewName) "_${varName.clean()}" else varName
|
||||
if (generateNewName) context.line("val $newVarName = $varName")
|
||||
context.section("when ($newVarName)") {
|
||||
listBuilder(thisClass.subclasses) { item ->
|
||||
val linesBuilder = LinesBuilder(StringBuilder(), context.indentLevel+1, context.indentSize).wrapper()
|
||||
if (item is ValueType.SealedClass) {
|
||||
processSealedClass(item, newVarName, linesBuilder, operation, generateNewName)
|
||||
}
|
||||
else if (item is ValueType.DataClass) {
|
||||
processDataClassProperties(newVarName, linesBuilder, item.properties, operation)
|
||||
}
|
||||
section("is ${item.javaClassName.toQualifiedName()} -> ") {
|
||||
result.append(linesBuilder.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun ObjClass<*>.operateUpdateLink(context: LinesBuilder) {
|
||||
allFields.noSymbolicId().noRefs().forEach { field ->
|
||||
val retType = field.valueType.processType(context, field.name)
|
||||
if (retType != null) {
|
||||
context.`if`("$retType != null") {
|
||||
if (field.valueType is ValueType.Set<*> && !field.valueType.isRefType()) {
|
||||
line("${field.name} = $retType as ${field.valueType.javaMutableType}")
|
||||
} else if (field.valueType is ValueType.List<*> && !field.valueType.isRefType()) {
|
||||
line("${field.name} = $retType as ${field.valueType.javaMutableType}")
|
||||
} else {
|
||||
line("${field.name} = $retType")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ValueType<*>.processType(
|
||||
context: LinesBuilder,
|
||||
varName: String,
|
||||
): String? {
|
||||
return when (this) {
|
||||
is ValueType.JvmClass -> {
|
||||
when {
|
||||
isSymbolicId -> {
|
||||
val name = "${varName.clean()}_data"
|
||||
context.lineNoNl("val $name = ")
|
||||
context.ifElse("$varName == oldLink", {
|
||||
line("changed = true")
|
||||
line("newLink as ${javaClassName.toQualifiedName()}")
|
||||
}) { line("null") }
|
||||
name
|
||||
}
|
||||
this is ValueType.SealedClass<*> -> {
|
||||
processSealedClass(this, varName, context)
|
||||
}
|
||||
this is ValueType.DataClass<*> -> {
|
||||
val updates = properties.mapNotNull label@{
|
||||
val retVar = it.type.processType(
|
||||
context,
|
||||
"$varName.${it.name}"
|
||||
)
|
||||
if (retVar != null) it.name to retVar else null
|
||||
}
|
||||
if (updates.isEmpty()) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
val name = "${varName.clean()}_data"
|
||||
context.line("var $name = $varName")
|
||||
updates.forEach { (fieldName, update) ->
|
||||
context.`if`("$update != null") {
|
||||
line("$name = $name.copy($fieldName = $update)")
|
||||
}
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
is ValueType.Collection<*, *> -> {
|
||||
var name: String? = "${varName.clean()}_data"
|
||||
val builder = lines(context.indentLevel) {
|
||||
section("val $name = $varName.map") label@{
|
||||
val returnVar = elementType.processType(
|
||||
this@label,
|
||||
"it"
|
||||
)
|
||||
if (returnVar != null) {
|
||||
ifElse("$returnVar != null", {
|
||||
line(returnVar)
|
||||
}) { line("it") }
|
||||
}
|
||||
else {
|
||||
name = null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
context.result.append(builder)
|
||||
}
|
||||
name
|
||||
}
|
||||
is ValueType.Optional<*> -> {
|
||||
var name: String? = "${varName.clean()}_data_optional"
|
||||
val builder = lines(context.indentLevel) {
|
||||
lineNoNl("var $name = ")
|
||||
ifElse("$varName != null", labelIf@{
|
||||
val returnVar = type.processType(
|
||||
this@labelIf,
|
||||
"$varName!!"
|
||||
)
|
||||
if (returnVar != null) {
|
||||
line(returnVar)
|
||||
}
|
||||
else {
|
||||
name = null
|
||||
}
|
||||
}) { line("null") }
|
||||
}
|
||||
if (name != null) {
|
||||
context.result.append(builder)
|
||||
}
|
||||
name
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun processSealedClass(thisClass: ValueType.SealedClass<*>,
|
||||
varName: String,
|
||||
context: LinesBuilder): String {
|
||||
val newVarName = "_${varName.clean()}"
|
||||
val resVarName = "res_${varName.clean()}"
|
||||
context.line("val $newVarName = $varName")
|
||||
context.lineNoNl("val $resVarName = ")
|
||||
context.section("when ($newVarName)") {
|
||||
listBuilder(thisClass.subclasses) { item ->
|
||||
section("is ${item.javaClassName.toQualifiedName()} -> ") label@{
|
||||
var sectionVarName = newVarName
|
||||
val properties: List<ValueType.DataClassProperty>
|
||||
if (item is ValueType.SealedClass) {
|
||||
sectionVarName = processSealedClass(item, sectionVarName, this)
|
||||
properties = emptyList()
|
||||
}
|
||||
else if (item is ValueType.DataClass) {
|
||||
properties = item.properties
|
||||
}
|
||||
else {
|
||||
properties = emptyList()
|
||||
}
|
||||
val updates = properties.mapNotNull {
|
||||
val retVar = it.type.processType(
|
||||
this@label,
|
||||
"$sectionVarName.${it.name}"
|
||||
)
|
||||
if (retVar != null) it.name to retVar else null
|
||||
}
|
||||
if (updates.isEmpty()) {
|
||||
line(sectionVarName)
|
||||
}
|
||||
else {
|
||||
val name = "${sectionVarName.clean()}_data"
|
||||
line("var $name = $sectionVarName")
|
||||
updates.forEach { (fieldName, update) ->
|
||||
`if`("$update != null") {
|
||||
line("$name = $name.copy($fieldName = $update)")
|
||||
}
|
||||
}
|
||||
line(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resVarName
|
||||
}
|
||||
|
||||
private fun String.clean(): String {
|
||||
return this.replace(".", "_").replace('!', '_')
|
||||
}
|
||||
-335
@@ -1,335 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer.classes
|
||||
|
||||
import com.intellij.workspaceModel.codegen.*
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.implWsDataFieldCode
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.implWsDataFieldInitializedCode
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.javaType
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.codegen.writer.allFields
|
||||
import com.intellij.workspaceModel.storage.*
|
||||
import com.intellij.workspaceModel.storage.impl.SoftLinkable
|
||||
import com.intellij.workspaceModel.storage.impl.UsedClassesCollector
|
||||
import com.intellij.workspaceModel.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceList
|
||||
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceSet
|
||||
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
|
||||
|
||||
/**
|
||||
* - Soft links
|
||||
* - with SymbolicId
|
||||
*/
|
||||
|
||||
val ObjClass<*>.javaDataName
|
||||
get() = "${name.replace(".", "")}Data"
|
||||
|
||||
val ObjClass<*>.isEntityWithSymbolicId: Boolean
|
||||
get() = superTypes.any {
|
||||
it is ObjClass<*> && (it.javaFullName.decoded == WorkspaceEntityWithSymbolicId::class.java.name || it.isEntityWithSymbolicId)
|
||||
}
|
||||
|
||||
fun ObjClass<*>.implWsDataClassCode(): String {
|
||||
val entityDataBaseClass = if (isEntityWithSymbolicId) {
|
||||
"${WorkspaceEntityData::class.fqn}.WithCalculableSymbolicId<$javaFullName>()"
|
||||
}
|
||||
else {
|
||||
"${WorkspaceEntityData::class.fqn}<$javaFullName>()"
|
||||
}
|
||||
val hasSoftLinks = hasSoftLinks()
|
||||
val softLinkable = if (hasSoftLinks) SoftLinkable::class.fqn else null
|
||||
return lines {
|
||||
section("class $javaDataName : ${sups(entityDataBaseClass, softLinkable?.encodedString)}") label@{
|
||||
listNl(allFields.noRefs().noEntitySource().noSymbolicId()) { implWsDataFieldCode }
|
||||
|
||||
listNl(allFields.noRefs().noEntitySource().noSymbolicId().noOptional().noDefaultValue()) { implWsDataFieldInitializedCode }
|
||||
|
||||
this@implWsDataClassCode.softLinksCode(this, hasSoftLinks)
|
||||
|
||||
sectionNl(
|
||||
"override fun wrapAsModifiable(diff: ${MutableEntityStorage::class.fqn}): ${WorkspaceEntity.Builder::class.fqn}<$javaFullName>") {
|
||||
line("val modifiable = $javaImplBuilderName(null)")
|
||||
line("modifiable.diff = diff")
|
||||
line("modifiable.snapshot = diff")
|
||||
line("modifiable.id = createEntityId()")
|
||||
line("return modifiable")
|
||||
}
|
||||
|
||||
// --- createEntity
|
||||
sectionNl("override fun createEntity(snapshot: ${EntityStorage::class.fqn}): $javaFullName") {
|
||||
section("return getCached(snapshot)") {
|
||||
line("val entity = $javaImplName(this)")
|
||||
line("entity.snapshot = snapshot")
|
||||
line("entity.id = createEntityId()")
|
||||
line("entity")
|
||||
}
|
||||
}
|
||||
|
||||
val collectionFields = allFields.noRefs().filter { it.valueType is ValueType.Collection<*, *> }
|
||||
if (collectionFields.isNotEmpty()) {
|
||||
sectionNl("override fun clone(): $javaDataName") {
|
||||
val fieldName = "clonedEntity"
|
||||
line("val $fieldName = super.clone()")
|
||||
line("$fieldName as $javaDataName")
|
||||
collectionFields.forEach { field ->
|
||||
if (field.valueType is ValueType.Set<*>) {
|
||||
line("$fieldName.${field.name} = $fieldName.${field.name}.${fqn7(Collection<*>::toMutableWorkspaceSet)}()")
|
||||
} else {
|
||||
line("$fieldName.${field.name} = $fieldName.${field.name}.${fqn7(Collection<*>::toMutableWorkspaceList)}()")
|
||||
}
|
||||
}
|
||||
line("return $fieldName")
|
||||
}
|
||||
}
|
||||
|
||||
if (isEntityWithSymbolicId) {
|
||||
val symbolicIdField = fields.first { it.name == "symbolicId" }
|
||||
val valueKind = symbolicIdField.valueKind
|
||||
val methodBody = (valueKind as ObjProperty.ValueKind.Computable).expression
|
||||
if (methodBody.contains("return")) {
|
||||
if (methodBody.startsWith("{")) {
|
||||
line("override fun symbolicId(): ${SymbolicEntityId::class.fqn}<*> $methodBody \n")
|
||||
} else {
|
||||
sectionNl("override fun symbolicId(): ${SymbolicEntityId::class.fqn}<*>") {
|
||||
line(methodBody)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sectionNl("override fun symbolicId(): ${SymbolicEntityId::class.fqn}<*>") {
|
||||
if (methodBody.startsWith("=")) {
|
||||
line("return ${methodBody.substring(2)}")
|
||||
}
|
||||
else {
|
||||
line("return $methodBody")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- getEntityInterface method
|
||||
sectionNl("override fun getEntityInterface(): Class<out ${WorkspaceEntity::class.fqn}>") {
|
||||
line("return $name::class.java")
|
||||
}
|
||||
|
||||
sectionNl("override fun serialize(ser: ${EntityInformation.Serializer::class.fqn})") {
|
||||
//InterfaceTraverser(simpleTypes).traverse(this@implWsDataClassCode, SerializatorVisitor(this@sectionNl))
|
||||
}
|
||||
|
||||
sectionNl("override fun deserialize(de: ${EntityInformation.Deserializer::class.fqn})") {
|
||||
//InterfaceTraverser(simpleTypes).traverse(this@implWsDataClassCode, DeserializationVisitor(this@sectionNl))
|
||||
}
|
||||
|
||||
sectionNl("override fun createDetachedEntity(parents: List<${WorkspaceEntity::class.fqn}>): ${WorkspaceEntity::class.fqn}") {
|
||||
val noRefs = allFields.noRefs().noSymbolicId()
|
||||
val mandatoryFields = allFields.mandatoryFields()
|
||||
val constructor = mandatoryFields.joinToString(", ") { it.name }.let { if (it.isNotBlank()) "($it)" else "" }
|
||||
val optionalFields = noRefs.filterNot { it in mandatoryFields }
|
||||
|
||||
section("return $javaFullName$constructor") {
|
||||
optionalFields.forEach {
|
||||
line("this.${it.name} = this@$javaDataName.${it.name}")
|
||||
}
|
||||
allRefsFields.filterNot { it.valueType.getRefType().child }.forEach {
|
||||
val parentType = it.valueType
|
||||
if (parentType is ValueType.Optional) {
|
||||
line("this.${it.name} = parents.filterIsInstance<${parentType.type.javaType}>().singleOrNull()")
|
||||
} else {
|
||||
line("parents.filterIsInstance<${parentType.javaType}>().singleOrNull()?.let { this.${it.name} = it }")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sectionNl("override fun getRequiredParents(): List<Class<out WorkspaceEntity>>") {
|
||||
line("val res = mutableListOf<Class<out WorkspaceEntity>>()")
|
||||
allRefsFields.filterNot { it.valueType.getRefType().child }.forEach {
|
||||
val parentType = it.valueType
|
||||
if (parentType !is ValueType.Optional) {
|
||||
line("res.add(${parentType.javaType}::class.java)")
|
||||
}
|
||||
}
|
||||
line("return res")
|
||||
}
|
||||
|
||||
// --- equals
|
||||
val keyFields = allFields.filter { it.isKey }
|
||||
sectionNl("override fun equals(other: Any?): Boolean") {
|
||||
line("if (other == null) return false")
|
||||
line("if (this.javaClass != other.javaClass) return false")
|
||||
|
||||
lineWrapped("other as $javaDataName")
|
||||
|
||||
list(allFields.noRefs().noSymbolicId()) {
|
||||
"if (this.$name != other.$name) return false"
|
||||
}
|
||||
|
||||
line("return true")
|
||||
}
|
||||
|
||||
// --- equalsIgnoringEntitySource
|
||||
sectionNl("override fun equalsIgnoringEntitySource(other: Any?): Boolean") {
|
||||
line("if (other == null) return false")
|
||||
line("if (this.javaClass != other.javaClass) return false")
|
||||
|
||||
lineWrapped("other as $javaDataName")
|
||||
|
||||
list(allFields.noRefs().noEntitySource().noSymbolicId()) {
|
||||
"if (this.$name != other.$name) return false"
|
||||
}
|
||||
|
||||
line("return true")
|
||||
}
|
||||
|
||||
// --- hashCode
|
||||
section("override fun hashCode(): Int") {
|
||||
line("var result = entitySource.hashCode()")
|
||||
list(allFields.noRefs().noEntitySource().noSymbolicId()) {
|
||||
"result = 31 * result + $name.hashCode()"
|
||||
}
|
||||
line("return result")
|
||||
}
|
||||
|
||||
// --- hashCodeIgnoringEntitySource
|
||||
section("override fun hashCodeIgnoringEntitySource(): Int") {
|
||||
line("var result = javaClass.hashCode()")
|
||||
list(allFields.noRefs().noEntitySource().noSymbolicId()) {
|
||||
"result = 31 * result + $name.hashCode()"
|
||||
}
|
||||
line("return result")
|
||||
}
|
||||
|
||||
if (keyFields.isNotEmpty()) {
|
||||
line()
|
||||
section("override fun equalsByKey(other: Any?): Boolean") {
|
||||
line("if (other == null) return false")
|
||||
line("if (this.javaClass != other.javaClass) return false")
|
||||
|
||||
lineWrapped("other as $javaDataName")
|
||||
|
||||
list(keyFields) {
|
||||
"if (this.$name != other.$name) return false"
|
||||
}
|
||||
|
||||
line("return true")
|
||||
}
|
||||
line()
|
||||
section("override fun hashCodeByKey(): Int") {
|
||||
line("var result = javaClass.hashCode()")
|
||||
list(keyFields) {
|
||||
"result = 31 * result + $name.hashCode()"
|
||||
}
|
||||
line("return result")
|
||||
}
|
||||
}
|
||||
|
||||
cacheCollector(this@lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun List<ObjProperty<*, *>>.noRefs(): List<ObjProperty<*, *>> = this.filterNot { it.valueType.isRefType() }
|
||||
fun List<ObjProperty<*, *>>.noEntitySource() = this.filter { it.name != "entitySource" }
|
||||
fun List<ObjProperty<*, *>>.noSymbolicId() = this.filter { it.name != "symbolicId" }
|
||||
fun List<ObjProperty<*, *>>.noOptional() = this.filter { it.valueType !is ValueType.Optional<*> }
|
||||
fun List<ObjProperty<*, *>>.noDefaultValue() = this.filter { it.valueKind == ObjProperty.ValueKind.Plain }
|
||||
|
||||
private fun ObjClass<*>.cacheCollector(linesBuilder: LinesBuilder) {
|
||||
val clazzes = HashSet<String>()
|
||||
val accessors = HashSet<String>()
|
||||
val objects = HashSet<String>()
|
||||
val res = allFields.map {
|
||||
it.valueType.getClasses(it.name, clazzes, accessors, objects)
|
||||
}.all{ it }
|
||||
linesBuilder.section("override fun collectClassUsagesData(collector: ${UsedClassesCollector::class.fqn})") {
|
||||
clazzes.forEach {
|
||||
line("collector.add(${it.toQualifiedName()}::class.java)")
|
||||
}
|
||||
objects.forEach {
|
||||
line("collector.addObject(${it.toQualifiedName()}::class.java)")
|
||||
}
|
||||
accessors.forEach {
|
||||
line(it)
|
||||
}
|
||||
line("collector.sameForAllEntities = $res")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ValueType<*>.getClasses(fieldName: String, clazzes: HashSet<String>, accessors: HashSet<String>, objects: HashSet<String>): Boolean {
|
||||
var res = true
|
||||
when (this) {
|
||||
is ValueType.List<*> -> {
|
||||
if (!this.isRefType()) {
|
||||
accessors.add("this.$fieldName?.let { collector.add(it::class.java) }")
|
||||
res = false
|
||||
}
|
||||
this.elementType.getClasses(fieldName, clazzes, accessors, objects)
|
||||
return res
|
||||
}
|
||||
is ValueType.Set<*> -> {
|
||||
if (!this.isRefType()) {
|
||||
accessors.add("this.$fieldName?.let { collector.add(it::class.java) }")
|
||||
res = false
|
||||
}
|
||||
this.elementType.getClasses(fieldName, clazzes, accessors, objects)
|
||||
return res
|
||||
}
|
||||
is ValueType.Blob -> {
|
||||
val className = this.javaClassName
|
||||
if (className !in setOf(VirtualFileUrl::class.java.name, EntitySource::class.java.name, SymbolicEntityId::class.java.name)) {
|
||||
accessors.add("this.$fieldName?.let { collector.addDataToInspect(it) }")
|
||||
return res
|
||||
}
|
||||
if (className == VirtualFileUrl::class.java.name) {
|
||||
accessors.add("this.$fieldName?.let { collector.add(it::class.java) }")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
is ValueType.Enum -> {
|
||||
val className = this.javaClassName
|
||||
clazzes.add(className)
|
||||
return res
|
||||
}
|
||||
is ValueType.DataClass -> {
|
||||
// Here we might filter SymbolicIds and get them from the index, but in this case we would need to inspect their fields on the fly
|
||||
// Here we have all the information about the symbolic ids and it's fields, so let's keep them here (at least for a while).
|
||||
clazzes.add(javaClassName)
|
||||
properties.forEach { property ->
|
||||
property.type.getClasses(fieldName, clazzes, accessors, objects)
|
||||
}
|
||||
return true
|
||||
}
|
||||
is ValueType.SealedClass -> {
|
||||
clazzes.add(javaClassName)
|
||||
this.subclasses.forEach { subclass ->
|
||||
subclass.getClasses(fieldName, clazzes, accessors, objects)
|
||||
}
|
||||
return true
|
||||
}
|
||||
is ValueType.Map<*, *> -> {
|
||||
if (!this.isRefType()) {
|
||||
accessors.add("this.$fieldName?.let { collector.add(it::class.java) }")
|
||||
res = false
|
||||
}
|
||||
this.keyType.getClasses(fieldName, clazzes, accessors, objects)
|
||||
this.valueType.getClasses(fieldName, clazzes, accessors, objects)
|
||||
return res
|
||||
}
|
||||
is ValueType.Optional -> {
|
||||
return this.type.getClasses(fieldName, clazzes, accessors, objects)
|
||||
}
|
||||
is ValueType.Structure -> {
|
||||
this.fields.forEach {
|
||||
it.getClasses(fieldName, clazzes, accessors, objects)
|
||||
}
|
||||
return true
|
||||
}
|
||||
is ValueType.Object<*> -> {
|
||||
objects.add(javaClassName)
|
||||
return true
|
||||
}
|
||||
else -> return true
|
||||
}
|
||||
}
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.classes
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.implWsBuilderFieldCode
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.implWsBuilderIsInitializedCode
|
||||
import com.intellij.workspaceModel.storage.MutableEntityStorage
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntity
|
||||
import com.intellij.workspaceModel.storage.bridgeEntities.LibraryEntity
|
||||
import com.intellij.workspaceModel.storage.impl.ConnectionId
|
||||
import com.intellij.workspaceModel.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.workspaceModel.storage.impl.containers.MutableWorkspaceList
|
||||
import com.intellij.workspaceModel.storage.impl.containers.MutableWorkspaceSet
|
||||
|
||||
fun ObjClass<*>.implWsEntityBuilderCode(): String {
|
||||
return """
|
||||
class Builder(result: $javaDataName?): ${ModifiableWorkspaceEntityBase::class.fqn}<$javaFullName, $javaDataName>(result), $javaBuilderName {
|
||||
constructor(): this($javaDataName())
|
||||
|
||||
${
|
||||
lines(2) {
|
||||
section("override fun applyToBuilder(builder: ${MutableEntityStorage::class.fqn})") {
|
||||
`if`("this.diff != null") {
|
||||
ifElse("existsInBuilder(builder)", {
|
||||
line("this.diff = builder")
|
||||
line("return")
|
||||
}) {
|
||||
line("error(\"Entity $name is already created in a different builder\")")
|
||||
}
|
||||
}
|
||||
line()
|
||||
line("this.diff = builder")
|
||||
line("this.snapshot = builder")
|
||||
line("addToBuilder()")
|
||||
line("this.id = getEntityData().createEntityId()")
|
||||
lineComment("After adding entity data to the builder, we need to unbind it and move the control over entity data to builder")
|
||||
lineComment("Builder may switch to snapshot at any moment and lock entity data to modification")
|
||||
line("this.currentEntityData = null")
|
||||
line()
|
||||
list(vfuFields) {
|
||||
"index(this, \"$name\", this.$name)"
|
||||
}
|
||||
if (name == LibraryEntity::class.simpleName) {
|
||||
line("indexLibraryRoots(${LibraryEntity::roots.name})")
|
||||
}
|
||||
lineComment("Process linked entities that are connected without a builder")
|
||||
line("processLinkedEntities(builder)")
|
||||
|
||||
//------------
|
||||
|
||||
line("checkInitialization() // TODO uncomment and check failed tests")
|
||||
}
|
||||
result.append("\n")
|
||||
|
||||
section("fun checkInitialization()") {
|
||||
line("val _diff = diff")
|
||||
list(allFields.noSymbolicId().noOptional().noDefaultValue()) { lineBuilder, field ->
|
||||
lineBuilder.implWsBuilderIsInitializedCode(field)
|
||||
}
|
||||
}
|
||||
|
||||
line()
|
||||
section("override fun connectionIdList(): List<${ConnectionId::class.fqn}>") {
|
||||
line("return connections")
|
||||
}
|
||||
line()
|
||||
|
||||
val collectionFields = allFields.noRefs().filter { it.valueType is ValueType.Collection<*,*> }
|
||||
if (collectionFields.isNotEmpty()) {
|
||||
section("override fun afterModification()") {
|
||||
collectionFields.forEach { field ->
|
||||
line("val collection_${field.javaName} = getEntityData().${field.javaName}")
|
||||
if (field.valueType is ValueType.List<*>) {
|
||||
`if`("collection_${field.javaName} is ${MutableWorkspaceList::class.fqn}<*>") {
|
||||
line("collection_${field.javaName}.cleanModificationUpdateAction()")
|
||||
}
|
||||
}
|
||||
if (field.valueType is ValueType.Set<*>) {
|
||||
`if`("collection_${field.javaName} is ${MutableWorkspaceSet::class.fqn}<*>") {
|
||||
line("collection_${field.javaName}.cleanModificationUpdateAction()")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
line()
|
||||
}
|
||||
|
||||
lineComment("Relabeling code, move information from dataSource to this builder")
|
||||
section("override fun relabel(dataSource: ${WorkspaceEntity::class.fqn}, parents: Set<WorkspaceEntity>?)") {
|
||||
line("dataSource as $javaFullName")
|
||||
list(allFields.noSymbolicId().noRefs()) { lineBuilder, field ->
|
||||
var type = field.valueType
|
||||
var qm = ""
|
||||
if (type is ValueType.Optional<*>) {
|
||||
qm = "?"
|
||||
type = type.type
|
||||
}
|
||||
when (type) {
|
||||
is ValueType.List<*> -> lineBuilder.line("if (this.${field.name} != dataSource${qm}.${field.name}) this.${field.name} = dataSource${qm}.${field.name}${qm}.toMutableList()")
|
||||
is ValueType.Set<*> -> lineBuilder.line("if (this.${field.name} != dataSource${qm}.${field.name}) this.${field.name} = dataSource${qm}.${field.name}${qm}.toMutableSet()")
|
||||
is ValueType.Map<*, *> -> lineBuilder.line("if (this.${field.name} != dataSource${qm}.${field.name}) this.${field.name} = dataSource${qm}.${field.name}${qm}.toMutableMap()")
|
||||
else -> lineBuilder.line("if (this.${field.name} != dataSource${qm}.${field.name}) this.${field.name} = dataSource.${field.name}")
|
||||
}
|
||||
}
|
||||
|
||||
line("updateChildToParentReferences(parents)")
|
||||
}
|
||||
|
||||
if (name == LibraryEntity::class.simpleName) {
|
||||
section("private fun indexLibraryRoots(libraryRoots: List<LibraryRoot>)") {
|
||||
line("val jarDirectories = mutableSetOf<VirtualFileUrl>()")
|
||||
line("val libraryRootList = libraryRoots.map {")
|
||||
line(" if (it.inclusionOptions != LibraryRoot.InclusionOptions.ROOT_ITSELF) {")
|
||||
line(" jarDirectories.add(it.url)")
|
||||
line(" }")
|
||||
line(" it.url")
|
||||
line("}.toHashSet()")
|
||||
line("index(this, \"roots\", libraryRootList)")
|
||||
line("indexJarDirectories(this, jarDirectories)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${allFields.filter { it.name != "symbolicId" }.lines(" ") { implWsBuilderFieldCode }.trimEnd()}
|
||||
|
||||
override fun getEntityClass(): Class<$javaFullName> = $javaFullName::class.java
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.classes
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.implWsEntityFieldCode
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.refsConnectionId
|
||||
import com.intellij.workspaceModel.codegen.writer.fields.refsConnectionIdCode
|
||||
import com.intellij.workspaceModel.storage.CodeGeneratorVersions
|
||||
import com.intellij.workspaceModel.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.workspaceModel.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.workspaceModel.storage.impl.ConnectionId
|
||||
import com.intellij.workspaceModel.storage.impl.WorkspaceEntityBase
|
||||
|
||||
fun ObjClass<*>.implWsEntityCode(): String {
|
||||
return """
|
||||
package ${module.name}
|
||||
|
||||
@${GeneratedCodeApiVersion::class.fqn}(${CodeGeneratorVersions.API_VERSION})
|
||||
@${GeneratedCodeImplVersion::class.fqn}(${CodeGeneratorVersions.IMPL_VERSION})
|
||||
${if (openness.instantiatable) "open" else "abstract"} class $javaImplName(val dataSource: $javaDataName): $javaFullName, ${WorkspaceEntityBase::class.fqn}() {
|
||||
${
|
||||
"""
|
||||
companion object {
|
||||
${allRefsFields.lines(" ") { refsConnectionIdCode }.trimEnd()}
|
||||
|
||||
${getLinksOfConnectionIds(this)}
|
||||
}"""
|
||||
}
|
||||
|
||||
${allFields.filter { it.name !in listOf("entitySource", "symbolicId") }.lines(" ") { implWsEntityFieldCode }.trimEnd()}
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() = dataSource.entitySource
|
||||
|
||||
override fun connectionIdList(): List<${ConnectionId::class.fqn}> {
|
||||
return connections
|
||||
}
|
||||
|
||||
${implWsEntityBuilderCode().indentRestOnly(" ")}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun getLinksOfConnectionIds(type: ObjClass<*>): String {
|
||||
return lines(2) {
|
||||
line("val connections = listOf<${ConnectionId::class.fqn}>(")
|
||||
type.allRefsFields.forEach {
|
||||
line(" " + it.refsConnectionId + ",")
|
||||
}
|
||||
line(")")
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.classes
|
||||
|
||||
import com.intellij.workspaceModel.codegen.writer.LinesBuilder
|
||||
|
||||
internal fun LinesBuilder.lineWrapped(str: String) {
|
||||
line()
|
||||
line(str)
|
||||
line()
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.sectionNl(head: String, s: LinesBuilder.() -> Unit) {
|
||||
section(head, s)
|
||||
result.append("\n")
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.conditionalLine(predicate: () -> Boolean, head: String, s: LinesBuilder.() -> Unit) {
|
||||
if (predicate.invoke()) {
|
||||
section(head, s)
|
||||
result.append("\n")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> LinesBuilder.listNl(c: Collection<T>, f: T.() -> String = { "$this" }) {
|
||||
list(c, f)
|
||||
result.append("\n")
|
||||
}
|
||||
|
||||
internal fun <T> LinesBuilder.list(c: Collection<T>, func: (LinesBuilder, T) -> Unit) {
|
||||
c.forEach {
|
||||
func(this, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.`if`(condition: String, s: LinesBuilder.() -> Unit) {
|
||||
section("if ($condition)", s)
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.lineComment(text: String) {
|
||||
line("// $text")
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.`for`(condition: String, s: LinesBuilder.() -> Unit) {
|
||||
section("for ($condition)", s)
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.`else`(s: LinesBuilder.() -> Unit) {
|
||||
section("else", s)
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.ifElse(condition: String, s: LinesBuilder.() -> Unit, `else`: (LinesBuilder.() -> Unit)) {
|
||||
section("if ($condition)", s)
|
||||
section("else", `else`)
|
||||
}
|
||||
|
||||
internal fun <T> LinesBuilder.listBuilder(c: Collection<T>, f: LinesBuilder.(item: T) -> Unit) {
|
||||
c.forEach {
|
||||
this.f(it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun LinesBuilder.wrapper(): LinesBuilder {
|
||||
return LinesBuilder(result, indentLevel+1, indentSize)
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.codegen.writer.javaFullName
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.QualifiedName
|
||||
import com.intellij.workspaceModel.codegen.writer.toQualifiedName
|
||||
|
||||
val ValueType<*>.javaType: QualifiedName
|
||||
get() = when (this) {
|
||||
ValueType.Boolean -> "Boolean".toQualifiedName()
|
||||
ValueType.Int -> "Int".toQualifiedName()
|
||||
ValueType.String -> "String".toQualifiedName()
|
||||
is ValueType.List<*> -> "List".toQualifiedName().appendSuffix("<${elementType.javaType}>")
|
||||
is ValueType.Set<*> -> "Set".toQualifiedName().appendSuffix("<${elementType.javaType}>")
|
||||
is ValueType.Map<*, *> -> "Map".toQualifiedName().appendSuffix("<${keyType.javaType}, ${valueType.javaType}>")
|
||||
is ValueType.ObjRef -> target.javaFullName
|
||||
is ValueType.Optional<*> -> type.javaType.appendSuffix("?")
|
||||
is ValueType.JvmClass -> javaClassName.toQualifiedName()
|
||||
else -> throw UnsupportedOperationException("$this type isn't supported")
|
||||
}
|
||||
|
||||
val ValueType<*>.javaMutableType: QualifiedName
|
||||
get() = when (this) {
|
||||
is ValueType.List<*> -> "MutableList".toQualifiedName().appendSuffix("<${elementType.javaType}>")
|
||||
is ValueType.Set<*> -> "MutableSet".toQualifiedName().appendSuffix("<${elementType.javaType}>")
|
||||
is ValueType.Map<*, *> -> "MutableMap".toQualifiedName().appendSuffix("<${keyType.javaType}, ${valueType.javaType}>")
|
||||
is ValueType.Optional<*> -> type.javaMutableType.appendSuffix("?")
|
||||
else -> javaType
|
||||
}
|
||||
|
||||
|
||||
fun ValueType<*>.unsupportedTypeError(): Nothing = error("Unsupported field type: $this")
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.storage.EntityStorage
|
||||
import com.intellij.workspaceModel.storage.impl.*
|
||||
import com.intellij.workspaceModel.codegen.writer.getRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.refsFields
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
|
||||
val ObjProperty<*, *>.refsConnectionId: String
|
||||
get() = if (name == "parent") {
|
||||
val originalField = receiver.refsFields.first { it.valueType.javaType == valueType.javaType }
|
||||
"${originalField.name.uppercase()}_CONNECTION_ID"
|
||||
}
|
||||
else "${name.uppercase()}_CONNECTION_ID"
|
||||
|
||||
val ObjProperty<*, *>.refsConnectionIdCode: String
|
||||
get() = buildString {
|
||||
val ref = valueType.getRefType()
|
||||
val isListType = valueType is ValueType.List<*> || ((valueType as? ValueType.Optional<*>)?.type is ValueType.List<*>)
|
||||
|
||||
append("internal val $refsConnectionId: ${ConnectionId::class.fqn} = ConnectionId.create(")
|
||||
if (ref.child) {
|
||||
append("${receiver.name}::class.java, ${ref.javaType}::class.java,")
|
||||
}
|
||||
else {
|
||||
append("${ref.javaType}::class.java, ${receiver.name}::class.java,")
|
||||
}
|
||||
val isParentNullable = if (ref.child) {
|
||||
if (isListType) {
|
||||
if (ref.target.openness.extendable) {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_ABSTRACT_MANY,")
|
||||
}
|
||||
else {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_MANY,")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ref.target.openness.extendable) {
|
||||
append(" ConnectionId.ConnectionType.ABSTRACT_ONE_TO_ONE,")
|
||||
}
|
||||
else {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_ONE,")
|
||||
}
|
||||
}
|
||||
referencedField.valueType is ValueType.Optional<*>
|
||||
}
|
||||
else {
|
||||
val declaredReferenceFromParent = referencedField
|
||||
var valueType = declaredReferenceFromParent.valueType
|
||||
if (valueType is ValueType.Optional<*>) {
|
||||
valueType = valueType.type
|
||||
}
|
||||
if (valueType is ValueType.List<*>) {
|
||||
if (receiver.openness.extendable) {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_ABSTRACT_MANY,")
|
||||
}
|
||||
else {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_MANY,")
|
||||
}
|
||||
}
|
||||
else if (valueType is ValueType.ObjRef<*>) {
|
||||
if (receiver.openness.extendable) {
|
||||
append(" ConnectionId.ConnectionType.ABSTRACT_ONE_TO_ONE,")
|
||||
}
|
||||
else {
|
||||
append(" ConnectionId.ConnectionType.ONE_TO_ONE,")
|
||||
}
|
||||
}
|
||||
this@refsConnectionIdCode.valueType is ValueType.Optional<*>
|
||||
}
|
||||
append(" $isParentNullable)")
|
||||
}
|
||||
|
||||
fun ObjProperty<*, *>.refsConnectionMethodCode(genericType: String = ""): String {
|
||||
val ref = valueType.getRefType()
|
||||
val connectionName = name.uppercase() + "_CONNECTION_ID"
|
||||
val getterName = if (ref.child) {
|
||||
if (ref.target.openness.extendable)
|
||||
"${fqn1(EntityStorage::extractOneToAbstractOneChild)}$genericType"
|
||||
else
|
||||
"${fqn1(EntityStorage::extractOneToOneChild)}$genericType"
|
||||
}
|
||||
else {
|
||||
var valueType = referencedField.valueType
|
||||
if (valueType is ValueType.Optional<*>) {
|
||||
valueType = valueType.type
|
||||
}
|
||||
when (valueType) {
|
||||
is ValueType.List<*> -> if (receiver.openness.extendable)
|
||||
"${fqn1(EntityStorage::extractOneToAbstractManyParent)}$genericType"
|
||||
else
|
||||
"${fqn1(EntityStorage::extractOneToManyParent)}$genericType"
|
||||
is ValueType.ObjRef<*> -> if (receiver.openness.extendable)
|
||||
"${fqn1(EntityStorage::extractOneToAbstractOneParent)}$genericType"
|
||||
else
|
||||
"${fqn1(EntityStorage::extractOneToOneParent)}$genericType"
|
||||
else -> error("Unsupported reference type")
|
||||
}
|
||||
}
|
||||
return "$getterName($connectionName, this)"
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.hasSetter
|
||||
import com.intellij.workspaceModel.codegen.writer.isOverride
|
||||
import com.intellij.workspaceModel.codegen.writer.javaName
|
||||
|
||||
val ObjProperty<*, *>.implWsDataFieldCode: String
|
||||
get() = buildString {
|
||||
if (hasSetter) {
|
||||
if (isOverride && name !in listOf("name", "entitySource")) append(implWsBlockingCodeOverride)
|
||||
else append(implWsDataBlockingCode)
|
||||
}
|
||||
else {
|
||||
val expression = when (val kind = valueKind) {
|
||||
is ObjProperty.ValueKind.Computable -> kind.expression
|
||||
is ObjProperty.ValueKind.WithDefault -> kind.value
|
||||
else -> error(kind)
|
||||
}
|
||||
if (expression.startsWith("=")) {
|
||||
append("var $javaName: ${valueType.javaType} $expression")
|
||||
} else {
|
||||
append("var $javaName: ${valueType.javaType} = $expression")
|
||||
}
|
||||
}
|
||||
}
|
||||
private val ObjProperty<*, *>.implWsDataBlockingCode: String
|
||||
get() = implWsDataBlockCode(valueType, name)
|
||||
|
||||
private fun ObjProperty<*, *>.implWsDataBlockCode(fieldType: ValueType<*>, name: String, isOptional: Boolean = false): String {
|
||||
return when (fieldType) {
|
||||
ValueType.Int -> "var $javaName: ${fieldType.javaType} = 0"
|
||||
ValueType.Boolean -> "var $javaName: ${fieldType.javaType} = false"
|
||||
ValueType.String -> "lateinit var $javaName: String"
|
||||
is ValueType.ObjRef<*> -> error("Reference type at EntityData not supported")
|
||||
is ValueType.Collection<*, *> -> {
|
||||
if (fieldType.isRefType()) error("Reference type at EntityData not supported")
|
||||
if (!isOptional) {
|
||||
"lateinit var $javaName: ${fieldType.javaMutableType}"
|
||||
}
|
||||
else {
|
||||
"var $javaName: ${fieldType.javaMutableType}? = null"
|
||||
}
|
||||
}
|
||||
is ValueType.Map<*, *> -> {
|
||||
if (!isOptional) {
|
||||
"lateinit var $javaName: ${fieldType.javaType}"
|
||||
}
|
||||
else {
|
||||
"var $javaName: ${fieldType.javaType}? = null"
|
||||
}
|
||||
}
|
||||
is ValueType.Optional<*> -> when (fieldType.type) {
|
||||
ValueType.Int, ValueType.Boolean, ValueType.String -> "var $javaName: ${fieldType.javaType} = null"
|
||||
else -> implWsDataBlockCode(fieldType.type, name, true)
|
||||
}
|
||||
is ValueType.JvmClass -> {
|
||||
if (!isOptional) {
|
||||
"lateinit var $javaName: ${fieldType.javaType}"
|
||||
}
|
||||
else {
|
||||
"var $javaName: ${fieldType.javaType}? = null"
|
||||
}
|
||||
}
|
||||
else -> error("Unsupported field type: $this")
|
||||
}
|
||||
}
|
||||
|
||||
val ObjProperty<*, *>.implWsDataFieldInitializedCode: String
|
||||
get() = when (valueType) {
|
||||
is ValueType.Int, is ValueType.Boolean -> ""
|
||||
is ValueType.String, is ValueType.JvmClass, is ValueType.Collection<*, *>, is ValueType.Map<*, *> -> {
|
||||
val capitalizedFieldName = javaName.replaceFirstChar { it.titlecaseChar() }
|
||||
"fun is${capitalizedFieldName}Initialized(): Boolean = ::${javaName}.isInitialized"
|
||||
}
|
||||
else -> error("Unsupported field type: $this")
|
||||
}
|
||||
-354
@@ -1,354 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.codegen.writer.classes.*
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.getRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
import com.intellij.workspaceModel.codegen.writer.javaName
|
||||
import com.intellij.workspaceModel.storage.EntityStorage
|
||||
import com.intellij.workspaceModel.storage.bridgeEntities.LibraryRoot
|
||||
import com.intellij.workspaceModel.storage.impl.*
|
||||
import com.intellij.workspaceModel.storage.impl.containers.MutableWorkspaceList
|
||||
import com.intellij.workspaceModel.storage.impl.containers.MutableWorkspaceSet
|
||||
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
|
||||
|
||||
val ObjProperty<*, *>.implWsBuilderFieldCode: String
|
||||
get() = valueType.implWsBuilderBlockingCode(this)
|
||||
|
||||
private fun ValueType<*>.implWsBuilderBlockingCode(field: ObjProperty<*, *>, optionalSuffix: String = ""): String = when (this) {
|
||||
ValueType.Boolean, ValueType.Int -> """
|
||||
override var ${field.javaName}: ${field.valueType.javaMutableType}$optionalSuffix
|
||||
get() = getEntityData().${field.javaName}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
changedProperty.add("${field.javaName}")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
ValueType.String -> """
|
||||
override var ${field.javaName}: ${field.valueType.javaMutableType}
|
||||
get() = getEntityData().${field.javaName}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
changedProperty.add("${field.javaName}")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
is ValueType.ObjRef -> {
|
||||
val connectionName = field.refsConnectionId
|
||||
val getterSetterNames = field.refNames()
|
||||
|
||||
// Opposite field may be either one-to-one or one-to-many
|
||||
|
||||
val notNullAssertion = if (optionalSuffix.isBlank()) "!!" else ""
|
||||
lines {
|
||||
sectionNoBrackets("override var ${field.javaName}: $javaType$optionalSuffix") {
|
||||
section("get()") {
|
||||
line("val _diff = diff")
|
||||
line("return if (_diff != null) {")
|
||||
line(" _diff.${getterSetterNames.getter}($connectionName, this) ?: this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})]$notNullAssertion as$optionalSuffix $javaType")
|
||||
line("} else {")
|
||||
line(" this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})]$notNullAssertion as$optionalSuffix $javaType")
|
||||
line("}")
|
||||
}
|
||||
section("set(value)") {
|
||||
line("checkModificationAllowed()")
|
||||
line("val _diff = diff")
|
||||
`if`("_diff != null && value is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *> && value.diff == null") {
|
||||
backrefSetup(field)
|
||||
line("_diff.addEntity(value)")
|
||||
}
|
||||
section("if (_diff != null && (value !is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *> || value.diff != null))") {
|
||||
line("_diff.${getterSetterNames.setter}($connectionName, this, value)")
|
||||
}
|
||||
section("else") {
|
||||
backrefSetup(field)
|
||||
line()
|
||||
line("this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] = value")
|
||||
}
|
||||
line("changedProperty.add(\"${field.javaName}\")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is ValueType.List<*> -> {
|
||||
val elementType = this.elementType
|
||||
if (this.isRefType()) {
|
||||
val connectionName = field.refsConnectionId
|
||||
val notNullAssertion = if (optionalSuffix.isBlank()) "!!" else error("It's prohibited to have nullable reference list")
|
||||
if ((elementType as ValueType.ObjRef<*>).target.openness.extendable) {
|
||||
lines(level = 1) {
|
||||
sectionNoBrackets("override var ${field.javaName}: $javaType$optionalSuffix") {
|
||||
section("get()") {
|
||||
line("val _diff = diff")
|
||||
line("return if (_diff != null) {")
|
||||
line(" _diff.${fqn2(EntityStorage::extractOneToAbstractManyChildren)}<${elementType.javaType}>($connectionName, this)$notNullAssertion.toList() + (this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] as? $javaType ?: emptyList())")
|
||||
line("} else {")
|
||||
line(" this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] as $javaType ${if (notNullAssertion.isNotBlank()) "?: emptyList()" else ""}")
|
||||
line("}")
|
||||
}
|
||||
section("set(value)") {
|
||||
lineComment("Set list of ref types for abstract entities")
|
||||
line("checkModificationAllowed()")
|
||||
line("val _diff = diff")
|
||||
`if`("_diff != null") {
|
||||
`for`("item_value in value") {
|
||||
`if`("item_value is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *> && (item_value as? ${
|
||||
ModifiableWorkspaceEntityBase::class.fqn
|
||||
}<*, *>)?.diff == null") {
|
||||
lineComment("Backref setup before adding to store an abstract entity")
|
||||
backrefSetup(field, "item_value")
|
||||
line("_diff.addEntity(item_value)")
|
||||
}
|
||||
}
|
||||
line("_diff.${fqn5(EntityStorage::updateOneToAbstractManyChildrenOfParent)}($connectionName, this, value.asSequence())")
|
||||
}
|
||||
`else` {
|
||||
backrefListSetup(field)
|
||||
line()
|
||||
line("this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] = value")
|
||||
}
|
||||
line("changedProperty.add(\"${field.javaName}\")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lines {
|
||||
lineComment("List of non-abstract referenced types")
|
||||
line("var _${field.javaName}: $javaType? = emptyList()")
|
||||
sectionNoBrackets("override var ${field.javaName}: $javaType$optionalSuffix") {
|
||||
section("get()") {
|
||||
lineComment("Getter of the list of non-abstract referenced types")
|
||||
line("val _diff = diff")
|
||||
line("return if (_diff != null) {")
|
||||
line(" _diff.${fqn2(EntityStorage::extractOneToManyChildren)}<${elementType.javaType}>($connectionName, this)$notNullAssertion.toList() + (this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] as? $javaType ?: emptyList())")
|
||||
line("} else {")
|
||||
line(
|
||||
" this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] as? $javaType ${if (notNullAssertion.isNotBlank()) "?: emptyList()" else ""}")
|
||||
line("}")
|
||||
}
|
||||
section("set(value)") {
|
||||
lineComment("Setter of the list of non-abstract referenced types")
|
||||
line("checkModificationAllowed()")
|
||||
line("val _diff = diff")
|
||||
`if`("_diff != null") {
|
||||
`for`("item_value in value") {
|
||||
`if`("item_value is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *> && (item_value as? ${ModifiableWorkspaceEntityBase::class.fqn}<*, *>)?.diff == null") {
|
||||
lineComment("Backref setup before adding to store")
|
||||
backrefSetup(field, "item_value")
|
||||
line()
|
||||
line("_diff.addEntity(item_value)")
|
||||
}
|
||||
}
|
||||
line("_diff.${fqn4(EntityStorage::updateOneToManyChildrenOfParent)}($connectionName, this, value)")
|
||||
}
|
||||
`else` {
|
||||
backrefListSetup(field)
|
||||
line()
|
||||
line("this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] = value")
|
||||
}
|
||||
line("changedProperty.add(\"${field.javaName}\")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
"""
|
||||
private val ${field.javaName}Updater: (value: List<${elementType.javaType}>) -> Unit = { value ->
|
||||
${elementType.addVirtualFileIndex(field)}
|
||||
changedProperty.add("${field.javaName}")
|
||||
}
|
||||
override var ${field.javaName}: MutableList<${elementType.javaType}>
|
||||
get() {
|
||||
val collection_${field.javaName} = getEntityData().${field.javaName}
|
||||
if (collection_${field.javaName} !is ${MutableWorkspaceList::class.fqn}) return collection_${field.javaName}
|
||||
if (diff == null || modifiable.get()) {
|
||||
collection_${field.javaName}.setModificationUpdateAction(${field.javaName}Updater)
|
||||
} else {
|
||||
collection_${field.javaName}.cleanModificationUpdateAction()
|
||||
}
|
||||
return collection_${field.javaName}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
${field.javaName}Updater.invoke(value)
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
is ValueType.Set<*> -> {
|
||||
val elementType = this.elementType
|
||||
if (this.isRefType()) {
|
||||
error("Set of references is not supported")
|
||||
} else {
|
||||
"""
|
||||
private val ${field.javaName}Updater: (value: Set<${elementType.javaType}>) -> Unit = { value ->
|
||||
${elementType.addVirtualFileIndex(field)}
|
||||
changedProperty.add("${field.javaName}")
|
||||
}
|
||||
override var ${field.javaName}: MutableSet<${elementType.javaType}>
|
||||
get() {
|
||||
val collection_${field.javaName} = getEntityData().${field.javaName}
|
||||
if (collection_${field.javaName} !is ${MutableWorkspaceSet::class.fqn}) return collection_${field.javaName}
|
||||
if (diff == null || modifiable.get()) {
|
||||
collection_${field.javaName}.setModificationUpdateAction(${field.javaName}Updater)
|
||||
} else {
|
||||
collection_${field.javaName}.cleanModificationUpdateAction()
|
||||
}
|
||||
return collection_${field.javaName}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
${field.javaName}Updater.invoke(value)
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
is ValueType.Map<*, *> -> """
|
||||
override var ${field.javaName}: $javaType
|
||||
get() = getEntityData().${field.javaName}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
changedProperty.add("${field.javaName}")
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
is ValueType.Optional<*> -> type.implWsBuilderBlockingCode(field, "?")
|
||||
is ValueType.Structure<*> -> "//TODO: ${field.javaName}"
|
||||
is ValueType.JvmClass -> """
|
||||
override var ${field.javaName}: ${javaType.appendSuffix(optionalSuffix)}
|
||||
get() = getEntityData().${field.javaName}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).${field.javaName} = value
|
||||
changedProperty.add("${field.javaName}")
|
||||
${
|
||||
if (javaType.decoded == VirtualFileUrl::class.java.name)
|
||||
"""val _diff = diff
|
||||
| if (_diff != null) index(this, "${field.javaName}", value)
|
||||
""".trimMargin()
|
||||
else ""
|
||||
}
|
||||
}
|
||||
|
||||
""".trimIndent()
|
||||
else -> unsupportedTypeError()
|
||||
}
|
||||
|
||||
private fun LinesBuilder.backrefSetup(
|
||||
field: ObjProperty<*, *>,
|
||||
varName: String = "value",
|
||||
) {
|
||||
val referencedField = field.referencedField
|
||||
val type = referencedField.valueType
|
||||
val isChild = type.getRefType().child
|
||||
when (type) {
|
||||
is ValueType.List<*> -> {
|
||||
lineComment("Setting backref of the list")
|
||||
`if`("$varName is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *>") {
|
||||
line("val data = ($varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] as? List<Any> ?: emptyList()) + this")
|
||||
line("$varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] = data")
|
||||
}
|
||||
line("// else you're attaching a new entity to an existing entity that is not modifiable")
|
||||
}
|
||||
is ValueType.Set<*> -> {
|
||||
lineComment("Setting backref of the set")
|
||||
`if`("$varName is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *>") {
|
||||
line("val data = ($varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] as? Set<Any> ?: emptySet()) + this")
|
||||
line("$varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] = data")
|
||||
}
|
||||
line("// else you're attaching a new entity to an existing entity that is not modifiable")
|
||||
}
|
||||
is ValueType.Optional<*> -> {
|
||||
`if`("$varName is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *>") {
|
||||
line("$varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] = this")
|
||||
}
|
||||
line("// else you're attaching a new entity to an existing entity that is not modifiable")
|
||||
}
|
||||
is ValueType.ObjRef<*> -> {
|
||||
`if`("$varName is ${ModifiableWorkspaceEntityBase::class.fqn}<*, *>") {
|
||||
line("$varName.entityLinks[${EntityLink::class.fqn}($isChild, ${field.refsConnectionId})] = this")
|
||||
}
|
||||
line("// else you're attaching a new entity to an existing entity that is not modifiable")
|
||||
}
|
||||
else -> error("Unexpected")
|
||||
}
|
||||
}
|
||||
|
||||
private fun LinesBuilder.backrefListSetup(
|
||||
field: ObjProperty<*, *>,
|
||||
varName: String = "value",
|
||||
) {
|
||||
val itemName = "item_$varName"
|
||||
`for`("$itemName in $varName") {
|
||||
backrefSetup(field, itemName)
|
||||
}
|
||||
}
|
||||
|
||||
fun LinesBuilder.implWsBuilderIsInitializedCode(field: ObjProperty<*, *>) {
|
||||
val javaName = field.javaName
|
||||
when (field.valueType) {
|
||||
is ValueType.List<*> -> if (field.valueType.isRefType()) {
|
||||
lineComment("Check initialization for list with ref type")
|
||||
ifElse("_diff != null", {
|
||||
`if`("_diff.${fqn2(EntityStorage::extractOneToManyChildren)}<${WorkspaceEntityBase::class.fqn}>(${field.refsConnectionId}, this) == null") {
|
||||
line("error(\"Field ${field.receiver.name}#$javaName should be initialized\")")
|
||||
}
|
||||
}) {
|
||||
isInitializedBaseCode(field, "this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] == null")
|
||||
}
|
||||
}
|
||||
else {
|
||||
val capitalizedFieldName = javaName.replaceFirstChar { it.titlecaseChar() }
|
||||
isInitializedBaseCode(field, "!getEntityData().is${capitalizedFieldName}Initialized()")
|
||||
}
|
||||
is ValueType.ObjRef<*> -> {
|
||||
ifElse("_diff != null", {
|
||||
`if`("_diff.${field.refsConnectionMethodCode("<${WorkspaceEntityBase::class.fqn}>")} == null") {
|
||||
line("error(\"Field ${field.receiver.name}#$javaName should be initialized\")")
|
||||
}
|
||||
}) {
|
||||
isInitializedBaseCode(field, "this.entityLinks[${EntityLink::class.fqn}(${field.valueType.getRefType().child}, ${field.refsConnectionId})] == null")
|
||||
}.toString()
|
||||
}
|
||||
is ValueType.Int, is ValueType.Boolean -> return
|
||||
else -> {
|
||||
val capitalizedFieldName = javaName.replaceFirstChar { it.titlecaseChar() }
|
||||
isInitializedBaseCode(field, "!getEntityData().is${capitalizedFieldName}Initialized()")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LinesBuilder.isInitializedBaseCode(field: ObjProperty<*, *>, expression: String) {
|
||||
section("if ($expression)") {
|
||||
line("error(\"Field ${field.receiver.name}#${field.javaName} should be initialized\")")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ValueType<*>.addVirtualFileIndex(field: ObjProperty<*, *>): String {
|
||||
return when {
|
||||
this is ValueType.Blob && javaClassName == VirtualFileUrl::class.java.name ->
|
||||
"""val _diff = diff
|
||||
| if (_diff != null) index(this, "${field.javaName}", value)
|
||||
""".trimMargin()
|
||||
this is ValueType.JvmClass && javaClassName == LibraryRoot::class.java.name -> """
|
||||
val _diff = diff
|
||||
if (_diff != null) {
|
||||
indexLibraryRoots(value)
|
||||
}
|
||||
"""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.storage.EntityStorage
|
||||
import com.intellij.workspaceModel.storage.impl.*
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.*
|
||||
|
||||
data class RefMethods(val getter: QualifiedName, val setter: QualifiedName)
|
||||
|
||||
infix fun QualifiedName.getterWithSetter(setter: QualifiedName): RefMethods = RefMethods(this, setter)
|
||||
|
||||
fun ObjProperty<*, *>.refNames(): RefMethods {
|
||||
if (!valueType.isRefType()) error("Call this on ref field")
|
||||
return when (valueType) {
|
||||
is ValueType.ObjRef -> constructCode(valueType)
|
||||
is ValueType.Optional -> constructCode((this.valueType as ValueType.Optional<*>).type)
|
||||
is ValueType.List<*> -> fqn2(EntityStorage::extractOneToManyChildren) getterWithSetter fqn4(EntityStorage::updateOneToManyChildrenOfParent)
|
||||
else -> error("Call this on ref field")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ObjProperty<*, *>.constructCode(type: ValueType<*>): RefMethods {
|
||||
type as ValueType.ObjRef<*>
|
||||
|
||||
return if (type.child) {
|
||||
if (type.target.openness.extendable) {
|
||||
fqn1(EntityStorage::extractOneToAbstractOneChild) getterWithSetter fqn3(EntityStorage::updateOneToAbstractOneChildOfParent)
|
||||
}
|
||||
else {
|
||||
fqn1(EntityStorage::extractOneToOneChild) getterWithSetter fqn3(EntityStorage::updateOneToOneChildOfParent)
|
||||
}
|
||||
}
|
||||
else {
|
||||
var valueType = referencedField.valueType
|
||||
if (valueType is ValueType.Optional<*>) {
|
||||
valueType = valueType.type
|
||||
}
|
||||
when (valueType) {
|
||||
is ValueType.List<*> -> {
|
||||
if (receiver.openness.extendable) {
|
||||
fqn1(EntityStorage::extractOneToAbstractManyParent) getterWithSetter fqn3(EntityStorage::updateOneToAbstractManyParentOfChild)
|
||||
}
|
||||
else {
|
||||
fqn1(EntityStorage::extractOneToManyParent) getterWithSetter fqn3(EntityStorage::updateOneToManyParentOfChild)
|
||||
}
|
||||
}
|
||||
is ValueType.ObjRef<*> -> {
|
||||
if (receiver.openness.extendable) {
|
||||
fqn1(EntityStorage::extractOneToAbstractOneParent) getterWithSetter fqn3(EntityStorage::updateOneToAbstractOneParentOfChild)
|
||||
}
|
||||
else {
|
||||
fqn1(EntityStorage::extractOneToOneParent) getterWithSetter fqn3(EntityStorage::updateOneToOneParentOfChild)
|
||||
}
|
||||
}
|
||||
else -> error("Unsupported reference type")
|
||||
}
|
||||
}
|
||||
}
|
||||
-159
@@ -1,159 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.codegen.writer.getRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.isRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.refsFields
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn1
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn2
|
||||
import com.intellij.workspaceModel.codegen.writer.toQualifiedName
|
||||
import com.intellij.workspaceModel.codegen.writer.hasSetter
|
||||
import com.intellij.workspaceModel.codegen.writer.isOverride
|
||||
import com.intellij.workspaceModel.codegen.writer.javaName
|
||||
import com.intellij.workspaceModel.storage.EntityStorage
|
||||
import com.intellij.workspaceModel.storage.impl.*
|
||||
|
||||
val ObjProperty<*, *>.implWsEntityFieldCode: String
|
||||
get() = buildString {
|
||||
if (hasSetter) {
|
||||
if (isOverride && name !in listOf("name", "entitySource")) {
|
||||
append(implWsBlockingCodeOverride)
|
||||
}
|
||||
else append(implWsBlockingCode)
|
||||
} else {
|
||||
append("override var $javaName: ${valueType.javaType} = dataSource.$javaName\n")
|
||||
}
|
||||
}
|
||||
|
||||
private val ObjProperty<*, *>.implWsBlockingCode: String
|
||||
get() = implWsBlockCode(valueType, name, "")
|
||||
|
||||
internal fun ObjProperty<*, *>.implWsBlockCode(fieldType: ValueType<*>, name: String, optionalSuffix: String = ""): String {
|
||||
return when (fieldType) {
|
||||
ValueType.Int -> "override val $name: ${fieldType.javaType} get() = dataSource.$name"
|
||||
ValueType.Boolean -> "override val $name: ${fieldType.javaType} get() = dataSource.$name"
|
||||
ValueType.String -> """
|
||||
override val $name: ${fieldType.javaType}${optionalSuffix}
|
||||
get() = dataSource.$name
|
||||
|
||||
""".trimIndent()
|
||||
is ValueType.ObjRef -> {
|
||||
val notNullAssertion = if (optionalSuffix.isBlank()) "!!" else ""
|
||||
"""
|
||||
override val $name: ${fieldType.javaType}$optionalSuffix
|
||||
get() = snapshot.${refsConnectionMethodCode()}$notNullAssertion
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
is ValueType.List<*> -> {
|
||||
if (fieldType.isRefType()) {
|
||||
val connectionName = name.uppercase() + "_CONNECTION_ID"
|
||||
val notNullAssertion = if (optionalSuffix.isBlank()) "!!" else ""
|
||||
if ((fieldType.elementType as ValueType.ObjRef<*>).target.openness.extendable) {
|
||||
"""
|
||||
override val $name: ${fieldType.javaType}$optionalSuffix
|
||||
get() = snapshot.${fqn2(EntityStorage::extractOneToAbstractManyChildren)}<${fieldType.elementType.javaType}>($connectionName, this)$notNullAssertion.toList()
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
else {
|
||||
"""
|
||||
override val $name: ${fieldType.javaType}$optionalSuffix
|
||||
get() = snapshot.${fqn2(EntityStorage::extractOneToManyChildren)}<${fieldType.elementType.javaType}>($connectionName, this)$notNullAssertion.toList()
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
else {
|
||||
"""
|
||||
override val $name: ${fieldType.javaType}$optionalSuffix
|
||||
get() = dataSource.$name
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
is ValueType.Set<*> -> {
|
||||
if (fieldType.isRefType()) {
|
||||
error("Set of references is not supported")
|
||||
}
|
||||
else {
|
||||
"""
|
||||
override val $javaName: ${fieldType.javaType}$optionalSuffix
|
||||
get() = dataSource.$name
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
is ValueType.Map<*, *> -> """
|
||||
override val $name: ${fieldType.javaType}$optionalSuffix
|
||||
get() = dataSource.$name
|
||||
""".trimIndent()
|
||||
is ValueType.Optional<*> -> when (fieldType.type) {
|
||||
ValueType.Int, ValueType.Boolean -> "override val $name: ${fieldType.javaType} get() = dataSource.$name"
|
||||
else -> implWsBlockCode(fieldType.type, name, "?")
|
||||
}
|
||||
is ValueType.JvmClass -> """
|
||||
override val $name: ${fieldType.javaClassName.toQualifiedName()}$optionalSuffix
|
||||
get() = dataSource.$name
|
||||
|
||||
""".trimIndent()
|
||||
else -> error("Unsupported field type: $this")
|
||||
}
|
||||
}
|
||||
|
||||
internal val ObjProperty<*, *>.implWsBlockingCodeOverride: String
|
||||
get() {
|
||||
val originalField = receiver.refsFields.first { it.valueType.javaType == valueType.javaType }
|
||||
val connectionName = originalField.name.uppercase() + "_CONNECTION_ID"
|
||||
var valueType = referencedField.valueType
|
||||
val notNullAssertion = if (valueType is ValueType.Optional<*>) "" else "!!"
|
||||
if (valueType is ValueType.Optional<*>) {
|
||||
valueType = valueType.type
|
||||
}
|
||||
val getterName = when (valueType) {
|
||||
is ValueType.List<*> -> if (receiver.openness.extendable)
|
||||
fqn1(EntityStorage::extractOneToAbstractManyParent)
|
||||
else
|
||||
fqn1(EntityStorage::extractOneToManyParent)
|
||||
is ValueType.ObjRef<*> -> if (receiver.openness.extendable)
|
||||
fqn1(EntityStorage::extractOneToAbstractOneParent)
|
||||
else
|
||||
fqn1(EntityStorage::extractOneToOneParent)
|
||||
else -> error("Unsupported reference type")
|
||||
}
|
||||
return """
|
||||
override val $name: ${this.valueType.javaType}
|
||||
get() = snapshot.$getterName($connectionName, this)$notNullAssertion
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
internal val ObjProperty<*, *>.referencedField: ObjProperty<*, *>
|
||||
get() {
|
||||
val ref = valueType.getRefType()
|
||||
val declaredReferenceFromChild =
|
||||
ref.target.refsFields.filter { it.valueType.getRefType().target == receiver && it != this } +
|
||||
setOf(ref.target.module,
|
||||
receiver.module).flatMap { it.extensions }.filter { it.valueType.getRefType().target == receiver && it.receiver == ref.target && it != this }
|
||||
if (declaredReferenceFromChild.isEmpty()) {
|
||||
error("Reference should be declared at both entities. It exist at ${receiver.name}#$name but absent at ${ref.target.name}")
|
||||
}
|
||||
if (declaredReferenceFromChild.size > 1) {
|
||||
error("""
|
||||
|More then one reference to ${receiver.name} declared at ${declaredReferenceFromChild[0].receiver.name}#${declaredReferenceFromChild[0].name},
|
||||
|${declaredReferenceFromChild[1].receiver.name}#${declaredReferenceFromChild[1].name}
|
||||
|""".trimMargin())
|
||||
}
|
||||
val referencedField = declaredReferenceFromChild[0]
|
||||
if (this.valueType.getRefType().child == referencedField.valueType.getRefType().child) {
|
||||
val (childStr, fix) = if (this.valueType.getRefType().child) {
|
||||
"child" to "Have you @Child annotation on both sides?"
|
||||
}
|
||||
else {
|
||||
"parent" to "Did you forget to add @Child annotation?"
|
||||
}
|
||||
error("Both fields ${receiver.name}#$name and ${ref.target.name}#${referencedField.name} are marked as $childStr. $fix")
|
||||
}
|
||||
return referencedField
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer.fields
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ExtProperty
|
||||
import com.intellij.workspaceModel.codegen.writer.getRefType
|
||||
import com.intellij.workspaceModel.codegen.writer.javaBuilderName
|
||||
import com.intellij.workspaceModel.codegen.writer.fqn
|
||||
import com.intellij.workspaceModel.codegen.writer.lines
|
||||
import org.jetbrains.deft.annotations.Child
|
||||
|
||||
val ExtProperty<*, *>.wsCode: String
|
||||
get() = lines {
|
||||
val isChild = valueType.getRefType().child
|
||||
val annotation = if (isChild) "@${Child::class.fqn} " else ""
|
||||
sectionNoBrackets("var ${receiver.javaBuilderName}.$name: $annotation${valueType.javaType}") {
|
||||
line("by WorkspaceEntity.extension()")
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.OwnProperty
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntity
|
||||
import com.intellij.workspaceModel.storage.WorkspaceEntityWithSymbolicId
|
||||
|
||||
val ObjClass<*>.isStandardInterface: Boolean
|
||||
get() = name in setOf(WorkspaceEntity::class.java.simpleName, WorkspaceEntityWithSymbolicId::class.java.simpleName)
|
||||
|
||||
val ObjClass<*>.allSuperClasses: List<ObjClass<*>>
|
||||
get() = superTypes.filterIsInstance<ObjClass<*>>().flatMapTo(LinkedHashSet()) { it.allSuperClasses + listOf(it) }.toList()
|
||||
|
||||
val ObjClass<*>.allFields: List<OwnProperty<*, *>>
|
||||
get() {
|
||||
val fieldsByName = LinkedHashMap<String, OwnProperty<*, *>>()
|
||||
collectFields(this, fieldsByName)
|
||||
return fieldsByName.values.toList()
|
||||
}
|
||||
|
||||
private fun collectFields(objClass: ObjClass<*>, fieldsByName: MutableMap<String, OwnProperty<*, *>>) {
|
||||
for (superType in objClass.superTypes) {
|
||||
if (superType is ObjClass<*>) {
|
||||
collectFields(superType, fieldsByName)
|
||||
}
|
||||
}
|
||||
for (field in objClass.fields) {
|
||||
if (field.valueKind !is ObjProperty.ValueKind.Computable) {
|
||||
fieldsByName.remove(field.name)
|
||||
fieldsByName[field.name] = field
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val ObjProperty<*, *>.hasSetter: Boolean
|
||||
get() = open || valueKind == ObjProperty.ValueKind.Plain
|
||||
|
||||
val ObjProperty<*, *>.javaName: String
|
||||
get() = name
|
||||
|
||||
val ObjProperty<*, *>.isOverride: Boolean
|
||||
get() = receiver.allSuperClasses.any { name in it.fieldsByName }
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.OwnProperty
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
|
||||
|
||||
val ObjClass<*>.refsFields: List<OwnProperty<*, *>>
|
||||
get() = fields.filter { !it.isOverride && it.valueType.isRefType() }
|
||||
|
||||
val ObjClass<*>.allRefsFields: List<OwnProperty<*, *>>
|
||||
get() = allFields.filter { it.valueType.isRefType() }
|
||||
|
||||
val ObjClass<*>.vfuFields: List<OwnProperty<*, *>>
|
||||
get() = fields.filter { !it.isOverride && it.valueType.isVfuType() }
|
||||
|
||||
fun ValueType<*>.getRefType(): ValueType.ObjRef<*> = when (this) {
|
||||
is ValueType.ObjRef<*> -> this
|
||||
is ValueType.Optional<*> -> type.getRefType()
|
||||
is ValueType.Collection<*, *> -> elementType.getRefType()
|
||||
else -> error("Unsupported type of requester, should be called only if `isRefType` is true")
|
||||
}
|
||||
|
||||
fun ValueType<*>.isRefType(): Boolean = when (this) {
|
||||
is ValueType.ObjRef<*> -> true
|
||||
is ValueType.Optional<*> -> type.isRefType()
|
||||
is ValueType.Collection<*, *> -> elementType.isRefType()
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun ValueType<*>.isVfuType(): Boolean = when (this) {
|
||||
is ValueType.Blob -> javaClassName == VirtualFileUrl::class.java.name
|
||||
is ValueType.Optional<*> -> type.isVfuType()
|
||||
is ValueType.Collection<*, *> -> elementType.isVfuType()
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun sups(vararg extensions: String?): String = extensions.filterNotNull().joinToString(separator = ", ")
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
fun <T> Collection<T>.lines(f: T.() -> String = { "$this" }): String =
|
||||
mapNotNull { f(it).takeIf { item -> item.isNotBlank() } }.joinToString("\n")
|
||||
|
||||
fun <T> Collection<T>.lines(indent: String, f: T.() -> String = { "$this" }): String =
|
||||
mapNotNull { f(it).takeIf { item -> item.isNotBlank() } }.indent(indent)
|
||||
|
||||
fun Collection<String>.indent(indent: String): String = when {
|
||||
size > 1 -> first().indentRestOnly(indent) + "\n" +
|
||||
drop(1).joinToString("\n") { it.indentAll(indent) }
|
||||
size == 1 -> single().indentRestOnly(indent)
|
||||
else -> joinToString("\n") { it.indentAll(indent) }
|
||||
}
|
||||
|
||||
fun String.indentRestOnly(indent: String): String {
|
||||
val lines = lines()
|
||||
return when {
|
||||
lines.size > 1 -> lines.first() + "\n" + lines.drop(1).joinToString("\n") { "$indent$it" }
|
||||
lines.size == 1 -> lines.first()
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.indentAll(indent: String): String {
|
||||
return lines().joinToString("\n") { "$indent$it" }
|
||||
}
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.codegen.writer
|
||||
|
||||
import com.intellij.workspaceModel.codegen.writer.classes.implWsDataClassCode
|
||||
import com.intellij.workspaceModel.codegen.writer.classes.implWsEntityCode
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* - Abstract Class do
|
||||
* - This about mutable lists (custom implementation?)
|
||||
* - This about mutable lists for properties
|
||||
* - This about mutable lists for references
|
||||
* - Facet: 2 parents, how to implement?
|
||||
* Поправить генерилку, чтоб все было чисто без лишних строк (почистил в applyToBuilder)
|
||||
* factory: ObjType<ChildSubSubEntity, *>
|
||||
* hasNewValue -- Будем обсуждать с Сережей после НГ
|
||||
* setValue -- Будем обсуждать с Сережей после НГ
|
||||
* builder(): ObjBuilder<*>
|
||||
* Привести билдер в порядок: поля идут первыми, потом applyBuilder, потом все утильные методы..
|
||||
*
|
||||
* Done:
|
||||
* createReference проверить нужны ли они в ентити (не нужны, грохнул)
|
||||
* hasEqualProperties (забахали на всяк случай) // Там всего одно использование, посовещавшись мы решили хрохнуть его
|
||||
* Поправить импорты
|
||||
* Метод проверки, что все поля заиничены
|
||||
*
|
||||
* ---------------------------
|
||||
* Перенести тесты идеи к нам или наоборрот <--
|
||||
*/
|
||||
|
||||
fun ObjClass<*>.implWsCode(): String? {
|
||||
if (!openness.instantiatable) return null
|
||||
return """
|
||||
${implWsEntityCode()}
|
||||
|
||||
${implWsDataClassCode()}
|
||||
""".trimIndent()
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
com.intellij.workspaceModel.codegen.engine.impl.CodeGeneratorImpl
|
||||
Reference in New Issue
Block a user