Skip to content

Commit

Permalink
Merge pull request #472 from Shalima/master
Browse files Browse the repository at this point in the history
Iiea 10932 site targets (#6)
  • Loading branch information
srinivasankavitha authored Oct 25, 2022
2 parents e1dad8e + 71d84e4 commit b3bb058
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.netflix.graphql.dgs.codegen.CodeGenConfig
import com.netflix.graphql.dgs.codegen.CodeGenResult
import com.netflix.graphql.dgs.codegen.filterSkipped
import com.netflix.graphql.dgs.codegen.generators.shared.ParserConstants
import com.netflix.graphql.dgs.codegen.generators.shared.SiteTarget
import com.netflix.graphql.dgs.codegen.shouldSkip
import com.squareup.javapoet.*
import graphql.language.*
Expand Down Expand Up @@ -179,18 +180,27 @@ abstract class BaseDataTypeGenerator(
}

/**
* Applies directives like customAnnotation
* Applies directives like customAnnotation, deprecated etc. The target value in the directives is used to decide where to apply the annotation.
* @input directives: list of directive that needs to be applied
* @return Pair of (map of target site and corresponding annotations) and comments
*/
private fun applyDirectives(directives: List<Directive>): Pair<MutableList<AnnotationSpec>, String?> {
private fun applyDirectives(directives: List<Directive>): Pair<MutableMap<String, MutableList<AnnotationSpec>>, String?> {
var commentFormat: String? = null
return Pair(
directives.fold(mutableListOf()) { annotations, directive ->
directives.fold(mutableMapOf()) { annotations, directive ->
val argumentMap = createArgumentMap(directive)
val siteTarget = if (argumentMap.containsKey(ParserConstants.SITE_TARGET)) (argumentMap[ParserConstants.SITE_TARGET] as StringValue).value.uppercase() else SiteTarget.DEFAULT.name
if (directive.name == ParserConstants.CUSTOM_ANNOTATION && config.generateCustomAnnotations) {
annotations.add(customAnnotation(argumentMap, config))
annotations[siteTarget] = if (annotations.containsKey(siteTarget)) {
var annotationList: MutableList<AnnotationSpec> = annotations[siteTarget]!!
annotationList.add(customAnnotation(argumentMap, config))
annotationList
} else {
mutableListOf(customAnnotation(argumentMap, config))
}
}
if (directive.name == ParserConstants.DEPRECATED && config.addDeprecatedAnnotation) {
annotations.add(deprecatedAnnotation())
annotations[siteTarget] = mutableListOf(deprecatedAnnotation())
if (argumentMap.containsKey(ParserConstants.REASON)) {
val reason: String = (argumentMap[ParserConstants.REASON] as StringValue).value
val replace = reason.substringAfter(ParserConstants.REPLACE_WITH_STR, "")
Expand Down Expand Up @@ -229,7 +239,9 @@ abstract class BaseDataTypeGenerator(

if (directives.isNotEmpty()) {
val (annotations, comments) = applyDirectives(directives)
javaType.addAnnotations(annotations)
if (annotations.containsKey(SiteTarget.DEFAULT.name)) {
javaType.addAnnotations(annotations[SiteTarget.DEFAULT.name])
}
if (!comments.isNullOrBlank()) {
javaType.addJavadoc("\$L", comments)
}
Expand Down Expand Up @@ -359,8 +371,17 @@ abstract class BaseDataTypeGenerator(
private fun addParameterizedConstructor(fieldDefinitions: List<Field>, javaType: TypeSpec.Builder) {
val constructorBuilder = MethodSpec.constructorBuilder()
fieldDefinitions.forEach {
val parameterBuilder = ParameterSpec.builder(it.type, ReservedKeywordSanitizer.sanitize(it.name))
if (it.directives.isNotEmpty()) {
val (annotations, comments) = applyDirectives(it.directives)
annotations.forEach { entry ->
if (SiteTarget.valueOf(entry.key) == SiteTarget.PARAM) {
parameterBuilder.addAnnotations(annotations[SiteTarget.PARAM.name])
}
}
}
constructorBuilder
.addParameter(it.type, ReservedKeywordSanitizer.sanitize(it.name))
.addParameter(parameterBuilder.build())
.addModifiers(Modifier.PUBLIC)
.addStatement("this.\$N = \$N", ReservedKeywordSanitizer.sanitize(it.name), ReservedKeywordSanitizer.sanitize(it.name))
}
Expand Down Expand Up @@ -390,22 +411,10 @@ abstract class BaseDataTypeGenerator(
FieldSpec.builder(returnType, ReservedKeywordSanitizer.sanitize(fieldDefinition.name)).addModifiers(Modifier.PRIVATE)
}

if (fieldDefinition.directives.isNotEmpty()) {
val (annotations, comments) = applyDirectives(fieldDefinition.directives)
fieldBuilder.addAnnotations(annotations)
if (!comments.isNullOrBlank()) {
fieldBuilder.addJavadoc("\$L", comments)
}
}

if (fieldDefinition.description != null) {
fieldBuilder.addJavadoc(fieldDefinition.description.sanitizeJavaDoc())
}

val field = fieldBuilder.build()

javaType.addField(field)

val getterName = typeUtils.transformIfDefaultClassMethodExists("get${fieldDefinition.name[0].uppercase()}${fieldDefinition.name.substring(1)}", TypeUtils.Companion.getClass)
val getterMethodBuilder = MethodSpec.methodBuilder(getterName).addModifiers(Modifier.PUBLIC).returns(returnType).addStatement("return \$N", ReservedKeywordSanitizer.sanitize(fieldDefinition.name))
if (fieldDefinition.overrideGetter) {
Expand All @@ -416,19 +425,37 @@ abstract class BaseDataTypeGenerator(
getterMethodBuilder.addJavadoc(fieldDefinition.description.sanitizeJavaDoc())
}

javaType.addMethod(getterMethodBuilder.build())

val setterName = typeUtils.transformIfDefaultClassMethodExists("set${fieldDefinition.name[0].uppercase()}${fieldDefinition.name.substring(1)}", TypeUtils.Companion.setClass)
javaType.addMethod(
MethodSpec.methodBuilder(setterName)
.addModifiers(Modifier.PUBLIC)
.addParameter(returnType, ReservedKeywordSanitizer.sanitize(fieldDefinition.name))
.addStatement(
"this.\$N = \$N",
ReservedKeywordSanitizer.sanitize(fieldDefinition.name),
ReservedKeywordSanitizer.sanitize(fieldDefinition.name)
).build()
)
val parameterBuilder = ParameterSpec.builder(returnType, ReservedKeywordSanitizer.sanitize(fieldDefinition.name))
val setterMethodBuilder = MethodSpec.methodBuilder(setterName)
.addModifiers(Modifier.PUBLIC)
.addStatement(
"this.\$N = \$N",
ReservedKeywordSanitizer.sanitize(fieldDefinition.name),
ReservedKeywordSanitizer.sanitize(fieldDefinition.name)
)

if (fieldDefinition.directives.isNotEmpty()) {
val (annotations, comments) = applyDirectives(fieldDefinition.directives)
if (!comments.isNullOrBlank()) {
fieldBuilder.addJavadoc("\$L", comments)
}
for (entry in annotations) {
when (SiteTarget.valueOf(entry.key)) {
SiteTarget.FIELD -> fieldBuilder.addAnnotations(annotations[SiteTarget.FIELD.name])
SiteTarget.GET -> getterMethodBuilder.addAnnotations(annotations[SiteTarget.GET.name])
SiteTarget.SET -> setterMethodBuilder.addAnnotations(annotations[SiteTarget.SET.name])
SiteTarget.SETPARAM -> parameterBuilder.addAnnotations(annotations[SiteTarget.SETPARAM.name])
SiteTarget.PARAM -> continue
else -> fieldBuilder.addAnnotations(annotations[entry.key])
}
}
}
setterMethodBuilder.addParameter(parameterBuilder.build())

javaType.addField(fieldBuilder.build())
javaType.addMethod(getterMethodBuilder.build())
javaType.addMethod(setterMethodBuilder.build())
}

private fun addAbstractGetter(returnType: com.squareup.javapoet.TypeName?, fieldDefinition: Field, javaType: TypeSpec.Builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ private fun ktTypeClassBestGuess(name: String): ClassName {
* name -> Name of the class to be annotated. It will contain className with oor without the package name (Mandatory)
* type -> The type of operation intended with this annotation. This value is also used to look up if there is any default packages associated with this annotation in the config
* inputs -> These are the input parameters needed for the annotation. If empty no inputs will be present for the annotation
* target -> The site target where the annotation should be applied. If no site target is present annotation will not contain any site targets
*/
fun customAnnotation(annotationArgumentMap: MutableMap<String, Value<Value<*>>>, config: CodeGenConfig): AnnotationSpec {
if (annotationArgumentMap.isEmpty() || !annotationArgumentMap.containsKey(ParserConstants.NAME) || annotationArgumentMap[ParserConstants.NAME] is NullValue || (annotationArgumentMap[ParserConstants.NAME] as StringValue).value.isEmpty()) {
Expand All @@ -299,6 +300,9 @@ fun customAnnotation(annotationArgumentMap: MutableMap<String, Value<Value<*>>>,
)
val className = ClassName(packageName = packageName, simpleNames = listOf(simpleName))
val annotation: AnnotationSpec.Builder = AnnotationSpec.builder(className)
if (annotationArgumentMap.containsKey(ParserConstants.SITE_TARGET)) {
annotation.useSiteTarget(AnnotationSpec.UseSiteTarget.valueOf((annotationArgumentMap[ParserConstants.SITE_TARGET] as StringValue).value.uppercase()))
}
if (annotationArgumentMap.containsKey(ParserConstants.INPUTS)) {
val codeBlocks: List<CodeBlock> = parseInputs(config, annotationArgumentMap[ParserConstants.INPUTS] as ObjectValue, (annotationArgumentMap[ParserConstants.NAME] as StringValue).value)
codeBlocks.forEach { codeBlock ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ object ParserConstants {
const val MESSAGE = "message"
const val REPLACE_WITH = "replaceWith"
const val REPLACE_WITH_CLASS = "ReplaceWith"
const val SITE_TARGET = "target"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
*
* Copyright 2020 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.netflix.graphql.dgs.codegen.generators.shared

// The site targets as defined https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets.
enum class SiteTarget {
DEFAULT,
FILE,
PROPERTY,
FIELD,
GET,
SET,
RECEIVER,
PARAM,
SETPARAM,
DELEGATE;
}
Loading

0 comments on commit b3bb058

Please sign in to comment.