Code Monkey home page Code Monkey logo

sealedx's Introduction

SealedX


Google
License API Build Status Android Weekly Profile


๐ŸŽฒ Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin.

Why SealedX?

SealedX generates extensive sealed classes & interfaces based on common sealed classes for each different model. You can reduce writing repeated sealed classes for every different model by auto-generating based on KSP (Kotlin Symbol Processor).

You can massively reduce writing repeated files such as _UiState sealed interfaces if your project is based on MVI architecture.

Use Cases

If you want to learn more about how to migrate and use cases, check out the repositories below:

Gradle Setup

To use KSP (Kotlin Symbol Processing) and SealedX library in your project, you need to follow steps below.

1. Enable KSP in your module

Add the KSP plugin below into your module's build.gradle file:

Kotlin (KTS)
plugins {
    id("com.google.devtools.ksp") version "1.9.0-1.0.12"
}
Groovy
plugins {
    id("com.google.devtools.ksp") version "1.9.0-1.0.12"
}

Note: Make sure your current Kotlin version and KSP version is the same.

2. Add SealedX dependencies

Maven Central

Add the dependency below into your module's build.gradle file:

dependencies {
    implementation("com.github.skydoves:sealedx-core:1.0.2")
    ksp("com.github.skydoves:sealedx-processor:1.0.2")
}

3. Add KSP source path

To access generated codes from KSP, you need to set up the source path like the below into your module's build.gradle file:

Android Kotlin (KTS)
kotlin {
  sourceSets.configureEach {
    kotlin.srcDir("$buildDir/generated/ksp/$name/kotlin/")
  }
}
Android Groovy
android {
    applicationVariants.all { variant ->
        kotlin.sourceSets {
            def name = variant.name
            getByName(name) {
                kotlin.srcDir("build/generated/ksp/$name/kotlin")
            }
        }
    }
}
Pure Kotlin (KTS)
kotlin {
    sourceSets.main {
        kotlin.srcDir("build/generated/ksp/main/kotlin")
    }
    sourceSets.test {
        kotlin.srcDir("build/generated/ksp/test/kotlin")
    }
}
Pure Kotlin Groovy
kotlin {
    sourceSets {
        main.kotlin.srcDirs += 'build/generated/ksp/main/kotlin'
        test.kotlin.srcDirs += 'build/generated/ksp/test/kotlin'
    }
}

Usage

ExtensiveSealed

@ExtensiveSealed annotation is the main trigger of the Kotlin Symbol Processor to run a sealed-extensive processor on compile time.

  • @ExtensiveSealed must be annotated to sealed classes or interfaces, which should be a common model to generate extensive sealed classes and interfaces.
  • @ExtensiveSealed receives an array of @ExtensiveModel annotations, which include the extensive model types.
  • If you build your project, extensive sealed classes or interfaces will be generated based on those extensive models.

Let's see a common UiState sealed interface below that is annotated with @ExtensiveSealed annotation:

@ExtensiveSealed(
  models = [
    ExtensiveModel(Poster::class),
    ExtensiveModel(PosterDetails::class)
  ]
)
sealed interface UiState {
  data class Success(val data: Extensive) : UiState
  object Loading : UiState
  object Error : UiState
}

The example codes above will generate PosterUiState and PosterDetailsUiState sealed interfaces below:

PosterUiState (generated):

public sealed interface PosterUiState {
  public object Error : PosterUiState

  public object Loading : PosterUiState

  public data class Success(
    public val `data`: Poster,
  ) : PosterUiState
}

PosterDetailsUiState (generated):

public sealed interface PosterDetailsUiState {
  public object Error : PosterDetailsUiState

  public object Loading : PosterDetailsUiState

  public data class Success(
    public val `data`: PosterDetails,
  ) : PosterDetailsUiState
}
See further sealed class examples

In the case of the sealed classes, it's not different fundamentally from sealed interface examples.

@ExtensiveSealed(
  models = [ ExtensiveModel(type = Poster::class) ]
)
sealed class UiState {
  data class Success(val data: Extensive) : UiState()
  object Loading : UiState()
  object Error : UiState()
}

The example codes above will generate the PosterUiState sealed class below:

PosterUiState (generated):

public sealed class PosterUiState {
  public object Error : PosterUiState()

  public object Loading : PosterUiState()

  public data class Success(
    public val `data`: Poster,
  ) : PosterUiState()
}

ExtensiveModel

@ExtensiveModel annotation class contains information on extensive models like model type and a custom name, which decides the name of generated classes. Basically, (the simple name of the type) + (the name of common sealed classes) will be used to name of generated classes, but you can modify the prefix with the name parameter like the example below:

@ExtensiveSealed(
  models = [ ExtensiveModel(type = PosterExtensive::class, name = "Movie") ]
)
sealed interface UiState {
  data class Success(val data: Extensive) : UiState
  object Loading : UiState
  object Error : UiState
}

The example codes above will generate MovieUiState file instead of PosterExtensiveUiState like the below:

MovieUiState (generated):

public sealed interface MovieUiState {
  public object Error : MovieUiState

  public object Loading : MovieUiState

  public data class Success(
    public val `data`: PosterExtensive,
  ) : MovieUiState
}

Collection type in @ExtensiveModel

Basically, you can't set a collection type like a List to the type parameter of the @ExtensiveModel annotation. So if you need to set a collection type as an extensive model, you need to write a wrapper class like the below:

data class PosterExtensive(
  val posters: List<Poster>
)

@ExtensiveSealed(
  models = [ ExtensiveModel(type = PosterExtensive::class) ]
)
sealed interface UiState {
    ..
}

Extensive

Extensive is an interface that is used to represent extensive model types of sealed classes and interfaces. When you need to use an extensive model type in your primary constructor of data class, you can use the Extensive extensive type on your common sealed classes and interfaces. It will be replaced by the extensive model type on compile time.

@ExtensiveSealed(
  models = [ ExtensiveModel(type = PosterExtensive::class) ]
)
sealed interface UiState {
  // You need to use the Extensive type if you want to use an extensive model type in the generated code.
  data class Success(val data: Extensive) : UiState
  ..
}

The example codes above will generate PosterExtensiveUiState sealed interface like the below:

PosterExtensiveUiState (generated):

public sealed interface PosterExtensiveUiState {
  public object Error : PosterExtensiveUiState

  public object Loading : PosterExtensiveUiState

  public data class Success(
    public val `data`: PosterExtensive,
  ) : PosterExtensiveUiState
}

As you can see from the example above, the Extensive interface type will be replaced with the extensive model by the SealedX processor on compile time.

Find this repository useful? โค๏ธ

Support it by joining stargazers for this repository. โญ
Also, follow me on GitHub for my next creations! ๐Ÿคฉ

License

Designed and developed by 2022 skydoves (Jaewoong Eum)

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

   http://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.

sealedx's People

Contributors

skydoves avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sealedx's Issues

All @ExtensiveSealed declaration combines state in all generated files resulting in compilation error when similar states are defined in different sealed Interfaces

Please complete the following information:

  • Library Version [e.g. v1.0.1]

Describe the Bug:
When 2 sealed interfaces are defined with the @ExtensiveSealed with similar states the between both the sealed classes(The naming of the states are the same ) the processor generates files with duplicate states which results in a compilation error.In short it combines the states defined in all @ExtensiveSealed declarations into all generated states

Expected Behavior:
The processor should generate states for the models that are defined for a particular @ExtensiveSealed and not combine the states

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.