redsnow 0.4.0 → 0.4.1

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +16 -16
  3. data/ext/drafter/bin/drafter +0 -0
  4. data/ext/drafter/build/out/Release/drafter +0 -0
  5. data/ext/drafter/build/out/Release/libdrafter.dylib +0 -0
  6. data/ext/drafter/build/out/Release/libmarkdownparser.a +0 -0
  7. data/ext/drafter/build/out/Release/libsnowcrash.a +0 -0
  8. data/ext/drafter/build/out/Release/libsos.a +0 -0
  9. data/ext/drafter/build/out/Release/libsundown.a +0 -0
  10. data/ext/drafter/build/out/Release/obj.target/drafter/src/config.o +0 -0
  11. data/ext/drafter/build/out/Release/obj.target/drafter/src/main.o +0 -0
  12. data/ext/drafter/build/out/Release/obj.target/drafter/src/reporting.o +0 -0
  13. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/Serialize.o +0 -0
  14. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeAST.o +0 -0
  15. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeResult.o +0 -0
  16. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeSourcemap.o +0 -0
  17. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/cdrafter.o +0 -0
  18. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/drafter.o +0 -0
  19. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.o +0 -0
  20. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.o +0 -0
  21. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.o +0 -0
  22. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Blueprint.o +0 -0
  23. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/BlueprintSourcemap.o +0 -0
  24. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/HTTP.o +0 -0
  25. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/HeadersParser.o +0 -0
  26. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSON.o +0 -0
  27. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONOneOfParser.o +0 -0
  28. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONSourcemap.o +0 -0
  29. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONTypeSectionParser.o +0 -0
  30. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONValueMemberParser.o +0 -0
  31. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Section.o +0 -0
  32. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Signature.o +0 -0
  33. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/UriTemplateParser.o +0 -0
  34. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/posix/RegexMatch.o +0 -0
  35. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/snowcrash.o +0 -0
  36. data/ext/drafter/build/out/Release/obj.target/libsos/ext/sos/src/sos.o +0 -0
  37. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_href_e.o +0 -0
  38. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_html_e.o +0 -0
  39. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html.o +0 -0
  40. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html_smartypants.o +0 -0
  41. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/autolink.o +0 -0
  42. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/buffer.o +0 -0
  43. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.o +0 -0
  44. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/src_map.o +0 -0
  45. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/stack.o +0 -0
  46. data/ext/drafter/configure +1 -1
  47. data/ext/drafter/ext/snowcrash/configure +1 -1
  48. data/ext/drafter/ext/snowcrash/src/BlueprintParser.h +111 -22
  49. data/ext/drafter/ext/snowcrash/src/MSON.h +5 -1
  50. data/ext/drafter/ext/snowcrash/src/MSONMixinParser.h +8 -0
  51. data/ext/drafter/ext/snowcrash/src/MSONNamedTypeParser.h +12 -1
  52. data/ext/drafter/ext/snowcrash/src/MSONUtility.h +69 -7
  53. data/ext/drafter/ext/snowcrash/src/MSONValueMemberParser.h +23 -0
  54. data/ext/drafter/ext/snowcrash/src/ParameterParser.h +8 -2
  55. data/ext/drafter/ext/snowcrash/src/ResourceParser.h +8 -0
  56. data/ext/drafter/ext/snowcrash/src/SectionParserData.h +6 -0
  57. data/ext/drafter/ext/snowcrash/src/SignatureSectionProcessor.h +9 -3
  58. data/ext/drafter/ext/snowcrash/src/SourceAnnotation.h +2 -1
  59. data/ext/drafter/ext/snowcrash/src/UriTemplateParser.cc +1 -1
  60. data/ext/drafter/ext/snowcrash/src/snowcrash.cc +2 -2
  61. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
  62. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
  63. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
  64. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
  65. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
  66. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
  67. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
  68. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
  69. data/ext/drafter/src/Version.h +1 -1
  70. data/ext/drafter/src/main.cc +6 -6
  71. data/ext/drafter/tools/homebrew/drafter.rb +1 -1
  72. data/lib/redsnow.rb +2 -2
  73. data/lib/redsnow/blueprint.rb +1 -1
  74. data/lib/redsnow/version.rb +1 -1
  75. data/redsnow.gemspec +2 -2
  76. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7a42395c3a357bc8d783eeafe217eb8169bf802
4
- data.tar.gz: c3272147eb4b1ac934b7b675e38f216e5011941b
3
+ metadata.gz: a87a6fa01c627672f57d9c43bd053eb472bf34f5
4
+ data.tar.gz: 50f8b9c504bbb3450a1ec6eaebb261beb92e9e31
5
5
  SHA512:
