[F#] minor improvements (#2825)

* Add template owner of F#

Add template owner of F#

* rename fsharp-giraffe-server

* add nmfisher to tech committee

* update windows batch file

* update doc
This commit is contained in:
William Cheng 2019-05-06 22:11:50 +08:00 committed by GitHub
parent 5e92ec1b4c
commit 909d454f9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 124 additions and 91 deletions

View File

@ -48,7 +48,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks |
|-|-|
**API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Dart (1.x, 2.x)**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client), **Kotlin**, **Lua**, **Node.js** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types) **Objective-C**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 7.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs)
**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples)), **Kotlin** (Spring Boot, Ktor), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra)
**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples)), **Kotlin** (Spring Boot, Ktor), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra)
**API documentation generators** | **HTML**, **Confluence Wiki**
**Configuration files** | [**Apache2**](https://httpd.apache.org/)
**Others** | **GraphQL**, **JMeter**, **MySQL Schema**
@ -663,6 +663,7 @@ Here is a list of template creators:
* C++ Pistache: @sebymiano
* C++ Restbed: @stkrwork
* Erlang Server: @galaxie
* F# (Giraffe) Server: @nmfisher
* Go Server: @guohuang
* Go (Gin) Server: @kemokemo
* GraphQL Express Server: @renepardon
@ -745,6 +746,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Elixir | @mrmstn (2018/12) |
| Elm | @eriktim (2018/09) |
| Erlang | @tsloughter (2017/11) @jfacorro (2018/10) @robertoaloi (2018/10) |
| F# | @nmfisher (2019/05) |
| Go | @antihax (2017/11) @bvwells (2017/12) @grokify (2018/07) @kemokemo (2018/09 |
| GraphQL | @renepardon (2018/12) |
| Groovy | |

View File

@ -27,6 +27,6 @@ fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -t modules/openapi-generator/src/main/resources/fsharp-giraffe-server -g fsharp-giraffe -o samples/server/petstore/fsharp-giraffe $@"
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -t modules/openapi-generator/src/main/resources/fsharp-giraffe-server -g fsharp-giraffe-server -o samples/server/petstore/fsharp-giraffe $@"
java ${JAVA_OPTS} -jar ${executable} ${ags}

View File

@ -5,6 +5,6 @@ If Not Exist %executable% (
)
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate --artifact-id "fsharp-giraffe-petstore-server" -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g fsharp-giraffe -o samples\server\petstore\fsharp-giraffe
set ags=generate --artifact-id "fsharp-giraffe-petstore-server" -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g fsharp-giraffe-server -o samples\server\petstore\fsharp-giraffe
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -71,7 +71,7 @@ The following generators are available:
- [cpp-restbed-server](generators/cpp-restbed-server.md)
- [csharp-nancyfx](generators/csharp-nancyfx.md)
- [erlang-server](generators/erlang-server.md)
- [fsharp-giraffe](generators/fsharp-giraffe.md)
- [fsharp-giraffe-server](generators/fsharp-giraffe-server.md)
- [go-gin-server](generators/go-gin-server.md)
- [go-server](generators/go-server.md)
- [graphql-nodejs-express-server](generators/graphql-nodejs-express-server.md)

View File

@ -0,0 +1,25 @@
---
id: generator-opts-server-fsharp-giraffe-server
title: Config Options for fsharp-giraffe-server
sidebar_label: fsharp-giraffe-server
---
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|licenseUrl|The URL of the license| |http://localhost|
|licenseName|The name of the license| |NoLicense|
|packageCopyright|Specifies an AssemblyCopyright for the .NET Framework global assembly attributes stored in the AssemblyInfo file.| |No Copyright|
|packageAuthors|Specifies Authors property in the .NET Core project file.| |OpenAPI|
|packageTitle|Specifies an AssemblyTitle for the .NET Framework global assembly attributes stored in the AssemblyInfo file.| |OpenAPI Library|
|packageName|F# module name (convention: Title.Case).| |OpenAPI|
|packageVersion|F# package version.| |1.0.0|
|packageGuid|The GUID that will be associated with the C# project| |null|
|sourceFolder|source folder for generated code| |OpenAPI/src|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|useSwashbuckle|Uses the Swashbuckle.AspNetCore NuGet package for documentation.| |false|
|generateBody|Generates method body.| |true|
|buildTarget|Target the build for a program or library.| |program|

View File

@ -89,7 +89,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
collectionTypes = new HashSet<String>(Arrays.asList("list", "seq"));
mapTypes = new HashSet<String>(
Arrays.asList("IDictionary")
Arrays.asList("IDictionary")
);
reservedWords.addAll(
@ -101,7 +101,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
"localVarHttpContentTypes", "localVarHttpContentType",
"localVarStatusCode",
// F# reserved words
"abstract", "and", "as", "async", "await", "assert", "base","begin", "bool", "break", "byte", "case", "catch", "char", "checked",
"abstract", "and", "as", "async", "await", "assert", "base", "begin", "bool", "break", "byte", "case", "catch", "char", "checked",
"class", "const", "continue", "decimal", "default", "delegate", "do", "done", "double", "downcast", "downto", "dynamic",
"elif", "else", "end", "enum", "event", "exception", "explicit", "extern", "false", "finally", "fixed", "float", "for",
"foreach", "fun", "function", "if", "in", "inherit", "inline", "int", "interface", "internal", "is", "lazy", "let", "let!", "lock",
@ -174,7 +174,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
// nullable type
nullableType = new HashSet<String>(
Arrays.asList("decimal", "bool", "int", "float", "long", "double", "string", "Guid","apiKey")
Arrays.asList("decimal", "bool", "int", "float", "long", "double", "string", "Guid", "apiKey")
);
}
@ -390,65 +390,66 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
}
/*
* F# does not allow forward declarations, so files must be imported in the correct order.
* Output of CodeGen models must therefore bein dependency order (rather than alphabetical order, which seems to be the default).
* We achieve this by creating a comparator to check whether the first model contains any properties of the comparison model's type
* This could probably be made more efficient if absolutely needed.
*/
* F# does not allow forward declarations, so files must be imported in the correct order.
* Output of CodeGen models must therefore bein dependency order (rather than alphabetical order, which seems to be the default).
* We achieve this by creating a comparator to check whether the first model contains any properties of the comparison model's type
* This could probably be made more efficient if absolutely needed.
*/
@SuppressWarnings({"unchecked"})
public Map<String,Object> postProcessDependencyOrders(final Map<String, Object> objs) {
Comparator<String> comparator = new Comparator<String>() {
@Override public int compare(String key1, String key2) {
// Get the corresponding models
CodegenModel model1 = ModelUtils.getModelByName(key1, objs);
CodegenModel model2 = ModelUtils.getModelByName(key2, objs);
public Map<String, Object> postProcessDependencyOrders(final Map<String, Object> objs) {
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String key1, String key2) {
// Get the corresponding models
CodegenModel model1 = ModelUtils.getModelByName(key1, objs);
CodegenModel model2 = ModelUtils.getModelByName(key2, objs);
List<String> complexVars1 = new ArrayList<String>();
List<String> complexVars2 = new ArrayList<String>();
List<String> complexVars1 = new ArrayList<String>();
List<String> complexVars2 = new ArrayList<String>();
for (CodegenProperty prop : model1.vars) {
if (prop.complexType != null)
complexVars1.add(prop.complexType);
}
for (CodegenProperty prop : model2.vars) {
if (prop.complexType != null)
complexVars2.add(prop.complexType);
}
// if first has complex vars and second has none, first is greater
if (complexVars1.size() > 0 && complexVars2.size() == 0)
return 1;
// if second has complex vars and first has none, first is lesser
if (complexVars1.size() == 0 && complexVars2.size() > 0)
return -1;
// if first has complex var that matches the second's key, first is greater
if (complexVars1.contains(key2))
return 1;
// if second has complex var that matches the first's key, first is lesser
if (complexVars2.contains(key1))
return -1;
// if none of the above, don't care
return 0;
for(CodegenProperty prop : model1.vars) {
if(prop.complexType != null)
complexVars1.add(prop.complexType);
}
for(CodegenProperty prop : model2.vars) {
if(prop.complexType != null)
complexVars2.add(prop.complexType);
}
// if first has complex vars and second has none, first is greater
if(complexVars1.size() > 0 && complexVars2.size() == 0)
return 1;
// if second has complex vars and first has none, first is lesser
if(complexVars1.size() == 0 && complexVars2.size() > 0)
return -1;
// if first has complex var that matches the second's key, first is greater
if(complexVars1.contains(key2))
return 1;
// if second has complex var that matches the first's key, first is lesser
if(complexVars2.contains(key1))
return -1;
// if none of the above, don't care
return 0;
}
};
PriorityQueue<String> queue = new PriorityQueue<String>(objs.size(), comparator);
for(Object k : objs.keySet()) {
queue.add(k.toString());
for (Object k : objs.keySet()) {
queue.add(k.toString());
}
Map<String,Object> sorted = new LinkedHashMap<String,Object>();
Map<String, Object> sorted = new LinkedHashMap<String, Object>();
while(queue.size() > 0) {
String key = queue.poll();
sorted.put(key, objs.get(key));
while (queue.size() > 0) {
String key = queue.poll();
sorted.put(key, objs.get(key));
}
return sorted;
}
}
/**
* F# differs from other languages in that Enums are not _true_ objects; enums are compiled to integral types.
@ -789,6 +790,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
/**
* Return the default value of the property
*
* @param p OpenAPI property object
* @return string presentation of the default value of the property
*/
@ -842,15 +844,15 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
public String getNullableType(Schema p, String type) {
if (languageSpecificPrimitives.contains(type)) {
if (isSupportNullable() && ModelUtils.isNullable(p) && nullableType.contains(type)) {
return type + " option";
if (languageSpecificPrimitives.contains(type)) {
if (isSupportNullable() && ModelUtils.isNullable(p) && nullableType.contains(type)) {
return type + " option";
} else {
return type;
}
} else {
return type;
return null;
}
} else {
return null;
}
}
@Override
@ -864,11 +866,11 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
}
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
String languageType = getNullableType(p, type);
if (languageType != null) {
return languageType;
}
type = typeMapping.get(openAPIType);
String languageType = getNullableType(p, type);
if (languageType != null) {
return languageType;
}
} else {
type = openAPIType;
}
@ -949,7 +951,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
@Override
public String modelTestFileFolder() {
return outputFolder + File.separator + testFolder;
return outputFolder + File.separator + testFolder;
}
@Override
@ -962,9 +964,13 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
return toModelName(name) + "Tests";
}
public void setLicenseUrl(String licenseUrl) {this.licenseUrl = licenseUrl;}
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
public void setLicenseName(String licenseName) {this.licenseName = licenseName;}
public void setLicenseName(String licenseName) {
this.licenseName = licenseName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;

View File

@ -155,12 +155,12 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
@Override
public String getName() {
return "fsharp-giraffe";
return "fsharp-giraffe-server";
}
@Override
public String getHelp() {
return "Generates a fsharp-giraffe server.";
return "Generates a F# Giraffe server (beta).";
}
@Override
@ -207,8 +207,8 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
supportingFiles.add(new SupportingFile("AuthSchemes.mustache", authFolder, "AuthSchemes.fs"));
supportingFiles.add(new SupportingFile("Helpers.mustache", helperFolder, "Helpers.fs"));
supportingFiles.add(new SupportingFile("CustomHandlers.mustache", implFolder, "CustomHandlers.fs"));
supportingFiles.add(new SupportingFile("Project.Tests.fsproj.mustache",testFolder, packageName + "Tests.fsproj"));
supportingFiles.add(new SupportingFile("TestHelper.mustache",testFolder, "TestHelper.fs"));
supportingFiles.add(new SupportingFile("Project.Tests.fsproj.mustache", testFolder, packageName + "Tests.fsproj"));
supportingFiles.add(new SupportingFile("TestHelper.mustache", testFolder, "TestHelper.fs"));
// TODO - support Swashbuckle
if (useSwashbuckle)
@ -221,7 +221,7 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
@Override
public String modelFileFolder() {
return super.modelFileFolder().replace("Model","model");
return super.modelFileFolder().replace("Model", "model");
}
@Override
@ -235,7 +235,7 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
@Override()
public String toModelImport(String name) {
return packageName + "." + modelPackage() + "." + name;
return packageName + "." + modelPackage() + "." + name;
}
@Override