redsnow 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -1
  3. data/README.md +12 -0
  4. data/ext/snowcrash/bin/snowcrash +0 -0
  5. data/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.c +5 -2
  6. data/ext/snowcrash/snowcrash.gyp +7 -2
  7. data/ext/snowcrash/src/ActionParser.h +141 -81
  8. data/ext/snowcrash/src/AssetParser.h +19 -11
  9. data/ext/snowcrash/src/Blueprint.h +44 -14
  10. data/ext/snowcrash/src/BlueprintParser.h +65 -51
  11. data/ext/snowcrash/src/BlueprintSourcemap.h +254 -0
  12. data/ext/snowcrash/src/BlueprintUtility.h +3 -24
  13. data/ext/snowcrash/src/CBlueprint.cc +40 -31
  14. data/ext/snowcrash/src/CBlueprint.h +54 -58
  15. data/ext/snowcrash/src/CBlueprintSourcemap.cc +620 -0
  16. data/ext/snowcrash/src/CBlueprintSourcemap.h +342 -0
  17. data/ext/snowcrash/src/CSourceAnnotation.cc +14 -0
  18. data/ext/snowcrash/src/CodeBlockUtility.h +42 -5
  19. data/ext/snowcrash/src/HeadersParser.h +84 -42
  20. data/ext/snowcrash/src/ParameterParser.h +110 -68
  21. data/ext/snowcrash/src/ParametersParser.h +26 -28
  22. data/ext/snowcrash/src/PayloadParser.h +164 -83
  23. data/ext/snowcrash/src/ResourceGroupParser.h +35 -41
  24. data/ext/snowcrash/src/ResourceParser.h +142 -97
  25. data/ext/snowcrash/src/SectionParser.h +15 -14
  26. data/ext/snowcrash/src/SectionParserData.h +11 -2
  27. data/ext/snowcrash/src/SectionProcessor.h +42 -18
  28. data/ext/snowcrash/src/Serialize.cc +2 -0
  29. data/ext/snowcrash/src/Serialize.h +3 -1
  30. data/ext/snowcrash/src/SerializeJSON.cc +608 -16
  31. data/ext/snowcrash/src/SerializeJSON.h +4 -1
  32. data/ext/snowcrash/src/SerializeYAML.cc +367 -19
  33. data/ext/snowcrash/src/SerializeYAML.h +4 -1
  34. data/ext/snowcrash/src/SymbolTable.h +12 -1
  35. data/ext/snowcrash/src/ValuesParser.h +12 -11
  36. data/ext/snowcrash/src/Version.h +1 -1
  37. data/ext/snowcrash/src/csnowcrash.cc +7 -3
  38. data/ext/snowcrash/src/csnowcrash.h +4 -2
  39. data/ext/snowcrash/src/snowcrash.cc +10 -11
  40. data/ext/snowcrash/src/snowcrash.h +3 -3
  41. data/ext/snowcrash/src/snowcrash/snowcrash.cc +38 -8
  42. data/ext/snowcrash/tools/homebrew/snowcrash.rb +1 -1
  43. data/lib/redsnow.rb +41 -2
  44. data/lib/redsnow/binding.rb +93 -8
  45. data/lib/redsnow/blueprint.rb +48 -25
  46. data/lib/redsnow/parseresult.rb +9 -2
  47. data/lib/redsnow/sourcemap.rb +369 -0
  48. data/lib/redsnow/version.rb +1 -1
  49. data/test/fixtures/sample-api-ast.json +1 -1
  50. data/test/fixtures/sample-api-sourcemap.json +169 -0
  51. data/test/redsnow_binding_test.rb +19 -2
  52. data/test/redsnow_options_test.rb +42 -0
  53. data/test/redsnow_parseresult_test.rb +5 -1
  54. data/test/redsnow_test.rb +5 -0
  55. metadata +11 -2