6
- metadata.gz: d4afc5e2fe580a75423a59ea58a8c5846562f23f73d20a6657d6f09c9c953599af1783304be443daa0619613e2969e66481f8173fac83e64cb19ff75ac284f8d
7
- data.tar.gz: 1125f2f86362bd272e5da418e7b3cca2462a52a05dd0374c91d3042f9341b8b38e769289bc1f85f7d1f5a514502f9827bf629cd682ede49b4b7bc371385d8b70
6
+ metadata.gz: e5a8649d40c41d014156a6d325e9f1fa448f988a6b3a0da550edef1902a2423f1cf5a083caaf3233dea1975fe3065b82eab03822fd7def00a9c8182a98016397
7
+ data.tar.gz: 065df0a1d76038edff0dfe5f6b81b059af0938b4c5ac984777e74270123fa381b372a40be56aea1762bee0ed76e95bd02de356d2bb2ecb9a0ffa9c3f46d06441
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redsnow (0.4.0)
4
+ redsnow (0.4.1)
5
5
  bundler (>= 1.7.0)
6
6
  ffi (~> 1.9.3)
7
7
  rake (>= 10.3.2)
@@ -23,9 +23,9 @@ GEM
23
23
  celluloid (0.16.0)
24
24
  timers (~> 4.0.0)
25
25
  coderay (1.1.0)
26
- ffi (1.9.6)
26
+ ffi (1.9.8)
27
27
  formatador (0.2.5)
28
- guard (2.11.1)
28
+ guard (2.12.5)
29
29
  formatador (>= 0.2.4)
30
30
  listen (~> 2.7)
31
31
  lumberjack (~> 1.0)
@@ -39,8 +39,8 @@ GEM
39
39
  rubocop (~> 0.20)
40
40
  hitimes (1.2.2)
41
41
  i18n (0.7.0)
42
- listen (2.8.5)
43
- celluloid (>= 0.15.2)
42
+ listen (2.10.0)
43
+ celluloid (~> 0.16.0)
44
44
  rb-fsevent (>= 0.9.3)
45
45
  rb-inotify (>= 0.9)
46
46
  lumberjack (1.0.9)
@@ -49,14 +49,14 @@ GEM
49
49
  minitest (4.7.5)
50
50
  mocha (1.1.0)
51
51
  metaclass (~> 0.0.1)
52
- multi_json (1.10.1)
52
+ multi_json (1.11.0)
53
53
  nenv (0.2.0)
54
- notiffany (0.0.3)
54
+ notiffany (0.0.6)
55
55
  nenv (~> 0.1)
56
56
  shellany (~> 0.0)
57
- parser (2.2.0.2)
57
+ parser (2.2.2.1)
58
58
  ast (>= 1.1, < 3.0)
59
- powerpack (0.0.9)
59
+ powerpack (0.1.0)
60
60
  pry (0.10.1)
61
61
  coderay (~> 1.1.0)
62
62
  method_source (~> 0.8.1)
@@ -66,29 +66,29 @@ GEM
66
66
  rb-fsevent (0.9.4)
67
67
  rb-inotify (0.9.5)
68
68
  ffi (>= 0.5.0)
69
- rubocop (0.28.0)
69
+ rubocop (0.30.1)
70
70
  astrolabe (~> 1.3)
71
- parser (>= 2.2.0.pre.7, < 3.0)
72
- powerpack (~> 0.0.6)
71
+ parser (>= 2.2.2.1, < 3.0)
72
+ powerpack (~> 0.1)
73
73
  rainbow (>= 1.99.1, < 3.0)
74
74
  ruby-progressbar (~> 1.4)
75
- ruby-progressbar (1.7.1)
75
+ ruby-progressbar (1.7.5)
76
76
  shellany (0.0.1)
77
77
  shoulda (3.5.0)
78
78
  shoulda-context (~> 1.0, >= 1.0.1)
79
79
  shoulda-matchers (>= 1.4.1, < 3.0)
80
80
  shoulda-context (1.2.1)
81
- shoulda-matchers (2.7.0)
81
+ shoulda-matchers (2.8.0)
82
82
  activesupport (>= 3.0.0)
83
83
  slop (3.6.0)
84
84
  thor (0.19.1)
85
- thread_safe (0.3.4)
85
+ thread_safe (0.3.5)
86
86
  timers (4.0.1)
87
87
  hitimes
88
88
  turn (0.9.7)
89
89
  ansi
90
90
  minitest (~> 4)
91
- tzinfo (0.3.42)
91
+ tzinfo (0.3.43)
92
92
  unindent (1.0)
93
93
  yard (0.8.7.6)
94
94
 
Binary file
@@ -8,7 +8,7 @@
8
8
  import sys
9
9
 
10
10
 
11
- if sys.version_info.major != 2:
11
+ if sys.version_info[0] != 2:
12
12
  # Since various Linux distros and OS X doesn't properly follow PEP 394,
