Skip to content

Commit

Permalink
Merge branch '213' into 203
Browse files Browse the repository at this point in the history
# Conflicts:
#	gradle.properties
#	src/main/kotlin/com/eitanliu/dart/mappable/settings/SettingLayout.kt
#	src/main/kotlin/com/eitanliu/dart/mappable/ui/JsonInputDialog.kt
  • Loading branch information
eitanliu committed Jul 18, 2023
2 parents 65b9e01 + b5ee0c2 commit c7f061d
Show file tree
Hide file tree
Showing 18 changed files with 270 additions and 28 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 33 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# DartMappable(Json To DartMappable Or JsonSerializable)
# DartMappable(Json To Dart Converter)

## How to use

1. GitHub [Releases](https://github.com/eitanliu/dart_mappable_plugin/releases) or IntelliJ IDEs Plugin Marketplace [DartMappable](https://plugins.jetbrains.com/plugin/21845) page download plugin
2. Open in the IDE `Setting` -> `Plugins`, right click setting icon ⚙️ -> `Install Plugin from Disk...` selected you download file.

<!-- Plugin description -->
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), [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 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
Expand All @@ -24,7 +28,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
Expand All @@ -33,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
Expand All @@ -42,10 +47,32 @@ 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
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
```
<!-- Plugin description end -->
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
org.gradle.caching=true
pluginGroup=com.eitanliu
pluginName=dart_mappable
pluginVersion=1.1.5_hotfix
pluginVersion=1.1.6

# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"
) {
Expand Down
16 changes: 10 additions & 6 deletions src/main/kotlin/com/eitanliu/dart/mappable/ast/DartGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,36 @@ interface DartGenerator : DartFileName {
fun Iterable<DartMemberModel>.paramsSyntax(
entitySuffix: String,
nullable: Boolean = false,
constructor: Boolean = false,
member: Boolean = false,
namedFunction: Boolean = false,
before: (suspend SequenceScope<DartMemberModel>.() -> Unit)?,
after: (suspend SequenceScope<DartMemberModel>.() -> Unit)?,
beforeScope: (suspend SequenceScope<DartMemberModel>.() -> Unit)? = null,
afterScope: (suspend SequenceScope<DartMemberModel>.() -> Unit)? = null,
beforeTransform: (StringBuilder.(DartMemberModel) -> Unit)? = null,
afterTransform: (StringBuilder.(DartMemberModel) -> Unit)? = null,
): Sequence<String> {
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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T> GraphProperty<T>.toBinding() = PropertyBinding(::get, ::set)

fun <T> GraphProperty<T>.selected(expected: T) = object : ComponentPredicate() {
override fun invoke(): Boolean = get() == expected

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -188,6 +188,14 @@ class DartMappableGenerator(
writeln("return _${sampleName}CopyWithImpl(this, \$identity, \$identity);")
}
}

writeln()
writeScoped(
"static late MapperContainer _ensureContainer = () {", "}();"
) {
writeln("$mapper.ensureInitialized();")
writeln("return MapperContainer.globals;")
}
}

// ensureInitialized
Expand Down
Original file line number Diff line number Diff line change
@@ -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<DartClassModel>) {

for (syntax in models.importsSyntax {
importJsonReflectable()
yield(DartImportModel("package:freezed_annotation/freezed_annotation.dart"))
}) {
writeln(syntax)
}
}

private fun CodeGenerator.writeFileParts(models: List<DartClassModel>) {
writeln()

for (syntax in models.partsSyntax {
yield(DartPartModel(fileFreezedName, fileName))
if (enableJson) {
yield(DartPartModel(fileGeneratorName, fileName))
}
}) {
writeln(syntax)
}
}

private fun CodeGenerator.writeDataClasses(models: List<DartClassModel>) {

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<String, dynamic> json) => _\$${sampleName}FromJson(json);")

// toJson
// writeln()
// writeln("Map<String, dynamic> 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())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Loading

0 comments on commit c7f061d

Please sign in to comment.