From ca1e33338972deffb84e507b025c5113bfbde3d3 Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Sun, 9 Jul 2023 04:58:50 +0800 Subject: [PATCH 01/11] remove import PropertyBinding --- .../com/eitanliu/dart/mappable/binding/CommandBinding.kt | 3 --- .../com/eitanliu/dart/mappable/settings/SettingLayout.kt | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/binding/CommandBinding.kt b/src/main/kotlin/com/eitanliu/dart/mappable/binding/CommandBinding.kt index 7fbd5d2..4e3664d 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/binding/CommandBinding.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/binding/CommandBinding.kt @@ -3,13 +3,10 @@ package com.eitanliu.dart.mappable.binding import com.eitanliu.dart.mappable.utils.SimpleKeyListener import com.intellij.openapi.observable.properties.GraphProperty import com.intellij.ui.layout.ComponentPredicate -import com.intellij.ui.layout.PropertyBinding import java.awt.Component import java.awt.event.KeyEvent import java.util.concurrent.atomic.AtomicBoolean -fun GraphProperty.toBinding() = PropertyBinding(::get, ::set) - fun GraphProperty.selected(expected: T) = object : ComponentPredicate() { override fun invoke(): Boolean = get() == expected diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt index 2182fdf..a889c06 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt @@ -2,7 +2,7 @@ package com.eitanliu.dart.mappable.settings import com.eitanliu.dart.mappable.binding.bindSelected import com.eitanliu.dart.mappable.binding.selected -import com.eitanliu.dart.mappable.binding.toBinding +import com.eitanliu.dart.mappable.extensions.createInstance import com.eitanliu.dart.mappable.extensions.createPropertyGraph import com.eitanliu.dart.mappable.extensions.propertyOf import com.eitanliu.dart.mappable.extensions.value @@ -127,7 +127,9 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { // buttonsGroup(title, indent, init).bind(binding::get, binding::set) try { methods.firstOrNull { it.name == "buttonGroup" && it.parameterCount == 5 }?.also { method -> - method.invoke(this, binding.toBinding(), T::class.java, title, indent, init) + val property = Class.forName("com.intellij.ui.layout.PropertyBinding") + .createInstance { arrayOf(binding::get, binding::set) } + method.invoke(this, property, T::class.java, title, indent, init) } ?: methods.firstOrNull { it.name == "buttonsGroup" && it.parameterCount == 3 }?.also { method -> val group = method.invoke(this, title, indent, init) val bind = group?.run { From 73c33f6ca8c59c318c73ebe2b5e728b4da9a250d Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Mon, 10 Jul 2023 23:56:47 +0800 Subject: [PATCH 02/11] update test json --- src/test/resources/test01.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/test01.json b/src/test/resources/test01.json index faa9a49..892d0f1 100644 --- a/src/test/resources/test01.json +++ b/src/test/resources/test01.json @@ -1,4 +1,5 @@ { + "_id": 0, "int8": 127, "int_16": 32767, "int-32": 2147483647, From 319f9b2c7eff800c4b7f89865fd5da9e60376856 Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Thu, 13 Jul 2023 01:58:55 +0800 Subject: [PATCH 03/11] update README.md and plugin name --- README.md | 15 +++++++++------ src/main/resources/META-INF/plugin.xml | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 094b161..e81f79a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# DartMappable(Json To DartMappable Or JsonSerializable) +# DartMappable(Json To Dart Converter) ## How to use @@ -6,15 +6,18 @@ 2. Open in the IDE `Setting` -> `Plugins`, right click setting icon ⚙️ -> `Install Plugin from Disk...` selected you download file. -Json to dart data classes are provided, and dart files ending in entity are provided to generate dart class factory for use. +Provide JSON to dart data classes conversion for use in Flutter and Dart projects. +Support multiple serialization schemes with [json_serializable](https://pub.dev/packages/json_serializable), [dart_mappable](https://pub.dev/packages/dart_mappable). Right click on package -> `New` -> `Json To DartMappable` And Then you will know how to use. -If you change the fields in the class, right click on package -> `Flutter Command` -> `Flutter Run Build Runner`, shortcut key is changed to `Alt + r`. +If you haven't added the dependency, it will automatically execute the command to add it. + +If you change the fields in the class, right click on package -> `Flutter Command` -> `Flutter Run Build Runner`, shortcut key is `Alt + r`. ### 1. Use dart_mappable -Open in the IDE `Setting` -> `Tools` -> `DartMappable Settings`, selected `dart_mappable`. +Open in the IDE `Setting` -> `Tools` -> `DartMappable Settings`, selected `dart_mappable`. Don't forget to set up `dart_mappable` into your project : https://pub.dev/packages/dart_mappable Add into your `pubspec.yaml` ```yaml @@ -24,7 +27,7 @@ dev_dependencies: build_runner: ^2.1.0 dart_mappable_builder: ^3.0.2 ``` -Or Run Terminal +Or Run command in Terminal ```shell flutter pub add dart_mappable flutter pub add build_runner --dev @@ -42,7 +45,7 @@ dev_dependencies: build_runner: ^2.3.3 json_serializable: ^6.6.0 ``` -Or Run Terminal +Or Run command in Terminal ```shell flutter pub add json_annotation flutter pub add build_runner --dev diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 44625b5..7f12daf 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -5,7 +5,7 @@ - DartMappable(Json To DartMappable Or JsonSerializable) + DartMappable(Flutter Json To DartMappable Or JsonSerializable) Eitan Liu From 9018d3e627dd7fc6e7676947dee500c8b140916a Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Thu, 13 Jul 2023 02:23:28 +0800 Subject: [PATCH 04/11] change DartMappable custom methods generator --- .../mappable/generator/DartMappableGenerator.kt | 10 +++++++++- .../dart/mappable/settings/SettingLayout.kt | 14 +++++++------- .../eitanliu/dart/mappable/GeneratorUnitTest.kt | 3 +++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt index 953e2aa..82aa30b 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt @@ -119,7 +119,7 @@ class DartMappableGenerator( writeln() writeln("factory $sampleName.$fromJson(String json) => $mapper.fromJson(json);") } else { - fun guard(fn: String) = "$mapper._guard((c) => c.$fn)" + fun guard(fn: String) = "_ensureContainer().$fn" // factory fromMap if (enableFromMap) { @@ -188,6 +188,14 @@ class DartMappableGenerator( writeln("return _${sampleName}CopyWithImpl(this, \$identity, \$identity);") } } + + writeln() + writeScoped( + "static MapperContainer _ensureContainer() {", "}" + ) { + writeln("$mapper.ensureInitialized();") + writeln("return MapperContainer.globals;") + } } // ensureInitialized diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt index aff61d8..de6033b 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt @@ -100,13 +100,13 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { bindText(graph.mappableToJson) }.horizontalAlign(HorizontalAlign.FILL) }.layout(RowLayout.LABEL_ALIGNED) - // row { - // checkBox("copyWith") - // .bindSelected(graph.enableCopyWith) - // textField().apply { - // bindText(graph.mappableCopyWith) - // }.horizontalAlign(HorizontalAlign.FILL) - // }.layout(RowLayout.LABEL_ALIGNED) + row { + checkBox("copyWith") + .bindSelected(graph.enableCopyWith) + textField().apply { + bindText(graph.mappableCopyWith) + }.horizontalAlign(HorizontalAlign.FILL) + }.layout(RowLayout.LABEL_ALIGNED) }.visibleIf(customPredicate) }.bind(::enableMixin) } diff --git a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt index 944cf85..8619737 100644 --- a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt +++ b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt @@ -69,6 +69,9 @@ class GeneratorUnitTest { constructor = false nullable = true final = false + + enableJsonReflectable = false + enableMixin = true } val generator = DartMappableGenerator(setting, "Text01", content) val classes = generator.buildString() From 41a180f1151b179c828cc2f54b3d7cb3b0a176bb Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Thu, 13 Jul 2023 02:40:13 +0800 Subject: [PATCH 05/11] change DartMappable custom methods generator --- .../eitanliu/dart/mappable/generator/DartMappableGenerator.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt index 82aa30b..8957ad1 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartMappableGenerator.kt @@ -119,7 +119,7 @@ class DartMappableGenerator( writeln() writeln("factory $sampleName.$fromJson(String json) => $mapper.fromJson(json);") } else { - fun guard(fn: String) = "_ensureContainer().$fn" + fun guard(fn: String) = "_ensureContainer.$fn" // factory fromMap if (enableFromMap) { @@ -191,7 +191,7 @@ class DartMappableGenerator( writeln() writeScoped( - "static MapperContainer _ensureContainer() {", "}" + "static late MapperContainer _ensureContainer = () {", "}();" ) { writeln("$mapper.ensureInitialized();") writeln("return MapperContainer.globals;") From 25d858f6483b9d0774614b8dffb0e3ab00ba0556 Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Mon, 17 Jul 2023 13:09:28 +0800 Subject: [PATCH 06/11] update support freezed readme --- README.md | 26 +++++++++++++++++++++++++- src/main/resources/META-INF/plugin.xml | 2 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e81f79a..36d81c8 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,10 @@ Provide JSON to dart data classes conversion for use in Flutter and Dart projects. -Support multiple serialization schemes with [json_serializable](https://pub.dev/packages/json_serializable), [dart_mappable](https://pub.dev/packages/dart_mappable). +Support multiple serialization schemes with [json_serializable](https://pub.dev/packages/json_serializable), [dart_mappable](https://pub.dev/packages/dart_mappable), [freezed](https://pub.dev/packages/freezed). Right click on package -> `New` -> `Json To DartMappable` And Then you will know how to use. +After converting JSON to dart classes, will be automatically run 'flutter pub run build_runner build --delete-conflicting-outputs'. If you haven't added the dependency, it will automatically execute the command to add it. @@ -36,6 +37,7 @@ flutter pub add dart_mappable_builder --dev ### 2. Use json_serializable +Open in the IDE `Setting` -> `Tools` -> `DartMappable Settings`, selected `json_serializable`. Don't forget to set up `json_serializable` into your project : https://pub.dev/packages/json_serializable Add into your `pubspec.yaml` ```yaml @@ -51,4 +53,26 @@ flutter pub add json_annotation flutter pub add build_runner --dev flutter pub add json_serializable --dev ``` + +### 2. Use freezed + +Open in the IDE `Setting` -> `Tools` -> `DartMappable Settings`, selected `freezed`. +Don't forget to set up `freezed` into your project : https://pub.dev/packages/freezed +Add into your `pubspec.yaml` +```yaml +dependencies: + freezed_annotation: ^2.4.1 +dev_dependencies: + build_runner: ^2.1.0 + freezed: ^2.4.1 +``` +Or Run command in Terminal +```shell +flutter pub add freezed_annotation +flutter pub add --dev build_runner +flutter pub add --dev freezed +# if using freezed to generate fromJson/toJson, also add: +flutter pub add json_annotation +flutter pub add --dev json_serializable +``` \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 7f12daf..f467313 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -5,7 +5,7 @@ - DartMappable(Flutter Json To DartMappable Or JsonSerializable) + DartMappable(Flutter Json To DartMappable JsonSerializable Freezed) Eitan Liu From 586911a4b301526ced138262a77b17c7c933a018 Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Tue, 18 Jul 2023 17:14:32 +0800 Subject: [PATCH 07/11] add freezed setting --- .../dart/mappable/entity/ModuleEntity.kt | 6 ++++++ .../dart/mappable/settings/Configs.kt | 1 + .../dart/mappable/settings/SettingLayout.kt | 21 +++++++++++++++++++ .../dart/mappable/settings/Settings.kt | 4 ++++ .../dart/mappable/utils/DependenciesUtils.kt | 7 +++++++ .../dart/mappable/GeneratorUnitTest.kt | 5 +++-- 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/entity/ModuleEntity.kt b/src/main/kotlin/com/eitanliu/dart/mappable/entity/ModuleEntity.kt index 1bd17e0..0574f21 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/entity/ModuleEntity.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/entity/ModuleEntity.kt @@ -40,5 +40,11 @@ data class DependenceEntity( DependenceEntity("dart_mappable_builder", SCOPE_DEV), DependenceEntity("build_runner", SCOPE_DEV), ) + + val FREEZED_VALUES = listOf( + DependenceEntity("freezed_annotation"), + DependenceEntity("freezed", SCOPE_DEV), + DependenceEntity("build_runner", SCOPE_DEV), + ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Configs.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Configs.kt index 7f23fdd..90f9927 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Configs.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Configs.kt @@ -2,5 +2,6 @@ package com.eitanliu.dart.mappable.settings object Implements { const val DART_MAPPABLE = "dart_mappable" + const val FREEZED = "freezed" const val JSON_SERIALIZABLE = "json_serializable" } \ No newline at end of file diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt index de6033b..20f0a30 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt @@ -56,6 +56,14 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { rowsRange { buildMappable() }.visibleIf(mappablePredicate) + val freezedPredicate = graph.implement.selected(Implements.FREEZED) + row { + radioButton("freezed", Implements.FREEZED) + .bindSelected(graph.implement, Implements.FREEZED) + } + rowsRange { + buildFreezed() + }.visibleIf(freezedPredicate) }.bind(::implement) } @@ -111,6 +119,15 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { }.bind(::enableMixin) } + private fun Panel.buildFreezed() { + indent { + row { + checkBox("fromJson/toJson") + .bindSelected(graph.freezedEnableJson) + } + } + } + private fun Panel.rowPanel( title: String? = null, indent: Boolean = true, @@ -143,6 +160,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { || settings.graph.mappableFromMap.value != graph.mappableFromMap.value || settings.graph.mappableToMap.value != graph.mappableToMap.value || settings.graph.mappableCopyWith.value != graph.mappableCopyWith.value + || settings.graph.freezedEnableJson.value != graph.freezedEnableJson.value } override fun apply() { @@ -160,6 +178,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { settings.graph.mappableFromMap.value = graph.mappableFromMap.value settings.graph.mappableToMap.value = graph.mappableToMap.value settings.graph.mappableCopyWith.value = graph.mappableCopyWith.value + settings.graph.freezedEnableJson.value = graph.freezedEnableJson.value } override fun reset() { @@ -177,6 +196,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { graph.mappableFromMap.value = settings.graph.mappableFromMap.value graph.mappableToMap.value = settings.graph.mappableToMap.value graph.mappableCopyWith.value = settings.graph.mappableCopyWith.value + graph.freezedEnableJson.value = settings.graph.freezedEnableJson.value } class Graph(data: SettingLayout) { @@ -196,6 +216,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { val mappableFromMap = propertyGraph.propertyOf(data.settings.mappableFromMap) val mappableToMap = propertyGraph.propertyOf(data.settings.mappableToMap) val mappableCopyWith = propertyGraph.propertyOf(data.settings.mappableCopyWith) + val freezedEnableJson = propertyGraph.propertyOf(data.settings.freezedEnableJson) } } diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt index 5881558..8928b6b 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt @@ -28,6 +28,7 @@ data class Settings( var mappableFromMap: String, var mappableToMap: String, var mappableCopyWith: String, + var freezedEnableJson: Boolean, ) : PersistentStateComponent { val graph = Graph(this) @@ -43,6 +44,7 @@ data class Settings( mappableFromJson = "fromString", mappableToJson = "toString", mappableFromMap = "fromJson", mappableToMap = "toJson", mappableCopyWith = "copyWith", + freezedEnableJson = true, ) override fun getState(): Settings { @@ -79,6 +81,8 @@ data class Settings( val mappableToMap = propertyGraph.propertyRef(data::mappableToMap) val mappableCopyWith = propertyGraph.propertyRef(data::mappableCopyWith) + val freezedEnableJson = propertyGraph.propertyRef(data::freezedEnableJson) + fun afterPropagation(disposable: Disposable? = null, listener: Graph.() -> Unit) = apply { propertyGraph.afterPropagation(disposable) { listener() } } diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/utils/DependenciesUtils.kt b/src/main/kotlin/com/eitanliu/dart/mappable/utils/DependenciesUtils.kt index 0eb186f..cb29de3 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/utils/DependenciesUtils.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/utils/DependenciesUtils.kt @@ -20,6 +20,13 @@ object DependenciesUtils { yieldAll(DependenceEntity.JSON_REFLECTABLE_VALUES) when (implement) { Implements.DART_MAPPABLE -> yieldAll(DependenceEntity.DART_MAPPABLE_VALUES) + Implements.FREEZED -> { + yieldAll(DependenceEntity.FREEZED_VALUES) + if (settings.graph.freezedEnableJson.value) { + yieldAll(DependenceEntity.JSON_SERIALIZABLE_VALUES) + } + } + Implements.JSON_SERIALIZABLE -> yieldAll(DependenceEntity.JSON_SERIALIZABLE_VALUES) } }.distinct().filterNot filter@{ diff --git a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt index 8619737..55131f7 100644 --- a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt +++ b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt @@ -98,7 +98,8 @@ class GeneratorUnitTest { val setting = Settings().apply { enableJsonReflectable = true - implement = Implements.DART_MAPPABLE + implement = Implements.FREEZED + freezedEnableJson = false } val pubspec = PubspecEntity( @@ -111,6 +112,6 @@ class GeneratorUnitTest { ), ) - DependenciesUtils.checkDependencies(setting, pubspec) + println("dependencies => " + DependenciesUtils.checkDependencies(setting, pubspec).joinToString()) } } \ No newline at end of file From 1426d314024888e54e9fe297437c548d83f0ff4b Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Tue, 18 Jul 2023 21:57:28 +0800 Subject: [PATCH 08/11] add freezed generator --- .../dart/mappable/ast/DartGenerator.kt | 16 ++- .../generator/DartGeneratorBuilder.kt | 1 + .../mappable/generator/FreezedGenerator.kt | 121 ++++++++++++++++++ .../dart/mappable/GeneratorUnitTest.kt | 28 +++- 4 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/com/eitanliu/dart/mappable/generator/FreezedGenerator.kt diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/ast/DartGenerator.kt b/src/main/kotlin/com/eitanliu/dart/mappable/ast/DartGenerator.kt index fab5070..411164e 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/ast/DartGenerator.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/ast/DartGenerator.kt @@ -15,32 +15,36 @@ interface DartGenerator : DartFileName { fun Iterable.paramsSyntax( entitySuffix: String, nullable: Boolean = false, - constructor: Boolean = false, + member: Boolean = false, namedFunction: Boolean = false, - before: (suspend SequenceScope.() -> Unit)?, - after: (suspend SequenceScope.() -> Unit)?, + beforeScope: (suspend SequenceScope.() -> Unit)? = null, + afterScope: (suspend SequenceScope.() -> Unit)? = null, + beforeTransform: (StringBuilder.(DartMemberModel) -> Unit)? = null, + afterTransform: (StringBuilder.(DartMemberModel) -> Unit)? = null, ): Sequence { val members = sequence { - if (before != null) before() + if (beforeScope != null) beforeScope() yieldAll(asSequence()) - if (after != null) after() + if (afterScope != null) afterScope() } return members .distinctBy { it.name } .map { val name = it.name.keyToFieldName() - if (constructor) return@map "this.$name" + if (member) return@map "this.$name" val nullable = it.nullable ?: nullable val type = it.typeName(entitySuffix, nullable) buildString { + beforeTransform?.invoke(this, it) if (namedFunction && !nullable) { append("required ") } append(type) append(" ") append(name) + afterTransform?.invoke(this, it) } } } diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartGeneratorBuilder.kt b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartGeneratorBuilder.kt index de9b63e..cf007d0 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartGeneratorBuilder.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/generator/DartGeneratorBuilder.kt @@ -12,5 +12,6 @@ fun buildDartGenerator( ): DartGenerator = when (settings.graph.implement.value) { Implements.JSON_SERIALIZABLE -> JsonSerializableGenerator(settings, className, json) Implements.DART_MAPPABLE -> DartMappableGenerator(settings, className, json) + Implements.FREEZED -> FreezedGenerator(settings, className, json) else -> JsonSerializableGenerator(settings, className, json) } \ No newline at end of file diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/generator/FreezedGenerator.kt b/src/main/kotlin/com/eitanliu/dart/mappable/generator/FreezedGenerator.kt new file mode 100644 index 0000000..601178c --- /dev/null +++ b/src/main/kotlin/com/eitanliu/dart/mappable/generator/FreezedGenerator.kt @@ -0,0 +1,121 @@ +package com.eitanliu.dart.mappable.generator + +import com.eitanliu.dart.mappable.ast.* +import com.eitanliu.dart.mappable.extensions.* +import com.eitanliu.dart.mappable.generator.builder.JsonReflectableBuilder +import com.eitanliu.dart.mappable.settings.Settings +import com.eitanliu.dart.mappable.settings.SettingsOwner +import com.google.gson.* + +class FreezedGenerator( + override val settings: Settings, + className: String, + json: String, + dartFileName: DartFileName = DartFileName.Impl(className, settings.graph.modelSuffix.value), +) : DartGenerator.Self, + JsonReflectableBuilder.Self, + DartJsonParser, + DartFileName by dartFileName, + SettingsOwner { + + val enableJson by lazy { settings.graph.freezedEnableJson.value } + + val fileFreezedName = "$underscoreNameAndSuffix.freezed.dart" + + val fileGeneratorName = "$underscoreNameAndSuffix.g.dart" + + val jsonElement by lazy { JsonParser.parseString(json) } + + override fun generator() = CodeGenerator { + val models = parserElement(jsonElement, camelCaseName) + + writeFileImports(models) + writeFileParts(models) + writeDataClasses(models) + + } + + private fun CodeGenerator.writeFileImports(models: List) { + + for (syntax in models.importsSyntax { + importJsonReflectable() + yield(DartImportModel("package:freezed_annotation/freezed_annotation.dart")) + }) { + writeln(syntax) + } + } + + private fun CodeGenerator.writeFileParts(models: List) { + writeln() + + for (syntax in models.partsSyntax { + yield(DartPartModel(fileFreezedName, fileName)) + if (enableJson) { + yield(DartPartModel(fileGeneratorName, fileName)) + } + }) { + writeln(syntax) + } + } + + private fun CodeGenerator.writeDataClasses(models: List) { + + for (model in models) { + + val sampleName = "${model.name}$camelCaseSuffix" + val mixinName = "_\$${sampleName}" + + val nullable = settings.graph.nullable.value + val final = settings.graph.final.value + + writeln() + writeJsonReflectableClassAnnotation() + writeln(if (final) "@freezed" else "@unfreezed") + writeScoped(buildString { + append("class $sampleName") + append(" with $mixinName") + append(" {") + }, "}") { + + // factory constructor + writeln() + writeln(buildString { + if (final) append("const ") + append("factory ") + append("$sampleName(") + if (model.members.isNotEmpty()) { + val params = model.members.joinToString( + separator = ", ", prefix = "", postfix = "," + ) { member -> + member.buildParam(nullable) + } + append("{$params}") + } + append(") = _$sampleName;") + }) + + if (enableJson) { + // factory fromJson + writeln() + writeln("factory $sampleName.fromJson(Map json) => _\$${sampleName}FromJson(json);") + + // toJson + // writeln() + // writeln("Map toJson() => _\$${sampleName}ToJson(this);") + } + } + } + } + + private fun DartMemberModel.buildParam(nullable: Boolean) = buildString { + val member = this@buildParam + val mNullable = member.nullable ?: nullable + if (member.name.needAnnotation()) { + append("@JsonKey(name: '${member.name}') ") + } + if (!mNullable) append("required ") + append(member.typeName(camelCaseSuffix, mNullable)) + append(" ") + append(member.name.keyToFieldName()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt index 55131f7..65c3f6f 100644 --- a/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt +++ b/src/test/kotlin/com/eitanliu/dart/mappable/GeneratorUnitTest.kt @@ -2,15 +2,13 @@ package com.eitanliu.dart.mappable import com.eitanliu.dart.mappable.ast.CodeGenerator import com.eitanliu.dart.mappable.entity.PubspecEntity -import com.eitanliu.dart.mappable.generator.DartMappableGenerator -import com.eitanliu.dart.mappable.generator.JsonSerializableGenerator +import com.eitanliu.dart.mappable.generator.buildDartGenerator import com.eitanliu.dart.mappable.settings.Implements import com.eitanliu.dart.mappable.settings.Settings import com.eitanliu.dart.mappable.utils.DependenciesUtils +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert.* - /** * Example local unit test, which will execute on the development machine (host). * @@ -65,6 +63,7 @@ class GeneratorUnitTest { val content = jsonParse() val setting = Settings().apply { + implement = Implements.DART_MAPPABLE modelSuffix = "Vo" constructor = false nullable = true @@ -73,7 +72,7 @@ class GeneratorUnitTest { enableJsonReflectable = false enableMixin = true } - val generator = DartMappableGenerator(setting, "Text01", content) + val generator = buildDartGenerator(setting, "Text01", content) val classes = generator.buildString() println("classes: \n$classes") } @@ -83,12 +82,29 @@ class GeneratorUnitTest { val content = jsonParse() val setting = Settings().apply { + implement = Implements.JSON_SERIALIZABLE modelSuffix = "Vo" constructor = false nullable = true final = false } - val generator = JsonSerializableGenerator(setting, "Text01", content) + val generator = buildDartGenerator(setting, "Text01", content) + val classes = generator.buildString() + println("classes: \n$classes") + } + + @Test + fun testFreezed() { + val content = jsonParse() + + val setting = Settings().apply { + implement = Implements.FREEZED + modelSuffix = "Vo" + constructor = false + nullable = false + final = true + } + val generator = buildDartGenerator(setting, "Text01", content) val classes = generator.buildString() println("classes: \n$classes") } From 72c5da854e5c2b8121b1ef06d5772d9f4dc3e9e8 Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Wed, 19 Jul 2023 01:55:08 +0800 Subject: [PATCH 09/11] support disable automatically run `flutter pub run build_runner build --delete-conflicting-outputs` --- .../dart/mappable/actions/JsonToDartAction.kt | 2 ++ .../dart/mappable/settings/SettingLayout.kt | 13 +++++++++++++ .../com/eitanliu/dart/mappable/settings/Settings.kt | 3 +++ .../eitanliu/dart/mappable/ui/JsonInputDialog.kt | 5 +++-- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/actions/JsonToDartAction.kt b/src/main/kotlin/com/eitanliu/dart/mappable/actions/JsonToDartAction.kt index 9bb4e4f..422b1a0 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/actions/JsonToDartAction.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/actions/JsonToDartAction.kt @@ -1,6 +1,7 @@ package com.eitanliu.dart.mappable.actions import com.eitanliu.dart.mappable.extensions.ApplicationScope +import com.eitanliu.dart.mappable.extensions.value import com.eitanliu.dart.mappable.ui.JsonInputDialog import com.eitanliu.dart.mappable.utils.ApplicationUtils import com.eitanliu.dart.mappable.utils.CommandUtils @@ -112,6 +113,7 @@ class JsonToDartAction : AnAction() { } FileDocumentManager.getInstance().saveDocument(doc) + if (!settings.graph.autoBuildRunner.value) return@launch CommandUtils.executeFlutterPubCommand( project, pubRoot, "run build_runner build --delete-conflicting-outputs" ) { diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt index 20f0a30..0a76f20 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt @@ -33,6 +33,15 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { rowComment("Configure dart data model files suffix.") } + row { + checkBox( + "auto run build_runner" + ).bindSelected( + graph.autoBuildRunner + ).applyToComponent { + toolTipText = "auto run 'flutter pub run build_runner build --delete-conflicting-outputs'" + } + } buttonsGroup("Implement") { row { checkBox( @@ -148,6 +157,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { override fun isModified(): Boolean { return settings.graph.modelSuffix.value != graph.modelSuffix.value || settings.graph.implement.value != graph.implement.value + || settings.graph.autoBuildRunner.value != graph.autoBuildRunner.value || settings.graph.enableJsonReflectable.value != graph.enableJsonReflectable.value || settings.graph.enableMixin.value != graph.enableMixin.value || settings.graph.enableFromJson.value != graph.enableFromJson.value @@ -166,6 +176,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { override fun apply() { settings.graph.modelSuffix.value = graph.modelSuffix.value settings.graph.implement.value = graph.implement.value + settings.graph.autoBuildRunner.value = graph.autoBuildRunner.value settings.graph.enableJsonReflectable.value = graph.enableJsonReflectable.value settings.graph.enableMixin.value = graph.enableMixin.value settings.graph.enableFromJson.value = graph.enableFromJson.value @@ -184,6 +195,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { override fun reset() { graph.modelSuffix.value = settings.graph.modelSuffix.value graph.implement.value = settings.graph.implement.value + graph.autoBuildRunner.value = settings.graph.autoBuildRunner.value graph.enableJsonReflectable.value = settings.graph.enableJsonReflectable.value graph.enableMixin.value = settings.graph.enableMixin.value graph.enableFromJson.value = settings.graph.enableFromJson.value @@ -204,6 +216,7 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { val modelSuffix = propertyGraph.propertyOf(data.settings.modelSuffix) val implement = propertyGraph.propertyOf(data.settings.implement) + val autoBuildRunner = propertyGraph.propertyOf(data.settings.autoBuildRunner) val enableJsonReflectable = propertyGraph.propertyOf(data.settings.enableJsonReflectable) val enableMixin = propertyGraph.propertyOf(data.settings.enableMixin) val enableFromJson = propertyGraph.propertyOf(data.settings.enableFromJson) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt index 8928b6b..3eb5546 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/Settings.kt @@ -16,6 +16,7 @@ data class Settings( var constructor: Boolean, var nullable: Boolean, var final: Boolean, + var autoBuildRunner: Boolean, var enableJsonReflectable: Boolean, var enableMixin: Boolean, var enableFromJson: Boolean, @@ -36,6 +37,7 @@ data class Settings( constructor() : this( modelSuffix = "entity", implement = Implements.JSON_SERIALIZABLE, constructor = true, nullable = false, final = false, + autoBuildRunner = true, enableJsonReflectable = true, enableMixin = true, enableFromJson = true, enableToJson = true, @@ -66,6 +68,7 @@ data class Settings( val nullable = propertyGraph.propertyRef(data::nullable) val final = propertyGraph.propertyRef(data::final) + val autoBuildRunner = propertyGraph.propertyRef(data::autoBuildRunner) val enableJsonReflectable = propertyGraph.propertyRef(data::enableJsonReflectable) val enableMixin = propertyGraph.propertyRef(data::enableMixin) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/ui/JsonInputDialog.kt b/src/main/kotlin/com/eitanliu/dart/mappable/ui/JsonInputDialog.kt index cfc1406..263498f 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/ui/JsonInputDialog.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/ui/JsonInputDialog.kt @@ -21,7 +21,6 @@ import com.intellij.ui.dsl.builder.bindText import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.gridLayout.HorizontalAlign import com.intellij.ui.dsl.gridLayout.VerticalAlign -import com.intellij.util.ui.JBDimension /** * Json input Dialog @@ -121,7 +120,9 @@ class JsonInputDialog( } }.apply { - preferredSize = JBDimension(600, 500) + // preferredSize = JBDimension(600, 500) + withPreferredSize(600, 500) + withMinimumHeight(400) } private fun handleFormatJSONString() { From 3b3f2621ff2618173c605eca873a9f0f57bf50ae Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Wed, 19 Jul 2023 01:56:54 +0800 Subject: [PATCH 10/11] update changelog 1.1.6 --- CHANGELOG.md | 9 +++++++++ gradle.properties | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82fab54..341b7db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ # Dart Mappable Changelog +## [1.1.6] + +### Release + +- Support freezed generator +- Support disable automatically run `flutter pub run build_runner build --delete-conflicting-outputs` +- Change dart_mappable custom methods generator +- Fix conversion of names with underscore prefixes + ## [1.1.5] ### Release diff --git a/gradle.properties b/gradle.properties index a0dd108..c6fff56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.caching=true pluginGroup=com.eitanliu pluginName=dart_mappable -pluginVersion=1.1.5 +pluginVersion=1.1.6 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. From b5ee0c2e82224d6d668bc3f6fd09f170ce81f39a Mon Sep 17 00:00:00 2001 From: Eitan Liu Date: Wed, 19 Jul 2023 02:04:31 +0800 Subject: [PATCH 11/11] merge branch 'main' into 213 --- .../kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt index 18097a3..660c5f8 100644 --- a/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt +++ b/src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt @@ -75,7 +75,6 @@ class SettingLayout(private val settings: Settings) : UnnamedConfigurable { rowsRange { buildFreezed() }.visibleIf(freezedPredicate) - }.bind(::implement) } }