-
-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support placeholder at apiReturnListType and apiReturnType #1200
Changes from 7 commits
a46d5f6
1c0914c
85c8392
25afb78
8cca330
eebc64a
45f0afd
2542b8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,16 @@ | |
|
||
import com.kobylynskyi.graphql.codegen.mapper.DataModelMapper; | ||
import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; | ||
import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants; | ||
import com.kobylynskyi.graphql.codegen.model.MappingContext; | ||
import com.kobylynskyi.graphql.codegen.model.NamedDefinition; | ||
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; | ||
import com.kobylynskyi.graphql.codegen.utils.Utils; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import static java.util.Arrays.asList; | ||
|
||
|
@@ -21,6 +24,7 @@ | |
public class KotlinGraphQLTypeMapper extends GraphQLTypeMapper { | ||
|
||
private static final String KOTLIN_UTIL_LIST = "List"; | ||
public static final Pattern KOTLIN_UTIL_LIST_ELEMENT_REGEX = Pattern.compile("List<(.+)>"); | ||
private static final String KOTLIN_UTIL_NULLABLE = "?"; | ||
// Char Boolean are not primitive type, but non null equivalent jvm primitive types. | ||
private static final Set<String> KOTLIN_PRIMITIVE_TYPES = new HashSet<>( | ||
|
@@ -92,11 +96,32 @@ public String wrapApiReturnTypeIfRequired(MappingContext mappingContext, | |
if (computedTypeName.startsWith(KOTLIN_UTIL_LIST) && | ||
Utils.isNotBlank(mappingContext.getApiReturnListType())) { | ||
// in case it is query/mutation, return type is list and apiReturnListType is set | ||
return computedTypeName.replace(KOTLIN_UTIL_LIST, mappingContext.getApiReturnListType()); | ||
if (mappingContext.getApiReturnListType().contains(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER)) { | ||
boolean isNullable = computedTypeName.endsWith(KOTLIN_UTIL_NULLABLE); | ||
|
||
Matcher matcher = KOTLIN_UTIL_LIST_ELEMENT_REGEX.matcher(computedTypeName); | ||
matcher.find(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @matsudamper I think it's better if you do |
||
String listElement = matcher.group(1); | ||
computedTypeName = mappingContext.getApiReturnListType() | ||
.replace(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER, listElement); | ||
|
||
if (isNullable) { | ||
return computedTypeName + "?"; | ||
} else { | ||
return computedTypeName; | ||
} | ||
} else { | ||
return computedTypeName.replace(KOTLIN_UTIL_LIST, mappingContext.getApiReturnListType()); | ||
} | ||
} | ||
if (Utils.isNotBlank(mappingContext.getApiReturnType())) { | ||
// in case it is query/mutation and apiReturnType is set | ||
return getGenericsString(mappingContext, mappingContext.getApiReturnType(), computedTypeName); | ||
if (mappingContext.getApiReturnType().contains(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER)) { | ||
return mappingContext.getApiReturnType() | ||
.replace(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER, computedTypeName); | ||
} else { | ||
return getGenericsString(mappingContext, mappingContext.getApiReturnType(), computedTypeName); | ||
} | ||
} | ||
return getTypeConsideringPrimitive(mappingContext, namedDefinition, computedTypeName); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,16 @@ | ||
package com.kobylynskyi.graphql.codegen.scala; | ||
|
||
import com.kobylynskyi.graphql.codegen.mapper.GraphQLTypeMapper; | ||
import com.kobylynskyi.graphql.codegen.model.MappingConfigConstants; | ||
import com.kobylynskyi.graphql.codegen.model.MappingContext; | ||
import com.kobylynskyi.graphql.codegen.model.NamedDefinition; | ||
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation; | ||
import com.kobylynskyi.graphql.codegen.utils.Utils; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import static com.kobylynskyi.graphql.codegen.java.JavaGraphQLTypeMapper.JAVA_UTIL_LIST; | ||
import static java.util.Arrays.asList; | ||
|
@@ -18,6 +21,7 @@ | |
public class ScalaGraphQLTypeMapper extends GraphQLTypeMapper { | ||
|
||
private static final String SCALA_UTIL_LIST = "scala.Seq"; | ||
private static final Pattern SCALA_UTIL_LIST_ELEMENT_REGEX = Pattern.compile("scala\\.Seq\\[(.+)]"); | ||
private static final String SCALA_UTIL_OPTIONAL = "scala.Option"; | ||
private static final Set<String> SCALA_PRIMITIVE_TYPES = new HashSet<>(asList( | ||
"Byte", "Short", "Int", "Long", "Float", "Double", "Char", "Boolean")); | ||
|
@@ -72,11 +76,25 @@ public String wrapApiReturnTypeIfRequired(MappingContext mappingContext, | |
if (computedTypeName.startsWith(SCALA_UTIL_LIST) && | ||
Utils.isNotBlank(mappingContext.getApiReturnListType())) { | ||
// in case it is query/mutation, return type is list and apiReturnListType is set | ||
return computedTypeName.replace(SCALA_UTIL_LIST, mappingContext.getApiReturnListType()); | ||
if (mappingContext.getApiReturnListType().contains(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER)) { | ||
Matcher matcher = SCALA_UTIL_LIST_ELEMENT_REGEX.matcher(computedTypeName); | ||
matcher.find(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @matsudamper I think it's better if you do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implemented. |
||
String listElement = matcher.group(1); | ||
return mappingContext.getApiReturnListType().replace( | ||
MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER, | ||
listElement); | ||
} else { | ||
return computedTypeName.replace(SCALA_UTIL_LIST, mappingContext.getApiReturnListType()); | ||
} | ||
} | ||
if (Utils.isNotBlank(mappingContext.getApiReturnType())) { | ||
// in case it is query/mutation and apiReturnType is set | ||
return getGenericsString(mappingContext, mappingContext.getApiReturnType(), computedTypeName); | ||
if (mappingContext.getApiReturnType().contains(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER)) { | ||
return mappingContext.getApiReturnType() | ||
.replace(MappingConfigConstants.API_RETURN_NAME_PLACEHOLDER, computedTypeName); | ||
} else { | ||
return getGenericsString(mappingContext, mappingContext.getApiReturnType(), computedTypeName); | ||
} | ||
} | ||
return getTypeConsideringPrimitive(mappingContext, namedDefinition, computedTypeName); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package com.kobylynskyi.graphql.codegen; | ||
|
||
import com.kobylynskyi.graphql.codegen.java.JavaGraphQLCodegen; | ||
import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; | ||
import com.kobylynskyi.graphql.codegen.model.MappingConfig; | ||
import com.kobylynskyi.graphql.codegen.utils.Utils; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Objects; | ||
|
||
import static com.kobylynskyi.graphql.codegen.TestUtils.assertFileContainsElements; | ||
import static java.util.Collections.singletonList; | ||
|
||
class GraphQLCodegenApiReturnTypeTest { | ||
|
||
private final File outputBuildDir = new File("build/generated"); | ||
private final File outputJavaClassesDir = new File("build/generated/com/kobylynskyi/graphql/test1"); | ||
|
||
private MappingConfig mappingConfig; | ||
|
||
@BeforeEach | ||
void init() { | ||
mappingConfig = new MappingConfig(); | ||
mappingConfig.setPackageName("com.kobylynskyi.graphql.test1"); | ||
mappingConfig.setGeneratedLanguage(GeneratedLanguage.JAVA); | ||
} | ||
|
||
@AfterEach | ||
void cleanup() { | ||
Utils.deleteDir(outputBuildDir); | ||
} | ||
|
||
@Test | ||
void generate_ApiReturnType_WithPlaceHolder() throws Exception { | ||
mappingConfig.setApiReturnType( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
|
||
generate("src/test/resources/schemas/test.graphqls"); | ||
|
||
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); | ||
|
||
String requireChildText = getChildText( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult" + | ||
"<java.util.List<EventProperty>>>" | ||
); | ||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.java", | ||
requireChildText | ||
); | ||
|
||
String requireParentText = getParentText( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<Event>>" | ||
); | ||
assertFileContainsElements(files, "EventPropertyResolver.java", | ||
requireParentText | ||
); | ||
} | ||
|
||
@Test | ||
void generate_ApiReturnType_And_ApiReturnListType_WithPlaceHolder() throws Exception { | ||
mappingConfig.setApiReturnType( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
mappingConfig.setApiReturnListType( | ||
"reactor.core.publisher.Mono<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
|
||
generate("src/test/resources/schemas/test.graphqls"); | ||
|
||
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); | ||
|
||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.java", | ||
getChildText( | ||
"reactor.core.publisher.Mono<graphql.execution.DataFetcherResult<EventProperty>>" | ||
) | ||
); | ||
|
||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.java", | ||
getParentText( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<Event>>" | ||
) | ||
); | ||
} | ||
|
||
private String getChildText(String returnType) { | ||
return returnType + " child(EventProperty eventProperty, Integer first, Integer last) throws Exception;"; | ||
} | ||
|
||
private String getParentText(String returnType) { | ||
return returnType + | ||
" parent(EventProperty eventProperty, EventStatus withStatus, String createdAfter) throws Exception;"; | ||
} | ||
|
||
private void generate(String path) throws IOException { | ||
new JavaGraphQLCodegen(singletonList(path), outputBuildDir, mappingConfig, | ||
TestUtils.getStaticGeneratedInfo(mappingConfig)).generate(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package com.kobylynskyi.graphql.codegen.kotlin; | ||
|
||
import com.kobylynskyi.graphql.codegen.TestUtils; | ||
import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; | ||
import com.kobylynskyi.graphql.codegen.model.MappingConfig; | ||
import com.kobylynskyi.graphql.codegen.utils.Utils; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Objects; | ||
|
||
import static com.kobylynskyi.graphql.codegen.TestUtils.assertFileContainsElements; | ||
import static java.util.Collections.singletonList; | ||
|
||
class GraphQLCodegenApiReturnTypeTest { | ||
|
||
private final File outputBuildDir = new File("build/generated"); | ||
private final File outputJavaClassesDir = new File("build/generated/com/kobylynskyi/graphql/test1"); | ||
|
||
private MappingConfig mappingConfig; | ||
|
||
@BeforeEach | ||
void init() { | ||
mappingConfig = new MappingConfig(); | ||
mappingConfig.setPackageName("com.kobylynskyi.graphql.test1"); | ||
mappingConfig.setGeneratedLanguage(GeneratedLanguage.KOTLIN); | ||
} | ||
|
||
@AfterEach | ||
void cleanup() { | ||
Utils.deleteDir(outputBuildDir); | ||
} | ||
|
||
@Test | ||
void generate_ApiReturnType_WithPlaceHolder() throws Exception { | ||
mappingConfig.setApiReturnType( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
|
||
generate("src/test/resources/schemas/test.graphqls"); | ||
|
||
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); | ||
|
||
String requireChildText = getChildFunction( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<List<EventProperty?>?>>" | ||
); | ||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.kt", | ||
requireChildText | ||
); | ||
|
||
String requireParentText = getParentFunction( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<Event?>>" | ||
); | ||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.kt", | ||
requireParentText | ||
); | ||
} | ||
|
||
@Test | ||
void generate_ApiReturnType_And_ApiReturnListType_WithPlaceHolder() throws Exception { | ||
mappingConfig.setApiReturnType( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
mappingConfig.setApiReturnListType( | ||
"reactor.core.publisher.Mono<graphql.execution.DataFetcherResult<{{TYPE}}>>" | ||
); | ||
|
||
generate("src/test/resources/schemas/test.graphqls"); | ||
|
||
File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); | ||
|
||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.kt", | ||
getChildFunction( | ||
"reactor.core.publisher.Mono<graphql.execution.DataFetcherResult<EventProperty?>>?" | ||
) | ||
); | ||
|
||
assertFileContainsElements( | ||
files, | ||
"EventPropertyResolver.kt", | ||
getParentFunction( | ||
"java.util.concurrent.CompletionStage<graphql.execution.DataFetcherResult<Event?>>" | ||
) | ||
); | ||
} | ||
|
||
private String getChildFunction(String returnType) { | ||
return "fun child(eventProperty: EventProperty, first: Int?, last: Int?)" + | ||
": " + returnType; | ||
} | ||
|
||
private String getParentFunction(String returnType) { | ||
return "fun parent(eventProperty: EventProperty, withStatus: EventStatus?, createdAfter: String?)" + | ||
": " + returnType; | ||
} | ||
|
||
private void generate(String path) throws IOException { | ||
new KotlinGraphQLCodegen(singletonList(path), outputBuildDir, mappingConfig, | ||
TestUtils.getStaticGeneratedInfo(mappingConfig)).generate(); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matsudamper I think it's better if you do
if (matcher.find()) { ... }