Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit c148599

Browse files
committed
feat(oas3): only emit a single warning per warning type
1 parent 3c0427b commit c148599

File tree

4 files changed

+75
-490
lines changed

4 files changed

+75
-490
lines changed

packages/openapi3-parser/lib/parser.js

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const R = require('ramda');
44
const parseYAML = require('./parser/parseYAML');
55

6-
const { isAnnotation, isObject } = require('./predicates');
6+
const { isAnnotation, isWarningAnnotation, isObject } = require('./predicates');
77
const { createError } = require('./elements');
88
const pipeParseResult = require('./pipeParseResult');
99

@@ -79,15 +79,61 @@ function removeColumnLine(result) {
7979
const filterColumnLine = recurseSkippingAnnotations(removeColumnLine);
8080
const filterSourceMaps = recurseSkippingAnnotations(removeSourceMap);
8181

82+
const isUnsupportedWarning = R.both(
83+
isWarningAnnotation,
84+
annotation => (
85+
annotation.content.includes('contains unsupported key')
86+
|| annotation.content === "'Media Type Object' 'examples' only one example is supported, other examples have been ignored"
87+
)
88+
);
89+
90+
const deduplicateUnsupportedAnnotations = R.curry((namespace, parseResult) => {
91+
// {str: Annotation[]} - indexes all warning annotations by message
92+
const warnings = {}; // {str: Annotation[]}
93+
94+
const filterWarnings = R.ifElse(isUnsupportedWarning,
95+
(warning) => {
96+
const annotations = warnings[warning.content];
97+
if (annotations !== undefined) {
98+
annotations.push(warning);
99+
return false;
100+
}
101+
102+
warnings[warning.content] = [warning];
103+
return true;
104+
},
105+
R.T);
106+
107+
const result = new namespace.elements.ParseResult(R.filter(filterWarnings, parseResult));
108+
109+
// Update warning messages to include count
110+
R.forEach(
111+
(annotations) => {
112+
const warning = annotations[0];
113+
// eslint-disable-next-line no-param-reassign
114+
warning.content = `${warning.content} (${annotations.length} occurances)`;
115+
},
116+
R.filter(annotations => annotations.length > 1, R.values(warnings))
117+
);
118+
119+
return result;
120+
});
121+
82122
function parse(source, context) {
83123
const document = parseYAML(source, context);
84124

85125
const parseDocument = pipeParseResult(context.namespace,
86126
R.unless(isObjectOrAnnotation, createError(context.namespace, 'Source document is not an object')),
87-
R.unless(isAnnotation, parseOpenAPIObject(context)),
88-
context.options.generateSourceMap ? filterColumnLine : filterSourceMaps);
127+
R.unless(isAnnotation, parseOpenAPIObject(context)));
89128

90-
return R.chain(parseDocument, document);
129+
return R.chain(
130+
R.pipe(
131+
parseDocument,
132+
deduplicateUnsupportedAnnotations(context.namespace),
133+
context.options.generateSourceMap ? filterColumnLine : filterSourceMaps
134+
),
135+
document
136+
);
91137
}
92138

93139
module.exports = parse;

packages/openapi3-parser/lib/predicates.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
const R = require('ramda');
22