13
13
  # We've set the shebang line to `python` and erroring when it isn't
14
14
  # Python 2.
@@ -9,7 +9,7 @@
9
9
  import sys
10
10
 
11
11
 
12
- if sys.version_info.major != 2:
12
+ if sys.version_info[0] != 2:
13
13
  # Since various Linux distros and OS X doesn't properly follow PEP 394,
14
14
  # We've set the shebang line to `python` and erroring when it isn't
15
15
  # Python 2.
@@ -9,6 +9,8 @@
9
9
  #ifndef SNOWCRASH_BLUEPRINTPARSER_H
10
10
  #define SNOWCRASH_BLUEPRINTPARSER_H
11
11
 
12
+ #include <iterator>
13
+ #include <algorithm>
12
14
  #include "ResourceParser.h"
13
15
  #include "ResourceGroupParser.h"
14
16
  #include "DataStructureGroupParser.h"
@@ -284,16 +286,14 @@ namespace snowcrash {
284
286
 
285
287
  // ERR: No API name specified
286
288
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
287
- out.report.error = Error(ExpectedAPINameMessage,
288
- BusinessError,
289
- sourceMap);
289
+ out.report.error = Error(ExpectedAPINameMessage, BusinessError, sourceMap);
290
290
 
291
291
  }
292
292
  else if (!out.node.description.empty()) {
293
+
294
+ // WARN: No API name specified
293
295
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
294
- out.report.warnings.push_back(Warning(ExpectedAPINameMessage,
295
- APINameWarning,
296
- sourceMap));
296
+ out.report.warnings.push_back(Warning(ExpectedAPINameMessage, APINameWarning, sourceMap));
297
297
  }
298
298
  }
299
299
 
@@ -343,21 +343,47 @@ namespace snowcrash {
343
343
  identifier = signature.identifier;
344
344
  }
345
345
 
