Skip to content

[core] consider polymorphism when computing unused schemas #4335

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

Merged
merged 1 commit into from
Nov 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ public static CodegenModel getModelByName(final String name, final Map<String, O
* @return schemas a list of used schemas
*/
public static List<String> getAllUsedSchemas(OpenAPI openAPI) {
Map<String, List<String>> childrenMap = getChildrenMap(openAPI);
List<String> allUsedSchemas = new ArrayList<String>();
visitOpenAPI(openAPI, (s, t) -> {
if (s.get$ref() != null) {
String ref = getSimpleRef(s.get$ref());
if (!allUsedSchemas.contains(ref)) {
allUsedSchemas.add(ref);
}
if (childrenMap.containsKey(ref)) {
for (String child : childrenMap.get(ref)) {
if (!allUsedSchemas.contains(child)) {
allUsedSchemas.add(child);
}
}
}
}
});
return allUsedSchemas;
Expand All @@ -109,14 +117,19 @@ public static List<String> getAllUsedSchemas(OpenAPI openAPI) {
* @return schemas a list of unused schemas
*/
public static List<String> getUnusedSchemas(OpenAPI openAPI) {
Map<String, List<String>> childrenMap = getChildrenMap(openAPI);
List<String> unusedSchemas = new ArrayList<String>();

Map<String, Schema> schemas = getSchemas(openAPI);
unusedSchemas.addAll(schemas.keySet());

visitOpenAPI(openAPI, (s, t) -> {
if (s.get$ref() != null) {
unusedSchemas.remove(getSimpleRef(s.get$ref()));
String ref = getSimpleRef(s.get$ref());
unusedSchemas.remove(ref);
if (childrenMap.containsKey(ref)) {
unusedSchemas.removeAll(childrenMap.get(ref));
}
}
});
return unusedSchemas;
Expand Down Expand Up @@ -859,6 +872,18 @@ public static Header getHeader(OpenAPI openAPI, String name) {
return null;
}

public static Map<String, List<String>> getChildrenMap(OpenAPI openAPI) {
Map<String, Schema> allSchemas = getSchemas(openAPI);

Map<String, List<Entry<String, Schema>>> groupedByParent = allSchemas.entrySet().stream()
.filter(entry -> isComposedSchema(entry.getValue()))
.collect(Collectors.groupingBy(entry -> getParentName((ComposedSchema) entry.getValue(), allSchemas)));

return groupedByParent.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().map(e -> e.getKey()).collect(Collectors.toList())));
}


/**
* Get the interfaces from the schema (composed)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class ModelUtilsTest {
public void testGetAllUsedSchemas() {
final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/unusedSchemas.yaml");
List<String> allUsedSchemas = ModelUtils.getAllUsedSchemas(openAPI);
Assert.assertEquals(allUsedSchemas.size(), 38);
Assert.assertEquals(allUsedSchemas.size(), 41);

Assert.assertTrue(allUsedSchemas.contains("SomeObjShared"), "contains 'SomeObjShared'");
Assert.assertTrue(allUsedSchemas.contains("SomeObj1"), "contains 'UnusedObj1'");
Expand Down Expand Up @@ -77,21 +77,30 @@ public void testGetAllUsedSchemas() {
Assert.assertTrue(allUsedSchemas.contains("SomeObj26"), "contains 'SomeObj26'");
Assert.assertTrue(allUsedSchemas.contains("Param27"), "contains 'Param27'");
Assert.assertTrue(allUsedSchemas.contains("Param28"), "contains 'Param28'");
Assert.assertTrue(allUsedSchemas.contains("Parent30"), "contains 'Parent30'");
Assert.assertTrue(allUsedSchemas.contains("AChild30"), "contains 'AChild30'");
Assert.assertTrue(allUsedSchemas.contains("BChild30"), "contains 'BChild30'");
}

@Test
public void testGetUnusedSchemas() {
final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/unusedSchemas.yaml");
List<String> unusedSchemas = ModelUtils.getUnusedSchemas(openAPI);
Assert.assertEquals(unusedSchemas.size(), 4);
//UnusedObj is not used at all:
Assert.assertEquals(unusedSchemas.size(), 7);
//UnusedObj1 is not used at all:
Assert.assertTrue(unusedSchemas.contains("UnusedObj1"), "contains 'UnusedObj1'");
//SomeObjUnused is used in a request body that is not used.
//UnusedObj2 is used in a request body that is not used.
Assert.assertTrue(unusedSchemas.contains("UnusedObj2"), "contains 'UnusedObj2'");
//SomeObjUnused is used in a response that is not used.
//UnusedObj3 is used in a response that is not used.
Assert.assertTrue(unusedSchemas.contains("UnusedObj3"), "contains 'UnusedObj3'");
//SomeObjUnused is used in a parameter that is not used.
//UnusedObj4 is used in a parameter that is not used.
Assert.assertTrue(unusedSchemas.contains("UnusedObj4"), "contains 'UnusedObj4'");
//Parent29 is not used at all (only unused children AChild29 and BChild29 are referencing him):
Assert.assertTrue(unusedSchemas.contains("Parent29"), "contains 'Parent29'");
//AChild29 is not used at all:
Assert.assertTrue(unusedSchemas.contains("AChild29"), "contains 'AChild29'");
//BChild29 is not used at all:
Assert.assertTrue(unusedSchemas.contains("BChild29"), "contains 'BChild29'");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,17 @@ paths:
responses:
'200':
description: OK
/some/p30:
post:
operationId: op27
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Parent30"
responses:
'200':
description: OK
components:
schemas:
UnusedObj1:
Expand Down Expand Up @@ -641,6 +652,56 @@ components:
type: string
r2:
type: string
Parent29:
type: object
required:
- childType
properties:
childType:
type: string
discriminator:
propertyName: childType
AChild29:
allOf:
- $ref: '#/components/schemas/Parent29'
- type: object
properties:
name:
type: string
BChild29:
allOf:
- $ref: '#/components/schemas/Parent29'
- type: object
properties:
firstName:
type: string
lastName:
type: string
Parent30:
type: object
required:
- childType
properties:
childType:
type: string
discriminator:
propertyName: childType
AChild30:
allOf:
- $ref: '#/components/schemas/Parent30'
- type: object
properties:
name:
type: string
BChild30:
allOf:
- $ref: '#/components/schemas/Parent30'
- type: object
properties:
firstName:
type: string
lastName:
type: string
SomeObjShared:
type: object
properties:
Expand Down