3+
const hasClass = R.curry((cls, element) => {
4+
// eslint-disable-next-line no-underscore-dangle
5+
if (element._meta === undefined) {
6+
// accessing meta will create and attach empty ObjectElement
7+
// which we can avoid by checking `_meta`.
8+
// We do not want to mutate the provided element.
9+
return false;
10+
}
11+
12+
const classes = element.meta.get('classes');
13+
if (classes === undefined) {
14+
return false;
15+
}
16+
17+
return classes.includes(cls);
18+
});
19+
320
/**
421
* @module predicates
522
* @private
@@ -14,6 +31,7 @@ const isString = element => element.element === 'string';
1431
const isBoolean = element => element.element === 'boolean';
1532
const isNull = element => element.element === 'null';
1633
const isDataStructure = element => element.element === 'dataStructure';
34+
const isWarningAnnotation = R.both(isAnnotation, hasClass('warning'));
1735

1836
// Member
1937

@@ -69,6 +87,7 @@ module.exports = {
6987
isBoolean,
7088
isNull,
7189
isDataStructure,
90+
isWarningAnnotation,
7291

7392
hasKey: R.curry(hasKey),
7493
hasValue: R.curry(hasValue),

packages/openapi3-parser/test/integration/fixtures/petstore.json

Lines changed: 3 additions & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@
934934
]
935935
}
936936
},
937-
"content": "'Operation Object' contains unsupported key 'tags'"
937+
"content": "'Operation Object' contains unsupported key 'tags' (3 occurances)"
938938
},
939939
{
940940
"element": "annotation",
@@ -994,7 +994,7 @@
994994
]
995995
}
996996
},
997-
"content": "'Parameter Object' contains unsupported key 'schema'"
997+
"content": "'Parameter Object' contains unsupported key 'schema' (2 occurances)"
998998
},
999999
{
10001000
"element": "annotation",
@@ -1116,186 +1116,6 @@
11161116
},
11171117
"content": "'Header Object' contains unsupported key 'schema'"
11181118
},
1119-
{
1120-
"element": "annotation",
1121-
"meta": {
1122-
"classes": {
1123-
"element": "array",
1124-
"content": [
1125-
{
1126-
"element": "string",
1127-
"content": "warning"
1128-
}
1129-
]
1130-
}
1131-
},
1132-
"attributes": {
1133-
"sourceMap": {
1134-
"element": "array",
1135-
"content": [
1136-
{
1137-
"element": "sourceMap",
1138-
"content": [
1139-
{
1140-
"element": "array",
1141-
"content": [
1142-
{
1143-
"element": "number",
1144-
"attributes": {
1145-
"line": {
1146-
"element": "number",
1147-
"content": 45
1148-
},
1149-
"column": {
1150-
"element": "number",
1151-
"content": 7
1152-
}
1153-
},
1154-
"content": 1083
1155-
},
1156-
{
1157-
"element": "number",
1158-
"attributes": {
1159-
"line": {
1160-
"element": "number",
1161-
"content": 45
1162-
},
1163-
"column": {
1164-
"element": "number",
1165-
"content": 11
1166-
}
1167-
},
1168-
"content": 4
1169-
}
1170-
]
1171-
}
1172-
]
1173-
}
1174-
]
1175-
}
1176-
},
1177-
"content": "'Operation Object' contains unsupported key 'tags'"
1178-
},
1179-
{
1180-
"element": "annotation",
1181-
"meta": {
1182-
"classes": {
1183-
"element": "array",
1184-
"content": [
1185-
{
1186-
"element": "string",
1187-
"content": "warning"
1188-
}
1189-
]
1190-
}
1191-
},
1192-
"attributes": {
1193-
"sourceMap": {
1194-
"element": "array",
1195-
"content": [
1196-
{
1197-
"element": "sourceMap",
1198-
"content": [
1199-
{
1200-
"element": "array",
1201-
"content": [
1202-
{
1203-
"element": "number",
1204-
"attributes": {
1205-
"line": {
1206-
"element": "number",
1207-
"content": 62
1208-
},
1209-
"column": {
1210-
"element": "number",
1211-
"content": 9
1212-
}
1213-
},
1214-
"content": 1504
1215-
},
1216-
{
1217-
"element": "number",
1218-
"attributes": {
1219-
"line": {
1220-
"element": "number",
1221-
"content": 62
1222-
},
1223-
"column": {
1224-
"element": "number",
1225-
"content": 15
1226-
}
1227-
},
1228-
"content": 6
1229-
}
1230-
]
1231-
}
1232-
]
1233-
}
1234-
]
1235-
}
1236-
},
1237-
"content": "'Parameter Object' contains unsupported key 'schema'"
1238-
},
1239-
{
1240-
"element": "annotation",
1241-
"meta": {
1242-
"classes": {
1243-
"element": "array",
1244-
"content": [
1245-
{
1246-
"element": "string",
1247-
"content": "warning"
1248-
}
1249-
]
1250-
}
1251-
},
1252-
"attributes": {
1253-
"sourceMap": {
1254-
"element": "array",
1255-
"content": [
1256-
{
1257-
"element": "sourceMap",
1258-
"content": [
1259-
{
1260-
"element": "array",
1261-
"content": [
1262-
{
1263-
"element": "number",
1264-
"attributes": {
1265-
"line": {
1266-
"element": "number",
1267-
"content": 67
1268-
},
1269-
"column": {
1270-
"element": "number",
1271-
"content": 7
1272-
}
1273-
},
1274-
"content": 1620
1275-
},
1276-
{
1277-
"element": "number",
1278-
"attributes": {
1279-
"line": {
1280-
"element": "number",
1281-
"content": 67
1282-
},
1283-
"column": {
1284-
"element": "number",
1285-
"content": 11
1286-
}
1287-
},
1288-
"content": 4
1289-
}
1290-
]
1291-
}
1292-
]
1293-
}
1294-
]
1295-
}
1296-
},
1297-
"content": "'Operation Object' contains unsupported key 'tags'"
1298-
},
12991119
{
13001120
"element": "annotation",
13011121
"meta": {
@@ -1354,67 +1174,7 @@
13541174
]
13551175
}
13561176
},
1357-
"content": "'Schema Object' contains unsupported key 'format'"
1358-
},
1359-
{
1360-
"element": "annotation",
1361-
"meta": {
1362-
"classes": {
1363-
"element": "array",
1364-
"content": [
1365-
{
1366-
"element": "string",
1367-
"content": "warning"
1368-
}
1369-
]
1370-
}
1371-
},
1372-
"attributes": {
1373-
"sourceMap": {
1374-
"element": "array",
1375-
"content": [
1376-
{
1377-
"element": "sourceMap",
1378-
"content": [
1379-
{
1380-
"element": "array",
1381-
"content": [
1382-
{
1383-
"element": "number",
1384-
"attributes": {
1385-
"line": {
1386-
"element": "number",
1387-
"content": 109
1388-
},
1389-
"column": {
1390-
"element": "number",
1391-
"content": 11
1392-
}
1393-
},
1394-
"content": 2506
1395-
},
1396-
{
1397-
"element": "number",
1398-
"attributes": {
1399-
"line": {
1400-
"element": "number",
1401-
"content": 109
1402-
},
1403-
"column": {
1404-
"element": "number",
1405-
"content": 17
1406-
}
1407-
},
1408-
"content": 6
1409-
}
1410-
]
1411-
}
1412-
]
1413-
}
1414-
]
1415-
}
1416-
},
1417-
"content": "'Schema Object' contains unsupported key 'format'"
1177+
"content": "'Schema Object' contains unsupported key 'format' (2 occurances)"
14181178
}
14191179
]
14201180
}

0 commit comments

Comments
 (0)