@@ -23,9 +23,7 @@ namespace snowcrash {
23
23
  /** No parameters specified message */
24
24
  const char* const NoParametersMessage = "no parameters specified, expected a nested list of parameters, one parameter per list item";
25
25
 
26
- /** Internal type alias for Collection of Parameter */
27
- typedef Collection<Parameter>::type Parameters;
28
-
26
+ /** Internal type alias for Collection iterator of Parameter */
29
27
  typedef Collection<Parameter>::iterator ParameterIterator;
30
28
 
31
29
  /**
@@ -38,8 +36,7 @@ namespace snowcrash {
38
36
  const MarkdownNodes& siblings,
39
37
  SectionParserData& pd,
40
38
  SectionLayout& layout,
41
- Report& report,
42
- Parameters& out) {
39
+ ParseResult<Parameters>& out) {
43
40
 
44
41
  mdp::ByteBuffer remainingContent;
45
42
 
@@ -53,9 +50,9 @@ namespace snowcrash {
53
50
  ss << " expected a nested list of parameters, one parameter per list item";
54
51
 
55
52
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
56
- report.warnings.push_back(Warning(ss.str(),
57
- IgnoringWarning,
58
- sourceMap));
53
+ out.report.warnings.push_back(Warning(ss.str(),
54
+ IgnoringWarning,
55
+ sourceMap));
59
56
  }
60
57
 
61
58
  return ++MarkdownNodeIterator(node);
@@ -64,8 +61,7 @@ namespace snowcrash {
64
61
  static MarkdownNodeIterator processDescription(const MarkdownNodeIterator& node,
65
62
  const MarkdownNodes& siblings,
66
63
  SectionParserData& pd,
67
- Report& report,
68
- Parameters& out) {
64
+ ParseResult<Parameters>& out) {
69
65
 
70
66
  return node;
71
67
  }
@@ -73,34 +69,37 @@ namespace snowcrash {
73
69
  static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
74
70
  const MarkdownNodes& siblings,
75
71
  SectionParserData& pd,
76
- Report& report,
77
- Parameters& out) {
72
+ ParseResult<Parameters>& out) {
78
73
 
79
74
  if (pd.sectionContext() != ParameterSectionType) {
80
75
  return node;
81
76
  }
82
77
 
83
- Parameter parameter;
84
- ParameterParser::parse(node, siblings, pd, report, parameter);
78
+ ParseResult<Parameter> parameter(out.report);
79
+ ParameterParser::parse(node, siblings, pd, parameter);
85
80
 
86
- if (!out.empty()) {
81
+ if (!out.node.empty()) {
87
82
 
88
- ParameterIterator duplicate = findParameter(out, parameter);
83
+ ParameterIterator duplicate = findParameter(out.node, parameter.node);
89
84
 
90
- if (duplicate != out.end()) {
85
+ if (duplicate != out.node.end()) {
91
86
 
92
87
  // WARN: Parameter already defined
93
88
  std::stringstream ss;
94
- ss << "overshadowing previous parameter '" << parameter.name << "' definition";
89
+ ss << "overshadowing previous parameter '" << parameter.node.name << "' definition";
95
90
 
96
91
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
97
- report.warnings.push_back(Warning(ss.str(),
98
- RedefinitionWarning,
99
- sourceMap));
92
+ out.report.warnings.push_back(Warning(ss.str(),
93
+ RedefinitionWarning,
94
+ sourceMap));
100
95
  }
101
96
  }
102
97
 
103
- out.push_back(parameter);
98
+ out.node.push_back(parameter.node);
99
+
100
+ if (pd.exportSourceMap()) {
101
+ out.sourceMap.collection.push_back(parameter.sourceMap);
102
+ }
104
103
 
105
104
  return ++MarkdownNodeIterator(node);
106
105
  }
@@ -147,16 +146,15 @@ namespace snowcrash {
147
146
 
148
147
  static void finalize(const MarkdownNodeIterator& node,
149
148
  SectionParserData& pd,
150
- Report& report,
151
- Parameters& out) {
149
+ ParseResult<Parameters>& out) {
152
150
 
153
- if (out.empty()) {
151
+ if (out.node.empty()) {
154
152
 
155
153
  // WARN: No parameters defined
156
154
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
157
- report.warnings.push_back(Warning(NoParametersMessage,
158
- FormattingWarning,
159
- sourceMap));
155
+ out.report.warnings.push_back(Warning(NoParametersMessage,
156
+ FormattingWarning,
157
+ sourceMap));
160
158
  }
161
159
  }
162
160
 
@@ -20,6 +20,10 @@
20
20
 
21
21
  namespace snowcrash {
22
22
 
23
+ /** Internal type alias for Collection iterator of Response */
24
+ typedef Collection<Response>::const_iterator ResponseIterator;
25
+ typedef Collection<Request>::const_iterator RequestIterator;
26
+
23
27
  /// Payload signature
24
28
  enum PayloadSignature {
25
29
  NoPayloadSignature = 0,
@@ -48,35 +52,42 @@ namespace snowcrash {
48
52
  const MarkdownNodes& siblings,
49
53
  SectionParserData& pd,
50
54
  SectionLayout& layout,
51
- Report& report,
52
- Payload& out) {
55
+ ParseResult<Payload>& out) {
53
56
 
54
57
  mdp::ByteBuffer signature, remainingContent;
55
58
  signature = GetFirstLine(node->text, remainingContent);
56
59
 
57
- parseSignature(node, pd, signature, report, out);
60
+ parseSignature(node, pd, signature, out);
58
61
 
59
62
  // WARN: missing status code
60
- if (out.name.empty() &&
63
+ if (out.node.name.empty() &&
61
64
  (pd.sectionContext() == ResponseSectionType || pd.sectionContext() == ResponseBodySectionType)) {
62
65
 
63
66
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
64
- report.warnings.push_back(Warning("missing response HTTP status code, assuming 'Response 200'",
65
- EmptyDefinitionWarning,
66
- sourceMap));
67
- out.name = "200";
67
+ out.report.warnings.push_back(Warning("missing response HTTP status code, assuming 'Response 200'",
68
+ EmptyDefinitionWarning,
69
+ sourceMap));
70
+ out.node.name = "200";
68
71
  }
69
72
 
70
73
  if (!remainingContent.empty()) {
71
74
  if (!isAbbreviated(pd.sectionContext())) {
72
- out.description = remainingContent;
73
- } else if (!parseSymbolReference(node, pd, remainingContent, report, out)) {
75
+ out.node.description = remainingContent;
76
+
77
+ if (pd.exportSourceMap() && !out.node.description.empty()) {
78
+ out.sourceMap.description.sourceMap.append(node->sourceMap);
79
+ }
80
+ } else if (!parseSymbolReference(node, pd, remainingContent, out)) {
74
81
 
75
82
  // NOTE: NOT THE CORRECT WAY TO DO THIS
76
83
  // https://github.com/apiaryio/snowcrash/commit/a7c5868e62df0048a85e2f9aeeb42c3b3e0a2f07#commitcomment-7322085
77
84
  pd.sectionsContext.push_back(BodySectionType);
78
- CodeBlockUtility::signatureContentAsCodeBlock(node, pd, report, out.body);
85
+ CodeBlockUtility::signatureContentAsCodeBlock(node, pd, out.report, out.node.body);
79
86
  pd.sectionsContext.pop_back();
87
+
88
+ if (pd.exportSourceMap() && !out.node.body.empty()) {
89
+ out.sourceMap.body.sourceMap.append(node->sourceMap);
90
+ }
80
91
  }
81
92
  }
82
93
 
@@ -86,35 +97,38 @@ namespace snowcrash {
86
97
  static MarkdownNodeIterator processContent(const MarkdownNodeIterator& node,
87
98
  const MarkdownNodes& siblings,
88
99
  SectionParserData& pd,
89
- Report& report,
90
- Payload& out) {
100
+ ParseResult<Payload>& out) {
91
101
 
92
102
  mdp::ByteBuffer content;
93
103
 
94
- if (!out.symbol.empty()) {
104
+ if (!out.node.symbol.empty()) {
95
105
  //WARN: ignoring extraneous content after symbol reference
96
106
  std::stringstream ss;
97
107
 
98
108
  ss << "ignoring extraneous content after symbol reference";
99
- ss << ", expected symbol reference only e.g. '[" << out.symbol << "][]'";
109
+ ss << ", expected symbol reference only e.g. '[" << out.node.symbol << "][]'";
100
110
 
101
111
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
102
- report.warnings.push_back(Warning(ss.str(),
103
- IgnoringWarning,
104
- sourceMap));
112
+ out.report.warnings.push_back(Warning(ss.str(),
113
+ IgnoringWarning,
114
+ sourceMap));
105
115
  } else {
106
116
 
107
- if (!out.body.empty() ||
117
+ if (!out.node.body.empty() ||
108
118
  node->type != mdp::ParagraphMarkdownNodeType ||
109
- !parseSymbolReference(node, pd, node->text, report, out)) {
119
+ !parseSymbolReference(node, pd, node->text, out)) {
110
120
 
111
121
  // NOTE: NOT THE CORRECT WAY TO DO THIS
112
122
  // https://github.com/apiaryio/snowcrash/commit/a7c5868e62df0048a85e2f9aeeb42c3b3e0a2f07#commitcomment-7322085
113
123
  pd.sectionsContext.push_back(BodySectionType);
114
- CodeBlockUtility::contentAsCodeBlock(node, pd, report, content);
124
+ CodeBlockUtility::contentAsCodeBlock(node, pd, out.report, content);
115
125
  pd.sectionsContext.pop_back();
116
126
 
117
- out.body += content;
127
+ out.node.body += content;
128
+
129
+ if (pd.exportSourceMap() && !content.empty()) {
130
+ out.sourceMap.body.sourceMap.append(node->sourceMap);
131
+ }
118
132
  }
119
133
  }
120
134
 
@@ -124,34 +138,42 @@ namespace snowcrash {
124
138
  static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
125
139
  const MarkdownNodes& siblings,
126
140
  SectionParserData& pd,
127
- Report& report,
128
- Payload& out) {
141
+ ParseResult<Payload>& out) {
129
142
 
130
143
  switch (pd.sectionContext()) {
131
144
  case HeadersSectionType:
132
- return HeadersParser::parse(node, siblings, pd, report, out.headers);
145
+ {
146
+ ParseResult<Headers> headers(out.report, out.node.headers, out.sourceMap.headers);
147
+ return HeadersParser::parse(node, siblings, pd, headers);
148
+ }
133
149
 
134
150
  case BodySectionType:
135
- if (!out.body.empty()) {
151
+ {
152
+ if (!out.node.body.empty()) {
136
153
  // WARN: Multiple body section
137
154
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
138
- report.warnings.push_back(Warning("ignoring additional 'body' content, it is already defined",
139
- RedefinitionWarning,
140
- sourceMap));
155
+ out.report.warnings.push_back(Warning("ignoring additional 'body' content, it is already defined",
156
+ RedefinitionWarning,
157
+ sourceMap));
141
158
  }
142
159
 
143
- return AssetParser::parse(node, siblings, pd, report, out.body);
160
+ ParseResult<Asset> asset(out.report, out.node.body, out.sourceMap.body);
161
+ return AssetParser::parse(node, siblings, pd, asset);
162
+ }
144
163
 
145
164
  case SchemaSectionType:
146
- if (!out.schema.empty()) {
165
+ {
166
+ if (!out.node.schema.empty()) {
147
167
  // WARN: Multiple schema section
148
168
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
149
- report.warnings.push_back(Warning("ignoring additional 'schema' content, it is already defined",
150
- RedefinitionWarning,
151
- sourceMap));
169
+ out.report.warnings.push_back(Warning("ignoring additional 'schema' content, it is already defined",
170
+ RedefinitionWarning,
171
+ sourceMap));
152
172
  }
153
173
 
154
- return AssetParser::parse(node, siblings, pd, report, out.schema);
174
+ ParseResult<Asset> asset(out.report, out.node.schema, out.sourceMap.schema);
175
+ return AssetParser::parse(node, siblings, pd, asset);
176
+ }
155
177
 
156
178
  default:
157
179
  break;
@@ -164,18 +186,22 @@ namespace snowcrash {
164
186
  const MarkdownNodes& siblings,
165
187
  SectionParserData& pd,
166
188
  SectionType& sectionType,
167
- Report& report,
168
- Payload& out) {
189
+ ParseResult<Payload>& out) {
169
190
 
170
191
  if ((node->type == mdp::ParagraphMarkdownNodeType ||
171
192
  node->type == mdp::CodeMarkdownNodeType) &&
172
193
  sectionType == BodySectionType) {
173
194
 
174
- CodeBlockUtility::addDanglingAsset(node, pd, sectionType, report, out.body);
195
+ mdp::ByteBuffer content = CodeBlockUtility::addDanglingAsset(node, pd, sectionType, out.report, out.node.body);
196
+
197
+ if (pd.exportSourceMap() && !content.empty()) {
198
+ out.sourceMap.body.sourceMap.append(node->sourceMap);
199
+ }
200
+
175
201
  return ++MarkdownNodeIterator(node);
176
202
  }
177
203
 
178
- return SectionProcessorBase<Payload>::processUnexpectedNode(node, siblings, pd, sectionType, report, out);
204
+ return SectionProcessorBase<Payload>::processUnexpectedNode(node, siblings, pd, sectionType, out);
179
205
  }
180
206
 
181
207
  static bool isDescriptionNode(const MarkdownNodeIterator& node,
@@ -270,8 +296,7 @@ namespace snowcrash {
270
296
 
271
297
  static void finalize(const MarkdownNodeIterator& node,
272
298
  SectionParserData& pd,
273
- Report& report,
274
- Payload& out) {
299
+ ParseResult<Payload>& out) {
275
300
 
276
301
  bool warnEmptyBody = false;
277
302
 
@@ -280,8 +305,8 @@ namespace snowcrash {
280
305
 
281
306
  SectionType sectionType = pd.sectionContext();
282
307
 
283
- for (Collection<Header>::const_iterator it = out.headers.begin();
284
- it != out.headers.end();
308
+ for (HeaderIterator it = out.node.headers.begin();
309
+ it != out.node.headers.end();
285
310
  ++it) {
286
311
 
287
312
  if (it->first == HTTPHeaderName::ContentLength) {
@@ -293,10 +318,10 @@ namespace snowcrash {
293
318
  }
294
319
  }
295
320
 
296
- if ((sectionType == RequestSectionType || sectionType == RequestBodySectionType) && out.body.empty()) {
321
+ if ((sectionType == RequestSectionType || sectionType == RequestBodySectionType) && out.node.body.empty()) {
297
322
 
298
323
  // Warn when content-length or transfer-encoding is specified or both headers and body are empty
299
- if (out.headers.empty()) {
324
+ if (out.node.headers.empty()) {
300
325
  warnEmptyBody = true;
301
326
  } else {
302
327
  warnEmptyBody = !contentLength.empty() || !transferEncoding.empty();
@@ -314,29 +339,29 @@ namespace snowcrash {
314
339
  }
315
340
 
316
341
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
317
- report.warnings.push_back(Warning(ss.str(),
318
- EmptyDefinitionWarning,
319
- sourceMap));
342
+ out.report.warnings.push_back(Warning(ss.str(),
343
+ EmptyDefinitionWarning,
344
+ sourceMap));
320
345
  }
321
346
  } else if ((sectionType == ResponseSectionType || sectionType == ResponseBodySectionType)) {
322
347
 
323
348
  HTTPStatusCode code = 200;
324
349
 
325
- if (!out.name.empty()) {
326
- std::stringstream(out.name) >> code;
350
+ if (!out.node.name.empty()) {
351
+ std::stringstream(out.node.name) >> code;
327
352
  }
328
353
 
329
354
  StatusCodeTraits statusCodeTraits = GetStatusCodeTrait(code);
330
355
 
331
- if (!statusCodeTraits.allowBody && !out.body.empty()) {
356
+ if (!statusCodeTraits.allowBody && !out.node.body.empty()) {
332
357
  // WARN: not empty body
333
358
  std::stringstream ss;
334
359
  ss << "the " << code << " response MUST NOT include a " << SectionName(BodySectionType);
335
360
 
336
361
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
337
- report.warnings.push_back(Warning(ss.str(),
338
- EmptyDefinitionWarning,
339
- sourceMap));
362
+ out.report.warnings.push_back(Warning(ss.str(),
363
+ EmptyDefinitionWarning,
364
+ sourceMap));
340
365
  }
341
366
  }
342
367
  }
@@ -396,8 +421,7 @@ namespace snowcrash {
396
421
  static bool parseSignature(const MarkdownNodeIterator& node,
397
422
  SectionParserData& pd,
398
423
  const mdp::ByteBuffer& signature,
399
- Report& report,
400
- Payload& out) {
424
+ ParseResult<Payload>& out) {
401
425
 
402
426
  const char* regex;
403
427
  mdp::ByteBuffer mediaType;
@@ -461,9 +485,9 @@ namespace snowcrash {
461
485
  }
462
486
 
463
487
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
464
- report.warnings.push_back(Warning(ss.str(),
465
- FormattingWarning,
466
- sourceMap));
488
+ out.report.warnings.push_back(Warning(ss.str(),
489
+ FormattingWarning,
490
+ sourceMap));
467
491
 
468
492
  return false;
469
493
  }
@@ -471,19 +495,29 @@ namespace snowcrash {
471
495
  if (pd.sectionContext() == ModelSectionType ||
472
496
  pd.sectionContext() == ModelBodySectionType) {
473
497
 
474
- out.name = captureGroups[2];
498
+ out.node.name = captureGroups[2];
475
499
  mediaType = captureGroups[4];
476
500
  } else {
477
- out.name = captureGroups[1];
501
+ out.node.name = captureGroups[1];
478
502
  mediaType = captureGroups[3];
479
503
  }
480
504
 
481
- TrimString(out.name);
505
+ TrimString(out.node.name);
482
506
  TrimString(mediaType);
483
507
 
508
+ if (pd.exportSourceMap() && !out.node.name.empty()) {
509
+ out.sourceMap.name.sourceMap = node->sourceMap;
510
+ }
511
+
484
512
  if (!mediaType.empty()) {
485
513
  Header header = std::make_pair(HTTPHeaderName::ContentType, mediaType);
486
- out.headers.push_back(header);
514
+ out.node.headers.push_back(header);
515
+
516
+ if (pd.exportSourceMap()) {
517
+ SourceMap<Header> headerSM;
518
+ headerSM.sourceMap = node->sourceMap;
519
+ out.sourceMap.headers.collection.push_back(headerSM);
520
+ }
487
521
  }
488
522
  }
489
523
 
@@ -493,16 +527,20 @@ namespace snowcrash {
493
527
  static bool parseSymbolReference(const MarkdownNodeIterator& node,
494
528
  SectionParserData& pd,
495
529
  mdp::ByteBuffer& source,
496
- Report& report,
497
- Payload& out) {
530
+ ParseResult<Payload>& out) {
498
531
 
499
532
  SymbolName symbol;
500
533
  ResourceModel model;
534
+ SourceMap<ResourceModel> modelSM;
501
535
 
502
536
  TrimString(source);
503
537
 
504
538
  if (GetSymbolReference(source, symbol)) {
505
- out.symbol = symbol;
539
+ out.node.symbol = symbol;
540
+
541
+ if (pd.exportSourceMap() && !symbol.empty()) {
542
+ out.sourceMap.symbol.sourceMap = node->sourceMap;
543
+ }
506
544
 
507
545
  // If symbol doesn't exist
508
546
  if (pd.symbolTable.resourceModels.find(symbol) == pd.symbolTable.resourceModels.end()) {
@@ -512,22 +550,22 @@ namespace snowcrash {
512
550
  ss << "Undefined symbol " << symbol;
513
551
 
514
552
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
515
- report.error = Error(ss.str(), SymbolError, sourceMap);
553
+ out.report.error = Error(ss.str(), SymbolError, sourceMap);
516
554
 
517
555
  return true;
518
556
  }
519
557
 
520
558
  model = pd.symbolTable.resourceModels.at(symbol);
521
559
 
522
- out.description = model.description;
523
- out.parameters = model.parameters;
560
+ out.node.description = model.description;
561
+ out.node.parameters = model.parameters;
524
562
 
525
- Collection<Header>::const_iterator modelContentType = std::find_if(model.headers.begin(),
526
- model.headers.end(),
527
- std::bind2nd(MatchFirstWith<Header, std::string>(),
528
- HTTPHeaderName::ContentType));
563
+ HeaderIterator modelContentType = std::find_if(model.headers.begin(),
564
+ model.headers.end(),
565
+ std::bind2nd(MatchFirstWith<Header, std::string>(),
566
+ HTTPHeaderName::ContentType));
529
567
 
530
- bool isPayloadContentType = !out.headers.empty();
568
+ bool isPayloadContentType = !out.node.headers.empty();
531
569
  bool isModelContentType = modelContentType != model.headers.end();
532
570
 
533
571
  if (isPayloadContentType && isModelContentType) {
@@ -539,26 +577,69 @@ namespace snowcrash {
539
577
  ss << "specify this header(s) in the referenced model definition instead";
540
578
 
541
579
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
542
- report.warnings.push_back(Warning(ss.str(),
543
- IgnoringWarning,
544
- sourceMap));
580
+ out.report.warnings.push_back(Warning(ss.str(),
581
+ IgnoringWarning,
582
+ sourceMap));
545
583
  }
546
584
 
547
585
  if (isPayloadContentType && !isModelContentType) {
548
- out.headers.insert(out.headers.end(), model.headers.begin(), model.headers.end());
549
- }
550
- else {
551
- out.headers = model.headers;
586
+ out.node.headers.insert(out.node.headers.end(), model.headers.begin(), model.headers.end());
587
+ } else {
588
+ out.node.headers = model.headers;
552
589
  }
553
590
 
554
- out.body = model.body;
555
- out.schema = model.schema;
591
+ out.node.body = model.body;
592
+ out.node.schema = model.schema;
593
+
594
+ if (pd.exportSourceMap()) {
595
+
596
+ modelSM = pd.symbolSourceMapTable.resourceModels.at(symbol);
597
+
598
+ out.sourceMap.description = modelSM.description;
599
+ out.sourceMap.parameters = modelSM.parameters;
600
+ out.sourceMap.body = modelSM.body;
601
+ out.sourceMap.schema = modelSM.schema;
602
+
603
+ if (isPayloadContentType && !isModelContentType) {
604
+ out.sourceMap.headers.collection.insert(out.sourceMap.headers.collection.end(), modelSM.headers.collection.begin(), modelSM.headers.collection.end());
605
+ } else {
606
+ out.sourceMap.headers = modelSM.headers;
607
+ }
608
+ }
556
609
 
557
610
  return true;
558
611
  }
559
612
 
560
613
  return false;
561
614
  }
615
+
616
+ /**
617
+ * \brief Find a request within given action.
618
+ * \param transaction A transaction to check.
619
+ * \param request A request to look for.
620
+ * \return Iterator pointing to the matching request within given method requests.
621
+ */
622
+ static RequestIterator findRequest(const TransactionExample& example,
623
+ const Request& request) {
624
+
625
+ return std::find_if(example.requests.begin(),
626
+ example.requests.end(),
627
+ std::bind2nd(MatchPayload(), request));
628
+ }
629
+
630
+ /**
631
+ * \brief Find a response within responses of a given action.
632
+ * \param transaction A transaction to check.
633
+ * \param response A response to look for.
634
+ * \return Iterator pointing to the matching response within given method requests.
635
+ */
636
+ static ResponseIterator findResponse(const TransactionExample& example,
637
+ const Response& response) {
638
+
639
+ return std::find_if(example.responses.begin(),
640
+ example.responses.end(),
641
+ std::bind2nd(MatchPayload(), response));
642
+ }
562
643
  };
563
644
 
564
645
  /** Payload Section Parser */