Skip to content

Commit

Permalink
added customization options to BaseTypeScriptProcessor, fixed enum to…
Browse files Browse the repository at this point in the history
… have constant names, fixed to types to be added by canonical name instead of simple name
  • Loading branch information
dpnolte committed Nov 12, 2018
1 parent 3a49336 commit 6a2b90e
Show file tree
Hide file tree
Showing 33 changed files with 2,284 additions and 94 deletions.
12 changes: 12 additions & 0 deletions annotation/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/kotlin">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
23 changes: 23 additions & 0 deletions annotation/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>annotation</name>
<comment>Project annotation created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions annotation/.settings/org.eclipse.buildship.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
connection.project.dir=../../../jsProjects/sourcerer
eclipse.preferences.version=1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.laidpack.typescript.annotation

@Retention(AnnotationRetention.SOURCE)
annotation class TypeScript
24 changes: 24 additions & 0 deletions codegen-impl/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/kotlin">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/kotlin">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
23 changes: 23 additions & 0 deletions codegen-impl/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>codegen-impl</name>
<comment>Project codegen-impl created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions codegen-impl/.settings/org.eclipse.buildship.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
connection.project.dir=../../../jsProjects/sourcerer
eclipse.preferences.version=1
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.laidpack.typescript.codegen

import com.laidpack.typescript.annotation.TypeScript
import com.laidpack.typescript.codegen.moshi.ITargetType
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.asTypeName
import me.eugeniomarletti.kotlin.metadata.*
import me.eugeniomarletti.kotlin.processing.KotlinAbstractProcessor
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import javax.annotation.processing.Messager
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.lang.model.util.Elements
import javax.lang.model.util.Types
import javax.tools.Diagnostic

typealias DefinitionProcessor = (targetType: ITargetType) -> String?
typealias FileProcessor = (
targetTypes: HashMap<String, ITargetType>,
rootPackageNames: Set<String>,
packageNames: Set<String>
) -> String?
typealias SuperTypeProcessor = (superClassName: ClassName, currentModuleName: String) -> String
abstract class BaseTypeScriptProcessor(
private val customTransformers: List<TypeTransformer> = listOf(),
private val constrainToCurrentModulePackage: Boolean = false,
private val filePreProcessors: List<FileProcessor> = listOf(),
private val filePostProcessors: List<FileProcessor> = listOf(),
private val definitionPreProcessors: List<DefinitionProcessor> = listOf(),
private val definitionPostProcessors: List<DefinitionProcessor> = listOf(),
private val superTypeTransformer: SuperTypeProcessor = {c, _ -> c.simpleName}
) : KotlinAbstractProcessor(), KotlinMetadataUtils {
private val annotation = TypeScript::class.java
private var moduleName: String = "NativeTypes"
private var indent: String = " "
private var customOutputDir: String? = null
private var fileName = "types.d.ts"

override fun getSupportedAnnotationTypes() = setOf(annotation.canonicalName)

override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun getSupportedOptions() = setOf(OPTION_MODULE, OPTION_OUTPUTDIR, OPTION_INDENT, OPTION_FILENAME, kaptGeneratedOption)

override fun init(processingEnv: ProcessingEnvironment) {
super.init(processingEnv)
moduleName = processingEnv.options[OPTION_MODULE] ?: moduleName
indent = processingEnv.options[OPTION_INDENT] ?: indent
customOutputDir = processingEnv.options[OPTION_OUTPUTDIR]
fileName = processingEnv.options[OPTION_FILENAME] ?: fileName
}

override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {

val context = createContext()
val targetedTypes = hashMapOf<String, ITargetType>()
val rootPackageNames = mutableSetOf<String>()
val packageNames = mutableSetOf<String>()
for (element in roundEnv.getElementsAnnotatedWith(annotation)) {
val typeName = element.asType().asTypeName()
if (typeName is ClassName) {
rootPackageNames.add(typeName.packageName)
}
val foundTypes = TargetResolver.resolve(element, context)
foundTypes.forEach {
targetedTypes[it.name.simpleName] = it
packageNames.add(it.name.packageName)
}
}

if (targetedTypes.isNotEmpty()) {
val content = TypeScriptGenerator.generate(
moduleName,
targetedTypes,
indent,
customTransformers,
constrainToCurrentModulePackage,
rootPackageNames,
packageNames,
filePreProcessors,
filePostProcessors,
definitionPreProcessors,
definitionPostProcessors,
superTypeTransformer
)
var outputDir : String = customOutputDir ?: options[kaptGeneratedOption] ?: System.getProperty("user.dir")
if (!outputDir.endsWith(File.separator))
outputDir += File.separator

val path = Paths.get(outputDir)
if (!Files.exists(path) || !Files.isDirectory(path)) {
messager.printMessage(Diagnostic.Kind.ERROR, "Path '$outputDir' doesn't exist or is not a directory")
return false
}

val file = File(outputDir, fileName)
file.createNewFile() // overwrite any existing file
file.writeText(content)

messager.printMessage(Diagnostic.Kind.OTHER, "TypeScript definitions saved at $outputDir$fileName")
}

return true
}

private fun createContext(): TargetContext {
return TargetContext(
messager,
elementUtils,
typeUtils,
typesWithinScope = mutableSetOf(),
typesWithTypeScriptAnnotation = mutableSetOf(),
typesToBeAddedToScope = hashMapOf(),
abortOnError = true
)
}
companion object {
const val OPTION_MODULE = "typescript.module"
const val OPTION_OUTPUTDIR = "typescript.outputDir"
const val OPTION_INDENT = "typescript.indent"
const val OPTION_FILENAME = "typescript.filename"
}
}

