redsnow 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/snowcrash.xcworkspace/contents.xcworkspacedata +10 -0
- data/ext/snowcrash/src/ActionParser.h +35 -33
- data/ext/snowcrash/src/AssetParser.h +17 -17
- data/ext/snowcrash/src/Blueprint.h +101 -66
- data/ext/snowcrash/src/BlueprintParser.h +219 -10
- data/ext/snowcrash/src/BlueprintSourcemap.h +1 -1
- data/ext/snowcrash/src/BlueprintUtility.h +14 -14
- data/ext/snowcrash/src/CBlueprint.cc +29 -10
- data/ext/snowcrash/src/CBlueprint.h +19 -3
- data/ext/snowcrash/src/CBlueprintSourcemap.cc +20 -10
- data/ext/snowcrash/src/CBlueprintSourcemap.h +12 -3
- data/ext/snowcrash/src/CodeBlockUtility.h +25 -25
- data/ext/snowcrash/src/HTTP.cc +3 -0
- data/ext/snowcrash/src/HTTP.h +9 -6
- data/ext/snowcrash/src/HeadersParser.h +34 -14
- data/ext/snowcrash/src/ParameterParser.h +21 -21
- data/ext/snowcrash/src/ParametersParser.h +6 -5
- data/ext/snowcrash/src/PayloadParser.h +174 -129
- data/ext/snowcrash/src/RegexMatch.h +3 -3
- data/ext/snowcrash/src/ResourceGroupParser.h +5 -4
- data/ext/snowcrash/src/ResourceParser.h +30 -26
- data/ext/snowcrash/src/Section.cc +6 -6
- data/ext/snowcrash/src/Section.h +2 -2
- data/ext/snowcrash/src/SectionParser.h +41 -41
- data/ext/snowcrash/src/SectionParserData.h +10 -10
- data/ext/snowcrash/src/SectionProcessor.h +70 -30
- data/ext/snowcrash/src/Serialize.h +3 -3
- data/ext/snowcrash/src/SerializeJSON.cc +124 -96
- data/ext/snowcrash/src/SerializeJSON.h +1 -1
- data/ext/snowcrash/src/SerializeYAML.cc +71 -53
- data/ext/snowcrash/src/SerializeYAML.h +1 -1
- data/ext/snowcrash/src/Signature.cc +2 -2
- data/ext/snowcrash/src/Signature.h +1 -1
- data/ext/snowcrash/src/SourceAnnotation.h +23 -23
- data/ext/snowcrash/src/StringUtility.h +71 -9
- data/ext/snowcrash/src/SymbolTable.h +17 -17
- data/ext/snowcrash/src/UriTemplateParser.cc +5 -5
- data/ext/snowcrash/src/UriTemplateParser.h +9 -9
- data/ext/snowcrash/src/ValuesParser.h +2 -2
- data/ext/snowcrash/src/Version.h +1 -1
- data/ext/snowcrash/src/csnowcrash.cc +10 -8
- data/ext/snowcrash/src/snowcrash.cc +9 -9
- data/ext/snowcrash/src/snowcrash.h +6 -8
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +14 -14
- data/ext/snowcrash/src/win/RegexMatch.cc +7 -7
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +1 -1
- data/lib/redsnow/binding.rb +8 -2
- data/lib/redsnow/blueprint.rb +4 -3
- data/lib/redsnow/sourcemap.rb +6 -4
- data/lib/redsnow/version.rb +1 -1
- metadata +4 -17
@@ -39,13 +39,13 @@ namespace snowcrash {
|
|
39
39
|
|
40
40
|
/** Additonal Parameter Traits Type matching regex */
|
41
41
|
const char* const AdditionalTraitsTypeRegex = CSV_LEADINOUT "([^,]*)" CSV_LEADINOUT;
|
42
|
-
|
42
|
+
|
43
43
|
/** Parameter Values matching regex */
|
44
44
|
const char* const ParameterValuesRegex = "^[[:blank:]]*[Vv]alues[[:blank:]]*$";
|
45
45
|
|
46
46
|
/** Values expected content */
|
47
47
|
const char* const ExpectedValuesContent = "nested list of possible parameter values, one element per list item e.g. '`value`'";
|
48
|
-
|
48
|
+
|
49
49
|
/** Parameter description delimiter */
|
50
50
|
const std::string DescriptionIdentifier = "...";
|
51
51
|
|
@@ -59,7 +59,7 @@ namespace snowcrash {
|
|
59
59
|
const MarkdownNodes& siblings,
|
60
60
|
SectionParserData& pd,
|
61
61
|
SectionLayout& layout,
|
62
|
-
|
62
|
+
const ParseResultRef<Parameter>& out) {
|
63
63
|
|
64
64
|
mdp::ByteBuffer signature, remainingContent;
|
65
65
|
signature = GetFirstLine(node->text, remainingContent);
|
@@ -81,7 +81,7 @@ namespace snowcrash {
|
|
81
81
|
static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
|
82
82
|
const MarkdownNodes& siblings,
|
83
83
|
SectionParserData& pd,
|
84
|
-
|
84
|
+
const ParseResultRef<Parameter>& out) {
|
85
85
|
|
86
86
|
if (pd.sectionContext() != ValuesSectionType) {
|
87
87
|
return node;
|
@@ -107,7 +107,7 @@ namespace snowcrash {
|
|
107
107
|
out.sourceMap.values.collection.clear();
|
108
108
|
}
|
109
109
|
|
110
|
-
|
110
|
+
ParseResultRef<Values> values(out.report, out.node.values, out.sourceMap.values);
|
111
111
|
ValuesParser::parse(node, siblings, pd, values);
|
112
112
|
|
113
113
|
if (out.node.values.empty()) {
|
@@ -163,7 +163,7 @@ namespace snowcrash {
|
|
163
163
|
static void parseSignature(const mdp::MarkdownNodeIterator& node,
|
164
164
|
SectionParserData& pd,
|
165
165
|
mdp::ByteBuffer& signature,
|
166
|
-
|
166
|
+
const ParseResultRef<Parameter>& out) {
|
167
167
|
|
168
168
|
out.node.use = UndefinedParameterUse;
|
169
169
|
|
@@ -172,10 +172,10 @@ namespace snowcrash {
|
|
172
172
|
CaptureGroups captureGroups;
|
173
173
|
|
174
174
|
if (isValidParameterSignature(signature)) {
|
175
|
-
|
175
|
+
|
176
176
|
mdp::ByteBuffer innerSignature = signature;
|
177
177
|
innerSignature = TrimString(innerSignature);
|
178
|
-
|
178
|
+
|
179
179
|
size_t firstSpace = innerSignature.find(" ");
|
180
180
|
|
181
181
|
if (firstSpace == std::string::npos) {
|
@@ -196,7 +196,7 @@ namespace snowcrash {
|
|
196
196
|
innerSignature = innerSignature.substr(0, descriptionPos);
|
197
197
|
innerSignature = TrimString(innerSignature);
|
198
198
|
}
|
199
|
-
|
199
|
+
|
200
200
|
size_t attributesPos = innerSignature.find("(");
|
201
201
|
|
202
202
|
if (attributesPos != std::string::npos) {
|
@@ -212,7 +212,7 @@ namespace snowcrash {
|
|
212
212
|
innerSignature = TrimString(innerSignature);
|
213
213
|
}
|
214
214
|
}
|
215
|
-
|
215
|
+
|
216
216
|
if (innerSignature.length() > 0) {
|
217
217
|
// Remove =
|
218
218
|
out.node.defaultValue = innerSignature;
|
@@ -264,7 +264,7 @@ namespace snowcrash {
|
|
264
264
|
static void parseAdditionalTraits(const mdp::MarkdownNodeIterator& node,
|
265
265
|
SectionParserData& pd,
|
266
266
|
mdp::ByteBuffer& traits,
|
267
|
-
|
267
|
+
const ParseResultRef<Parameter>& out) {
|
268
268
|
|
269
269
|
TrimString(traits);
|
270
270
|
|
@@ -351,7 +351,7 @@ namespace snowcrash {
|
|
351
351
|
|
352
352
|
static void checkExampleAndDefaultValue(const mdp::MarkdownNodeIterator& node,
|
353
353
|
SectionParserData& pd,
|
354
|
-
|
354
|
+
const ParseResultRef<Parameter>& out) {
|
355
355
|
|
356
356
|
bool isExampleFound = false;
|
357
357
|
bool isDefaultFound = false;
|
@@ -395,23 +395,23 @@ namespace snowcrash {
|
|
395
395
|
sourceMap));
|
396
396
|
}
|
397
397
|
}
|
398
|
-
|
398
|
+
|
399
399
|
/** Determine if a signature is a valid parameter*/
|
400
400
|
static bool isValidParameterSignature(const mdp::ByteBuffer& signature) {
|
401
|
-
|
401
|
+
|
402
402
|
mdp::ByteBuffer innerSignature = signature;
|
403
403
|
innerSignature = TrimString(innerSignature);
|
404
|
-
|
404
|
+
|
405
405
|
if (innerSignature.length() == 0) {
|
406
406
|
return false; // Empty string, invalid
|
407
407
|
}
|
408
|
-
|
408
|
+
|
409
409
|
size_t firstSpace = innerSignature.find(" ");
|
410
410
|
|
411
411
|
if (firstSpace == std::string::npos) {
|
412
412
|
return RegexMatch(innerSignature, "^" PARAMETER_IDENTIFIER "$");
|
413
413
|
}
|
414
|
-
|
414
|
+
|
415
415
|
std::string paramName = innerSignature.substr(0, firstSpace);
|
416
416
|
|
417
417
|
if (!RegexMatch(paramName, "^" PARAMETER_IDENTIFIER "$")) {
|
@@ -427,7 +427,7 @@ namespace snowcrash {
|
|
427
427
|
innerSignature = innerSignature.substr(0, descriptionPos);
|
428
428
|
innerSignature = TrimString(innerSignature);
|
429
429
|
}
|
430
|
-
|
430
|
+
|
431
431
|
size_t attributesPos = innerSignature.find("(");
|
432
432
|
|
433
433
|
if (attributesPos != std::string::npos) {
|
@@ -441,11 +441,11 @@ namespace snowcrash {
|
|
441
441
|
innerSignature = innerSignature.substr(0, attributesPos);
|
442
442
|
innerSignature = TrimString(innerSignature);
|
443
443
|
}
|
444
|
-
|
444
|
+
|
445
445
|
if (innerSignature.length() == 0) {
|
446
446
|
return true;
|
447
447
|
}
|
448
|
-
|
448
|
+
|
449
449
|
if (innerSignature.substr(0,1) == "=") {
|
450
450
|
innerSignature = innerSignature.substr(1);
|
451
451
|
innerSignature = TrimString(innerSignature);
|
@@ -458,7 +458,7 @@ namespace snowcrash {
|
|
458
458
|
return true;
|
459
459
|
}
|
460
460
|
}
|
461
|
-
|
461
|
+
|
462
462
|
return false;
|
463
463
|
}
|
464
464
|
|
@@ -36,7 +36,7 @@ namespace snowcrash {
|
|
36
36
|
const MarkdownNodes& siblings,
|
37
37
|
SectionParserData& pd,
|
38
38
|
SectionLayout& layout,
|
39
|
-
|
39
|
+
const ParseResultRef<Parameters>& out) {
|
40
40
|
|
41
41
|
mdp::ByteBuffer remainingContent;
|
42
42
|
|
@@ -61,7 +61,7 @@ namespace snowcrash {
|
|
61
61
|
static MarkdownNodeIterator processDescription(const MarkdownNodeIterator& node,
|
62
62
|
const MarkdownNodes& siblings,
|
63
63
|
SectionParserData& pd,
|
64
|
-
|
64
|
+
const ParseResultRef<Parameters>& out) {
|
65
65
|
|
66
66
|
return node;
|
67
67
|
}
|
@@ -69,13 +69,14 @@ namespace snowcrash {
|
|
69
69
|
static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
|
70
70
|
const MarkdownNodes& siblings,
|
71
71
|
SectionParserData& pd,
|
72
|
-
|
72
|
+
const ParseResultRef<Parameters>& out) {
|
73
73
|
|
74
74
|
if (pd.sectionContext() != ParameterSectionType) {
|
75
75
|
return node;
|
76
76
|
}
|
77
77
|
|
78
|
-
|
78
|
+
IntermediateParseResult<Parameter> parameter(out.report);
|
79
|
+
|
79
80
|
ParameterParser::parse(node, siblings, pd, parameter);
|
80
81
|
|
81
82
|
if (!out.node.empty()) {
|
@@ -146,7 +147,7 @@ namespace snowcrash {
|
|
146
147
|
|
147
148
|
static void finalize(const MarkdownNodeIterator& node,
|
148
149
|
SectionParserData& pd,
|
149
|
-
|
150
|
+
const ParseResultRef<Parameters>& out) {
|
150
151
|
|
151
152
|
if (out.node.empty()) {
|
152
153
|
|
@@ -52,7 +52,7 @@ namespace snowcrash {
|
|
52
52
|
const MarkdownNodes& siblings,
|
53
53
|
SectionParserData& pd,
|
54
54
|
SectionLayout& layout,
|
55
|
-
|
55
|
+
const ParseResultRef<Payload>& out) {
|
56
56
|
|
57
57
|
mdp::ByteBuffer signature, remainingContent;
|
58
58
|
signature = GetFirstLine(node->text, remainingContent);
|
@@ -97,16 +97,16 @@ namespace snowcrash {
|
|
97
97
|
static MarkdownNodeIterator processContent(const MarkdownNodeIterator& node,
|
98
98
|
const MarkdownNodes& siblings,
|
99
99
|
SectionParserData& pd,
|
100
|
-
|
100
|
+
const ParseResultRef<Payload>& out) {
|
101
101
|
|
102
102
|
mdp::ByteBuffer content;
|
103
103
|
|
104
|
-
if (!out.node.
|
104
|
+
if (!out.node.reference.id.empty()) {
|
105
105
|
//WARN: ignoring extraneous content after symbol reference
|
106
106
|
std::stringstream ss;
|
107
107
|
|
108
108
|
ss << "ignoring extraneous content after symbol reference";
|
109
|
-
ss << ", expected symbol reference only e.g. '[" << out.node.
|
109
|
+
ss << ", expected symbol reference only e.g. '[" << out.node.reference.id << "][]'";
|
110
110
|
|
111
111
|
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
112
112
|
out.report.warnings.push_back(Warning(ss.str(),
|
@@ -138,12 +138,12 @@ namespace snowcrash {
|
|
138
138
|
static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
|
139
139
|
const MarkdownNodes& siblings,
|
140
140
|
SectionParserData& pd,
|
141
|
-
|
141
|
+
const ParseResultRef<Payload>& out) {
|
142
142
|
|
143
143
|
switch (pd.sectionContext()) {
|
144
144
|
case HeadersSectionType:
|
145
145
|
{
|
146
|
-
|
146
|
+
ParseResultRef<Headers> headers(out.report, out.node.headers, out.sourceMap.headers);
|
147
147
|
return HeadersParser::parse(node, siblings, pd, headers);
|
148
148
|
}
|
149
149
|
|
@@ -157,7 +157,7 @@ namespace snowcrash {
|
|
157
157
|
sourceMap));
|
158
158
|
}
|
159
159
|
|
160
|
-
|
160
|
+
ParseResultRef<Asset> asset(out.report, out.node.body, out.sourceMap.body);
|
161
161
|
return AssetParser::parse(node, siblings, pd, asset);
|
162
162
|
}
|
163
163
|
|
@@ -171,7 +171,7 @@ namespace snowcrash {
|
|
171
171
|
sourceMap));
|
172
172
|
}
|
173
173
|
|
174
|
-
|
174
|
+
ParseResultRef<Asset> asset(out.report, out.node.schema, out.sourceMap.schema);
|
175
175
|
return AssetParser::parse(node, siblings, pd, asset);
|
176
176
|
}
|
177
177
|
|
@@ -186,7 +186,7 @@ namespace snowcrash {
|
|
186
186
|
const MarkdownNodes& siblings,
|
187
187
|
SectionParserData& pd,
|
188
188
|
SectionType& sectionType,
|
189
|
-
|
189
|
+
const ParseResultRef<Payload>& out) {
|
190
190
|
|
191
191
|
if ((node->type == mdp::ParagraphMarkdownNodeType ||
|
192
192
|
node->type == mdp::CodeMarkdownNodeType) &&
|
@@ -200,7 +200,7 @@ namespace snowcrash {
|
|
200
200
|
|
201
201
|
return ++MarkdownNodeIterator(node);
|
202
202
|
}
|
203
|
-
|
203
|
+
|
204
204
|
return SectionProcessorBase<Payload>::processUnexpectedNode(node, siblings, pd, sectionType, out);
|
205
205
|
}
|
206
206
|
|
@@ -296,73 +296,16 @@ namespace snowcrash {
|
|
296
296
|
|
297
297
|
static void finalize(const MarkdownNodeIterator& node,
|
298
298
|
SectionParserData& pd,
|
299
|
-
|
300
|
-
|
301
|
-
bool warnEmptyBody = false;
|
302
|
-
|
303
|
-
mdp::ByteBuffer contentLength;
|
304
|
-
mdp::ByteBuffer transferEncoding;
|
299
|
+
const ParseResultRef<Payload>& out) {
|
305
300
|
|
306
301
|
SectionType sectionType = pd.sectionContext();
|
307
302
|
|
308
|
-
|
309
|
-
it != out.node.headers.end();
|
310
|
-
++it) {
|
303
|
+
if (sectionType == RequestSectionType || sectionType == RequestBodySectionType) {
|
311
304
|
|
312
|
-
|
313
|
-
|
314
|
-
}
|
305
|
+
checkRequest(node, pd, out);
|
306
|
+
} else if (sectionType == ResponseSectionType || sectionType == ResponseBodySectionType) {
|
315
307
|
|
316
|
-
|
317
|
-
transferEncoding = it->second;
|
318
|
-
}
|
319
|
-
}
|
320
|
-
|
321
|
-
if ((sectionType == RequestSectionType || sectionType == RequestBodySectionType) && out.node.body.empty()) {
|
322
|
-
|
323
|
-
// Warn when content-length or transfer-encoding is specified or both headers and body are empty
|
324
|
-
if (out.node.headers.empty()) {
|
325
|
-
warnEmptyBody = true;
|
326
|
-
} else {
|
327
|
-
warnEmptyBody = !contentLength.empty() || !transferEncoding.empty();
|
328
|
-
}
|
329
|
-
|
330
|
-
if (warnEmptyBody) {
|
331
|
-
// WARN: empty body
|
332
|
-
std::stringstream ss;
|
333
|
-
ss << "empty " << SectionName(sectionType) << " " << SectionName(BodySectionType);
|
334
|
-
|
335
|
-
if (!contentLength.empty()) {
|
336
|
-
ss << ", expected " << SectionName(BodySectionType) << " for '" << contentLength << "' Content-Length";
|
337
|
-
} else if (!transferEncoding.empty()) {
|
338
|
-
ss << ", expected " << SectionName(BodySectionType) << " for '" << transferEncoding << "' Transfer-Encoding";
|
339
|
-
}
|
340
|
-
|
341
|
-
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
342
|
-
out.report.warnings.push_back(Warning(ss.str(),
|
343
|
-
EmptyDefinitionWarning,
|
344
|
-
sourceMap));
|
345
|
-
}
|
346
|
-
} else if ((sectionType == ResponseSectionType || sectionType == ResponseBodySectionType)) {
|
347
|
-
|
348
|
-
HTTPStatusCode code = 200;
|
349
|
-
|
350
|
-
if (!out.node.name.empty()) {
|
351
|
-
std::stringstream(out.node.name) >> code;
|
352
|
-
}
|
353
|
-
|
354
|
-
StatusCodeTraits statusCodeTraits = GetStatusCodeTrait(code);
|
355
|
-
|
356
|
-
if (!statusCodeTraits.allowBody && !out.node.body.empty()) {
|
357
|
-
// WARN: not empty body
|
358
|
-
std::stringstream ss;
|
359
|
-
ss << "the " << code << " response MUST NOT include a " << SectionName(BodySectionType);
|
360
|
-
|
361
|
-
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
362
|
-
out.report.warnings.push_back(Warning(ss.str(),
|
363
|
-
EmptyDefinitionWarning,
|
364
|
-
sourceMap));
|
365
|
-
}
|
308
|
+
checkResponse(node, pd, out);
|
366
309
|
}
|
367
310
|
}
|
368
311
|
|
@@ -421,7 +364,7 @@ namespace snowcrash {
|
|
421
364
|
static bool parseSignature(const MarkdownNodeIterator& node,
|
422
365
|
SectionParserData& pd,
|
423
366
|
const mdp::ByteBuffer& signature,
|
424
|
-
|
367
|
+
const ParseResultRef<Payload>& out) {
|
425
368
|
|
426
369
|
const char* regex;
|
427
370
|
mdp::ByteBuffer mediaType;
|
@@ -524,93 +467,195 @@ namespace snowcrash {
|
|
524
467
|
return true;
|
525
468
|
}
|
526
469
|
|
470
|
+
/** Given the reference id(name), initializes reference of the payload accordingly(if possible resolve it) */
|
527
471
|
static bool parseSymbolReference(const MarkdownNodeIterator& node,
|
528
472
|
SectionParserData& pd,
|
529
473
|
mdp::ByteBuffer& source,
|
530
|
-
|
474
|
+
const ParseResultRef<Payload>& out) {
|
531
475
|
|
532
|
-
|
533
|
-
ResourceModel model;
|
534
|
-
SourceMap<ResourceModel> modelSM;
|
476
|
+
Identifier symbol;
|
535
477
|
|
536
478
|
TrimString(source);
|
537
479
|
|
538
480
|
if (GetSymbolReference(source, symbol)) {
|
539
|
-
|
481
|
+
|
482
|
+
out.node.reference.id = symbol;
|
483
|
+
out.node.reference.meta.node = node;
|
484
|
+
out.node.reference.type = Reference::SymbolReference;
|
540
485
|
|
541
486
|
if (pd.exportSourceMap() && !symbol.empty()) {
|
542
|
-
out.sourceMap.
|
487
|
+
out.sourceMap.reference.sourceMap = node->sourceMap;
|
543
488
|
}
|
544
489
|
|
545
|
-
// If symbol
|
490
|
+
// If symbol has not been defined yet in symbol table
|
546
491
|
if (pd.symbolTable.resourceModels.find(symbol) == pd.symbolTable.resourceModels.end()) {
|
547
492
|
|
548
|
-
|
549
|
-
std::stringstream ss;
|
550
|
-
ss << "Undefined symbol " << symbol;
|
551
|
-
|
552
|
-
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
553
|
-
out.report.error = Error(ss.str(), SymbolError, sourceMap);
|
493
|
+
out.node.reference.meta.state = Reference::StatePending;
|
554
494
|
|
555
495
|
return true;
|
556
496
|
}
|
557
497
|
|
558
|
-
|
559
|
-
|
560
|
-
out
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
498
|
+
out.node.reference.meta.state = Reference::StateResolved;
|
499
|
+
|
500
|
+
assingReferredPayload(pd, out);
|
501
|
+
|
502
|
+
return true;
|
503
|
+
}
|
504
|
+
|
505
|
+
return false;
|
506
|
+
}
|
507
|
+
|
508
|
+
/**
|
509
|
+
* \brief Assigns the reference, referred as reference id(name), into the payload
|
510
|
+
* \param pd Section parser state
|
511
|
+
* \param out Processed output
|
512
|
+
*/
|
513
|
+
static void assingReferredPayload(SectionParserData& pd,
|
514
|
+
const ParseResultRef<Payload>& out) {
|
515
|
+
|
516
|
+
SourceMap<ResourceModel> modelSM;
|
517
|
+
ResourceModel model = pd.symbolTable.resourceModels.at(out.node.reference.id);
|
518
|
+
|
519
|
+
|
520
|
+
out.node.description = model.description;
|
521
|
+
out.node.parameters = model.parameters;
|
522
|
+
|
523
|
+
HeaderIterator modelContentTypeIt = std::find_if(model.headers.begin(),
|
524
|
+
model.headers.end(),
|
525
|
+
std::bind2nd(MatchFirstWith<Header, std::string>(),
|
526
|
+
HTTPHeaderName::ContentType));
|
527
|
+
|
528
|
+
bool isPayloadContentType = !out.node.headers.empty();
|
529
|
+
bool isModelContentType = modelContentTypeIt != model.headers.end();
|
530
|
+
|
531
|
+
if (isPayloadContentType && isModelContentType) {
|
532
|
+
|
533
|
+
// WARN: Ignoring payload content-type, when referencing a model with headers
|
534
|
+
std::stringstream ss;
|
535
|
+
|
536
|
+
ss << "ignoring additional " << SectionName(pd.sectionContext()) << " header(s), ";
|
537
|
+
ss << "specify this header(s) in the referenced model definition instead";
|
538
|
+
|
539
|
+
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(out.node.reference.meta.node->sourceMap, pd.sourceData);
|
540
|
+
out.report.warnings.push_back(Warning(ss.str(),
|
541
|
+
IgnoringWarning,
|
542
|
+
sourceMap));
|
543
|
+
}
|
544
|
+
|
545
|
+
if (isPayloadContentType && !isModelContentType) {
|
546
|
+
out.node.headers.insert(out.node.headers.end(), model.headers.begin(), model.headers.end());
|
547
|
+
} else {
|
548
|
+
out.node.headers = model.headers;
|
549
|
+
}
|
550
|
+
|
551
|
+
out.node.body = model.body;
|
552
|
+
out.node.schema = model.schema;
|
553
|
+
|
554
|
+
if (pd.exportSourceMap()) {
|
555
|
+
|
556
|
+
modelSM = pd.symbolSourceMapTable.resourceModels.at(out.node.reference.id);
|
557
|
+
|
558
|
+
out.sourceMap.description = modelSM.description;
|
559
|
+
out.sourceMap.parameters = modelSM.parameters;
|
560
|
+
out.sourceMap.body = modelSM.body;
|
561
|
+
out.sourceMap.schema = modelSM.schema;
|
584
562
|
|
585
563
|
if (isPayloadContentType && !isModelContentType) {
|
586
|
-
out.
|
564
|
+
out.sourceMap.headers.collection.insert(out.sourceMap.headers.collection.end(), modelSM.headers.collection.begin(), modelSM.headers.collection.end());
|
587
565
|
} else {
|
588
|
-
out.
|
566
|
+
out.sourceMap.headers = modelSM.headers;
|
567
|
+
}
|
568
|
+
}
|
569
|
+
}
|
570
|
+
|
571
|
+
/**
|
572
|
+
* \brief Checks request given as out
|
573
|
+
* \param node Markdown node
|
574
|
+
* \param pd Section parser state
|
575
|
+
* \param out Processed output
|
576
|
+
*/
|
577
|
+
static void checkRequest(const MarkdownNodeIterator& node,
|
578
|
+
SectionParserData& pd,
|
579
|
+
const ParseResultRef<Payload>& out) {
|
580
|
+
|
581
|
+
bool warnEmptyBody = false;
|
582
|
+
|
583
|
+
mdp::ByteBuffer contentLength;
|
584
|
+
mdp::ByteBuffer transferEncoding;
|
585
|
+
|
586
|
+
for (HeaderIterator it = out.node.headers.begin();
|
587
|
+
it != out.node.headers.end();
|
588
|
+
++it) {
|
589
|
+
|
590
|
+
if (it->first == HTTPHeaderName::ContentLength) {
|
591
|
+
contentLength = it->second;
|
592
|
+
}
|
593
|
+
|
594
|
+
if (it->first == HTTPHeaderName::TransferEncoding) {
|
595
|
+
transferEncoding = it->second;
|
589
596
|
}
|
590
|
-
|
591
|
-
out.node.body = model.body;
|
592
|
-
out.node.schema = model.schema;
|
597
|
+
}
|
593
598
|
|
594
|
-
|
599
|
+
if (out.node.body.empty() && out.node.reference.meta.state != Reference::StatePending) {
|
595
600
|
|
596
|
-
|
601
|
+
// Warn when content-length or transfer-encoding is specified or both headers and body are empty
|
602
|
+
if (out.node.headers.empty()) {
|
603
|
+
warnEmptyBody = true;
|
604
|
+
} else {
|
605
|
+
warnEmptyBody = !contentLength.empty() || !transferEncoding.empty();
|
606
|
+
}
|
597
607
|
|
598
|
-
|
599
|
-
out.sourceMap.parameters = modelSM.parameters;
|
600
|
-
out.sourceMap.body = modelSM.body;
|
601
|
-
out.sourceMap.schema = modelSM.schema;
|
608
|
+
if (warnEmptyBody) {
|
602
609
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
610
|
+
// WARN: empty body
|
611
|
+
std::stringstream ss;
|
612
|
+
ss << "empty " << SectionName(RequestSectionType) << " " << SectionName(BodySectionType);
|
613
|
+
|
614
|
+
if (!contentLength.empty()) {
|
615
|
+
ss << ", expected " << SectionName(BodySectionType) << " for '" << contentLength << "' Content-Length";
|
616
|
+
} else if (!transferEncoding.empty()) {
|
617
|
+
ss << ", expected " << SectionName(BodySectionType) << " for '" << transferEncoding << "' Transfer-Encoding";
|
607
618
|
}
|
619
|
+
|
620
|
+
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
621
|
+
out.report.warnings.push_back(Warning(ss.str(),
|
622
|
+
EmptyDefinitionWarning,
|
623
|
+
sourceMap));
|
608
624
|
}
|
625
|
+
}
|
626
|
+
}
|
609
627
|
|
610
|
-
|
628
|
+
/**
|
629
|
+
* \brief Checks response given as out
|
630
|
+
* \param node Markdown node
|
631
|
+
* \param pd Section parser state
|
632
|
+
* \param out Processed output
|
633
|
+
*/
|
634
|
+
static void checkResponse(const MarkdownNodeIterator& node,
|
635
|
+
SectionParserData& pd,
|
636
|
+
const ParseResultRef<Payload>& out) {
|
637
|
+
|
638
|
+
HTTPStatusCode code = 200;
|
639
|
+
|
640
|
+
if (!out.node.name.empty()) {
|
641
|
+
std::stringstream(out.node.name) >> code;
|
611
642
|
}
|
612
643
|
|
613
|
-
|
644
|
+
StatusCodeTraits statusCodeTraits = GetStatusCodeTrait(code);
|
645
|
+
|
646
|
+
if (!statusCodeTraits.allowBody &&
|
647
|
+
!out.node.body.empty() &&
|
648
|
+
out.node.reference.meta.state != Reference::StatePending) {
|
649
|
+
|
650
|
+
// WARN: not empty body
|
651
|
+
std::stringstream ss;
|
652
|
+
ss << "the " << code << " response MUST NOT include a " << SectionName(BodySectionType);
|
653
|
+
|
654
|
+
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
655
|
+
out.report.warnings.push_back(Warning(ss.str(),
|
656
|
+
EmptyDefinitionWarning,
|
657
|
+
sourceMap));
|
658
|
+
}
|
614
659
|
}
|
615
660
|
|
616
661
|
/**
|