├── base
├── check
│ ├── .gitignore
│ ├── gradle.properties
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── spirytusz
│ │ └── booster
│ │ └── processor
│ │ └── check
│ │ ├── ClassCheckerFactory.kt
│ │ ├── field
│ │ ├── FieldTypeVarianceChecker.kt
│ │ ├── FieldMapTypeKeyGenericsChecker.kt
│ │ └── FieldNamingChecker.kt
│ │ ├── clazz
│ │ ├── ClassGenericsChecker.kt
│ │ ├── InvisibleGetterSetterFieldChecker.kt
│ │ └── NoArgsConstructorChecker.kt
│ │ ├── FieldCheckerImpl.kt
│ │ └── ClassCheckerImpl.kt
├── gen
│ ├── .gitignore
│ ├── gradle.properties
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── spirytusz
│ │ └── booster
│ │ └── processor
│ │ └── gen
│ │ ├── functions
│ │ ├── read
│ │ │ └── strategy
│ │ │ │ ├── base
│ │ │ │ ├── KtTypeReadCodeGenerator.kt
│ │ │ │ └── AbstractKtTypeReadCodeGenerator.kt
│ │ │ │ ├── KtTypeReadCodeGeneratorImpl.kt
│ │ │ │ ├── EnumKtTypeReadCodeGenerator.kt
│ │ │ │ ├── ObjectKtTypeReadCodeGenerator.kt
│ │ │ │ ├── CollectionKtTypeReadCodeGenerator.kt
│ │ │ │ └── PrimitiveKtTypeReadCodeGenerator.kt
│ │ └── write
│ │ │ ├── strategy
│ │ │ ├── base
│ │ │ │ ├── KtTypeWriteCodeGenerator.kt
│ │ │ │ └── AbstractKtTypeWriteCodeGenerator.kt
│ │ │ ├── EnumKtTypeWriteCodeGenerator.kt
│ │ │ ├── PrimitiveKtTypeWriteCodeGenerator.kt
│ │ │ ├── ObjectKtTypeWriteCodeGenerator.kt
│ │ │ ├── CollectionKtTypeWriteCodeGenerator.kt
│ │ │ ├── MapKtTypeWriteCodeGenerator.kt
│ │ │ └── KtTypeWriteCodeGeneratorImpl.kt
│ │ │ └── WriteFunctionGenerator.kt
│ │ ├── TypeAdapterGeneratorFactory.kt
│ │ ├── TypeAdapterFactoryGeneratorFactory.kt
│ │ ├── const
│ │ └── Const.kt
│ │ ├── extensions
│ │ └── NamingExtensions.kt
│ │ ├── fields
│ │ └── FieldGenerator.kt
│ │ └── TypeAdapterFactoryClassGeneratorImpl.kt
├── processor-base
│ ├── .gitignore
│ ├── gradle.properties
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── com
│ │ │ └── spirytusz
│ │ │ └── booster
│ │ │ └── processor
│ │ │ └── base
│ │ │ ├── data
│ │ │ ├── type
│ │ │ │ ├── KtVariance.kt
│ │ │ │ ├── KtVariableType.kt
│ │ │ │ ├── JsonTokenName.kt
│ │ │ │ └── KtType.kt
│ │ │ ├── config
│ │ │ │ └── TypeAdapterClassGenConfig.kt
│ │ │ ├── BoosterClassKind.kt
│ │ │ ├── FieldInitializer.kt
│ │ │ ├── DeclarationScope.kt
│ │ │ └── KtField.kt
│ │ │ ├── const
│ │ │ └── Keys.kt
│ │ │ ├── check
│ │ │ ├── FieldChecker.kt
│ │ │ └── ClassChecker.kt
│ │ │ ├── utils
│ │ │ └── ServiceManager.kt
│ │ │ ├── log
│ │ │ └── MessageLogger.kt
│ │ │ ├── scan
│ │ │ └── ClassScanner.kt
│ │ │ └── gen
│ │ │ ├── TypeAdapterFactoryGenerator.kt
│ │ │ └── TypeAdapterGenerator.kt
│ └── build.gradle.kts
├── scan
│ ├── scan-kapt
│ │ ├── .gitignore
│ │ ├── gradle.properties
│ │ ├── src
│ │ │ └── main
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── spirytusz
│ │ │ │ └── booster
│ │ │ │ └── processor
│ │ │ │ └── scan
│ │ │ │ └── kapt
│ │ │ │ ├── data
│ │ │ │ ├── IElementOwner.kt
│ │ │ │ ├── KaptKtType.kt
│ │ │ │ └── KaptKtField.kt
│ │ │ │ ├── KmClassKindResolver.kt
│ │ │ │ ├── KmClassCacheHolder.kt
│ │ │ │ ├── KmPropertyResolver.kt
│ │ │ │ ├── KmValueParameterResolver.kt
│ │ │ │ └── KmTypeResolver.kt
│ │ └── build.gradle.kts
│ └── scan-ksp
│ │ ├── .gitignore
│ │ ├── gradle.properties
│ │ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── com
│ │ │ └── spirytusz
│ │ │ └── booster
│ │ │ └── processor
│ │ │ └── scan
│ │ │ └── ksp
│ │ │ ├── data
│ │ │ ├── IKsNodeOwner.kt
│ │ │ ├── KspKtType.kt
│ │ │ └── KspKtField.kt
│ │ │ ├── impl
│ │ │ ├── KsClassKindResolver.kt
│ │ │ ├── KspJavaClassScanner.kt
│ │ │ ├── KspKtClassScanner.kt
│ │ │ └── JsonTokenNameResolver.kt
│ │ │ ├── extensions
│ │ │ └── KspExtensions.kt
│ │ │ └── KspClassScannerFactory.kt
│ │ └── build.gradle.kts
└── processor-base-test
│ ├── .gitignore
│ ├── src
│ └── main
│ │ ├── resources
│ │ ├── com
│ │ │ └── spirytusz
│ │ │ │ └── booster
│ │ │ │ └── bean
│ │ │ │ ├── ClassWithArgsConstructor.kt
│ │ │ │ ├── ClassWithGenerics.kt
│ │ │ │ ├── ClassWithMapIntAny.kt
│ │ │ │ ├── ClassWithFieldNamedByKeyword.kt
│ │ │ │ ├── ClassWithInvisibleGetterSetterFields.kt
│ │ │ │ ├── ClassWithVariantTypeFields.kt
│ │ │ │ ├── ClassWithSuperInvisibleFields.kt
│ │ │ │ ├── ComplexBean.kt
│ │ │ │ ├── Beans.kt
│ │ │ │ └── ComplexStructureBean.kt
│ │ └── json
│ │ │ ├── complex_bean_result.json
│ │ │ ├── bean_result.json
│ │ │ └── complex_struct_bean_result.json
│ │ └── java
│ │ └── com
│ │ └── spirytusz
│ │ └── booster
│ │ └── processor
│ │ └── test
│ │ ├── AbstractCompilePhaseCheckerTest.kt
│ │ ├── extensions
│ │ └── KotlinCompilerTestExtensions.kt
│ │ └── AbstractSerializeTest.kt
│ └── build.gradle.kts
├── benchmark
├── .gitignore
├── src
│ ├── main
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── spirytusz
│ │ └── benchmark
│ │ └── Benchmark.kt
├── benchmark-proguard-rules.pro
└── build.gradle.kts
├── kapt-demo
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values-night
│ │ │ └── themes.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ └── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── spirytusz
│ │ │ └── gsonbooster
│ │ │ └── kapt
│ │ │ ├── MainActivity.kt
│ │ │ └── data
│ │ │ └── Beans.kt
│ │ └── assets
│ │ └── test.json
├── proguard-rules.pro
└── build.gradle.kts
├── ksp-demo
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values-night
│ │ │ └── themes.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ └── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── spirytusz
│ │ │ └── gsonbooster
│ │ │ └── ksp
│ │ │ ├── MainActivity.kt
│ │ │ └── data
│ │ │ └── Beans.kt
│ │ └── assets
│ │ └── test.json
├── proguard-rules.pro
└── build.gradle.kts
├── booster-annotation
├── .gitignore
├── build.gradle.kts
├── gradle.properties
└── src
│ └── main
│ └── java
│ └── com
│ └── spirytusz
│ └── booster
│ └── annotation
│ └── Boost.kt
├── booster-processor
├── processor-ksp
│ ├── .gitignore
│ ├── gradle.properties
│ ├── src
│ │ ├── main
│ │ │ ├── resources
│ │ │ │ └── META-INF
│ │ │ │ │ └── services
│ │ │ │ │ └── com.google.devtools.ksp.processing.SymbolProcessorProvider
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── spirytusz
│ │ │ │ └── booster
│ │ │ │ └── processor
│ │ │ │ └── ksp
│ │ │ │ ├── provider
│ │ │ │ └── BoosterProcessorProvider.kt
│ │ │ │ └── log
│ │ │ │ └── KspMessageLogger.kt
│ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── spirytusz
│ │ │ └── booster
│ │ │ └── processor
│ │ │ └── ksp
│ │ │ └── test
│ │ │ ├── checker
│ │ │ ├── KspMapFieldCheckerTest.kt
│ │ │ ├── KspClassGenericsCheckerTest.kt
│ │ │ ├── KspNoArgsConstructorCheckerTest.kt
│ │ │ ├── KspFieldNamingCheckerTest.kt
│ │ │ ├── KspSuperInvisibleFieldCheckerTest.kt
│ │ │ ├── KspGetterSetterVisibilityCheckerTest.kt
│ │ │ └── KspTypeVarianceCheckerTest.kt
│ │ │ ├── base
│ │ │ ├── AbstractKspCompilePhaseCheckerPatternTest.kt
│ │ │ ├── AbstractKspCompilePhaseCheckerTest.kt
│ │ │ └── AbstractKspSerializeTest.kt
│ │ │ ├── serialize
│ │ │ ├── KspBoosterProcessorSerializeTest.kt
│ │ │ ├── KspBoosterProcessorSerializeComplexBeanTest.kt
│ │ │ └── KspBoosterProcessorSerializeComplexStructBeanTest.kt
│ │ │ └── extensions
│ │ │ └── KspTestExtensions.kt
│ └── build.gradle.kts
└── processor-kapt
│ ├── .gitignore
│ ├── gradle.properties
│ ├── src
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── spirytusz
│ │ │ └── booster
│ │ │ └── processor
│ │ │ └── kapt
│ │ │ └── test
│ │ │ ├── checker
│ │ │ ├── KaptMapFieldCheckerTest.kt
│ │ │ ├── KaptClassGenericsCheckerTest.kt
│ │ │ ├── KaptNoArgsConstructorCheckerTest.kt
│ │ │ ├── KaptFieldNamingCheckerTest.kt
│ │ │ ├── KaptSuperInvisibleFieldCheckerTest.kt
│ │ │ ├── KaptGetterSetterVisibilityCheckerTest.kt
│ │ │ └── KaptTypeVarianceCheckerTest.kt
│ │ │ ├── base
│ │ │ ├── AbstractKaptCompilePhaseCheckerPatternTest.kt
│ │ │ ├── AbstractKaptCompilePhaseCheckerTest.kt
│ │ │ └── AbstractKaptSerializeTest.kt
│ │ │ └── serialize
│ │ │ ├── KaptBoosterProcessorSerializeTest.kt
│ │ │ ├── KaptBoosterProcessorSerializeComplexBeanTest.kt
│ │ │ └── KaptBoosterProcessorSerializeComplexStructBeanTest.kt
│ └── main
│ │ └── java
│ │ └── com
│ │ └── spirytusz
│ │ └── booster
│ │ └── processor
│ │ └── kapt
│ │ └── log
│ │ └── KaptMessageLogger.kt
│ └── build.gradle.kts
├── .idea
├── .gitignore
├── vcs.xml
├── compiler.xml
├── misc.xml
├── jarRepositories.xml
├── gradle.xml
└── libraries-with-intellij-classes.xml
├── img
└── compare.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle.kts
├── LICENSE
├── gradle.properties
└── gradlew.bat
/base/check/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/base/gen/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/benchmark/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/kapt-demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/ksp-demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/base/processor-base/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/base/scan/scan-kapt/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/base/scan/scan-ksp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/booster-annotation/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/base/processor-base-test/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/img/compare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/img/compare.png
--------------------------------------------------------------------------------
/booster-annotation/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | id("maven-publish-plugin")
4 | }
--------------------------------------------------------------------------------
/booster-annotation/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-annotation
2 | MAVEN_POM_DESCRIPTION=Gson Booster Annotations
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/base/scan/scan-kapt/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-scan
2 | MAVEN_POM_DESCRIPTION=Gson Booster Scanner
--------------------------------------------------------------------------------
/benchmark/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | GsonBooster-kapt
3 |
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | GsonBooster-ksp
3 |
--------------------------------------------------------------------------------
/base/check/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-check
2 | MAVEN_POM_DESCRIPTION=Gson Booster Processor Code Checkers
--------------------------------------------------------------------------------
/base/gen/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-gen
2 | MAVEN_POM_DESCRIPTION=Gson Booster Processor Code Generator
--------------------------------------------------------------------------------
/base/processor-base/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-base
2 | MAVEN_POM_DESCRIPTION=Gson Booster Base Processor
--------------------------------------------------------------------------------
/base/scan/scan-ksp/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-scan-ksp
2 | MAVEN_POM_DESCRIPTION=Gson Booster KSP Scanner
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor
2 | MAVEN_POM_DESCRIPTION=Gson Booster Annotation Processor
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/gradle.properties:
--------------------------------------------------------------------------------
1 | MAVEN_ARTIFACT_ID=booster-processor-ksp
2 | MAVEN_POM_DESCRIPTION=Gson Booster Annotation Processor Using KSP
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/kapt-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spirytusz/GsonBooster/HEAD/ksp-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider:
--------------------------------------------------------------------------------
1 | com.spirytusz.booster.processor.ksp.provider.BoosterProcessorProvider
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/booster-annotation/src/main/java/com/spirytusz/booster/annotation/Boost.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.annotation
2 |
3 | @Target(AnnotationTarget.CLASS)
4 | @Retention(AnnotationRetention.SOURCE)
5 | annotation class Boost
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithArgsConstructor.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithArgsConstructor(val stringValue: String)
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/type/KtVariance.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data.type
2 |
3 | /**
4 | * 可变性
5 | */
6 | enum class KtVariance {
7 | IN,
8 | OUT,
9 | INVARIANT
10 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/const/Keys.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.const
2 |
3 | object Keys {
4 | const val KEY_TYPE_ADAPTER_FACTORY_NAME = "factory"
5 |
6 | const val KEY_NULL_SAFE = "nullSafe"
7 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithGenerics.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithGenerics {
7 |
8 | var stringValue: String = ""
9 | }
--------------------------------------------------------------------------------
/base/scan/scan-kapt/src/main/java/com/spirytusz/booster/processor/scan/kapt/data/IElementOwner.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.kapt.data
2 |
3 | import javax.lang.model.element.Element
4 |
5 | interface IElementOwner {
6 |
7 | val target: Element?
8 | }
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/data/IKsNodeOwner.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp.data
2 |
3 | import com.google.devtools.ksp.symbol.KSNode
4 |
5 | interface IKsNodeOwner {
6 |
7 | val target: KSNode?
8 | }
--------------------------------------------------------------------------------
/base/processor-base-test/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | }
4 |
5 | dependencies {
6 | api(Dependencies.junit)
7 | api(Dependencies.gson)
8 | api(Dependencies.kotlin_compiler_testing)
9 |
10 | api(project(":booster-annotation"))
11 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithMapIntAny.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithMapIntAny {
7 | var mapIntInt: Map = mapOf()
8 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithFieldNamedByKeyword.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithFieldNamedByKeyword {
7 |
8 | var `in`: String = ""
9 | }
--------------------------------------------------------------------------------
/base/scan/scan-ksp/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | id("maven-publish-plugin")
4 | }
5 |
6 | dependencies {
7 | implementation(Dependencies.kotlin_stdlib)
8 |
9 | api(project(":base:processor-base"))
10 | implementation(Dependencies.ksp_api)
11 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 03 10:07:27 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
7 |
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/config/TypeAdapterClassGenConfig.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data.config
2 |
3 | data class TypeAdapterClassGenConfig(
4 | val nullSafe: Boolean = false,
5 | val strictType: Boolean = false
6 | )
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/BoosterClassKind.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data
2 |
3 | enum class BoosterClassKind {
4 | CLASS,
5 | OBJECT,
6 | ENUM_CLASS,
7 | ENUM_ENTRY,
8 | INTERFACE,
9 | ANNOTATION
10 | }
--------------------------------------------------------------------------------
/base/scan/scan-kapt/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | id("maven-publish-plugin")
4 | }
5 |
6 | dependencies {
7 | implementation(Dependencies.kotlin_stdlib)
8 |
9 | api(project(":base:processor-base"))
10 | implementation(Dependencies.kotlinx_metadata)
11 | }
--------------------------------------------------------------------------------
/base/gen/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | kotlin("kapt")
4 | id("maven-publish-plugin")
5 | }
6 |
7 | dependencies {
8 | api(project(":base:processor-base"))
9 |
10 | implementation(Dependencies.auto_service_annotation)
11 | kapt(Dependencies.auto_service)
12 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithInvisibleGetterSetterFields.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithInvisibleGetterSetterFields {
7 |
8 | val stringValue: String = ""
9 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithVariantTypeFields.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithVariantTypeFields {
7 |
8 | var listOutString: List = listOf()
9 | }
--------------------------------------------------------------------------------
/base/check/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | kotlin("kapt")
4 | id("maven-publish-plugin")
5 | }
6 |
7 | dependencies {
8 | api(project(":base:processor-base"))
9 |
10 | implementation(Dependencies.auto_service_annotation)
11 | kapt(Dependencies.auto_service)
12 | }
--------------------------------------------------------------------------------
/base/processor-base/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | id("maven-publish-plugin")
4 | }
5 |
6 | dependencies {
7 | implementation(Dependencies.kotlin_stdlib)
8 |
9 | api(Dependencies.kotlin_poet)
10 | api(Dependencies.kotlin_reflect)
11 | api(Dependencies.gson)
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | secret.gpg
17 | .repo
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ClassWithSuperInvisibleFields.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.spirytusz.booster.annotation.Boost
4 |
5 | @Boost
6 | class ClassWithSuperInvisibleFields : InvisibleFieldClass()
7 |
8 | open class InvisibleFieldClass {
9 |
10 | val stringValue: String = ""
11 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/check/FieldChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.check
2 |
3 | import com.spirytusz.booster.processor.base.data.KtField
4 | import com.spirytusz.booster.processor.base.scan.ClassScanner
5 |
6 | interface FieldChecker {
7 |
8 | fun check(classScanner: ClassScanner, ktField: KtField)
9 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/FieldInitializer.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data
2 |
3 | /**
4 | * 这个字段的的初始化方式?
5 | *
6 | * 1. NONE -> 无
7 | * 2. HAS_DEFAULT -> 默认值
8 | * 3. DELEGATED -> 委托
9 | */
10 | enum class FieldInitializer {
11 | NONE,
12 | HAS_DEFAULT,
13 | DELEGATED
14 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/utils/ServiceManager.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.utils
2 |
3 | import java.util.*
4 |
5 | object ServiceManager {
6 |
7 | inline fun fetchService(): T {
8 | return ServiceLoader.load(T::class.java, this::class.java.classLoader).iterator().next()
9 | }
10 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/json/complex_bean_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "complex_bean_str": "123",
3 | "complex_bean_int": 4,
4 | "complex_bean_long": 5,
5 | "complex_bean_float": 6.7,
6 | "complex_bean_double": 7.8,
7 | "complex_bean_bool": true,
8 | "complex_bean_interface_long": 9,
9 | "complex_bean_interface_string": "10",
10 | "super_bean_long": 11,
11 | "super_bean_string": "12"
12 | }
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/DeclarationScope.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data
2 |
3 | /**
4 | * 这个字段定义在哪里?
5 | *
6 | * 1. PRIMARY_CONSTRUCTOR -> 主构造方法
7 | * 2. BODY -> 类体
8 | * 3. SUPER_CLASS -> 超类
9 | * 4. SUPER_INTERFACE -> 接口
10 | */
11 | enum class DeclarationScope {
12 | PRIMARY_CONSTRUCTOR,
13 | BODY,
14 | SUPER_CLASS,
15 | SUPER_INTERFACE
16 | }
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "GsonBooster"
2 |
3 | include(":booster-annotation")
4 | include(":kapt-demo")
5 | include(":ksp-demo")
6 | include(":benchmark")
7 | include(":base:processor-base")
8 | include(":base:scan:scan-kapt")
9 | include(":base:scan:scan-ksp")
10 | include(":booster-processor:processor-kapt")
11 | include(":booster-processor:processor-ksp")
12 | include(":base:processor-base-test")
13 | include(":base:gen")
14 | include(":base:check")
15 |
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/check/ClassChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.check
2 |
3 | import com.spirytusz.booster.processor.base.log.MessageLogger
4 | import com.spirytusz.booster.processor.base.scan.ClassScanner
5 |
6 | interface ClassChecker {
7 |
8 | fun check(classScanner: ClassScanner)
9 |
10 | interface Factory {
11 |
12 | fun create(logger: MessageLogger): ClassChecker
13 | }
14 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/read/strategy/base/KtTypeReadCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.read.strategy.base
2 |
3 | import com.spirytusz.booster.processor.base.data.type.KtType
4 | import com.squareup.kotlinpoet.CodeBlock
5 |
6 | interface KtTypeReadCodeGenerator {
7 |
8 | fun generate(
9 | ktType: KtType,
10 | codegenHook: (CodeBlock.Builder, String) -> Unit
11 | ): CodeBlock
12 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/base/KtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy.base
2 |
3 | import com.spirytusz.booster.processor.base.data.type.KtType
4 | import com.squareup.kotlinpoet.CodeBlock
5 |
6 | interface KtTypeWriteCodeGenerator {
7 |
8 | fun generate(
9 | fieldName: String,
10 | ktType: KtType,
11 | codegenHook: (CodeBlock.Builder, String) -> Unit
12 | ): CodeBlock
13 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/ClassCheckerFactory.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check
2 |
3 | import com.google.auto.service.AutoService
4 | import com.spirytusz.booster.processor.base.check.ClassChecker
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 |
7 | @AutoService(ClassChecker.Factory::class)
8 | internal class ClassCheckerFactory : ClassChecker.Factory {
9 | override fun create(logger: MessageLogger): ClassChecker {
10 | return ClassCheckerImpl(logger)
11 | }
12 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/TypeAdapterGeneratorFactory.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen
2 |
3 | import com.google.auto.service.AutoService
4 | import com.spirytusz.booster.processor.base.gen.TypeAdapterGenerator
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 |
7 | @AutoService(TypeAdapterGenerator.Factory::class)
8 | internal class TypeAdapterGeneratorFactory : TypeAdapterGenerator.Factory {
9 |
10 | override fun create(logger: MessageLogger): TypeAdapterGenerator {
11 | return TypeAdapterGeneratorImpl(logger)
12 | }
13 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspMapFieldCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspMapFieldCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithMapIntAny.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("InvalidMapKeyGenericsException: .* \\[.*ClassWithMapIntAny]")
11 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspClassGenericsCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspClassGenericsCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithGenerics.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("ClassWithGenericsException: .* \\[.*ClassWithGenerics]")
11 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptMapFieldCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptMapFieldCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithMapIntAny.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("InvalidMapKeyGenericsException: .* \\[.*ClassWithMapIntAny]")
11 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptClassGenericsCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptClassGenericsCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithGenerics.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("ClassWithGenericsException: .* \\[.*ClassWithGenerics]")
11 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/TypeAdapterFactoryGeneratorFactory.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen
2 |
3 | import com.google.auto.service.AutoService
4 | import com.spirytusz.booster.processor.base.gen.TypeAdapterFactoryGenerator
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 |
7 | @AutoService(TypeAdapterFactoryGenerator.Factory::class)
8 | internal class TypeAdapterFactoryGeneratorFactory : TypeAdapterFactoryGenerator.Factory {
9 | override fun create(logger: MessageLogger): TypeAdapterFactoryGenerator {
10 | return TypeAdapterFactoryClassGeneratorImpl(logger)
11 | }
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/main/java/com/spirytusz/booster/processor/ksp/provider/BoosterProcessorProvider.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.provider
2 |
3 | import com.google.devtools.ksp.processing.SymbolProcessor
4 | import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
5 | import com.google.devtools.ksp.processing.SymbolProcessorProvider
6 | import com.spirytusz.booster.processor.ksp.KspBoosterProcessor
7 |
8 | class BoosterProcessorProvider : SymbolProcessorProvider {
9 | override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
10 | return KspBoosterProcessor(environment)
11 | }
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspNoArgsConstructorCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspNoArgsConstructorCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithArgsConstructor.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("WithoutNoArgsConstructorException: .* \\[.*ClassWithArgsConstructor]")
11 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/log/MessageLogger.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.log
2 |
3 | interface MessageLogger {
4 |
5 | fun debug(message: String) = debug(message, null)
6 |
7 | fun debug(message: String, target: Any? = null)
8 |
9 | fun info(message: String) = info(message, null)
10 |
11 | fun info(message: String, target: Any? = null)
12 |
13 | fun warn(message: String) = warn(message, null)
14 |
15 | fun warn(message: String, target: Any? = null)
16 |
17 | fun error(message: String) = error(message, null)
18 |
19 | fun error(message: String, target: Any? = null)
20 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptNoArgsConstructorCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptNoArgsConstructorCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ClassWithArgsConstructor.kt"
8 |
9 | override val pattern: Pattern =
10 | Pattern.compile("WithoutNoArgsConstructorException: .* \\[.*ClassWithArgsConstructor]")
11 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspFieldNamingCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspFieldNamingCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithFieldNamedByKeyword.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("FieldNamedByKotlinKeywordException: .* \\[.*ClassWithFieldNamedByKeyword]")
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptFieldNamingCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptFieldNamingCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithFieldNamedByKeyword.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("FieldNamedByKotlinKeywordException: .* \\[.*ClassWithFieldNamedByKeyword]")
12 | }
--------------------------------------------------------------------------------
/benchmark/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
16 |
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspSuperInvisibleFieldCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspSuperInvisibleFieldCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithSuperInvisibleFields.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("InvisibleGetterSetterException: .* \\[.*ClassWithSuperInvisibleFields]")
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptSuperInvisibleFieldCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptSuperInvisibleFieldCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithSuperInvisibleFields.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("InvisibleGetterSetterException: .* \\[.*ClassWithSuperInvisibleFields]")
12 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/scan/ClassScanner.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.scan
2 |
3 | import com.spirytusz.booster.processor.base.data.BoosterClassKind
4 | import com.spirytusz.booster.processor.base.data.KtField
5 | import com.spirytusz.booster.processor.base.data.type.KtType
6 |
7 | /**
8 | * 类扫描器
9 | */
10 | interface ClassScanner {
11 |
12 | /**
13 | * 类别,class、object、interface、interface、annotation或者是enum
14 | */
15 | val classKind: BoosterClassKind
16 |
17 | /**
18 | * 类型
19 | */
20 | val classKtType: KtType
21 |
22 | /**
23 | * 变量
24 | */
25 | val ktFields: List
26 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspGetterSetterVisibilityCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KspGetterSetterVisibilityCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithInvisibleGetterSetterFields.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("InvisibleGetterSetterException: .* \\[.*ClassWithInvisibleGetterSetterFields]")
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptGetterSetterVisibilityCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import java.util.regex.Pattern
5 |
6 | class KaptGetterSetterVisibilityCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
7 | override val sourceCodePath: String =
8 | "/com/spirytusz/booster/bean/ClassWithInvisibleGetterSetterFields.kt"
9 |
10 | override val pattern: Pattern =
11 | Pattern.compile("InvisibleGetterSetterException: .* \\[.*ClassWithInvisibleGetterSetterFields]")
12 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/base/AbstractKspCompilePhaseCheckerPatternTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.base
2 |
3 | import com.tschuchort.compiletesting.KotlinCompilation
4 | import java.util.regex.Pattern
5 |
6 | abstract class AbstractKspCompilePhaseCheckerPatternTest : AbstractKspCompilePhaseCheckerTest() {
7 |
8 | abstract val pattern: Pattern
9 |
10 | open val exitCode = KotlinCompilation.ExitCode.COMPILATION_ERROR
11 |
12 | override fun checkResult(result: KotlinCompilation.Result) {
13 | assert(result.exitCode == exitCode)
14 |
15 | assert(pattern.matcher(result.messages).find())
16 | }
17 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/base/AbstractKaptCompilePhaseCheckerPatternTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.base
2 |
3 | import com.tschuchort.compiletesting.KotlinCompilation
4 | import java.util.regex.Pattern
5 |
6 | abstract class AbstractKaptCompilePhaseCheckerPatternTest : AbstractKaptCompilePhaseCheckerTest() {
7 |
8 | abstract val pattern: Pattern
9 |
10 | open val exitCode = KotlinCompilation.ExitCode.INTERNAL_ERROR
11 |
12 | override fun checkResult(result: KotlinCompilation.Result) {
13 | assert(result.exitCode == exitCode)
14 |
15 | assert(pattern.matcher(result.messages).find())
16 | }
17 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/json/bean_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "bean_str": "123",
3 | "bean_int": 4,
4 | "bean_long": 5,
5 | "bean_float": 6.7,
6 | "bean_double": 7.8,
7 | "bean_bool": true,
8 | "bean_list_str": [
9 | "9",
10 | "10",
11 | "11"
12 | ],
13 | "bean_java_list_str": [
14 | "12",
15 | "13",
16 | "14"
17 | ],
18 | "bean_set_str": [
19 | "15",
20 | "16",
21 | "17"
22 | ],
23 | "bean_java_set_str": [
24 | "18",
25 | "19",
26 | "20"
27 | ],
28 | "bean_map_str_str": {
29 | "21": "22",
30 | "23": "24",
31 | "25": "26"
32 | },
33 | "bean_java_map_str_str": {
34 | "27": "28",
35 | "29": "30",
36 | "31": "32"
37 | }
38 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/type/KtVariableType.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data.type
2 |
3 | open class KtVariableType(
4 | override val rawType: String,
5 | override val nullable: Boolean,
6 | override val variance: KtVariance,
7 | override val jsonTokenName: JsonTokenName,
8 | override val generics: List
9 | ) : KtType {
10 |
11 | override fun copy(nullable: Boolean, variance: KtVariance): KtVariableType {
12 | return KtVariableType(
13 | rawType = this.rawType,
14 | nullable = nullable,
15 | variance = variance,
16 | jsonTokenName = this.jsonTokenName,
17 | generics = this.generics
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/checker/KspTypeVarianceCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.checker
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspCompilePhaseCheckerPatternTest
4 | import com.tschuchort.compiletesting.KotlinCompilation
5 | import java.util.regex.Pattern
6 |
7 | class KspTypeVarianceCheckerTest : AbstractKspCompilePhaseCheckerPatternTest() {
8 | override val sourceCodePath: String =
9 | "/com/spirytusz/booster/bean/ClassWithVariantTypeFields.kt"
10 |
11 | override val exitCode: KotlinCompilation.ExitCode = KotlinCompilation.ExitCode.OK
12 |
13 | override val pattern: Pattern =
14 | Pattern.compile("not recommend variant type")
15 | }
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/checker/KaptTypeVarianceCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.checker
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptCompilePhaseCheckerPatternTest
4 | import com.tschuchort.compiletesting.KotlinCompilation
5 | import java.util.regex.Pattern
6 |
7 | class KaptTypeVarianceCheckerTest : AbstractKaptCompilePhaseCheckerPatternTest() {
8 | override val sourceCodePath: String =
9 | "/com/spirytusz/booster/bean/ClassWithVariantTypeFields.kt"
10 |
11 | override val exitCode: KotlinCompilation.ExitCode = KotlinCompilation.ExitCode.OK
12 |
13 | override val pattern: Pattern =
14 | Pattern.compile("not recommend variant type")
15 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | kotlin("kapt")
4 | id("maven-publish-plugin")
5 | }
6 |
7 | dependencies {
8 | implementation(Dependencies.kotlin_stdlib)
9 |
10 | implementation(Dependencies.kotlin_poet)
11 | compileOnly(Dependencies.gson)
12 |
13 | implementation(project(":booster-annotation"))
14 | api(project(":base:processor-base"))
15 | implementation(project(":base:scan:scan-kapt"))
16 | runtimeOnly(project(":base:check"))
17 | runtimeOnly(project(":base:gen"))
18 |
19 | implementation(Dependencies.auto_service_annotation)
20 | kapt(Dependencies.auto_service)
21 |
22 | testImplementation(Dependencies.kotlin_compiler_testing)
23 | testApi(project(":base:processor-base-test"))
24 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/const/Const.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.const
2 |
3 | internal object Const {
4 | object Naming {
5 | const val TYPE_ADAPTER = "TypeAdapter"
6 |
7 | const val TYPE_ADAPTER_FACTORY = "TypeAdapterFactory"
8 |
9 | const val GSON = "gson"
10 |
11 | const val TYPE = "type"
12 |
13 | const val READER = "reader"
14 |
15 | const val WRITER = "writer"
16 |
17 | const val OBJECT = "obj"
18 |
19 | const val PEEKED = "peeked"
20 |
21 | const val TYPE_TOKEN = "typeToken"
22 |
23 | const val DEFAULT_VALUE = "defaultValue"
24 |
25 | const val RETURN_VALUE = "returnValue"
26 |
27 | const val TEMP_FIELD_PREFIX = "temp"
28 | }
29 | }
--------------------------------------------------------------------------------
/ksp-demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/kapt-demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/serialize/KspBoosterProcessorSerializeTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.serialize
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspSerializeTest
4 |
5 | class KspBoosterProcessorSerializeTest : AbstractKspSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/Beans.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.Bean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/bean_result.json"
19 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/java/com/spirytusz/booster/processor/test/AbstractCompilePhaseCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.test
2 |
3 | import com.spirytusz.booster.processor.test.extensions.fromResource
4 | import com.tschuchort.compiletesting.KotlinCompilation
5 | import com.tschuchort.compiletesting.SourceFile
6 | import org.junit.Test
7 |
8 | abstract class AbstractCompilePhaseCheckerTest {
9 |
10 | abstract val sourceCodePath: String
11 |
12 | abstract fun compile(sources: List): KotlinCompilation.Result
13 |
14 | abstract fun checkResult(result: KotlinCompilation.Result)
15 |
16 | @Test
17 | fun test() {
18 | val source = SourceFile.fromResource(sourceCodePath)
19 | val sources = listOf(source)
20 | val result = compile(sources)
21 |
22 | checkResult(result)
23 | }
24 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/serialize/KaptBoosterProcessorSerializeTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.serialize
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptSerializeTest
4 |
5 | class KaptBoosterProcessorSerializeTest : AbstractKaptSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/Beans.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.Bean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/bean_result.json"
19 | }
--------------------------------------------------------------------------------
/ksp-demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/field/FieldTypeVarianceChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.field
2 |
3 | import com.spirytusz.booster.processor.base.check.FieldChecker
4 | import com.spirytusz.booster.processor.base.data.KtField
5 | import com.spirytusz.booster.processor.base.data.type.KtVariance
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 | import com.spirytusz.booster.processor.base.scan.ClassScanner
8 |
9 | internal class FieldTypeVarianceChecker(private val messageLogger: MessageLogger) : FieldChecker {
10 | override fun check(classScanner: ClassScanner, ktField: KtField) {
11 | val variantTypes = ktField.ktType.dfs { variance != KtVariance.INVARIANT }
12 | if (variantTypes.isEmpty()) {
13 | return
14 | }
15 | messageLogger.warn("not recommend variant type", ktField)
16 | }
17 | }
--------------------------------------------------------------------------------
/kapt-demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/clazz/ClassGenericsChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.clazz
2 |
3 | import com.spirytusz.booster.processor.base.check.ClassChecker
4 | import com.spirytusz.booster.processor.base.log.MessageLogger
5 | import com.spirytusz.booster.processor.base.scan.ClassScanner
6 |
7 | internal class ClassGenericsChecker(private val messageLogger: MessageLogger) : ClassChecker {
8 |
9 | override fun check(classScanner: ClassScanner) {
10 | val classKtType = classScanner.classKtType
11 | if (classKtType.generics.isEmpty()) {
12 | return
13 | }
14 | messageLogger.error("class with generics", classKtType)
15 | throw ClassWithGenericsException("class with generics [${classKtType.rawType}]")
16 | }
17 |
18 | private class ClassWithGenericsException(msg: String) : Exception(msg)
19 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/base/AbstractKaptCompilePhaseCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.base
2 |
3 | import com.spirytusz.booster.processor.kapt.KaptBoosterProcessor
4 | import com.spirytusz.booster.processor.test.AbstractCompilePhaseCheckerTest
5 | import com.tschuchort.compiletesting.KotlinCompilation
6 | import com.tschuchort.compiletesting.SourceFile
7 |
8 | abstract class AbstractKaptCompilePhaseCheckerTest : AbstractCompilePhaseCheckerTest() {
9 | override fun compile(sources: List): KotlinCompilation.Result {
10 | return KotlinCompilation().apply {
11 | this.sources = sources
12 | inheritClassPath = true
13 | messageOutputStream = System.out
14 | annotationProcessors = listOf(KaptBoosterProcessor())
15 | }.compile()
16 | }
17 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/serialize/KspBoosterProcessorSerializeComplexBeanTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.serialize
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspSerializeTest
4 |
5 | class KspBoosterProcessorSerializeComplexBeanTest : AbstractKspSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ComplexBean.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.ComplexBean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/complex_bean_result.json"
19 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/serialize/KaptBoosterProcessorSerializeComplexBeanTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.serialize
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptSerializeTest
4 |
5 | class KaptBoosterProcessorSerializeComplexBeanTest : AbstractKaptSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ComplexBean.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.ComplexBean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/complex_bean_result.json"
19 | }
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/serialize/KspBoosterProcessorSerializeComplexStructBeanTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.serialize
2 |
3 | import com.spirytusz.booster.processor.ksp.test.base.AbstractKspSerializeTest
4 |
5 | class KspBoosterProcessorSerializeComplexStructBeanTest : AbstractKspSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ComplexStructureBean.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.ComplexStructureBean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/complex_struct_bean_result.json"
19 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/serialize/KaptBoosterProcessorSerializeComplexStructBeanTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.serialize
2 |
3 | import com.spirytusz.booster.processor.kapt.test.base.AbstractKaptSerializeTest
4 |
5 | class KaptBoosterProcessorSerializeComplexStructBeanTest : AbstractKaptSerializeTest() {
6 |
7 | companion object {
8 | private const val TYPE_ADAPTER_FACTORY_CLASS_NAME =
9 | "com.spirytusz.booster.BoosterTypeAdapterFactory"
10 | }
11 |
12 | override val sourceCodePath: String = "/com/spirytusz/booster/bean/ComplexStructureBean.kt"
13 |
14 | override val beanClassName: String = "com.spirytusz.booster.bean.ComplexStructureBean"
15 |
16 | override val typeAdapterFactoryClassName: String = TYPE_ADAPTER_FACTORY_CLASS_NAME
17 |
18 | override val jsonFilePath: String = "/json/complex_struct_bean_result.json"
19 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/base/AbstractKspCompilePhaseCheckerTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.base
2 |
3 | import com.spirytusz.booster.processor.ksp.provider.BoosterProcessorProvider
4 | import com.spirytusz.booster.processor.test.AbstractCompilePhaseCheckerTest
5 | import com.tschuchort.compiletesting.KotlinCompilation
6 | import com.tschuchort.compiletesting.SourceFile
7 | import com.tschuchort.compiletesting.symbolProcessorProviders
8 |
9 | abstract class AbstractKspCompilePhaseCheckerTest : AbstractCompilePhaseCheckerTest() {
10 | override fun compile(sources: List): KotlinCompilation.Result {
11 | return KotlinCompilation().apply {
12 | this.sources = sources
13 | inheritClassPath = true
14 | messageOutputStream = System.out
15 | symbolProcessorProviders = listOf(BoosterProcessorProvider())
16 | }.compile()
17 | }
18 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/extensions/KspTestExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.extensions
2 |
3 | import com.tschuchort.compiletesting.KotlinCompilation
4 | import java.io.File
5 |
6 | internal val KotlinCompilation.Result.workingDir: File
7 | get() = outputDirectory.parentFile!!
8 |
9 | val KotlinCompilation.Result.kspGeneratedSources: List
10 | get() {
11 | val kspWorkingDir = workingDir.resolve("ksp")
12 | val kspGeneratedDir = kspWorkingDir.resolve("sources")
13 | val kotlinGeneratedDir = kspGeneratedDir.resolve("kotlin")
14 | val javaGeneratedDir = kspGeneratedDir.resolve("java")
15 | val kotlinSources = kotlinGeneratedDir.walkTopDown().filter { it.name.endsWith(".kt") }
16 | val javaSources = javaGeneratedDir.walkTopDown().filter { it.name.endsWith(".java") }
17 | return kotlinSources.toList() + javaSources.toList()
18 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/gen/TypeAdapterFactoryGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.gen
2 |
3 | import com.google.gson.TypeAdapter
4 | import com.google.gson.TypeAdapterFactory
5 | import com.spirytusz.booster.processor.base.data.type.KtType
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 | import com.squareup.kotlinpoet.TypeSpec
8 |
9 | /**
10 | * [TypeAdapterFactory]类生成器
11 | */
12 | interface TypeAdapterFactoryGenerator {
13 |
14 | /**
15 | * 根据数据类与[TypeAdapter]之间的映射关系集合[classToTypeAdapters]生成一个[TypeAdapterFactory]
16 | *
17 | * @param typeAdapterFactoryName 生成类的权限定名
18 | * @param classToTypeAdapters 数据类与[TypeAdapter]之间的映射关系集合
19 | */
20 | fun generate(
21 | typeAdapterFactoryName: String,
22 | classToTypeAdapters: Set>
23 | ): TypeSpec
24 |
25 | interface Factory {
26 |
27 | fun create(logger: MessageLogger): TypeAdapterFactoryGenerator
28 | }
29 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2 |
3 | plugins {
4 | kotlin("jvm")
5 | kotlin("kapt")
6 | id("maven-publish-plugin")
7 | }
8 |
9 | dependencies {
10 | implementation(Dependencies.kotlin_stdlib)
11 |
12 | implementation(Dependencies.kotlin_poet)
13 | implementation(Dependencies.kotlin_poet_ksp)
14 | implementation(Dependencies.gson)
15 |
16 | implementation(project(":booster-annotation"))
17 | api(project(":base:processor-base"))
18 | implementation(project(":base:scan:scan-ksp"))
19 | runtimeOnly(project(":base:check"))
20 | runtimeOnly(project(":base:gen"))
21 |
22 | implementation(Dependencies.ksp_api)
23 |
24 | testImplementation(Dependencies.kotlin_compiler_testing_ksp)
25 | testApi(project(":base:processor-base-test"))
26 | }
27 |
28 | tasks.withType(KotlinCompile::class.java).all {
29 | kotlinOptions.freeCompilerArgs += "-Xopt-in=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview"
30 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/gen/TypeAdapterGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.gen
2 |
3 | import com.google.gson.TypeAdapter
4 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
5 | import com.spirytusz.booster.processor.base.data.type.KtType
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 | import com.spirytusz.booster.processor.base.scan.ClassScanner
8 | import com.squareup.kotlinpoet.TypeSpec
9 |
10 | /**
11 | * [TypeAdapter]类生成器
12 | */
13 | interface TypeAdapterGenerator {
14 |
15 | /**
16 | * 根据扫描结果[scanner],生成一个TypeAdapter
17 | *
18 | * @param scanner 类扫描器
19 | * @param config 逻辑代码生成上的配置
20 | */
21 | fun generate(
22 | scanner: ClassScanner,
23 | classFilter: Set,
24 | config: TypeAdapterClassGenConfig = TypeAdapterClassGenConfig()
25 | ): TypeSpec
26 |
27 | interface Factory {
28 | fun create(logger: MessageLogger): TypeAdapterGenerator
29 | }
30 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/impl/KsClassKindResolver.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp.impl
2 |
3 | import com.google.devtools.ksp.symbol.ClassKind
4 | import com.google.devtools.ksp.symbol.KSClassDeclaration
5 | import com.spirytusz.booster.processor.base.data.BoosterClassKind
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 |
8 | class KsClassKindResolver(
9 | private val ksClass: KSClassDeclaration,
10 | private val logger: MessageLogger
11 | ) {
12 |
13 | fun resolveClassKind(): BoosterClassKind {
14 | return when (ksClass.classKind) {
15 | ClassKind.CLASS -> BoosterClassKind.CLASS
16 | ClassKind.ENUM_CLASS -> BoosterClassKind.ENUM_CLASS
17 | ClassKind.INTERFACE -> BoosterClassKind.INTERFACE
18 | ClassKind.ANNOTATION_CLASS -> BoosterClassKind.ANNOTATION
19 | ClassKind.ENUM_ENTRY -> BoosterClassKind.ENUM_ENTRY
20 | ClassKind.OBJECT -> BoosterClassKind.OBJECT
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/type/JsonTokenName.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data.type
2 |
3 | enum class JsonTokenName(val jsonToken: String, val nextFuncExp: String) {
4 | INT("NUMBER", "nextInt()"),
5 | LONG("NUMBER", "nextLong()"),
6 | FLOAT("NUMBER", "nextDouble().toFloat()"),
7 | DOUBLE("NUMBER", "nextDouble()"),
8 | STRING("STRING", "nextString()"),
9 | BOOLEAN("BOOLEAN", "nextBoolean()"),
10 | LIST("BEGIN_ARRAY", ""),
11 | JAVA_LIST("BEGIN_ARRAY", ""),
12 | SET("BEGIN_ARRAY", ""),
13 | JAVA_SET("BEGIN_ARRAY", ""),
14 | ENUM("STRING", "nextString()"),
15 | MAP("BEGIN_OBJECT", ""),
16 | JAVA_MAP("BEGIN_OBJECT", ""),
17 | OBJECT("BEGIN_OBJECT", "");
18 |
19 | fun isPrimitive() = this in listOf(INT, LONG, FLOAT, DOUBLE, STRING, BOOLEAN)
20 |
21 | fun isObject() = this == OBJECT
22 |
23 | fun isArray() = this in listOf(LIST, SET, JAVA_LIST, JAVA_SET)
24 |
25 | fun isMap() = this in listOf(MAP, JAVA_MAP)
26 |
27 | fun isEnum() = this == ENUM
28 | }
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/extensions/KspExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp.extensions
2 |
3 | import com.google.devtools.ksp.symbol.KSClassDeclaration
4 | import com.google.devtools.ksp.symbol.KSDeclaration
5 | import com.google.devtools.ksp.symbol.KSType
6 | import com.google.devtools.ksp.symbol.KSTypeAlias
7 |
8 | fun KSType.isChildTypeOf(fqName: String): Boolean {
9 | var declaration = declaration
10 | while (declaration is KSTypeAlias) {
11 | declaration = declaration.type.resolve().declaration
12 | }
13 |
14 | if (declaration.qualifiedName?.asString() == fqName) {
15 | return true
16 | }
17 |
18 | return (declaration.findActualDeclaration() as KSClassDeclaration).superTypes.any {
19 | it.resolve().isChildTypeOf(fqName)
20 | }
21 | }
22 |
23 | fun KSDeclaration.findActualDeclaration(): KSDeclaration {
24 | return if (this is KSTypeAlias) {
25 | this.type.resolve().declaration.findActualDeclaration()
26 | } else {
27 | this
28 | }
29 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/EnumKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.functions.write.strategy.base.AbstractKtTypeWriteCodeGenerator
8 | import com.squareup.kotlinpoet.CodeBlock
9 |
10 | internal class EnumKtTypeWriteCodeGenerator(
11 | logger: MessageLogger,
12 | config: TypeAdapterClassGenConfig
13 | ) : AbstractKtTypeWriteCodeGenerator(logger, config) {
14 | override fun realGenerate(
15 | fieldName: String,
16 | codeBlockBuilder: CodeBlock.Builder,
17 | ktType: KtType,
18 | tempFieldName: String
19 | ) {
20 | codeBlockBuilder.addStatement("$WRITER.value($tempFieldName.name)")
21 | }
22 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/java/com/spirytusz/booster/processor/test/extensions/KotlinCompilerTestExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.test.extensions
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.JsonObject
5 | import com.tschuchort.compiletesting.KotlinCompilation
6 | import com.tschuchort.compiletesting.SourceFile
7 | import java.io.File
8 |
9 | fun SourceFile.Companion.fromResource(path: String): SourceFile {
10 | val file = File(path)
11 | val name = file.name
12 | val content = this::class.java.getResource(path).readText()
13 | return when {
14 | name.endsWith(".kt") -> kotlin(name, content)
15 | name.endsWith(".java") -> java(name, content)
16 | else -> throw IllegalArgumentException("UnSupport file extension $path")
17 | }
18 | }
19 |
20 | fun Any.toJsonObject(): JsonObject {
21 | val gson = Gson()
22 | return gson.fromJson(gson.toJson(this), JsonObject::class.java)
23 | }
24 |
25 | fun KotlinCompilation.Result.getClassByName(name: String): Class<*> {
26 | return classLoader.loadClass(name)
27 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/PrimitiveKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.functions.write.strategy.base.AbstractKtTypeWriteCodeGenerator
8 | import com.squareup.kotlinpoet.CodeBlock
9 |
10 | internal class PrimitiveKtTypeWriteCodeGenerator(
11 | logger: MessageLogger,
12 | config: TypeAdapterClassGenConfig
13 | ) : AbstractKtTypeWriteCodeGenerator(logger, config) {
14 |
15 | override fun realGenerate(
16 | fieldName: String,
17 | codeBlockBuilder: CodeBlock.Builder,
18 | ktType: KtType,
19 | tempFieldName: String
20 | ) {
21 | codeBlockBuilder.addStatement("$WRITER.value($tempFieldName)")
22 | }
23 | }
--------------------------------------------------------------------------------
/base/scan/scan-kapt/src/main/java/com/spirytusz/booster/processor/scan/kapt/data/KaptKtType.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.kapt.data
2 |
3 | import com.spirytusz.booster.processor.base.data.type.JsonTokenName
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.data.type.KtVariance
6 | import javax.lang.model.element.Element
7 |
8 | data class KaptKtType(
9 | override val rawType: String,
10 | override val nullable: Boolean,
11 | override val variance: KtVariance,
12 | override val jsonTokenName: JsonTokenName,
13 | override val generics: List,
14 | override val target: Element?
15 | ) : KtType, IElementOwner {
16 | override fun copy(nullable: Boolean, variance: KtVariance): KtType {
17 | return KaptKtType(
18 | rawType = this.rawType,
19 | nullable = nullable,
20 | variance = variance,
21 | jsonTokenName = this.jsonTokenName,
22 | generics = this.generics,
23 | target = this.target
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/data/KspKtType.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp.data
2 |
3 | import com.google.devtools.ksp.symbol.KSNode
4 | import com.spirytusz.booster.processor.base.data.type.JsonTokenName
5 | import com.spirytusz.booster.processor.base.data.type.KtType
6 | import com.spirytusz.booster.processor.base.data.type.KtVariance
7 |
8 | data class KspKtType(
9 | override val rawType: String,
10 | override val nullable: Boolean,
11 | override val variance: KtVariance,
12 | override val jsonTokenName: JsonTokenName,
13 | override val generics: List,
14 | override val target: KSNode?
15 | ) : KtType, IKsNodeOwner {
16 | override fun copy(nullable: Boolean, variance: KtVariance): KtType {
17 | return KspKtType(
18 | rawType = this.rawType,
19 | nullable = nullable,
20 | variance = variance,
21 | jsonTokenName = this.jsonTokenName,
22 | generics = this.generics,
23 | target = this.target
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 ZSpirytus
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/json/complex_struct_bean_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "complex_struct_complex_collection_bean": {
3 | "complex_collection_bean_list_set_list_long": [
4 | null,
5 | [
6 | null,
7 | [
8 | 1,
9 | 2,
10 | 3,
11 | null
12 | ],
13 | [
14 | null
15 | ]
16 | ]
17 | ]
18 | },
19 | "complex_struct_complex_map_bean": {
20 | "complex_map_bean_map_str_map_str_map_str_str": {
21 | "gusha": {
22 | "wula": null,
23 | "cesi": {
24 | "puta": null,
25 | "gugu": "hhh",
26 | "spi": "666"
27 | }
28 | },
29 | "sug": null
30 | }
31 | },
32 | "complex_struct_complex_fusion_bean": {
33 | "complex_fusion_bean_map_str_list_map_str_set_str": {
34 | "wondar": [
35 | {
36 | "seig": [
37 | null,
38 | "haha",
39 | "666",
40 | "777"
41 | ]
42 | },
43 | {},
44 | null,
45 | {
46 | "sogu": null
47 | }
48 | ],
49 | "wizer": null
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/benchmark/benchmark-proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | -dontobfuscate
24 |
25 | -ignorewarnings
26 |
27 | -keepattributes *Annotation*
28 |
29 | -dontnote junit.framework.**
30 | -dontnote junit.runner.**
31 |
32 | -dontwarn androidx.test.**
33 | -dontwarn org.junit.**
34 | -dontwarn org.hamcrest.**
35 | -dontwarn com.squareup.javawriter.JavaWriter
36 |
37 | -keepclasseswithmembers @org.junit.runner.RunWith public class *
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/ObjectKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.extensions.getTypeAdapterFieldName
8 | import com.spirytusz.booster.processor.gen.functions.write.strategy.base.AbstractKtTypeWriteCodeGenerator
9 | import com.squareup.kotlinpoet.CodeBlock
10 |
11 | internal class ObjectKtTypeWriteCodeGenerator(
12 | logger: MessageLogger,
13 | config: TypeAdapterClassGenConfig
14 | ) : AbstractKtTypeWriteCodeGenerator(logger, config) {
15 |
16 | override fun realGenerate(
17 | fieldName: String,
18 | codeBlockBuilder: CodeBlock.Builder,
19 | ktType: KtType,
20 | tempFieldName: String
21 | ) {
22 | val typeAdapterFieldName = ktType.getTypeAdapterFieldName()
23 | codeBlockBuilder.addStatement("$typeAdapterFieldName.write($WRITER, $tempFieldName)")
24 | }
25 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 | GROUP=com.spirytusz
23 | VERSION=1.3.1
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ComplexBean.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import com.spirytusz.booster.annotation.Boost
5 |
6 | @Boost
7 | data class ComplexBean(
8 | @SerializedName("complex_bean_str")
9 | var stringValue: String = "",
10 | @SerializedName("complex_bean_int")
11 | val intValue: Int = 0,
12 | @SerializedName("complex_bean_long")
13 | val longValue: Long = 0L,
14 | @SerializedName("complex_bean_float")
15 | val floatValue: Float = 0f,
16 | @SerializedName("complex_bean_double")
17 | val doubleValue: Double = 0.0,
18 | @SerializedName("complex_bean_bool")
19 | val booleanValue: Boolean = false,
20 | @SerializedName("complex_bean_interface_long")
21 | override val interfaceLong: Long = 0L,
22 | @SerializedName("complex_bean_interface_string")
23 | override val interfaceString: String = ""
24 | ) : SuperBean(), ISuper
25 |
26 | open class SuperBean {
27 |
28 | @SerializedName("super_bean_long")
29 | var superLong: Long = 0L
30 |
31 | @SerializedName("super_bean_str")
32 | var superString: String = ""
33 | }
34 |
35 | interface ISuper {
36 | val interfaceLong: Long
37 |
38 | val interfaceString: String
39 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/FieldCheckerImpl.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check
2 |
3 | import com.spirytusz.booster.processor.base.check.FieldChecker
4 | import com.spirytusz.booster.processor.base.data.KtField
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.base.scan.ClassScanner
7 | import com.spirytusz.booster.processor.check.field.FieldMapTypeKeyGenericsChecker
8 | import com.spirytusz.booster.processor.check.field.FieldNamingChecker
9 | import com.spirytusz.booster.processor.check.field.FieldTypeVarianceChecker
10 |
11 | internal class FieldCheckerImpl(private val messageLogger: MessageLogger) : FieldChecker {
12 |
13 | private val fieldNamingChecker by lazy { FieldNamingChecker(messageLogger) }
14 |
15 | private val fieldMapTypeKeyGenericsChecker by lazy {
16 | FieldMapTypeKeyGenericsChecker(messageLogger)
17 | }
18 |
19 | private val fieldTypeVarianceChecker by lazy { FieldTypeVarianceChecker(messageLogger) }
20 | override fun check(classScanner: ClassScanner, ktField: KtField) {
21 | fieldNamingChecker.check(classScanner, ktField)
22 | fieldMapTypeKeyGenericsChecker.check(classScanner, ktField)
23 | fieldTypeVarianceChecker.check(classScanner, ktField)
24 | }
25 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/Beans.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import com.spirytusz.booster.annotation.Boost
5 |
6 | @Boost
7 | data class Bean(
8 | @SerializedName("bean_str")
9 | var stringValue: String = "",
10 | @SerializedName("bean_int")
11 | val intValue: Int = 0,
12 | @SerializedName("bean_long")
13 | val longValue: Long = 0L,
14 | @SerializedName("bean_float")
15 | val floatValue: Float = 0f,
16 | @SerializedName("bean_double")
17 | val doubleValue: Double = 0.0,
18 | @SerializedName("bean_bool")
19 | val booleanValue: Boolean = false,
20 | @SerializedName("bean_list_str")
21 | val listString: List = listOf(),
22 | @SerializedName("bean_java_list_str")
23 | val javaListString: java.util.ArrayList = arrayListOf(),
24 | @SerializedName("bean_set_str")
25 | val setString: Set = setOf(),
26 | @SerializedName("bean_java_set_str")
27 | val javaSetString: java.util.HashSet = hashSetOf(),
28 | @SerializedName("bean_map_str_str")
29 | val mapStringString: Map = mapOf(),
30 | @SerializedName("bean_java_map_str_str")
31 | val javaMapStringString: HashMap = hashMapOf()
32 | )
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/data/KspKtField.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp.data
2 |
3 | import com.google.devtools.ksp.symbol.KSNode
4 | import com.spirytusz.booster.processor.base.data.DeclarationScope
5 | import com.spirytusz.booster.processor.base.data.FieldInitializer
6 | import com.spirytusz.booster.processor.base.data.KtField
7 | import com.spirytusz.booster.processor.base.data.type.KtType
8 |
9 | data class KspKtField(
10 | override val isFinal: Boolean,
11 | override val fieldName: String,
12 | override val keys: List,
13 | override val ktType: KtType,
14 | override val initializer: FieldInitializer,
15 | override val declarationScope: DeclarationScope,
16 | override val transient: Boolean,
17 | override val target: KSNode?
18 | ) : KtField, IKsNodeOwner {
19 | override fun copy(declarationScope: DeclarationScope): KtField {
20 | return KspKtField(
21 | isFinal = this.isFinal,
22 | fieldName = this.fieldName,
23 | keys = this.keys,
24 | ktType = this.ktType,
25 | initializer = this.initializer,
26 | declarationScope = declarationScope,
27 | transient = this.transient,
28 | target = this.target
29 | )
30 | }
31 | }
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/base/scan/scan-kapt/src/main/java/com/spirytusz/booster/processor/scan/kapt/data/KaptKtField.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.kapt.data
2 |
3 | import com.spirytusz.booster.processor.base.data.DeclarationScope
4 | import com.spirytusz.booster.processor.base.data.FieldInitializer
5 | import com.spirytusz.booster.processor.base.data.KtField
6 | import com.spirytusz.booster.processor.base.data.type.KtType
7 | import javax.lang.model.element.Element
8 |
9 | data class KaptKtField(
10 | override val isFinal: Boolean,
11 | override val fieldName: String,
12 | override val keys: List,
13 | override val ktType: KtType,
14 | override val initializer: FieldInitializer,
15 | override val declarationScope: DeclarationScope,
16 | override val transient: Boolean,
17 | override val target: Element?
18 | ) : KtField, IElementOwner {
19 |
20 | override fun copy(declarationScope: DeclarationScope): KtField {
21 | return KaptKtField(
22 | isFinal = this.isFinal,
23 | fieldName = this.fieldName,
24 | keys = this.keys,
25 | ktType = this.ktType,
26 | initializer = this.initializer,
27 | declarationScope = declarationScope,
28 | transient = this.transient,
29 | target = this.target
30 | )
31 | }
32 | }
--------------------------------------------------------------------------------
/base/processor-base-test/src/main/resources/com/spirytusz/booster/bean/ComplexStructureBean.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.bean
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import com.spirytusz.booster.annotation.Boost
5 |
6 | @Boost
7 | data class ComplexStructureBean(
8 | @SerializedName("complex_struct_complex_collection_bean")
9 | val complexCollectionBean: ComplexCollectionBean = ComplexCollectionBean(),
10 | @SerializedName("complex_struct_complex_map_bean")
11 | val complexMapBean: ComplexMapBean = ComplexMapBean(),
12 | @SerializedName("complex_struct_complex_fusion_bean")
13 | val complexFusionBean: ComplexFusionBean = ComplexFusionBean()
14 | )
15 |
16 | @Boost
17 | data class ComplexCollectionBean(
18 | @SerializedName("complex_collection_bean_list_set_list_long")
19 | val listSetListLong: List?>?> = listOf()
20 | )
21 |
22 | @Boost
23 | data class ComplexMapBean(
24 | @SerializedName("complex_map_bean_map_str_map_str_map_str_str")
25 | val mapStringMapStringMapStringString: Map?>?> = mapOf()
26 | )
27 |
28 | @Boost
29 | data class ComplexFusionBean(
30 | @SerializedName("complex_fusion_bean_map_str_list_map_str_set_str")
31 | val mapStringListMapStringSetString: Map?>?>?> = mapOf()
32 | )
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/field/FieldMapTypeKeyGenericsChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.field
2 |
3 | import com.spirytusz.booster.processor.base.check.FieldChecker
4 | import com.spirytusz.booster.processor.base.data.KtField
5 | import com.spirytusz.booster.processor.base.data.type.JsonTokenName
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 | import com.spirytusz.booster.processor.base.scan.ClassScanner
8 |
9 | internal class FieldMapTypeKeyGenericsChecker(private val messageLogger: MessageLogger) :
10 | FieldChecker {
11 | override fun check(classScanner: ClassScanner, ktField: KtField) {
12 | val mapTypeField = ktField.ktType.dfs { jsonTokenName.isMap() }.firstOrNull() ?: return
13 | val keyGenerics = mapTypeField.generics.first()
14 | if (keyGenerics.jsonTokenName == JsonTokenName.STRING) {
15 | return
16 | }
17 |
18 | messageLogger.error("invalid map key generics type", ktField)
19 | throw InvalidMapKeyGenericsException(
20 | "invalid map key generics type [${keyGenerics.rawType}] " +
21 | "in field [${ktField.fieldName}] at class " +
22 | "[${classScanner.classKtType.rawType}]"
23 | )
24 | }
25 |
26 | private class InvalidMapKeyGenericsException(msg: String) : Exception(msg)
27 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/main/java/com/spirytusz/booster/processor/ksp/log/KspMessageLogger.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.log
2 |
3 | import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
4 | import com.google.devtools.ksp.symbol.KSNode
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.scan.ksp.data.IKsNodeOwner
7 |
8 | class KspMessageLogger(private val environment: SymbolProcessorEnvironment) : MessageLogger {
9 |
10 | companion object {
11 | private const val TAG = "[Booster]"
12 | }
13 |
14 | override fun debug(message: String, target: Any?) {
15 | environment.logger.logging("$TAG $message", target?.tryCastKsNode())
16 | }
17 |
18 | override fun info(message: String, target: Any?) {
19 | environment.logger.info("$TAG $message", target?.tryCastKsNode())
20 | }
21 |
22 | override fun warn(message: String, target: Any?) {
23 | environment.logger.warn("$TAG $message", target?.tryCastKsNode())
24 | }
25 |
26 | override fun error(message: String, target: Any?) {
27 | environment.logger.error("$TAG $message", target?.tryCastKsNode())
28 | }
29 |
30 | private fun Any.tryCastKsNode(): KSNode? {
31 | return when (this) {
32 | is IKsNodeOwner -> this.target
33 | is KSNode -> this
34 | else -> null
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/ClassCheckerImpl.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check
2 |
3 | import com.spirytusz.booster.processor.base.check.ClassChecker
4 | import com.spirytusz.booster.processor.base.log.MessageLogger
5 | import com.spirytusz.booster.processor.base.scan.ClassScanner
6 | import com.spirytusz.booster.processor.check.clazz.ClassGenericsChecker
7 | import com.spirytusz.booster.processor.check.clazz.InvisibleGetterSetterFieldChecker
8 | import com.spirytusz.booster.processor.check.clazz.NoArgsConstructorChecker
9 |
10 | internal class ClassCheckerImpl(private val messageLogger: MessageLogger) : ClassChecker {
11 |
12 | private val classGenericsChecker by lazy { ClassGenericsChecker(messageLogger) }
13 |
14 | private val noArgsConstructorChecker by lazy { NoArgsConstructorChecker(messageLogger) }
15 |
16 | private val invisibleGetterSetterFieldChecker by lazy {
17 | InvisibleGetterSetterFieldChecker(messageLogger)
18 | }
19 |
20 | private val fieldChecker by lazy { FieldCheckerImpl(messageLogger) }
21 |
22 | override fun check(classScanner: ClassScanner) {
23 | classGenericsChecker.check(classScanner)
24 | invisibleGetterSetterFieldChecker.check(classScanner)
25 | noArgsConstructorChecker.check(classScanner)
26 |
27 | classScanner.ktFields.forEach {
28 | fieldChecker.check(classScanner, it)
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/extensions/NamingExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.extensions
2 |
3 | import com.spirytusz.booster.processor.base.data.type.KtType
4 | import com.spirytusz.booster.processor.gen.const.Const.Naming.PEEKED
5 | import com.spirytusz.booster.processor.gen.const.Const.Naming.TEMP_FIELD_PREFIX
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.TYPE_ADAPTER
7 | import com.squareup.kotlinpoet.ClassName
8 |
9 | fun String.firstCharLowerCase() =
10 | this.replaceFirst(this.first(), this.first().toLowerCase())
11 |
12 | fun String.firstChatUpperCase() =
13 | this.replaceFirst(this.first(), this.first().toUpperCase())
14 |
15 | fun KtType.flatten(): String = buildString {
16 | append(ClassName.bestGuess(rawType).simpleName)
17 | generics.forEach { append(it.flatten()) }
18 | }
19 |
20 | fun KtType.getTypeAdapterFieldName(): String {
21 | return "${flatten()}$TYPE_ADAPTER".firstCharLowerCase()
22 | }
23 |
24 | fun KtType.getTypeAdapterClassName(): ClassName {
25 | return ClassName.bestGuess("$rawType$TYPE_ADAPTER")
26 | }
27 |
28 | fun KtType.getReadingTempFieldName(): String {
29 | return "${TEMP_FIELD_PREFIX}Reading${flatten()}"
30 | }
31 |
32 | fun KtType.getWritingTempFieldName(fieldName: String): String {
33 | return "${TEMP_FIELD_PREFIX}Writing${flatten()}${fieldName.firstChatUpperCase()}"
34 | }
35 |
36 | fun KtType.getPeekedFieldName(): String {
37 | return "${PEEKED}${flatten()}"
38 | }
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/test/java/com/spirytusz/booster/processor/kapt/test/base/AbstractKaptSerializeTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.test.base
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.JsonObject
5 | import com.spirytusz.booster.processor.base.const.Keys.KEY_TYPE_ADAPTER_FACTORY_NAME
6 | import com.spirytusz.booster.processor.kapt.KaptBoosterProcessor
7 | import com.spirytusz.booster.processor.test.AbstractSerializeTest
8 | import com.spirytusz.booster.processor.test.extensions.getClassByName
9 | import com.spirytusz.booster.processor.test.extensions.toJsonObject
10 | import com.tschuchort.compiletesting.KotlinCompilation
11 | import com.tschuchort.compiletesting.SourceFile
12 |
13 | abstract class AbstractKaptSerializeTest : AbstractSerializeTest() {
14 |
15 | override fun compile(sources: List): KotlinCompilation.Result {
16 | return KotlinCompilation().apply {
17 | this.sources = sources
18 | inheritClassPath = true
19 | messageOutputStream = System.out
20 | annotationProcessors = listOf(KaptBoosterProcessor())
21 | kaptArgs =
22 | mutableMapOf(KEY_TYPE_ADAPTER_FACTORY_NAME to typeAdapterFactoryClassName)
23 | }.compile()
24 | }
25 |
26 | override fun getExpectJsonObject(result: KotlinCompilation.Result): JsonObject {
27 | val beanClass = result.getClassByName(beanClassName)
28 | return Gson().fromJson(json, beanClass).toJsonObject()
29 | }
30 | }
--------------------------------------------------------------------------------
/base/scan/scan-kapt/src/main/java/com/spirytusz/booster/processor/scan/kapt/KmClassKindResolver.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.kapt
2 |
3 | import com.spirytusz.booster.processor.base.data.BoosterClassKind
4 | import com.spirytusz.booster.processor.base.log.MessageLogger
5 | import kotlinx.metadata.Flag
6 | import javax.lang.model.element.TypeElement
7 |
8 | class KmClassKindResolver(
9 | private val belongingClass: TypeElement,
10 | private val kmClassCacheHolder: KmClassCacheHolder,
11 | private val logger: MessageLogger
12 | ) {
13 |
14 | private val kmClass by lazy {
15 | kmClassCacheHolder.get(belongingClass)
16 | }
17 |
18 | fun resolveClassKind(): BoosterClassKind {
19 | return when {
20 | Flag.Class.IS_CLASS(kmClass.flags) -> BoosterClassKind.CLASS
21 | Flag.Class.IS_ANNOTATION_CLASS(kmClass.flags) -> BoosterClassKind.ANNOTATION
22 | Flag.Class.IS_ENUM_ENTRY(kmClass.flags) -> BoosterClassKind.ENUM_ENTRY
23 | Flag.Class.IS_ENUM_CLASS(kmClass.flags) -> BoosterClassKind.ENUM_CLASS
24 | Flag.Class.IS_INTERFACE(kmClass.flags) -> BoosterClassKind.INTERFACE
25 | Flag.Class.IS_OBJECT(kmClass.flags) || Flag.Class.IS_COMPANION_OBJECT(kmClass.flags) -> BoosterClassKind.OBJECT
26 | else -> {
27 | logger.error("unexpected class kind on class $belongingClass", belongingClass)
28 | throw IllegalArgumentException("unexpected class kind on class $belongingClass")
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/clazz/InvisibleGetterSetterFieldChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.clazz
2 |
3 | import com.spirytusz.booster.processor.base.check.ClassChecker
4 | import com.spirytusz.booster.processor.base.data.DeclarationScope
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.base.scan.ClassScanner
7 |
8 | internal class InvisibleGetterSetterFieldChecker(private val messageLogger: MessageLogger) :
9 | ClassChecker {
10 |
11 | override fun check(classScanner: ClassScanner) {
12 | val invisibleGetterSetterFields = classScanner.ktFields.asSequence().filter {
13 | !it.transient
14 | }.filter {
15 | it.declarationScope in listOf(DeclarationScope.BODY, DeclarationScope.SUPER_CLASS)
16 | }.filter {
17 | it.isFinal
18 | }.toList()
19 |
20 | if (invisibleGetterSetterFields.isEmpty()) {
21 | return
22 | }
23 |
24 | invisibleGetterSetterFields.forEach {
25 | messageLogger.error("invisible getter setter field", it)
26 | }
27 | val invisibleGetterSetterFieldNames = invisibleGetterSetterFields.map { it.fieldName }
28 |
29 | throw InvisibleGetterSetterException(
30 | "invisible getter setter field in " +
31 | "class [${classScanner.classKtType.rawType}]: " +
32 | "$invisibleGetterSetterFieldNames"
33 | )
34 | }
35 |
36 | private class InvisibleGetterSetterException(msg: String) : Exception(msg)
37 | }
--------------------------------------------------------------------------------
/base/scan/scan-ksp/src/main/java/com/spirytusz/booster/processor/scan/ksp/KspClassScannerFactory.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.ksp
2 |
3 | import com.google.devtools.ksp.processing.Resolver
4 | import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
5 | import com.google.devtools.ksp.symbol.KSClassDeclaration
6 | import com.google.devtools.ksp.symbol.Origin
7 | import com.spirytusz.booster.processor.base.log.MessageLogger
8 | import com.spirytusz.booster.processor.base.scan.ClassScanner
9 | import com.spirytusz.booster.processor.scan.ksp.impl.KspJavaClassScanner
10 | import com.spirytusz.booster.processor.scan.ksp.impl.KspKtClassScanner
11 |
12 | object KspClassScannerFactory {
13 |
14 | fun create(
15 | environment: SymbolProcessorEnvironment,
16 | resolver: Resolver,
17 | ksClass: KSClassDeclaration,
18 | logger: MessageLogger
19 | ): ClassScanner {
20 | val containingFile = ksClass.containingFile ?: run {
21 | logger.error("invalid class ${ksClass.qualifiedName?.asString()}", ksClass)
22 | throw IllegalArgumentException("invalid class ${ksClass.qualifiedName?.asString()}")
23 | }
24 | return when (containingFile.origin) {
25 | Origin.JAVA -> KspJavaClassScanner(environment, resolver, ksClass, logger)
26 | Origin.KOTLIN -> KspKtClassScanner(environment, resolver, ksClass, logger)
27 | else -> {
28 | logger.error("Unexpected origin", ksClass)
29 | throw IllegalArgumentException("Unexpected origin")
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/KtField.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data
2 |
3 | import com.spirytusz.booster.processor.base.data.type.KtType
4 |
5 | /**
6 | * 代表一个变量
7 | */
8 | interface KtField {
9 |
10 | /**
11 | * 是否可变
12 | */
13 | val isFinal: Boolean
14 |
15 | /**
16 | * 变量名
17 | */
18 | val fieldName: String
19 |
20 | /**
21 | * serialize names
22 | */
23 | val keys: List
24 |
25 | /**
26 | * 类型
27 | */
28 | val ktType: KtType
29 |
30 | /**
31 | * 初始化器,是否有默认值,或者没有初始化器(包括delegate)
32 | */
33 | val initializer: FieldInitializer
34 |
35 | /**
36 | * 定义处,主构造器、类体或超类型中
37 | */
38 | val declarationScope: DeclarationScope
39 |
40 | val transient: Boolean
41 |
42 | /**
43 | * 复制一个[KtField]
44 | */
45 | fun copy(declarationScope: DeclarationScope = this.declarationScope): KtField
46 |
47 | /**
48 | * 转换成可读的字符串,如:
49 | * val listInt: kotlin.collections.List? LIST HAS_DEFAULT BODY ["list_int"]
50 | */
51 | fun toReadableString(): String = buildString {
52 | if (isFinal) {
53 | append("val ")
54 | } else {
55 | append("var ")
56 | }
57 | append(fieldName)
58 | append(" : ")
59 | append(ktType.toReadableString())
60 | append(" ")
61 | append(initializer.toString())
62 | append(" ")
63 | append(declarationScope.toString())
64 | append(" keys: ")
65 | append(keys.toString())
66 | }
67 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/clazz/NoArgsConstructorChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.clazz
2 |
3 | import com.spirytusz.booster.processor.base.check.ClassChecker
4 | import com.spirytusz.booster.processor.base.data.DeclarationScope
5 | import com.spirytusz.booster.processor.base.data.FieldInitializer
6 | import com.spirytusz.booster.processor.base.log.MessageLogger
7 | import com.spirytusz.booster.processor.base.scan.ClassScanner
8 |
9 | internal class NoArgsConstructorChecker(private val messageLogger: MessageLogger) : ClassChecker {
10 |
11 | override fun check(classScanner: ClassScanner) {
12 | val noDefaultValueConstructParams = classScanner.ktFields.asSequence().filter {
13 | it.declarationScope == DeclarationScope.PRIMARY_CONSTRUCTOR
14 | }.filter {
15 | it.initializer == FieldInitializer.NONE
16 | }.toList()
17 |
18 | if (noDefaultValueConstructParams.isEmpty()) {
19 | return
20 | }
21 |
22 | noDefaultValueConstructParams.forEach {
23 | messageLogger.error("constructor param has no default value", it)
24 | }
25 |
26 | val noDefaultValueConstructParamNames = noDefaultValueConstructParams.map { it.fieldName }
27 | throw WithoutNoArgsConstructorException(
28 | "no default value fields in " +
29 | "[${classScanner.classKtType.rawType}] constructor: " +
30 | "$noDefaultValueConstructParamNames"
31 | )
32 | }
33 |
34 | private class WithoutNoArgsConstructorException(msg: String) : Exception(msg)
35 | }
--------------------------------------------------------------------------------
/kapt-demo/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | kotlin("android")
4 | kotlin("kapt")
5 | }
6 |
7 | android {
8 | compileSdk = BuildTools.compileSdkVersion
9 |
10 | defaultConfig {
11 | applicationId = "com.spirytusz.gsonbooster.kapt"
12 | minSdk = BuildTools.minSdkVersion
13 | targetSdk = BuildTools.targetSdkVersion
14 | versionCode = 1
15 | versionName = "1.0"
16 |
17 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | getByName("release") {
22 | isMinifyEnabled = true
23 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
24 | }
25 | }
26 |
27 | tasks.withType {
28 | kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
29 | }
30 |
31 | compileOptions {
32 | sourceCompatibility = JavaVersion.VERSION_1_8
33 | targetCompatibility = JavaVersion.VERSION_1_8
34 | }
35 | }
36 |
37 | dependencies {
38 |
39 | implementation(Dependencies.kotlin_stdlib)
40 | implementation(Dependencies.androidx_appcompat)
41 | implementation(Dependencies.material_design)
42 | implementation(Dependencies.androidx_constraintlayout)
43 | testImplementation(Dependencies.junit)
44 |
45 | implementation(Dependencies.gson)
46 | implementation(Dependencies.booster_annotation)
47 | kapt(Dependencies.booster_processor)
48 | }
49 |
50 | kapt {
51 | arguments {
52 | arg("factory", "com.spirytusz.booster.kapt.BoosterTypeAdapterFactory")
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
33 |
34 |
--------------------------------------------------------------------------------
/base/processor-base/src/main/java/com/spirytusz/booster/processor/base/data/type/KtType.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.base.data.type
2 |
3 | /**
4 | * 代表一个Kotlin类型
5 | */
6 | interface KtType {
7 |
8 | val rawType: String
9 |
10 | val nullable: Boolean
11 |
12 | /**
13 | * 可变性
14 | */
15 | val variance: KtVariance
16 |
17 | /**
18 | * 代表Gson的JsonToken
19 | */
20 | val jsonTokenName: JsonTokenName
21 |
22 | /**
23 | * 泛型
24 | */
25 | val generics: List
26 |
27 | /**
28 | * 复制一个[KtType]
29 | */
30 | fun copy(
31 | nullable: Boolean = this.nullable,
32 | variance: KtVariance = this.variance
33 | ): KtType
34 |
35 | /**
36 | * 根据[predicate]搜索,返回一个集合
37 | */
38 | fun dfs(predicate: KtType.() -> Boolean): Set {
39 | val result = if (predicate(this)) {
40 | setOf(this)
41 | } else {
42 | setOf()
43 | }
44 | return result + generics.map { it.dfs(predicate) }.flatten().toSet()
45 | }
46 |
47 | /**
48 | * 转换成可读的字符串,如:
49 | * kotlin.collections.List? LIST
50 | */
51 | fun toReadableString(): String = buildString {
52 | if (variance in listOf(KtVariance.IN, KtVariance.OUT)) {
53 | append(variance)
54 | append(" ")
55 | }
56 | append(rawType)
57 | if (generics.isNotEmpty()) {
58 | val genericsName = generics.map { it.toReadableString() }.joinToString { it }
59 | append("<")
60 | append(genericsName)
61 | append(">")
62 | }
63 | if (nullable) {
64 | append("?")
65 | }
66 | append(" ")
67 | append(jsonTokenName)
68 | }
69 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/read/strategy/KtTypeReadCodeGeneratorImpl.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.read.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.functions.read.strategy.base.KtTypeReadCodeGenerator
7 | import com.squareup.kotlinpoet.CodeBlock
8 |
9 | internal class KtTypeReadCodeGeneratorImpl(
10 | private val logger: MessageLogger,
11 | private val config: TypeAdapterClassGenConfig
12 | ) : KtTypeReadCodeGenerator {
13 |
14 | override fun generate(
15 | ktType: KtType,
16 | codegenHook: (CodeBlock.Builder, String) -> Unit
17 | ): CodeBlock {
18 | return when {
19 | ktType.jsonTokenName.isPrimitive() -> {
20 | PrimitiveKtTypeReadCodeGenerator(logger, config).generate(ktType, codegenHook)
21 | }
22 | ktType.jsonTokenName.isObject() -> {
23 | ObjectKtTypeReadCodeGenerator(logger, config).generate(ktType, codegenHook)
24 | }
25 | ktType.jsonTokenName.isArray() -> {
26 | CollectionKtTypeReadCodeGenerator(logger, config).generate(ktType, codegenHook)
27 | }
28 | ktType.jsonTokenName.isMap() -> {
29 | MapKtTypeReadCodeGenerator(logger, config).generate(ktType, codegenHook)
30 | }
31 | ktType.jsonTokenName.isEnum() -> {
32 | EnumKtTypeReadCodeGenerator(logger, config).generate(ktType, codegenHook)
33 | }
34 | else -> throw IllegalStateException("Unexpected json token ${ktType.jsonTokenName}")
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/kapt-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/ksp-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/booster-processor/processor-kapt/src/main/java/com/spirytusz/booster/processor/kapt/log/KaptMessageLogger.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.kapt.log
2 |
3 | import com.spirytusz.booster.processor.base.log.MessageLogger
4 | import com.spirytusz.booster.processor.scan.kapt.data.IElementOwner
5 | import javax.annotation.processing.ProcessingEnvironment
6 | import javax.lang.model.element.Element
7 | import javax.tools.Diagnostic
8 |
9 | class KaptMessageLogger(private val processingEnvironment: ProcessingEnvironment) : MessageLogger {
10 |
11 | companion object {
12 | private const val TAG = "[Booster]"
13 | }
14 |
15 | override fun debug(message: String, target: Any?) {
16 | processingEnvironment.messager.printMessage(
17 | Diagnostic.Kind.OTHER,
18 | "$TAG $message",
19 | target?.tryCastElement()
20 | )
21 | }
22 |
23 | override fun info(message: String, target: Any?) {
24 | processingEnvironment.messager.printMessage(
25 | Diagnostic.Kind.NOTE,
26 | "$TAG $message",
27 | target?.tryCastElement()
28 | )
29 | }
30 |
31 | override fun warn(message: String, target: Any?) {
32 | processingEnvironment.messager.printMessage(
33 | Diagnostic.Kind.WARNING,
34 | "$TAG $message",
35 | target?.tryCastElement()
36 | )
37 | }
38 |
39 | override fun error(message: String, target: Any?) {
40 | processingEnvironment.messager.printMessage(
41 | Diagnostic.Kind.ERROR,
42 | "$TAG $message",
43 | target?.tryCastElement()
44 | )
45 | }
46 |
47 | private fun Any.tryCastElement(): Element? {
48 | return when (this) {
49 | is IElementOwner -> this.target
50 | is Element -> this
51 | else -> null
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/CollectionKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.extensions.firstCharLowerCase
8 | import com.spirytusz.booster.processor.gen.extensions.flatten
9 | import com.spirytusz.booster.processor.gen.functions.write.strategy.base.AbstractKtTypeWriteCodeGenerator
10 | import com.squareup.kotlinpoet.CodeBlock
11 |
12 | internal class CollectionKtTypeWriteCodeGenerator(
13 | logger: MessageLogger,
14 | config: TypeAdapterClassGenConfig
15 | ) : AbstractKtTypeWriteCodeGenerator(logger, config) {
16 | override fun realGenerate(
17 | fieldName: String,
18 | codeBlockBuilder: CodeBlock.Builder,
19 | ktType: KtType,
20 | tempFieldName: String
21 | ) {
22 | val generic = ktType.generics.first()
23 |
24 | codeBlockBuilder.addStatement("$WRITER.beginArray()")
25 |
26 | val loopFieldName = generic.flatten().firstCharLowerCase()
27 | codeBlockBuilder.beginControlFlow("for ($loopFieldName in $tempFieldName)")
28 | val writeCodeGenerator = KtTypeWriteCodeGeneratorImpl(logger, config)
29 | val genericCodeBlock = writeCodeGenerator.generate(
30 | fieldName,
31 | generic
32 | ) { genericCodeBlockBuilder, genericTempFieldName ->
33 | genericCodeBlockBuilder.addStatement("val $genericTempFieldName = $loopFieldName")
34 | }
35 | codeBlockBuilder.add(genericCodeBlock)
36 | codeBlockBuilder.endControlFlow()
37 | codeBlockBuilder.addStatement("$WRITER.endArray()")
38 | }
39 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/base/AbstractKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy.base
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.extensions.getWritingTempFieldName
8 | import com.squareup.kotlinpoet.CodeBlock
9 |
10 | internal abstract class AbstractKtTypeWriteCodeGenerator(
11 | protected val logger: MessageLogger,
12 | protected val config: TypeAdapterClassGenConfig
13 | ) : KtTypeWriteCodeGenerator {
14 |
15 | final override fun generate(
16 | fieldName: String,
17 | ktType: KtType,
18 | codegenHook: (CodeBlock.Builder, String) -> Unit
19 | ): CodeBlock {
20 | val codeBlockBuilder = CodeBlock.Builder()
21 | val tempFieldName = ktType.getWritingTempFieldName(fieldName)
22 | codegenHook.invoke(codeBlockBuilder, tempFieldName)
23 | if (ktType.nullable) {
24 | codeBlockBuilder.beginControlFlow("if ($tempFieldName == null)")
25 | codeBlockBuilder.addStatement("$WRITER.nullValue()")
26 | codeBlockBuilder.endControlFlow()
27 |
28 | codeBlockBuilder.beginControlFlow("else")
29 | realGenerate(fieldName, codeBlockBuilder, ktType, tempFieldName)
30 | codeBlockBuilder.endControlFlow()
31 | } else {
32 | realGenerate(fieldName, codeBlockBuilder, ktType, tempFieldName)
33 | }
34 | return codeBlockBuilder.build()
35 | }
36 |
37 | abstract fun realGenerate(
38 | fieldName: String,
39 | codeBlockBuilder: CodeBlock.Builder,
40 | ktType: KtType,
41 | tempFieldName: String
42 | )
43 | }
--------------------------------------------------------------------------------
/ksp-demo/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | kotlin("android")
4 | id("com.google.devtools.ksp")
5 | }
6 |
7 | android {
8 | compileSdk = BuildTools.compileSdkVersion
9 |
10 | defaultConfig {
11 | applicationId = "com.spirytusz.gsonbooster.ksp"
12 | minSdk = BuildTools.minSdkVersion
13 | targetSdk = BuildTools.targetSdkVersion
14 | versionCode = 1
15 | versionName = "1.0"
16 |
17 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | getByName("debug") {
22 | sourceSets.getByName("main") {
23 | java.srcDir("build/generated/ksp/debug/kotlin")
24 | }
25 | }
26 | getByName("release") {
27 | isMinifyEnabled = true
28 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
29 |
30 | sourceSets.getByName("main") {
31 | java.srcDir("build/generated/ksp/release/kotlin")
32 | }
33 | }
34 | }
35 |
36 | tasks.withType {
37 | kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
38 | }
39 |
40 | compileOptions {
41 | sourceCompatibility = JavaVersion.VERSION_1_8
42 | targetCompatibility = JavaVersion.VERSION_1_8
43 | }
44 |
45 | }
46 |
47 | dependencies {
48 |
49 | implementation(Dependencies.kotlin_stdlib)
50 | implementation(Dependencies.androidx_appcompat)
51 | implementation(Dependencies.material_design)
52 | implementation(Dependencies.androidx_constraintlayout)
53 | testImplementation(Dependencies.junit)
54 |
55 | implementation(Dependencies.gson)
56 | implementation(Dependencies.booster_annotation)
57 | ksp(Dependencies.booster_processor_ksp)
58 | }
59 |
60 | ksp {
61 | arg("factory", "com.spirytusz.booster.ksp.BoosterTypeAdapterFactory")
62 | }
63 |
--------------------------------------------------------------------------------
/base/scan/scan-kapt/src/main/java/com/spirytusz/booster/processor/scan/kapt/KmClassCacheHolder.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.scan.kapt
2 |
3 | import com.spirytusz.booster.processor.base.log.MessageLogger
4 | import kotlinx.metadata.KmClass
5 | import kotlinx.metadata.jvm.KotlinClassHeader
6 | import kotlinx.metadata.jvm.KotlinClassMetadata
7 | import javax.lang.model.element.TypeElement
8 |
9 | class KmClassCacheHolder(private val logger: MessageLogger) {
10 |
11 | private val cache = mutableMapOf()
12 |
13 | fun get(typeElement: TypeElement): KmClass {
14 | val fqName = typeElement.qualifiedName.toString()
15 | return cache.getOrPut(fqName) {
16 | val kmClass = typeElement.asKmClass()
17 | ?: throw IllegalStateException("Unexpected metadata received for element $fqName")
18 | kmClass
19 | }
20 | }
21 |
22 | private fun TypeElement.asKmClass(): KmClass? {
23 | val metadataAnnotation = getAnnotation(Metadata::class.java) ?: run {
24 | logger.error("@Metadata annotation not found", this)
25 | return null
26 | }
27 | val header = KotlinClassHeader(
28 | kind = metadataAnnotation.kind,
29 | //bytecodeVersion = metadataAnnotation.bytecodeVersion,
30 | metadataVersion = metadataAnnotation.metadataVersion,
31 | data1 = metadataAnnotation.data1,
32 | data2 = metadataAnnotation.data2,
33 | extraInt = metadataAnnotation.extraInt,
34 | extraString = metadataAnnotation.extraString,
35 | packageName = metadataAnnotation.packageName
36 | )
37 | val kotlinClassMetadata = KotlinClassMetadata.read(header) ?: run {
38 | logger.error("parse KotlinClassMetadata return null", this)
39 | return null
40 | }
41 | kotlinClassMetadata as? KotlinClassMetadata.Class ?: run {
42 | logger.error("parse result is NOT KotlinClassMetadata.Class", this)
43 | return null
44 | }
45 | return kotlinClassMetadata.toKmClass()
46 | }
47 | }
--------------------------------------------------------------------------------
/base/check/src/main/java/com/spirytusz/booster/processor/check/field/FieldNamingChecker.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.check.field
2 |
3 | import com.spirytusz.booster.processor.base.check.FieldChecker
4 | import com.spirytusz.booster.processor.base.data.KtField
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.base.scan.ClassScanner
7 |
8 | internal class FieldNamingChecker(private val messageLogger: MessageLogger) : FieldChecker {
9 |
10 | companion object {
11 | private val keywords = mutableSetOf(
12 | "as?", "as", "break", "class", "continue",
13 | "do", "else", "false", "for", "fun",
14 | "if", "in", "!in", "interface", "is",
15 | "!is", "null", "object", "package", "return",
16 | "super", "this", "throw", "true", "try",
17 | "typealias", "typeof", "val", "var", "when",
18 | "while", "by", "catch", "constructor", "delegate",
19 | "dynamic", "field", "file", "finally", "get",
20 | "import", "init", "param", "property", "receiver",
21 | "set", "setparam", "value", "where", "actual",
22 | "abstract", "annotation", "companion", "const",
23 | "crossinline", "data", "enum", "expect", "external",
24 | "final", "infix", "inline", "inner", "internal",
25 | "lateinit", "noinline", "open", "operator", "out",
26 | "override", "private", "protected", "public", "reified",
27 | "sealed", "suspend", "tailrec", "vararg"
28 | )
29 | }
30 |
31 | override fun check(classScanner: ClassScanner, ktField: KtField) {
32 | if (ktField.fieldName !in keywords) {
33 | return
34 | }
35 |
36 | messageLogger.error("invalid fieldName ${ktField.fieldName}", ktField)
37 | throw FieldNamedByKotlinKeywordException(
38 | "invalid fieldName [${ktField.fieldName}]" +
39 | " at [${classScanner.classKtType.rawType}]"
40 | )
41 | }
42 |
43 | private class FieldNamedByKotlinKeywordException(msg: String) : Exception(msg)
44 | }
--------------------------------------------------------------------------------
/benchmark/src/androidTest/java/com/spirytusz/benchmark/Benchmark.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.benchmark
2 |
3 | import androidx.benchmark.junit4.BenchmarkRule
4 | import androidx.benchmark.junit4.measureRepeated
5 | import androidx.test.ext.junit.runners.AndroidJUnit4
6 | import androidx.test.platform.app.InstrumentationRegistry
7 | import com.google.gson.Gson
8 | import com.google.gson.GsonBuilder
9 | import org.junit.Rule
10 | import org.junit.Test
11 | import org.junit.runner.RunWith
12 |
13 | /**
14 | * Benchmark, which will execute on an Android device.
15 | *
16 | * The body of [BenchmarkRule.measureRepeated] is measured in a loop, and Studio will
17 | * output the result. Modify your code to see how it affects performance.
18 | */
19 | @RunWith(AndroidJUnit4::class)
20 | class Benchmark {
21 |
22 | @get:Rule
23 | val benchmarkRule = BenchmarkRule()
24 |
25 | @Test
26 | fun benchmarkCommon() {
27 | benchmarkRule.measureRepeated {
28 | lateinit var gson: Gson
29 | lateinit var json: String
30 | lateinit var clazz: Class<*>
31 | runWithTimingDisabled {
32 | gson = GsonBuilder().create()
33 | json = readJson()
34 | clazz = Foo::class.java
35 | }
36 | gson.fromJson(json, clazz)
37 | }
38 | }
39 |
40 | @Test
41 | fun benchmarkBoost() {
42 | benchmarkRule.measureRepeated {
43 | lateinit var gson: Gson
44 | lateinit var json: String
45 | lateinit var clazz: Class<*>
46 | runWithTimingDisabled {
47 | gson = GsonBuilder()
48 | .registerTypeAdapterFactory(BoosterTypeAdapterFactory())
49 | .create()
50 | json = readJson()
51 | clazz = Foo::class.java
52 | }
53 | gson.fromJson(json, clazz)
54 | }
55 | }
56 |
57 | private fun readJson(): String {
58 | val context = InstrumentationRegistry.getInstrumentation().context
59 | return context.assets.open("test.json").bufferedReader().use { it.readText() }
60 | }
61 | }
--------------------------------------------------------------------------------
/base/gen/src/main/java/com/spirytusz/booster/processor/gen/functions/write/strategy/MapKtTypeWriteCodeGenerator.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.gen.functions.write.strategy
2 |
3 | import com.spirytusz.booster.processor.base.data.config.TypeAdapterClassGenConfig
4 | import com.spirytusz.booster.processor.base.data.type.KtType
5 | import com.spirytusz.booster.processor.base.log.MessageLogger
6 | import com.spirytusz.booster.processor.gen.const.Const.Naming.WRITER
7 | import com.spirytusz.booster.processor.gen.extensions.firstChatUpperCase
8 | import com.spirytusz.booster.processor.gen.extensions.flatten
9 | import com.spirytusz.booster.processor.gen.functions.write.strategy.base.AbstractKtTypeWriteCodeGenerator
10 | import com.squareup.kotlinpoet.CodeBlock
11 |
12 | internal class MapKtTypeWriteCodeGenerator(
13 | logger: MessageLogger,
14 | config: TypeAdapterClassGenConfig
15 | ) : AbstractKtTypeWriteCodeGenerator(logger, config) {
16 | override fun realGenerate(
17 | fieldName: String,
18 | codeBlockBuilder: CodeBlock.Builder,
19 | ktType: KtType,
20 | tempFieldName: String
21 | ) {
22 | val valueGeneric = ktType.generics[1]
23 |
24 | codeBlockBuilder.addStatement("$WRITER.beginObject()")
25 |
26 | val loopKeyFieldName = "key" + valueGeneric.flatten().firstChatUpperCase()
27 | val loopValueFieldName = "value" + valueGeneric.flatten().firstChatUpperCase()
28 | codeBlockBuilder.beginControlFlow("for (($loopKeyFieldName, $loopValueFieldName) in $tempFieldName)")
29 |
30 | val writeCodeGenerator = KtTypeWriteCodeGeneratorImpl(logger, config)
31 | val genericCodeBlock = writeCodeGenerator.generate(
32 | fieldName,
33 | valueGeneric
34 | ) { genericCodeBlockBuilder, genericTempFieldName ->
35 | genericCodeBlockBuilder.addStatement("$WRITER.name($loopKeyFieldName)")
36 | genericCodeBlockBuilder.addStatement("val $genericTempFieldName = $loopValueFieldName")
37 | }
38 | codeBlockBuilder.add(genericCodeBlock)
39 |
40 | codeBlockBuilder.endControlFlow()
41 |
42 | codeBlockBuilder.addStatement("$WRITER.endObject()")
43 | }
44 | }
--------------------------------------------------------------------------------
/booster-processor/processor-ksp/src/test/java/com/spirytusz/booster/processor/ksp/test/base/AbstractKspSerializeTest.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.booster.processor.ksp.test.base
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.JsonObject
5 | import com.spirytusz.booster.processor.base.const.Keys.KEY_TYPE_ADAPTER_FACTORY_NAME
6 | import com.spirytusz.booster.processor.ksp.provider.BoosterProcessorProvider
7 | import com.spirytusz.booster.processor.ksp.test.extensions.kspGeneratedSources
8 | import com.spirytusz.booster.processor.test.AbstractSerializeTest
9 | import com.spirytusz.booster.processor.test.extensions.getClassByName
10 | import com.spirytusz.booster.processor.test.extensions.toJsonObject
11 | import com.tschuchort.compiletesting.KotlinCompilation
12 | import com.tschuchort.compiletesting.SourceFile
13 | import com.tschuchort.compiletesting.kspArgs
14 | import com.tschuchort.compiletesting.symbolProcessorProviders
15 |
16 | abstract class AbstractKspSerializeTest : AbstractSerializeTest() {
17 |
18 | override fun compile(sources: List): KotlinCompilation.Result {
19 | printLog("compile beans")
20 | val compileBeanResult = KotlinCompilation().apply {
21 | this.sources = sources
22 | inheritClassPath = true
23 | messageOutputStream = System.out
24 | symbolProcessorProviders = listOf(BoosterProcessorProvider())
25 | kspArgs =
26 | mutableMapOf(KEY_TYPE_ADAPTER_FACTORY_NAME to typeAdapterFactoryClassName)
27 | }.compile()
28 | val kspGenerateSources = compileBeanResult.kspGeneratedSources.map {
29 | SourceFile.fromPath(it)
30 | }
31 | printLog("compile again with kspGenerateSources=$kspGenerateSources")
32 | return KotlinCompilation().apply {
33 | this.sources = sources + kspGenerateSources
34 | inheritClassPath = true
35 | messageOutputStream = System.out
36 | }.compile()
37 | }
38 |
39 | override fun getExpectJsonObject(result: KotlinCompilation.Result): JsonObject {
40 | val beanClass = result.getClassByName(beanClassName)
41 | return Gson().fromJson(json, beanClass).toJsonObject()
42 | }
43 | }
--------------------------------------------------------------------------------
/ksp-demo/src/main/java/com/spirytusz/gsonbooster/ksp/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.spirytusz.gsonbooster.ksp
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import android.os.SystemClock
6 | import android.util.Log
7 | import android.widget.Button
8 | import android.widget.TextView
9 | import androidx.appcompat.app.AppCompatActivity
10 | import com.google.gson.Gson
11 | import com.google.gson.GsonBuilder
12 | import com.spirytusz.booster.ksp.BoosterTypeAdapterFactory
13 | import com.spirytusz.gsonbooster.ksp.data.Foo
14 | import java.util.concurrent.TimeUnit
15 |
16 | class MainActivity : AppCompatActivity() {
17 | companion object {
18 | private const val TAG = "MainActivityTest"
19 | }
20 |
21 | @SuppressLint("SetTextI18n")
22 | override fun onCreate(savedInstanceState: Bundle?) {
23 | super.onCreate(savedInstanceState)
24 | setContentView(R.layout.activity_main)
25 |
26 | val json = json()
27 | findViewById