internal class TargetContext (
val messager: Messager,
val elementUtils: Elements,
val typeUtils: Types,
val typesWithinScope: MutableSet<String>,
val typesWithTypeScriptAnnotation: MutableSet<String>,
var typesToBeAddedToScope: MutableMap<String, TypeElement>,
var abortOnError: Boolean
) {
var targetingTypscriptAnnotatedType = true // vs targeting a base bodyType
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.laidpack.typescript.codegen

import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.TypeName
import javax.lang.model.element.VariableElement

interface IWrappedBodyType {
val typeName: TypeName
val variableElement: VariableElement?
val isPropertyValue: Boolean
val isTypeVariable: Boolean
val isEnumValue: Boolean
val isBound: Boolean
val parameters: Map<String, IWrappedBodyType>
val annotationNames: Set<String>
val hasRawType: Boolean
val isInstantiable: Boolean
val nullable: Boolean
val isWildCard: Boolean
val rawType: ClassName?
val hasParameters: Boolean
val collectionType: CollectionType
val canonicalName : String?
var javaCanonicalName: String?
val name : String?
var isReturningTypeVariable: Boolean
val isPrimitiveOrStringType: Boolean
val bounds: Map<String, IWrappedBodyType>
val isMap: Boolean
val isIterable: Boolean
val isSet: Boolean
val isPair: Boolean
val isArray: Boolean
val firstParameterType: IWrappedBodyType
val secondParameterType: IWrappedBodyType
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.laidpack.typescript.codegen

import com.squareup.moshi.Json
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf
import javax.lang.model.element.*

/** A enum value in user code that maps to enum bodyType. */
internal data class TargetEnumValue(
override val name: String,
override val bodyType: WrappedBodyType,
val ordinal: Int,
val proto: ProtoBuf.EnumEntry,
private val field: VariableElement?
) : TargetPropertyOrEnumValue {


private val element get() = field!!

/** Returns the @Json name of this property, or this property's name if none is provided. */
override fun jsonName(): String {
val fieldJsonName = element.jsonName

return when {
fieldJsonName != null -> fieldJsonName
else -> name
}
}

private val Element?.jsonName: String?
get() {
if (this == null) return null
return getAnnotation<Json>(Json::class.java)?.name?.replace("$", "\\$")
}

override fun toString() = name

/** Returns the JsonQualifiers on the field and parameter of this property. */
/*
private fun jsonQualifiers(): Set<AnnotationMirror> {
val elementQualifiers = element.qualifiers
return when {
elementQualifiers.isNotEmpty() -> elementQualifiers
else -> setOf()
}
}
private val Element?.qualifiers: Set<AnnotationMirror>
get() {
if (this == null) return setOf()
return AnnotationMirrors.getAnnotatedAnnotations(this, JsonQualifier::class.java)
}
/** Returns the JsonQualifiers on the field and parameter of this property. */
/*
private fun jsonQualifiers(): Set<AnnotationMirror> {
val elementQualifiers = element.qualifiers
return when {
elementQualifiers.isNotEmpty() -> elementQualifiers
else -> setOf()
}
}
private val Element?.qualifiers: Set<AnnotationMirror>
get() {
if (this == null) return setOf()
return AnnotationMirrors.getAnnotatedAnnotations(this, JsonQualifier::class.java)
}
*/
*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.laidpack.typescript.codegen

interface TargetPropertyOrEnumValue {
val name: String
val bodyType: IWrappedBodyType

/** Returns the @Json name of this property, or this property's name if none is provided. */
fun jsonName(): String
}
Loading

0 comments on commit 6a2b90e

Please sign in to comment.