346
- // If named type already exists, do nothing
347
- mson::NamedTypeBaseTable::iterator it = pd.namedTypeBaseTable.find(identifier);
346
+ // If named type already exists, return error
347
+ if (pd.namedTypeDependencyTable.find(identifier) != pd.namedTypeDependencyTable.end()) {
348
348
 
349
- if (it != pd.namedTypeBaseTable.end()) {
349
+ // ERR: Named type is defined more than once
350
+ std::stringstream ss;
351
+ ss << "named type '" << identifier << "' is defined more than once";
352
+
353
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
354
+ report.error = Error(ss.str(), MSONError, sourceMap);
350
355
  return;
351
356
  }
352
357
 
353
- // Otherwise, add the respective entries to the tables
354
- if (typeDefinition.typeSpecification.name.base != mson::UndefinedTypeName) {
358
+ mson::BaseTypeName baseTypeName = typeDefinition.typeSpecification.name.base;
359
+
360
+ // Initialize an entry in the dependency table
361
+ pd.namedTypeDependencyTable[identifier] = std::set<mson::Literal>();
362
+
363
+ // Add the respective entries to the tables
364
+ if (baseTypeName != mson::UndefinedTypeName) {
355
365
  pd.namedTypeBaseTable[identifier] = mson::parseBaseType(typeDefinition.typeSpecification.name.base);
366
+
367
+ // Add nested types as dependents
368
+ if (baseTypeName == mson::ArrayTypeName || baseTypeName == mson::EnumTypeName) {
369
+
370
+ for (mson::TypeNames::iterator it = typeDefinition.typeSpecification.nestedTypes.begin();
371
+ it != typeDefinition.typeSpecification.nestedTypes.end();
372
+ ++it) {
373
+
374
+ if (!it->symbol.literal.empty() && !it->symbol.variable) {
375
+ pd.namedTypeDependencyTable[identifier].insert(it->symbol.literal);
376
+ }
377
+ }
378
+ }
356
379
  }
357
380
  else if (!typeDefinition.typeSpecification.name.symbol.literal.empty() &&
358
381
  !typeDefinition.typeSpecification.name.symbol.variable) {
359
382
 
360
- pd.namedTypeInheritanceTable[identifier] = typeDefinition.typeSpecification.name.symbol.literal;
383
+ pd.namedTypeInheritanceTable[identifier] = std::make_pair(typeDefinition.typeSpecification.name.symbol.literal, node->sourceMap);
384
+
385
+ // Make the sub type dependent on super type
386
+ pd.namedTypeDependencyTable[identifier].insert(typeDefinition.typeSpecification.name.symbol.literal);
361
387
  }
362
388
  else if (typeDefinition.typeSpecification.name.empty()) {
363
389
 
@@ -376,16 +402,62 @@ namespace snowcrash {
376
402
  Report& report) {
377
403
 
378
404
  mson::NamedTypeInheritanceTable::iterator it;
379
- mson::NamedTypeBaseTable::iterator baseIt;
405
+ mson::NamedTypeDependencyTable::iterator depIt;
406
+
407
+ // First resolve dependency tables
408
+ for (depIt = pd.namedTypeDependencyTable.begin();
409
+ depIt != pd.namedTypeDependencyTable.end();
410
+ depIt++) {
411
+
412
+ resolveNamedTypeDependencyTableEntry(pd, depIt->first, report);
413
+ }
380
414
 
381
415
  for (it = pd.namedTypeInheritanceTable.begin();
382
416
  it != pd.namedTypeInheritanceTable.end();
383
417
  it++) {
384
418
 
385
- resolveNamedTypeTableEntry(pd, it->first, it->second, report);
419
+ resolveNamedTypeBaseTableEntry(pd, it->first, it->second.first, it->second.second, report);
420
+
421
+ if (report.error.code != Error::OK) {
422
+ return;
423
+ }
386
424
  }
387
425
  }
388
426
 
427
+ /**
428
+ * \brief Resolve the inheritance dependencies of the current named type
429
+ * (Does not include mixin or member dependencies)
430
+ *
431
+ * \param pd Section parser data
432
+ * \param identifier The named type whose dependents need to be resolved
433
+ * \param report Parse report
434
+ */
435
+ static void resolveNamedTypeDependencyTableEntry(SectionParserData& pd,
436
+ const mson::Literal& identifier,
437
+ Report& report) {
438
+
439
+ std::set<mson::Literal> diffDeps, finalDeps, initialDeps;
440
+
441
+ do {
442
+ initialDeps = pd.namedTypeDependencyTable[identifier];
443
+ diffDeps.clear();
444
+
445
+ for (std::set<mson::Literal>::iterator it = initialDeps.begin();
446
+ it != initialDeps.end();
447
+ it++) {
448
+
449
+ std::set<mson::Literal> superTypeDeps = pd.namedTypeDependencyTable[*it];
450
+ pd.namedTypeDependencyTable[identifier].insert(superTypeDeps.begin(), superTypeDeps.end());
451
+ }
452
+
453
+ // Check if the list of dependents has grown
454
+ finalDeps = pd.namedTypeDependencyTable[identifier];
455
+ std::set_difference(finalDeps.begin(), finalDeps.end(), initialDeps.begin(), initialDeps.end(),
456
+ std::inserter(diffDeps, diffDeps.end()));
457
+
458
+ } while (!diffDeps.empty());
459
+ };
460
+
389
461
  /**
390
462
  * \brief For each entry in the named type inheritance table, resolve the sub-type's base type recursively
391
463
  *
@@ -394,10 +466,11 @@ namespace snowcrash {
394
466
  * \param superType The super named type between the two
395
467
  * \param report Parse report
396
468
  */
397
- static void resolveNamedTypeTableEntry(SectionParserData& pd,
398
- const mson::Literal& subType,
399
- const mson::Literal& superType,
400
- Report& report) {
469
+ static void resolveNamedTypeBaseTableEntry(SectionParserData& pd,
470
+ const mson::Literal& subType,
471
+ const mson::Literal& superType,
472
+ const mdp::BytesRangeSet& nodeSourceMap,
473
+ Report& report) {
401
474
 
402
475
  mson::BaseType baseType;
403
476
  mson::NamedTypeBaseTable::iterator it = pd.namedTypeBaseTable.find(subType);
@@ -407,6 +480,20 @@ namespace snowcrash {
407
480
  return;
408
481
  }
409
482
 
483
+ // Check for circular references
484
+ std::set<mson::Literal> deps = pd.namedTypeDependencyTable[subType];
485
+
486
+ if (deps.find(subType) != deps.end()) {
487
+
488
+ // ERR: A named type is circularly referenced
489
+ std::stringstream ss;
490
+ ss << "base type '" << subType << "' circularly referencing itself";
491
+
492
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(nodeSourceMap, pd.sourceData);
493
+ report.error = Error(ss.str(), MSONError, sourceMap);
494
+ return;
495
+ }
496
+
410
497
  // Otherwise, get the base type from super type
411
498
  it = pd.namedTypeBaseTable.find(superType);
412
499
 
@@ -416,19 +503,21 @@ namespace snowcrash {
416
503
  // Try to get the super type of the current super type
417
504
  mson::NamedTypeInheritanceTable::iterator inhIt = pd.namedTypeInheritanceTable.find(superType);
418
505
 
506
+ // Check for recursive MSON definitions
419
507
  if (inhIt == pd.namedTypeInheritanceTable.end()) {
420
508
 
421
- // We cannot find the super type in inheritance table at all
509
+ // ERR: We cannot find the super type in inheritance table at all
422
510
  // and there is not base type table entry for it, so, the blueprint is wrong
423
511
  std::stringstream ss;
424
- ss << "unable to find named type '" << superType << "' in the whole document";
512
+ ss << "base type '" << superType << "' is not defined in the document";
425
513
 
426
- report.error = Error(ss.str(), BusinessError, mdp::CharactersRangeSet());
514
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(nodeSourceMap, pd.sourceData);
515
+ report.error = Error(ss.str(), MSONError, sourceMap);
427
516
  return;
428
517
  }
429
518
 
430
519
  // Recursively, try to get a base type for the current super type
431
- resolveNamedTypeTableEntry(pd, superType, inhIt->second, report);
520
+ resolveNamedTypeBaseTableEntry(pd, superType, inhIt->second.first, inhIt->second.second, report);
432
521
 
433
522
  if (report.error.code != Error::OK) {
434
523
  return;
@@ -11,6 +11,7 @@
11
11
 
12
12
  #include <vector>
13
13
  #include <string>
14
+ #include <set>
14
15
  #include <map>
15
16
  #include <stdexcept>
16
17
 
@@ -54,7 +55,10 @@ namespace mson {
54
55
  typedef std::map<Literal, BaseType> NamedTypeBaseTable;
55
56
 
56
57
  /** Named Types inheritance table */
57
- typedef std::map<Literal, Literal> NamedTypeInheritanceTable;
58
+ typedef std::map<Literal, std::pair<Literal, mdp::BytesRangeSet> > NamedTypeInheritanceTable;
59
+
60
+ /** Named Types dependency table */
61
+ typedef std::map<Literal, std::set<Literal> > NamedTypeDependencyTable;
58
62
 
59
63
  /** A simple or actual value */
60
64
  struct Value {
@@ -65,6 +65,14 @@ namespace snowcrash {
65
65
  sourceMap));
66
66
  }
67
67
 
68
+ // Check circular references
69
+ if (out.node.typeSpecification.name.base == mson::UndefinedTypeName &&
70
+ !out.node.typeSpecification.name.symbol.literal.empty() &&
71
+ !out.node.typeSpecification.name.symbol.variable) {
72
+
73
+ mson::addDependency(node, pd, out.node.typeSpecification.name.symbol.literal, pd.namedTypeContext, out.report);
74
+ }
75
+
68
76
  return ++MarkdownNodeIterator(node);
69
77
  }
70
78
 
@@ -34,7 +34,7 @@ namespace snowcrash {
34
34
  const Signature& signature,
35
35
  const ParseResultRef<mson::NamedType>& out) {
36
36
 
37
- mson::parseTypeName(signature.identifier, out.node.name);
37
+ mson::parseTypeName(signature.identifier, out.node.name, false);
38
38
  mson::parseTypeDefinition(node, pd, signature.attributes, out.report, out.node.typeDefinition);
39
39
 
40
40
  if (pd.exportSourceMap()) {
@@ -53,6 +53,9 @@ namespace snowcrash {
53
53
  out.node.typeDefinition.baseType = mson::ImplicitObjectBaseType;
54
54
  }
55
55
 
56
+ // Setup named type context
57
+ pd.namedTypeContext = out.node.name.symbol.literal;
58
+
56
59
  return ++MarkdownNodeIterator(node);
57
60
  }
58
61
 
@@ -99,6 +102,14 @@ namespace snowcrash {
99
102
 
100
103
  return SectionProcessor<mson::ValueMember>::nestedSectionType(node);
101
104
  }
105
+
106
+ static void finalize(const MarkdownNodeIterator& node,
107
+ SectionParserData& pd,
108
+ const ParseResultRef<mson::NamedType>& out) {
109
+
110
+ // Clear named type context
111
+ pd.namedTypeContext.clear();
112
+ }
102
113
  };
103
114
 
104
115
  /** MSON Named Type Section Parser */
@@ -121,26 +121,28 @@ namespace mson {
121
121
  *
122
122
  * \param subject String which represents the type name
123
123
  * \param typeName MSON Type Name
124
+ * \param isBaseType If false, will be parsed as a symbol
124
125
  */
125
126
  inline void parseTypeName(const std::string& subject,
126
- TypeName& typeName) {
127
+ TypeName& typeName,
128
+ bool isBaseType = true) {
127
129
 
128
- if (subject == "boolean") {
130
+ if (isBaseType && subject == "boolean") {
129
131
  typeName.base = BooleanTypeName;
130
132
  }
131
- else if (subject == "string") {
133
+ else if (isBaseType && subject == "string") {
132
134
  typeName.base = StringTypeName;
133
135
  }
134
- else if (subject == "number") {
136
+ else if (isBaseType && subject == "number") {
135
137
  typeName.base = NumberTypeName;
136
138
  }
137
- else if (subject == "array") {
139
+ else if (isBaseType && subject == "array") {
138
140
  typeName.base = ArrayTypeName;
139
141
  }
140
- else if (subject == "enum") {
142
+ else if (isBaseType && subject == "enum") {
141
143
  typeName.base = EnumTypeName;
142
144
  }
143
- else if (subject == "object") {
145
+ else if (isBaseType && subject == "object") {
144
146
  typeName.base = ObjectTypeName;
145
147
  }
146
148
  else {
@@ -418,6 +420,66 @@ namespace mson {
418
420
  propertyName.literal = subject;
419
421
  }
420
422
  }
423
+
424
+ /**
425
+ * \brief Add a dependency to the dependency list of the dependents while checking for circular references
426
+ *
427
+ * \param node Current markdown node iterator
428
+ * \param pd Section parser data
429
+ * \param dependency The named type which should be added to the dependency list
430
+ * \param dependent The named type to which the dependency should be added
431
+ * \param report Parse result report
432
+ */
433
+ inline void addDependency(const mdp::MarkdownNodeIterator& node,
434
+ snowcrash::SectionParserData& pd,
435
+ const mson::Literal dependency,
436
+ const mson::Literal dependent,
437
+ snowcrash::Report& report) {
438
+
439
+ // First, check if the type exists
440
+ if (pd.namedTypeDependencyTable.find(dependency) == pd.namedTypeDependencyTable.end()) {
441
+
442
+ // ERR: We cannot find the dependency type
443
+ std::stringstream ss;
444
+ ss << "base type '" << dependency << "' is not defined in the document";
445
+
446
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
447
+ report.error = snowcrash::Error(ss.str(), snowcrash::MSONError, sourceMap);
448
+ return;
449
+ }
450
+
451
+ std::set<mson::Literal> dependencyDeps = pd.namedTypeDependencyTable[dependency];
452
+
453
+ // Second, check if it is circular reference between them
454
+ if (dependent == dependency ||
455
+ dependencyDeps.find(dependent) != dependencyDeps.end()) {
456
+
457
+ // ERR: Dependency named type circular references itself
458
+ std::stringstream ss;
459
+ ss << "base type '" << dependent << "' circularly referencing itself";
460
+
461
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
462
+ report.error = snowcrash::Error(ss.str(), snowcrash::MSONError, sourceMap);
463
+ return;
464
+ }
465
+
466
+ // Third, check if the dependency is already in the list
467
+ if (pd.namedTypeDependencyTable[dependent].find(dependency) != pd.namedTypeDependencyTable[dependent].end()) {
468
+ return;
469
+ }
470
+
471
+ for (mson::NamedTypeDependencyTable::iterator it = pd.namedTypeDependencyTable.begin();
472
+ it != pd.namedTypeDependencyTable.end();
473
+ ++it) {
474
+
475
+ // If the entry is dependent itself or contain dependent in its list
476
+ if (it->first == dependent || it->second.find(dependent) != it->second.end()) {
477
+
478
+ it->second.insert(dependency);
479
+ it->second.insert(dependencyDeps.begin(), dependencyDeps.end());
480
+ }
481
+ }
482
+ }
421
483
  }
422
484
 
423
485
  #endif
@@ -111,6 +111,29 @@ namespace snowcrash {
111
111
  mson::parseTypeDefinition(node, pd, signature.attributes, report, valueMember.valueDefinition.typeDefinition);
112
112
  parseRemainingContent(node, pd, signature.remainingContent, valueMember.sections, sourceMap.sections);
113
113
 
114
+ // Check for circular references
115
+ mson::TypeSpecification typeSpecification = valueMember.valueDefinition.typeDefinition.typeSpecification;
116
+
117
+ if (typeSpecification.name.base == mson::ArrayTypeName ||
118
+ typeSpecification.name.base == mson::EnumTypeName) {
119
+
120
+ for (mson::TypeNames::iterator it = typeSpecification.nestedTypes.begin();
121
+ it != typeSpecification.nestedTypes.end();
122
+ ++it) {
123
+
124
+ if (!it->symbol.literal.empty() && !it->symbol.variable) {
125
+ mson::addDependency(node, pd, it->symbol.literal, pd.namedTypeContext, report);
126
+ }
127
+ }
128
+ }
129
+ else if (typeSpecification.name.base == mson::UndefinedTypeName &&
130
+ !typeSpecification.name.symbol.literal.empty() &&
131
+ !typeSpecification.name.symbol.variable) {
132
+
133
+ mson::addDependency(node, pd, typeSpecification.name.symbol.literal, pd.namedTypeContext, report);
134
+ }
135
+
136
+ // Properly parse the values in the signature
114
137
  if (signature.values.size() > 1) {
115
138
 
116
139
  if (valueMember.valueDefinition.typeDefinition.baseType == mson::PrimitiveBaseType) {
@@ -255,7 +255,7 @@ namespace snowcrash {
255
255
  // ERR: unable to parse
256
256
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
257
257
  out.report.error = Error("unable to parse parameter specification",
258
- BusinessError,
258
+ ApplicationError,
259
259
  sourceMap);
260
260
  }
261
261
  }
@@ -470,7 +470,13 @@ namespace snowcrash {
470
470
  std::string first = innerSignature.substr(0, 1);
471
471
 
472
472
  if (first == "`") {
473
- RetrieveEscaped(innerSignature);
473
+ std::string escaped = RetrieveEscaped(innerSignature);
474
+
475
+ // If empty value is returned
476
+ if (escaped.empty()) {
477
+ innerSignature.clear();
478
+ }
479
+
474
480
  TrimString(innerSignature);
475
481
  }
476
482
  else if (first == "(") {
@@ -105,9 +105,17 @@ namespace snowcrash {
105
105
 
106
106
  case AttributesSectionType:
107
107
  {
108
+ // Set up named type context
109
+ if (!out.node.name.empty()) {
110
+ pd.namedTypeContext = out.node.name;
111
+ }
112
+
108
113
  ParseResultRef<Attributes> attributes(out.report, out.node.attributes, out.sourceMap.attributes);
109
114
  MarkdownNodeIterator cur = AttributesParser::parse(node, siblings, pd, attributes);
110
115
 
116
+ // Clear named type context
117
+ pd.namedTypeContext.clear();
118
+
111
119
  if (!out.node.name.empty()) {
112
120
 
113
121
  if (SectionProcessor<DataStructureGroup>::isNamedTypeDuplicate(pd.blueprint, out.node.name)) {
@@ -51,6 +51,12 @@ namespace snowcrash {
51
51
  /** Table mapping named type to sub types */
52
52
  mson::NamedTypeInheritanceTable namedTypeInheritanceTable;
53
53
 
54
+ /** Table mapping named types to their dependent named types */
55
+ mson::NamedTypeDependencyTable namedTypeDependencyTable;
56
+
57
+ /** Variable to store the current named type */
58
+ mson::Literal namedTypeContext;
59
+
54
60
  /** Model Table */
55
61
  ModelTable modelTable;
56
62
 
@@ -371,13 +371,15 @@ namespace scpl {
371
371
  * \param begin Character index representing the beginning of the bracket that needs to be matched
372
372
  * \param endBracket The type of bracket that needs to be matched
373
373
  * \param splitByAttribute If this is true, we need to return when we find a top-level attribute delimiter
374
+ * \param clearAtEnd If this is true, the string will be cleared at the end of parsing
374
375
  *
375
376
  * \return String inside the given brackets. If not splitting by comma, append the brackets too
376
377
  */
377
378
  static mdp::ByteBuffer matchBrackets(mdp::ByteBuffer& subject,
378
379
  size_t begin,
379
380
  const char endBracket,
380
- const bool splitByAttribute = false) {
381
+ const bool splitByAttribute = false,
382
+ const bool clearAtEnd = false) {
381
383
 
382
384
  size_t i = begin + 1;
383
385
  mdp::ByteBuffer returnString;
@@ -403,11 +405,11 @@ namespace scpl {
403
405
  }
404
406
  } else if (subject[i] == '[') {
405
407
 
406
- returnString += matchBrackets(subject, i, ']');
408
+ returnString += matchBrackets(subject, i, ']', false, true);
407
409
  i = 0;
408
410
  } else if (subject[i] == '(') {
409
411
 
410
- returnString += matchBrackets(subject, i, ')');
412
+ returnString += matchBrackets(subject, i, ')', false, true);
411
413
  i = 0;
412
414
  } else if (subject[i] == endBracket) {
413
415
 
@@ -431,6 +433,10 @@ namespace scpl {
431
433
  }
432
434
  }
433
435
 
436
+ if (i == subject.length() && clearAtEnd) {
437
+ subject.clear();
438
+ }
439
+
434
440
  return returnString;
435
441
  }
436
442
  };
@@ -101,7 +101,8 @@ namespace snowcrash {
101
101
  NoError = 0,
102
102
  ApplicationError = 1,
103
103
  BusinessError = 2,
104
- ModelError = 3
104
+ ModelError = 3,
105
+ MSONError = 4
105
106
  };
106
107
 
107
108
  /**
@@ -188,7 +188,7 @@ void URITemplateParser::parse(const URITemplate& uri, const mdp::CharactersRange
188
188
  }
189
189
  }
190
190
  else{
191
- result.report.error = Error("Failed to parse URI Template", URIWarning);
191
+ result.report.error = Error("Failed to parse URI Template", ApplicationError);
192
192
  }
193
193
 
194
194
  }
@@ -76,11 +76,11 @@ int snowcrash::parse(const mdp::ByteBuffer& source,
76
76
 
77
77
  std::stringstream ss;
78
78
  ss << "parser exception: '" << e.what() << "'";
79
- out.report.error = Error(ss.str(), 1);
79
+ out.report.error = Error(ss.str(), ApplicationError);
80
80
  }
81
81
  catch (...) {
82
82
 
83
- out.report.error = Error("parser exception has occured", 1);
83
+ out.report.error = Error("parser exception has occured", ApplicationError);
84
84
  }
85
85
 
86
86
  return out.report.error.code;
@@ -15,7 +15,7 @@
15
15
 
16
16
  #define DRAFTER_MAJOR_VERSION 0
17
17
  #define DRAFTER_MINOR_VERSION 1
18
- #define DRAFTER_PATCH_VERSION 0
18
+ #define DRAFTER_PATCH_VERSION 5
19
19
 
20
20
  #define DRAFTER_VERSION_IS_RELEASE 1
21
21
 
@@ -72,14 +72,14 @@ int main(int argc, const char *argv[])
72
72
  if (!config.validate) { // not just validate -> we will serialize
73
73
  sos::Serialize* serializer = CreateSerializer(config.format);
74
74
 
75
- Serialization(CreateStreamFromName<std::ostream>(config.output),
76
- drafter::WrapBlueprint(blueprint.node),
77
- serializer);
75
+ std::ostream *out = CreateStreamFromName<std::ostream>(config.output);
76
+ Serialization(out, drafter::WrapBlueprint(blueprint.node), serializer);
77
+ delete out;
78
78
 
79
79
  if (options & snowcrash::ExportSourcemapOption) {
80
- Serialization(CreateStreamFromName<std::ostream>(config.sourceMap),
81
- drafter::WrapBlueprintSourcemap(blueprint.sourceMap),
82
- serializer);
80
+ std::ostream *sourcemap = CreateStreamFromName<std::ostream>(config.sourceMap);
81
+ Serialization(sourcemap, drafter::WrapBlueprintSourcemap(blueprint.sourceMap), serializer);
82
+ delete sourcemap;
83
83
  }
84
84
 
85
85
  delete serializer;
@@ -2,7 +2,7 @@ require 'formula'
2
2
 
3
3
  class Drafter < Formula
4
4
  homepage 'http://apiblueprint.org'
5
- head 'https://github.com/apiaryio/drafter.git', :tag => 'v0.1.0'
5
+ head 'https://github.com/apiaryio/drafter.git', :tag => 'v0.1.5'
6
6
 
7
7
  def install
8
8
  system "./configure"
@@ -10,8 +10,8 @@ module RedSnow
10
10
  include Binding
11
11
 
12
12
  # Options
13
- EXPORT_SOURCEMAP_OPTION_KEY = :'exportSourcemap'
14
- REQUIRE_BLUEPRINT_NAME_OPTION_KEY = :'requireBlueprintName'
13
+ EXPORT_SOURCEMAP_OPTION_KEY = :exportSourcemap
14
+ REQUIRE_BLUEPRINT_NAME_OPTION_KEY = :requireBlueprintName
15
15
 
16
16
  # Parse options
17
17
  attr_accessor :options
@@ -80,7 +80,7 @@ module RedSnow
80
80
  end
81
81
 
82
82
  def get_item(key)
83
- @collection.select { |item| item[:name].downcase == key.downcase }.first
83
+ @collection.find { |item| item[:name].downcase == key.downcase }
84
84
  end
85
85
  end
86
86
 
@@ -1,5 +1,5 @@
1
1
  # Module RedSnow
2
2
  module RedSnow
3
3
  # Gem version
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -13,8 +13,8 @@ Gem::Specification.new do |gem|
13
13
  gem.homepage = 'https://github.com/apiaryio/redsnow'
14
14
  gem.license = 'MIT'
15
15
  gem.files = Dir['lib/**/*']
16
- gem.files << Dir['*']
17
- gem.files << Dir['ext/drafter/**/*'].reject { |f| f =~ /cmdline|test|features|README*|LICENSE|Gemfile*|\.xcode*/ }
16
+ gem.files << Dir['*']
17
+ gem.files << Dir['ext/drafter/**/*'].reject { |f| f =~ /cmdline|test|features|README*|LICENSE|Gemfile*|\.xcode*/ }
18
18
  gem.executables = gem.files.grep(/^bin/).map { |f| File.basename(f) }
19
19
  gem.test_files = gem.files.grep(/^(test|spec|features)/)
20
20
  gem.require_paths = %w(lib ext)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redsnow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ladislav Prskavec
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-30 00:00:00.000000000 Z
11
+ date: 2015-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -443,7 +443,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
443
443
  version: '0'
444
444
  requirements: []
445
445
  rubyforge_project:
446
- rubygems_version: 2.2.2
446
+ rubygems_version: 2.4.5
447
447
  signing_key:
448
448
  specification_version: 4
449
449
  summary: Ruby bindings for Snow Crash