Skip to content

Commit 1b15258

Browse files
committed
open-api: disable javadoc parsing by default
- fix #3841 - update docs
1 parent 52ba814 commit 1b15258

File tree

8 files changed

+227
-43
lines changed

8 files changed

+227
-43
lines changed

docs/asciidoc/modules/openapi.adoc

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This library supports:
1111
- https://github.com/Redocly/redoc[Redoc] (Optional)
1212
- AsciiDoc Output (Optional)
1313
14-
Checkout the [demo project](https://github.com/jooby-project/library-demo)
14+
Checkout the https://github.com/jooby-project/library-demo[demo project]
1515

1616
=== Configuration
1717

@@ -34,10 +34,7 @@ Checkout the [demo project](https://github.com/jooby-project/library-demo)
3434
<goal>openapi</goal>
3535
</goals>
3636
<configuration>
37-
<specVersion>...</specVersion>
38-
<adoc>
39-
<file>...</file>
40-
</adoc>
37+
...
4138
</configuration>
4239
</execution>
4340
</executions>
@@ -66,6 +63,12 @@ plugins {
6663
mainClassName = "myapp.App"
6764
...
6865
66+
// Configuration
67+
68+
openAPI {
69+
....
70+
}
71+
6972
// Run openAPI task on joobyRun
7073
joobyRun.dependsOn openAPI
7174
@@ -80,6 +83,49 @@ It may slow down `hot reload` process in case of large projects with a lot of co
8083
To avoid this behaviour you can specify maven build phase which suits your needs better (e.g. `prepare-package`).
8184
====
8285

86+
==== Options
87+
88+
[cols="1,1,4a"]
89+
|===
90+
| Option | Default Value | Description
91+
92+
|`adoc`
93+
|
94+
|List of asciidoc files used as template to generate documentation:
95+
96+
.Maven:
97+
98+
<adoc>
99+
<file>guide.adoc</file>
100+
</adoc>
101+
102+
.Gradle:
103+
{
104+
adoc = ["guide.adoc"]
105+
}
106+
107+
|`basedir`
108+
| `${project.dir}`
109+
|Set base directory used it for loading openAPI template file name.
110+
111+
|`includes`
112+
|
113+
|Regular expression used to includes/keep route. Example: `/api/.*`.
114+
115+
|`excludes`
116+
|
117+
|Regular expression used to excludes route. Example: `/web`.
118+
119+
|`specVersion`
120+
|`3.0`
121+
|Set the desired spec output
122+
123+
|`templateName`
124+
|`openapi.yaml`
125+
|Set openAPI template file name.
126+
127+
|===
128+
83129
=== Usage
84130

85131
To learn how it works, let's write a simple Pet API:
@@ -204,7 +250,7 @@ properties filter routes by their path pattern. The filter is a regular expressi
204250

205251
=== Documenting your API
206252

207-
Full/complete example available [here](https://github.com/jooby-project/library-demo)
253+
Full/complete example available https://github.com/jooby-project/library-demo[here]
208254

209255
==== JavaDoc comments
210256

modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/javadoc/JavaDocParser.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import io.jooby.Router;
3131

3232
public class JavaDocParser {
33+
34+
public static final JavaDocParser NOOP = new JavaDocParser(List.of());
35+
3336
private record ScriptRef(String operationId, DetailAST comment) {}
3437

3538
private final List<Path> baseDir;
@@ -47,6 +50,19 @@ public Optional<ClassDoc> parse(String typeName) {
4750
return ofNullable(traverse(resolveType(typeName)).get(typeName));
4851
}
4952

53+
public DetailAST resolve(Path path) {
54+
return lookup(path)
55+
.map(
56+
it ->
57+
cache.computeIfAbsent(
58+
it,
59+
throwingFunction(
60+
filePath -> {
61+
return parseFile(filePath.toFile(), JavaParser.Options.WITH_COMMENTS);
62+
})))
63+
.orElse(JavaDocNode.EMPTY_AST);
64+
}
65+
5066
private Map<String, ClassDoc> traverse(DetailAST tree) {
5167
var classes = new HashMap<String, ClassDoc>();
5268
traverse(
@@ -307,26 +323,13 @@ private String computePath(String prefix, String pattern) {
307323
return Router.noTrailingSlash(Router.normalizePath(prefix + pattern));
308324
}
309325

310-
public DetailAST resolve(Path path) {
311-
return lookup(path)
312-
.map(
313-
it ->
314-
cache.computeIfAbsent(
315-
it,
316-
throwingFunction(
317-
filePath -> {
318-
return parseFile(filePath.toFile(), JavaParser.Options.WITH_COMMENTS);
319-
})))
320-
.orElse(JavaDocNode.EMPTY_AST);
321-
}
322-
323326
private DetailAST resolveType(String typeName) {
324327
var segments = typeName.split("\\.");
325328
segments[segments.length - 1] = segments[segments.length - 1] + ".java";
326329
return resolve(Paths.get(String.join(File.separator, segments)));
327330
}
328331

329-
protected Optional<Path> lookup(Path path) {
332+
private Optional<Path> lookup(Path path) {
330333
return baseDir.stream()
331334
.map(parentDir -> parentDir.resolve(path))
332335
.filter(Files::exists)

modules/jooby-openapi/src/main/java/io/jooby/openapi/OpenAPIGenerator.java

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public List<Path> write(
164164

165165
private SpecVersion specVersion = SpecVersion.V30;
166166

167-
private AsciiDocContext asciidoc;
167+
private boolean javadoc = true;
168168

169169
/** Default constructor. */
170170
public OpenAPIGenerator() {}
@@ -216,17 +216,15 @@ public OpenAPIGenerator() {}
216216
* @return Model.
217217
*/
218218
public @NonNull OpenAPI generate(@NonNull String classname) {
219-
ClassLoader classLoader =
220-
Optional.ofNullable(this.classLoader).orElseGet(getClass()::getClassLoader);
219+
var classLoader = Optional.ofNullable(this.classLoader).orElseGet(getClass()::getClassLoader);
221220

222-
ClassSource source = new ClassSource(classLoader);
221+
var source = new ClassSource(classLoader);
223222

224223
/* Create OpenAPI from template and make sure min required information is present: */
225-
OpenAPIExt openapi =
226-
new OpenApiTemplate(specVersion).fromTemplate(basedir, classLoader, templateName);
224+
var openapi = new OpenApiTemplate(specVersion).fromTemplate(basedir, classLoader, templateName);
227225

228226
var mainType = TypeFactory.fromJavaName(classname);
229-
var javadoc = new JavaDocParser(sources);
227+
var javadoc = this.javadoc ? new JavaDocParser(sources) : JavaDocParser.NOOP;
230228

231229
if (openapi.getInfo() == null) {
232230
var info = new Info();
@@ -249,14 +247,13 @@ public OpenAPIGenerator() {}
249247
});
250248
}
251249

252-
RouteParser routes = new RouteParser();
250+
var routes = new RouteParser();
253251
var json = jsonMapper();
254252
var yaml = yamlMapper();
255-
ParserContext ctx =
256-
new ParserContext(specVersion, json, yaml, source, mainType, javadoc, debug);
257-
List<OperationExt> operations = routes.parse(ctx, openapi);
253+
var ctx = new ParserContext(specVersion, json, yaml, source, mainType, javadoc, debug);
254+
var operations = routes.parse(ctx, openapi);
258255

259-
String contextPath = ContextPathParser.parse(ctx);
256+
var contextPath = ContextPathParser.parse(ctx);
260257

261258
openapi.setSource(Optional.ofNullable(ctx.getMainClass()).orElse(classname));
262259

@@ -268,20 +265,20 @@ public OpenAPIGenerator() {}
268265
ctx.schemas().forEach(schema -> openapi.schema(schema.getName(), schema));
269266

270267
Map<String, Tag> globalTags = new LinkedHashMap<>();
271-
Paths paths = new Paths();
272-
for (OperationExt operation : operations) {
273-
String pattern = operation.getPath();
268+
var paths = new Paths();
269+
for (var operation : operations) {
270+
var pattern = operation.getPath();
274271
if (!includes(pattern) || excludes(pattern)) {
275272
log.debug("skipping {}", pattern);
276273
continue;
277274
}
278-
Map<String, String> regexMap = new HashMap<>();
275+
var regexMap = new HashMap<String, String>();
279276
Router.pathKeys(
280277
pattern, (key, value) -> Optional.ofNullable(value).ifPresent(v -> regexMap.put(key, v)));
281278
if (!regexMap.isEmpty()) {
282-
for (Map.Entry<String, String> e : regexMap.entrySet()) {
283-
String name = e.getKey();
284-
String regex = e.getValue();
279+
for (var e : regexMap.entrySet()) {
280+
var name = e.getKey();
281+
var regex = e.getValue();
285282
operation
286283
.getParameter(name)
287284
.ifPresent(parameter -> parameter.getSchema().setPattern(regex));
@@ -296,7 +293,7 @@ public OpenAPIGenerator() {}
296293
}
297294
}
298295
}
299-
PathItem pathItem = paths.computeIfAbsent(pattern, k -> new PathItem());
296+
var pathItem = paths.computeIfAbsent(pattern, k -> new PathItem());
300297
pathItem.operation(PathItem.HttpMethod.valueOf(operation.getMethod()), operation);
301298
Optional.ofNullable(operation.getPathSummary()).ifPresent(pathItem::setSummary);
302299
Optional.ofNullable(operation.getPathDescription()).ifPresent(pathItem::setDescription);
@@ -345,12 +342,12 @@ private Optional<Boolean> pattern(String pattern, String value) {
345342
}
346343

347344
private void defaults(String classname, String contextPath, OpenAPIExt openapi) {
348-
Info info = openapi.getInfo();
345+
var info = openapi.getInfo();
349346
if (info == null) {
350347
info = new Info();
351348
openapi.info(info);
352349
}
353-
String appname = appname(classname);
350+
var appname = appname(classname);
354351
info.setTitle(Optional.ofNullable(info.getTitle()).orElse(appname + " API"));
355352
info.setDescription(
356353
Optional.ofNullable(info.getDescription()).orElse(appname + " API description"));
@@ -561,7 +558,25 @@ public void setSpecVersion(String version) {
561558
}
562559
}
563560

564-
protected AsciiDocContext createAsciidoc(Path basedir, OpenAPIExt openapi) {
561+
/**
562+
* True/On to enabled.
563+
*
564+
* @param javadoc True/On to enabled.
565+
*/
566+
public void setJavadoc(String javadoc) {
567+
this.javadoc = Boolean.parseBoolean(javadoc) || "on".equalsIgnoreCase(javadoc);
568+
}
569+
570+
/**
571+
* True/On to enabled.
572+
*
573+
* @return True/On to enabled.
574+
*/
575+
public boolean getJavadoc() {
576+
return javadoc;
577+
}
578+
579+
private AsciiDocContext createAsciidoc(Path basedir, OpenAPIExt openapi) {
565580
return new AsciiDocContext(basedir, jsonMapper(), yamlMapper(), openapi);
566581
}
567582

modules/jooby-openapi/src/test/java/io/jooby/openapi/OpenAPIExtension.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
4545
: EnumSet.copyOf(Arrays.asList(metadata.debug()));
4646

4747
OpenAPIGenerator tool = newTool(debugOptions);
48+
tool.setJavadoc(metadata.javadoc());
4849
tool.setSpecVersion(metadata.version().name());
4950
String templateName = metadata.templateName();
5051
if (templateName.isEmpty()) {

modules/jooby-openapi/src/test/java/io/jooby/openapi/OpenAPITest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@
3434
String templateName() default "";
3535

3636
SpecVersion version() default SpecVersion.V30;
37+
38+
String javadoc() default "ON";
3739
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package issues.i3841;
7+
8+
import static io.jooby.openapi.MvcExtensionGenerator.toMvcExtension;
9+
10+
import io.jooby.Jooby;
11+
12+
/** App with or without doc. Description doc. */
13+
public class App3841 extends Jooby {
14+
{
15+
mvc(toMvcExtension(C3841.class));
16+
}
17+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package issues.i3841;
7+
8+
import io.jooby.annotation.GET;
9+
import io.jooby.annotation.Path;
10+
import io.jooby.annotation.QueryParam;
11+
12+
/** Paths. */
13+
@Path("/3841")
14+
public class C3841 {
15+
16+
/**
17+
* Hello endpoint.
18+
*
19+
* @param name Name arg.
20+
* @return Hello endpoint.
21+
*/
22+
@GET
23+
public String hello(@QueryParam String name) {
24+
return null;
25+
}
26+
}

0 commit comments

Comments
 (0)