Wizard: add shared code for iOS/Android template
fix android
This commit is contained in:
committed by
Kirill Shmakov
parent
66c756ad0f
commit
5ffcaf6508
+15
@@ -2,10 +2,25 @@ package ${package}
|
|||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
#if ($sharedPackage)
|
||||||
|
import ${sharedPackage}.Greeting
|
||||||
|
import android.widget.TextView
|
||||||
|
#end
|
||||||
|
|
||||||
|
#if( $sharedPackage )
|
||||||
|
fun greet(): String {
|
||||||
|
return Greeting().greeting()
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
|
#if( $sharedPackage )
|
||||||
|
val tv: TextView = findViewById(R.id.text_view)
|
||||||
|
tv.text = greet()
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-14
@@ -1,19 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
android:id="@+id/main_view"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Hello World!"
|
android:text="Hello World!"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:id="@+id/text_view"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"/>
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
+13
@@ -1,8 +1,21 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#if (${sharedModuleName})
|
||||||
|
import ${sharedModuleName}
|
||||||
|
#end
|
||||||
|
|
||||||
|
#if (${sharedModuleName})
|
||||||
|
func greet() -> String {
|
||||||
|
return Greeting().greeting()
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
#if (${sharedModuleName})
|
||||||
|
Text(greet())
|
||||||
|
#else
|
||||||
Text("Hello, World!")
|
Text("Hello, World!")
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+5
-2
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.tools.projectWizard.core.Writer
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.core.div
|
import org.jetbrains.kotlin.tools.projectWizard.core.div
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate
|
import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor
|
import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.templates.FileTextDescriptor
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.templates.Template
|
import org.jetbrains.kotlin.tools.projectWizard.templates.Template
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
|
||||||
@@ -30,9 +31,11 @@ abstract class TemplateEngineService : WizardService {
|
|||||||
|
|
||||||
fun Writer.writeTemplate(template: FileTemplate): TaskResult<Unit> {
|
fun Writer.writeTemplate(template: FileTemplate): TaskResult<Unit> {
|
||||||
val formatter = service<FileFormattingService>()
|
val formatter = service<FileFormattingService>()
|
||||||
val text = renderTemplate(template.descriptor, template.data).let { text ->
|
val unformattedText = when (val descriptor = template.descriptor) {
|
||||||
formatter.formatFile(text, template.descriptor.relativePath.fileName.toString())
|
is FileTemplateDescriptor -> renderTemplate(descriptor, template.data)
|
||||||
|
is FileTextDescriptor -> descriptor.text
|
||||||
}
|
}
|
||||||
|
val text = formatter.formatFile(unformattedText, template.descriptor.relativePath.fileName.toString())
|
||||||
return service<FileSystemWizardService>().createFile(template.rootPath / template.descriptor.relativePath, text)
|
return service<FileSystemWizardService>().createFile(template.rootPath / template.descriptor.relativePath, text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -33,6 +33,10 @@ operator fun Path.div(@NonNls other: String): Path =
|
|||||||
operator fun Path.div(other: Path): Path =
|
operator fun Path.div(other: Path): Path =
|
||||||
resolve(other.toString())
|
resolve(other.toString())
|
||||||
|
|
||||||
|
@JvmName("divNullable")
|
||||||
|
operator fun Path.div(other: Path?): Path =
|
||||||
|
other?.let { resolve(other.toString()) } ?: this
|
||||||
|
|
||||||
operator fun @receiver:NonNls String.div(other: Path): Path =
|
operator fun @receiver:NonNls String.div(other: Path): Path =
|
||||||
Paths.get(this).resolve(other)
|
Paths.get(this).resolve(other)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ object IOSSinglePlatformModuleConfigurator : SinglePlatformModuleConfigurator,
|
|||||||
+fileTemplate("$DEFAULT_APP_NAME.xcodeproj" / "project.pbxproj")
|
+fileTemplate("$DEFAULT_APP_NAME.xcodeproj" / "project.pbxproj")
|
||||||
|
|
||||||
+fileTemplate(DEFAULT_APP_NAME / "AppDelegate.swift")
|
+fileTemplate(DEFAULT_APP_NAME / "AppDelegate.swift")
|
||||||
+fileTemplate(DEFAULT_APP_NAME / "ContentView.swift")
|
+fileTemplate(DEFAULT_APP_NAME / "ContentView.swift.vm")
|
||||||
+fileTemplate(DEFAULT_APP_NAME / "SceneDelegate.swift")
|
+fileTemplate(DEFAULT_APP_NAME / "SceneDelegate.swift")
|
||||||
+fileTemplate(DEFAULT_APP_NAME / "Info.plist")
|
+fileTemplate(DEFAULT_APP_NAME / "Info.plist")
|
||||||
|
|
||||||
|
|||||||
+22
-8
@@ -75,7 +75,13 @@ class ModulesToIRsConverter(
|
|||||||
module.configurator == AndroidSinglePlatformModuleConfigurator
|
module.configurator == AndroidSinglePlatformModuleConfigurator
|
||||||
}
|
}
|
||||||
|
|
||||||
rootModules.mapSequence { module ->
|
allModules.mapSequenceIgnore { module ->
|
||||||
|
forModuleEachDependency(module) { from, to, dependencyType ->
|
||||||
|
with(dependencyType) {
|
||||||
|
runArbitraryTaskBeforeIRsCreated(from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} andThen rootModules.mapSequence { module ->
|
||||||
createBuildFileForModule(
|
createBuildFileForModule(
|
||||||
module,
|
module,
|
||||||
initialState.copy(parentModuleHasTransitivelySpecifiedKotlinVersion = parentModuleHasKotlinVersion)
|
initialState.copy(parentModuleHasTransitivelySpecifiedKotlinVersion = parentModuleHasKotlinVersion)
|
||||||
@@ -112,17 +118,25 @@ class ModulesToIRsConverter(
|
|||||||
else -> Success(emptyList())
|
else -> Success(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T : Any> forModuleEachDependency(
|
||||||
|
from: Module,
|
||||||
|
action: suspend ComputeContext<NoState>.(from: Module, to: Module, dependencyType: ModuleDependencyType) -> TaskResult<T>
|
||||||
|
): TaskResult<List<T>> {
|
||||||
|
return from.dependencies.mapComputeM { dependency ->
|
||||||
|
val to = data.moduleByPath.getValue(dependency.path)
|
||||||
|
val (dependencyType) = ModuleDependencyType.getPossibleDependencyType(from, to)
|
||||||
|
.toResult { InvalidModuleDependencyError(from, to) }
|
||||||
|
action(from, to, dependencyType)
|
||||||
|
}.sequence()
|
||||||
|
}
|
||||||
|
|
||||||
private fun Writer.createSinglePlatformModule(
|
private fun Writer.createSinglePlatformModule(
|
||||||
module: Module,
|
module: Module,
|
||||||
configurator: SinglePlatformModuleConfigurator,
|
configurator: SinglePlatformModuleConfigurator,
|
||||||
state: ModulesToIrsState
|
state: ModulesToIrsState
|
||||||
): TaskResult<List<BuildFileIR>> = computeM {
|
): TaskResult<List<BuildFileIR>> = computeM {
|
||||||
val modulePath = calculatePathForModule(module, state.parentPath)
|
val modulePath = calculatePathForModule(module, state.parentPath)
|
||||||
val (moduleDependencies) = module.dependencies.mapCompute { dependency ->
|
val (moduleDependencies) = forModuleEachDependency(module) { from, to, dependencyType ->
|
||||||
val to = data.moduleByPath.getValue(dependency.path)
|
|
||||||
val (dependencyType) = ModuleDependencyType.getPossibleDependencyType(module, to)
|
|
||||||
.toResult { InvalidModuleDependencyError(module, to) }
|
|
||||||
|
|
||||||
with(dependencyType) {
|
with(dependencyType) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
with(unsafeSettingWriter) {
|
with(unsafeSettingWriter) {
|
||||||
@@ -134,9 +148,9 @@ class ModulesToIRsConverter(
|
|||||||
).ensure()
|
).ensure()
|
||||||
}
|
}
|
||||||
irsToAddToModules.getOrPut(to) { mutableListOf() } += createToIRs(module, to, data).get()
|
irsToAddToModules.getOrPut(to) { mutableListOf() } += createToIRs(module, to, data).get()
|
||||||
createDependencyIrs(module, to, data)
|
createDependencyIrs(module, to, data).asSuccess()
|
||||||
}
|
}
|
||||||
}.sequence().map { it.flatten() }
|
}.map { it.flatten() }
|
||||||
mutateProjectStructureByModuleConfigurator(module, modulePath)
|
mutateProjectStructureByModuleConfigurator(module, modulePath)
|
||||||
val buildFileIR = run {
|
val buildFileIR = run {
|
||||||
if (!configurator.needCreateBuildFile) return@run null
|
if (!configurator.needCreateBuildFile) return@run null
|
||||||
|
|||||||
+64
-12
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleDependencyI
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
|
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.gradle.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.*
|
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleSubType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModulesToIrConversionData
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.isIOS
|
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.printer.GradlePrinter
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectPath
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
|
||||||
@@ -58,6 +58,12 @@ sealed class ModuleDependencyType(
|
|||||||
): TaskResult<Unit> =
|
): TaskResult<Unit> =
|
||||||
UNIT_SUCCESS
|
UNIT_SUCCESS
|
||||||
|
|
||||||
|
open fun Writer.runArbitraryTaskBeforeIRsCreated(
|
||||||
|
from: Module,
|
||||||
|
to: Module,
|
||||||
|
): TaskResult<Unit> =
|
||||||
|
UNIT_SUCCESS
|
||||||
|
|
||||||
open fun Reader.createToIRs(from: Module, to: Module, data: ModulesToIrConversionData): TaskResult<List<BuildSystemIR>> =
|
open fun Reader.createToIRs(from: Module, to: Module, data: ModulesToIrConversionData): TaskResult<List<BuildSystemIR>> =
|
||||||
Success(emptyList())
|
Success(emptyList())
|
||||||
|
|
||||||
@@ -69,7 +75,12 @@ sealed class ModuleDependencyType(
|
|||||||
object AndroidSinglePlatformToMPP : ModuleDependencyType(
|
object AndroidSinglePlatformToMPP : ModuleDependencyType(
|
||||||
from = AndroidSinglePlatformModuleConfigurator::class,
|
from = AndroidSinglePlatformModuleConfigurator::class,
|
||||||
to = MppModuleConfigurator::class
|
to = MppModuleConfigurator::class
|
||||||
)
|
) {
|
||||||
|
override fun Writer.runArbitraryTaskBeforeIRsCreated(
|
||||||
|
from: Module,
|
||||||
|
to: Module,
|
||||||
|
): TaskResult<Unit> = addExpectFilesForMppModuleForAndroidAndIos(to)
|
||||||
|
}
|
||||||
|
|
||||||
object IOSToMppSinglePlatformToMPP : ModuleDependencyType(
|
object IOSToMppSinglePlatformToMPP : ModuleDependencyType(
|
||||||
from = IOSSinglePlatformModuleConfigurator::class,
|
from = IOSSinglePlatformModuleConfigurator::class,
|
||||||
@@ -83,17 +94,35 @@ sealed class ModuleDependencyType(
|
|||||||
to: Module,
|
to: Module,
|
||||||
toModulePath: Path,
|
toModulePath: Path,
|
||||||
data: ModulesToIrConversionData
|
data: ModulesToIrConversionData
|
||||||
): TaskResult<Unit> = inContextOfModuleConfigurator(from) {
|
): TaskResult<Unit> = compute {
|
||||||
IOSSinglePlatformModuleConfigurator.dependentModule.reference.update {
|
inContextOfModuleConfigurator(from) {
|
||||||
IOSSinglePlatformModuleConfigurator.DependentModuleReference(to).asSuccess()
|
IOSSinglePlatformModuleConfigurator.dependentModule.reference.update {
|
||||||
}
|
IOSSinglePlatformModuleConfigurator.DependentModuleReference(to).asSuccess()
|
||||||
val dummyFilePath = Defaults.SRC_DIR / "${to.iosTargetSafe()!!.name}Main" / to.configurator.kotlinDirectoryName / "dummyFile.kt"
|
}
|
||||||
TemplatesPlugin.addFileTemplate.execute(
|
}.ensure()
|
||||||
FileTemplate(
|
addDummyFileIfNeeded(to, toModulePath).ensure()
|
||||||
FileTemplateDescriptor("ios/dummyFile.kt", dummyFilePath),
|
}
|
||||||
projectPath / toModulePath
|
|
||||||
|
override fun Writer.runArbitraryTaskBeforeIRsCreated(
|
||||||
|
from: Module,
|
||||||
|
to: Module,
|
||||||
|
): TaskResult<Unit> = addExpectFilesForMppModuleForAndroidAndIos(to)
|
||||||
|
|
||||||
|
private fun Writer.addDummyFileIfNeeded(
|
||||||
|
to: Module,
|
||||||
|
toModulePath: Path,
|
||||||
|
): TaskResult<Unit> {
|
||||||
|
val needDummyFile = inContextOfModuleConfigurator(to) { MppModuleConfigurator.mppFiles.reference.propertyValue.isEmpty() }
|
||||||
|
return if (needDummyFile) {
|
||||||
|
val dummyFilePath =
|
||||||
|
Defaults.SRC_DIR / "${to.iosTargetSafe()!!.name}Main" / to.configurator.kotlinDirectoryName / "dummyFile.kt"
|
||||||
|
TemplatesPlugin.addFileTemplate.execute(
|
||||||
|
FileTemplate(
|
||||||
|
FileTemplateDescriptor("ios/dummyFile.kt", dummyFilePath),
|
||||||
|
projectPath / toModulePath
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
} else UNIT_SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun additionalAcceptanceChecker(from: Module, to: Module): Boolean =
|
override fun additionalAcceptanceChecker(from: Module, to: Module): Boolean =
|
||||||
@@ -153,3 +182,26 @@ sealed class ModuleDependencyType(
|
|||||||
getPossibleDependencyType(from, to) != null
|
getPossibleDependencyType(from, to) != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Writer.addExpectFilesForMppModuleForAndroidAndIos(mppModule: Module): TaskResult<Unit> {
|
||||||
|
val expectFiles = mppFiles {
|
||||||
|
mppfile("Platform.kt") {
|
||||||
|
`class`("Platform") {
|
||||||
|
expectBody = "val platform: String"
|
||||||
|
actualFor(
|
||||||
|
ModuleSubType.android,
|
||||||
|
actualBody = """actual val platform: String = "Android ${'$'}{android.os.Build.VERSION.SDK_INT}""""
|
||||||
|
)
|
||||||
|
|
||||||
|
actualFor(
|
||||||
|
ModuleSubType.iosArm64, ModuleSubType.iosX64,
|
||||||
|
actualBody =
|
||||||
|
"""actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion"""
|
||||||
|
) {
|
||||||
|
import("platform.UIKit.UIDevice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inContextOfModuleConfigurator(mppModule) { MppModuleConfigurator.mppFiles.reference.addValues(expectFiles) }
|
||||||
|
}
|
||||||
+12
-7
@@ -6,16 +6,21 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.SourcesetTy
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
|
||||||
// Should be used to create any kind of files in the generated project
|
// Should be used to create any kind of files in the generated project
|
||||||
// Except build files as they will be generated using IR
|
// Except build files as they will be generated using IR
|
||||||
data class FileTemplateDescriptor(@NonNls val templateId: String, val relativePath: Path) {
|
sealed class FileDescriptor {
|
||||||
|
abstract val relativePath: Path
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FileTemplateDescriptor(@NonNls val templateId: String, override val relativePath: Path) : FileDescriptor() {
|
||||||
constructor(templateId: String) : this(
|
constructor(templateId: String) : this(
|
||||||
templateId,
|
templateId,
|
||||||
Paths.get(templateId).fileName.toString().removeSuffix(".vm").asPath()
|
Paths.get(templateId).fileName.toString().removeSuffix(".vm").asPath()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class FileTextDescriptor(val text: String, override val relativePath: Path) : FileDescriptor()
|
||||||
|
|
||||||
sealed class FilePath {
|
sealed class FilePath {
|
||||||
abstract val sourcesetType: SourcesetType
|
abstract val sourcesetType: SourcesetType
|
||||||
}
|
}
|
||||||
@@ -23,20 +28,20 @@ sealed class FilePath {
|
|||||||
data class SrcFilePath(override val sourcesetType: SourcesetType) : FilePath()
|
data class SrcFilePath(override val sourcesetType: SourcesetType) : FilePath()
|
||||||
data class ResourcesFilePath(override val sourcesetType: SourcesetType) : FilePath()
|
data class ResourcesFilePath(override val sourcesetType: SourcesetType) : FilePath()
|
||||||
|
|
||||||
data class FileTemplateDescriptorWithPath(val descriptor: FileTemplateDescriptor, val path: FilePath)
|
data class FileTemplateDescriptorWithPath(val descriptor: FileDescriptor, val path: FilePath)
|
||||||
|
|
||||||
infix fun FileTemplateDescriptor.asResourceOf(sourcesetType: SourcesetType) =
|
infix fun FileDescriptor.asResourceOf(sourcesetType: SourcesetType) =
|
||||||
FileTemplateDescriptorWithPath(this, ResourcesFilePath(sourcesetType))
|
FileTemplateDescriptorWithPath(this, ResourcesFilePath(sourcesetType))
|
||||||
|
|
||||||
infix fun FileTemplateDescriptor.asSrcOf(sourcesetType: SourcesetType) =
|
infix fun FileDescriptor.asSrcOf(sourcesetType: SourcesetType) =
|
||||||
FileTemplateDescriptorWithPath(this, SrcFilePath(sourcesetType))
|
FileTemplateDescriptorWithPath(this, SrcFilePath(sourcesetType))
|
||||||
|
|
||||||
|
|
||||||
data class FileTemplate(
|
data class FileTemplate(
|
||||||
val descriptor: FileTemplateDescriptor,
|
val descriptor: FileDescriptor,
|
||||||
val rootPath: Path,
|
val rootPath: Path,
|
||||||
val data: Map<String, Any?> = emptyMap()
|
val data: Map<String, Any?> = emptyMap()
|
||||||
) {
|
) {
|
||||||
constructor(descriptor: FileTemplateDescriptor, rootPath: Path, vararg data: Pair<String, Any?>) :
|
constructor(descriptor: FileDescriptor, rootPath: Path, vararg data: Pair<String, Any?>) :
|
||||||
this(descriptor, rootPath, data.toMap())
|
this(descriptor, rootPath, data.toMap())
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user