From 31f1aebbdd7db4e86094ee635e858df6824653f1 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Tue, 8 Aug 2017 11:29:25 +0200 Subject: [PATCH 01/12] Refactoring allows reimplemt template specialization for different EnumElement processing Changes: * ElementData now uses string for Primitives and RefractElements (std::vector) for complex Element * Reimplement specialisation for conversion processing * Move checking of primitive types conversion * Simplify stored info about ElementData * Rename some function to better names --- src/ConversionContext.h | 6 +- src/RefractDataStructure.cc | 239 +++++++++++++++++++----------------- 2 files changed, 126 insertions(+), 119 deletions(-) diff --git a/src/ConversionContext.h b/src/ConversionContext.h index 5b6f8b387..04c3adbbc 100644 --- a/src/ConversionContext.h +++ b/src/ConversionContext.h @@ -24,10 +24,8 @@ namespace drafter const WrapperOptions& options; std::vector warnings; - inline refract::Registry& GetNamedTypesRegistry() - { - return registry; - } + inline refract::Registry& GetNamedTypesRegistry() { return registry; } + inline const refract::Registry& GetNamedTypesRegistry() const { return registry; } ConversionContext(const WrapperOptions& options) : options(options) { diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 22f23fe04..e2993f88e 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -26,15 +26,26 @@ namespace drafter struct ElementData { typedef T ElementType; - typedef typename T::ValueType ValueType; + typedef typename ElementType::ValueType ValueType; typedef snowcrash::SourceMap ValueSourceMapType; - typedef std::tuple - ValueInfo; // [value, sourceMap, validity(by LiteralTo<>)] + static const bool IsPrimitive = std::conditional< + std::is_same::value, // check for primitive values + std::false_type, std::true_type>::type::value; + + typedef typename std::conditional< + IsPrimitive, + std::string, + refract::RefractElements + >::type StoredType; + + typedef std::tuple ElementInfo; // [value, sourceMap] + + typedef std::vector ElementInfoContainer; - std::vector values; - std::vector defaults; - std::vector samples; + ElementInfoContainer values; + ElementInfoContainer defaults; + ElementInfoContainer samples; std::vector descriptions; std::vector > descriptionsSourceMap; @@ -63,7 +74,7 @@ namespace drafter typedef T ElementType; typedef V ValueType; ElementType*& element; - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; Append(ElementType*& e) : element(e) { @@ -84,9 +95,11 @@ namespace drafter } } - void operator()(const ValueInfo& value) + void operator()(const ElementInfo& value) { - const NodeInfo nodeInfo = MakeNodeInfo(std::get<0>(value), std::get<1>(value)); + std::pair result = LiteralTo(std::get<0>(value)); + + const NodeInfo nodeInfo = MakeNodeInfo(std::get<1>(result), std::get<1>(value)); (*this)(nodeInfo); } }; @@ -96,7 +109,7 @@ namespace drafter typedef T ElementType; typedef typename T::ValueType ValueType; ElementType*& element; - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; Append(ElementType*& e) : element(e) { @@ -109,7 +122,7 @@ namespace drafter std::bind(&ElementType::push_back, element, std::placeholders::_1)); } - void operator()(const ValueInfo& value) + void operator()(const ElementInfo& value) { const NodeInfo nodeInfo = MakeNodeInfo(std::get<0>(value), std::get<1>(value)); (*this)(nodeInfo); @@ -119,10 +132,9 @@ namespace drafter template struct CheckValueValidity { - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; - void operator()(const ValueInfo&, ConversionContext&) - { + void operator()(const ElementInfo&, ConversionContext&) { // do nothing } }; @@ -130,16 +142,15 @@ namespace drafter template struct CheckValueValidity { - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; + typedef typename refract::NumberElement::ValueType ValueType; - void operator()(const ValueInfo& value, ConversionContext& context) - { + void operator()(const ElementInfo& value, ConversionContext& context) { - if (!std::get<2>(value)) { - context.warn(snowcrash::Warning( - "invalid value format for 'number' type. please check mson specification for valid format", - snowcrash::MSONError, - std::get<1>(value).sourceMap)); + std::pair result = LiteralTo(std::get<0>(value)); + + if (!std::get<0>(result)) { + context.warn(snowcrash::Warning("invalid value format for 'number' type. please check mson specification for valid format", snowcrash::MSONError, std::get<1>(value).sourceMap)); } } }; @@ -147,15 +158,14 @@ namespace drafter template struct CheckValueValidity { - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; + typedef typename refract::BooleanElement::ValueType ValueType; - void operator()(const ValueInfo& value, ConversionContext& context) - { - if (!std::get<2>(value)) { - context.warn( - snowcrash::Warning("invalid value for 'boolean' type. allowed values are 'true' or 'false'", - snowcrash::MSONError, - std::get<1>(value).sourceMap)); + void operator()(const ElementInfo& value, ConversionContext& context) { + std::pair result = LiteralTo(std::get<0>(value)); + + if (!std::get<0>(result)) { + context.warn(snowcrash::Warning("invalid value for 'boolean' type. allowed values are 'true' or 'false'", snowcrash::MSONError, std::get<1>(value).sourceMap)); } } }; @@ -283,7 +293,7 @@ namespace drafter class ExtractTypeSection { typedef typename T::ValueType ValueType; - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; ElementData& data; ConversionContext& context; @@ -299,34 +309,22 @@ namespace drafter */ template struct Fetch { - ValueInfo operator()(const NodeInfo& typeSection, - ConversionContext& context, - const mson::BaseTypeName& defaultNestedType) - { + ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { - std::pair val = LiteralTo(typeSection.node->content.value); snowcrash::SourceMap sourceMap = FetchSourceMap()(typeSection); - - ValueInfo result = std::make_tuple(val.second, sourceMap, val.first); - - CheckValueValidity()(result, context); - - return result; + return std::make_tuple(typeSection.node->content.value, sourceMap); } }; template struct Fetch { - ValueInfo operator()(const NodeInfo& typeSection, - ConversionContext& context, - const mson::BaseTypeName& defaultNestedType) - { + ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { return std::make_tuple(MsonElementsToRefract(MakeNodeInfo(typeSection.node->content.elements(), - typeSection.sourceMap->elements()), - context, - defaultNestedType), - FetchSourceMap()(typeSection), - true); + typeSection.sourceMap->elements()), + context, + defaultNestedType), + FetchSourceMap()(typeSection) + ); } }; @@ -426,13 +424,13 @@ namespace drafter case refract::TypeQueryVisitor::Ref: case refract::TypeQueryVisitor::Extend: case refract::TypeQueryVisitor::Option: - case refract::TypeQueryVisitor::Select:; + case refract::TypeQueryVisitor::Select: + ; }; return mson::UndefinedTypeName; } - static mson::BaseTypeName GetMsonTypeFromName(const std::string& name, ConversionContext& context) - { + static mson::BaseTypeName GetMsonTypeFromName(const std::string& name, const ConversionContext& context) { refract::IElement* e = FindRootAncestor(name, context.GetNamedTypesRegistry()); if (!e) { return mson::UndefinedTypeName; @@ -447,24 +445,23 @@ namespace drafter struct ExtractTypeDefinition { typedef T ElementType; - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfoContainer ElementInfoContainer; ElementData& data; - ConversionContext& context; + const ConversionContext& context; - template - struct Fetch { - ValueInfo operator()(const mson::TypeNames&, ConversionContext&) - { - typename T::ValueType val; - return std::make_tuple(val, *NodeInfo::NullSourceMap(), false); + template ::IsPrimitive> struct Fetch; + + template + struct Fetch { + void operator()(const mson::TypeNames&, const ConversionContext&, ElementInfoContainer&) { + // do nothing } }; - template - struct Fetch { - ValueInfo operator()(const mson::TypeNames& typeNames, ConversionContext& context) - { + template + struct Fetch { + void operator()(const mson::TypeNames& typeNames, const ConversionContext& context, ElementInfoContainer& values) { RefractElements types; for (mson::TypeNames::const_iterator it = typeNames.begin(); it != typeNames.end(); ++it) { @@ -480,29 +477,21 @@ namespace drafter types.push_back(f.Create(it->symbol.literal, method)); } - return std::make_tuple(types, *NodeInfo::NullSourceMap(), true); + values.push_back(std::make_tuple(types, *NodeInfo::NullSourceMap())); } }; - ExtractTypeDefinition(ElementData& data, ConversionContext& context) : data(data), context(context) - { - } - - void operator()(const NodeInfo& typeDefinition) - { - ValueInfo value - = Fetch()(typeDefinition.node->typeSpecification.nestedTypes, context); + ExtractTypeDefinition(ElementData& data, const ConversionContext& context) : data(data), context(context) {} - if (std::get<2>(value)) { - data.values.push_back(value); - } + void operator()(const NodeInfo& typeDefinition) { + Fetch()(typeDefinition.node->typeSpecification.nestedTypes, context, data.values); } }; template struct ExtractValueMember { typedef T ElementType; - typedef typename ElementData::ValueInfo ValueInfo; + typedef typename ElementData::ElementInfo ElementInfo; ElementData& data; ConversionContext& context; @@ -510,8 +499,7 @@ namespace drafter template struct Fetch { // primitive values - ValueInfo operator()(const NodeInfo& valueMember, ConversionContext& context) - { + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { if (valueMember.node->valueDefinition.values.size() > 1) { throw snowcrash::Error("only one value is supported for primitive types", snowcrash::MSONError, @@ -519,23 +507,17 @@ namespace drafter } const mson::Value& value = *valueMember.node->valueDefinition.values.begin(); - - std::pair val = LiteralTo(value.literal); snowcrash::SourceMap sourceMap = FetchSourceMap()(valueMember); - ValueInfo result = std::make_tuple(val.second, sourceMap, val.first); - - CheckValueValidity()(result, context); + return std::make_tuple(value.literal, sourceMap); - return result; } }; template struct Fetch { // Array|Object - ValueInfo operator()(const NodeInfo& valueMember, ConversionContext& context) - { + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { const mson::BaseTypeName type = SelectNestedTypeSpecification( valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); @@ -549,7 +531,7 @@ namespace drafter elements.push_back(f.Create(it->literal, it->variable ? eSample : eValue)); } - return std::make_tuple(elements, FetchSourceMap()(valueMember), true); + return std::make_tuple(elements, FetchSourceMap()(valueMember)); } }; @@ -593,7 +575,7 @@ namespace drafter if (!valueMember.node->valueDefinition.values.empty()) { const mson::Value& value = *valueMember.node->valueDefinition.values.begin(); - ValueInfo parsed = fetch(valueMember, context); + ElementInfo parsed = fetch(valueMember, context); if (attrs & mson::DefaultTypeAttribute) { data.defaults.push_back(parsed); @@ -655,6 +637,29 @@ namespace drafter } }; + template ::IsPrimitive> struct ElementInfoToElement; + + template + struct ElementInfoToElement { + E* operator()(const typename ElementData::ElementInfo& value) { + std::pair result = LiteralTo(std::get<0>(value)); + return new E(std::get<1>(result)); + } + }; + + template + struct ElementInfoToElement { + E* operator()(const typename ElementData::ElementInfo& value) { + return new E(std::get<0>(value)); + } + }; + + //template <> + //struct ElementInfoToElement::IsPrimitive> { + // refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { + // } + //}; + template struct SaveSamples { @@ -667,10 +672,10 @@ namespace drafter refract::ArrayElement* a = new refract::ArrayElement; + ElementInfoToElement fetch; + for (auto sample : samples) { - T* sampleElement = new T; - sampleElement->set(std::get<0>(sample)); - a->push_back(sampleElement); + a->push_back(fetch(sample)); } element->attributes[SerializeKey::Samples] = a; @@ -687,8 +692,9 @@ namespace drafter return; } - T* defaultElement = new T; - defaultElement->set(std::get<0>(*defaults.rbegin())); + ElementInfoToElement fetch; + T* defaultElement = fetch(*defaults.rbegin()); + element->attributes[SerializeKey::Default] = defaultElement; } }; @@ -701,9 +707,14 @@ namespace drafter } }; - template - void TransformElementData(T* element, ElementData& data) - { + template + void ElementDataToElement(T* element, const ElementData& data, ConversionContext& context) { + + for (auto collection : { data.values, data.samples, data.defaults } ) { + std::for_each(collection.begin(), collection.end(), + std::bind(CheckValueValidity(),std::placeholders::_1, std::ref(context))); + } + std::for_each(data.values.begin(), data.values.end(), Append(element)); SaveSamples()(data.samples, element); SaveDefault()(data.defaults, element); @@ -784,7 +795,7 @@ namespace drafter MoveFirstValueToSample()(value, data); } - TransformElementData(element, data); + ElementDataToElement(element, data, context); return element; } @@ -865,8 +876,7 @@ namespace drafter } std::string description; - std::string& descriptionRef = description; - Join join(descriptionRef); + Join join(std::ref(description)); snowcrash::SourceMap sourceMap; refract::IElement::MemberElementCollection::iterator iterator = value->meta.find(SerializeKey::Description); @@ -876,7 +886,7 @@ namespace drafter // // NOTE: potentionaly unsafe, but we set it already to StringElement // most safe is check it via refract::TypeQueryVisitor - descriptionRef = (static_cast((*iterator)->value.second)->value); + description = (static_cast((*iterator)->value.second)->value); element->meta.push_back(*iterator); value->meta.erase(iterator); // FIXME: extract source map @@ -886,23 +896,22 @@ namespace drafter } bool addNewLine = false; - if (!descriptionRef.empty()) { + if (!description.empty()) { addNewLine = true; } NodeInfoCollection typeSections(MAKE_NODE_INFO(property, sections)); - for (NodeInfoCollection::const_iterator it = typeSections.begin(); it != typeSections.end(); - ++it) { - if (it->node->klass == mson::TypeSection::BlockDescriptionClass) { - if (addNewLine) { - descriptionRef.append("\n"); - addNewLine = false; - } + for (NodeInfoCollection::const_iterator it = typeSections.begin(); it != typeSections.end(); ++it) { + if (it->node->klass == mson::TypeSection::BlockDescriptionClass) { + if (addNewLine) { + description.append("\n"); + addNewLine = false; + } - join(it->node->content.description); - sourceMap.sourceMap.append(it->sourceMap->description.sourceMap); - } + join(it->node->content.description); + sourceMap.sourceMap.append(it->sourceMap->description.sourceMap); + } } if (!description.empty()) { @@ -1143,7 +1152,7 @@ namespace drafter std::for_each(typeSections.begin(), typeSections.end(), ExtractTypeSection(data, context, ds)); - TransformElementData(element, data); + ElementDataToElement(element, data, context); if (refract::IElement* description = DescriptionToRefract(data)) { element->meta[SerializeKey::Description] = description; From 6ac31578ba4b805a17fdd1530a63dc069d4efc16 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Fri, 11 Aug 2017 15:17:42 +0200 Subject: [PATCH 02/12] Introduce Enumeration specialization Changes: * Remove AppendDecorator file * Remove Append * ElementData<> - moved to own header file * ElementData<>::description - joined with map * refactoring on description processing flow --- drafter.gyp | 2 +- drafter.xcodeproj/project.pbxproj | 4 - src/ElementData.h | 56 ++ src/RefractDataStructure.cc | 772 ++++++++++-------- src/RefractElementFactory.cc | 60 +- src/Serialize.cc | 1 + src/Serialize.h | 1 + src/refract/AppendDecorator.h | 58 -- .../api/data-structure.sourcemap.json | 25 + test/fixtures/api/mson.sourcemap.json | 113 +++ 10 files changed, 642 insertions(+), 450 deletions(-) create mode 100644 src/ElementData.h delete mode 100644 src/refract/AppendDecorator.h diff --git a/drafter.gyp b/drafter.gyp index 2903e021e..6c4ada72c 100644 --- a/drafter.gyp +++ b/drafter.gyp @@ -313,7 +313,6 @@ "src/refract/Build.h", - "src/refract/AppendDecorator.h", "src/refract/ElementInserter.h", "src/refract/Query.h", "src/refract/Query.cc", @@ -348,6 +347,7 @@ "test/test-ElementFactoryTest.cc", "test/test-OneOfTest.cc", "test/test-SyntaxIssuesTest.cc", + "test/test-ElementDataTest.cc", ], 'dependencies': [ "libdrafter", diff --git a/drafter.xcodeproj/project.pbxproj b/drafter.xcodeproj/project.pbxproj index 6061e867f..9672afe25 100644 --- a/drafter.xcodeproj/project.pbxproj +++ b/drafter.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 19A1298F1B70ABE100366AA7 /* SerializeResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A129791B70ABE100366AA7 /* SerializeResult.h */; }; 19A129921B70ABE100366AA7 /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A1297C1B70ABE100366AA7 /* stream.h */; }; 19A129931B70ABE100366AA7 /* Version.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A1297D1B70ABE100366AA7 /* Version.h */; }; - 19A129AF1B70AC9A00366AA7 /* AppendDecorator.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A129971B70AC9A00366AA7 /* AppendDecorator.h */; }; 19A129B01B70AC9A00366AA7 /* ComparableVisitor.cc in Sources */ = {isa = PBXBuildFile; fileRef = 19A129981B70AC9A00366AA7 /* ComparableVisitor.cc */; }; 19A129B11B70AC9A00366AA7 /* ComparableVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A129991B70AC9A00366AA7 /* ComparableVisitor.h */; }; 19A129B21B70AC9A00366AA7 /* Element.cc in Sources */ = {isa = PBXBuildFile; fileRef = 19A1299A1B70AC9A00366AA7 /* Element.cc */; }; @@ -141,7 +140,6 @@ 19A129791B70ABE100366AA7 /* SerializeResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SerializeResult.h; path = src/SerializeResult.h; sourceTree = SOURCE_ROOT; }; 19A1297C1B70ABE100366AA7 /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stream.h; path = src/stream.h; sourceTree = SOURCE_ROOT; }; 19A1297D1B70ABE100366AA7 /* Version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Version.h; path = src/Version.h; sourceTree = SOURCE_ROOT; }; - 19A129971B70AC9A00366AA7 /* AppendDecorator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppendDecorator.h; path = src/refract/AppendDecorator.h; sourceTree = SOURCE_ROOT; }; 19A129981B70AC9A00366AA7 /* ComparableVisitor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ComparableVisitor.cc; path = src/refract/ComparableVisitor.cc; sourceTree = SOURCE_ROOT; }; 19A129991B70AC9A00366AA7 /* ComparableVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComparableVisitor.h; path = src/refract/ComparableVisitor.h; sourceTree = SOURCE_ROOT; }; 19A1299A1B70AC9A00366AA7 /* Element.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Element.cc; path = src/refract/Element.cc; sourceTree = SOURCE_ROOT; }; @@ -291,7 +289,6 @@ 19A129961B70AC7B00366AA7 /* refract */ = { isa = PBXGroup; children = ( - 19A129971B70AC9A00366AA7 /* AppendDecorator.h */, 400F53F61C5989F1004EA235 /* Build.h */, 19A129981B70AC9A00366AA7 /* ComparableVisitor.cc */, 19A129991B70AC9A00366AA7 /* ComparableVisitor.h */, @@ -424,7 +421,6 @@ 400F53FD1C5989F1004EA235 /* Build.h in Headers */, 40D03D4F1C182FBD008AD2EF /* VisitorUtils.h in Headers */, 19A129B81B70AC9A00366AA7 /* IsExpandableVisitor.h in Headers */, - 19A129AF1B70AC9A00366AA7 /* AppendDecorator.h in Headers */, 40DDBDD81BE14EA700B10819 /* RefractSourceMap.h in Headers */, 19A129931B70ABE100366AA7 /* Version.h in Headers */, 19A129921B70ABE100366AA7 /* stream.h in Headers */, diff --git a/src/ElementData.h b/src/ElementData.h new file mode 100644 index 000000000..5c8356526 --- /dev/null +++ b/src/ElementData.h @@ -0,0 +1,56 @@ +// +// ElementData.h +// drafter +// +// Created by Jiri Kratochvil on 08/08/17. +// Copyright (c) 2017 Apiary Inc. All rights reserved. +// +#ifndef DRAFTER_ELEMENTDATA_H +#define DRAFTER_ELEMENTDATA_H + +#include "RefractSourceMap.h" + +namespace drafter { + + template + struct ElementData { + typedef T ElementType; + + typedef typename ElementType::ValueType ValueType; + typedef snowcrash::SourceMap ValueSourceMapType; + + static const bool IsPrimitive = std::conditional< + std::is_same::value || std::is_same::value, // check for primitive values + std::false_type, std::true_type>::type::value; + + // This is required because snowcrash internal stuctures holds data + // for primitive types as "string" for complex types as "element array" + // it will be converted into apropriated element typer once all required data are colected + + typedef typename std::conditional< + IsPrimitive, + std::string, // for primitive values, we will hold data as string + refract::RefractElements // for complex types, we will hold elements + >::type StoredType; + + typedef std::tuple ElementInfo; // [value, sourceMap] + typedef std::tuple > DescriptionInfo; // [description, sourceMap] + + typedef std::vector ElementInfoContainer; + typedef std::vector DescriptionInfoContainer; + + ElementInfoContainer values; + ElementInfoContainer defaults; + ElementInfoContainer samples; + ElementInfoContainer enumerations; + + DescriptionInfoContainer descriptions; + + //std::vector descriptions; + //std::vector > descriptionsSourceMap; + }; + +} // namespace drafter + +#endif // #ifndef DRAFTER_ELEMENTDATA_H + diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index e2993f88e..5b9ec3d8b 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -8,7 +8,6 @@ #include "SourceAnnotation.h" #include "RefractDataStructure.h" -#include "refract/AppendDecorator.h" #include "RefractSourceMap.h" #include "refract/VisitorUtils.h" @@ -19,116 +18,30 @@ #include "RefractElementFactory.h" #include "ConversionContext.h" -namespace drafter -{ +#include "ElementData.h" - template - struct ElementData { - typedef T ElementType; - - typedef typename ElementType::ValueType ValueType; - typedef snowcrash::SourceMap ValueSourceMapType; - - static const bool IsPrimitive = std::conditional< - std::is_same::value, // check for primitive values - std::false_type, std::true_type>::type::value; +#include - typedef typename std::conditional< - IsPrimitive, - std::string, - refract::RefractElements - >::type StoredType; +//#define ENUM_REIMPL 1 - typedef std::tuple ElementInfo; // [value, sourceMap] - - typedef std::vector ElementInfoContainer; - - ElementInfoContainer values; - ElementInfoContainer defaults; - ElementInfoContainer samples; - - std::vector descriptions; - std::vector > descriptionsSourceMap; - }; +namespace drafter { template struct FetchSourceMap { - snowcrash::SourceMap operator()(const NodeInfo& valueMember) - { + snowcrash::SourceMap operator()(const NodeInfo& valueMember) { snowcrash::SourceMap sourceMap = *NodeInfo::NullSourceMap(); sourceMap.sourceMap = valueMember.sourceMap->valueDefinition.sourceMap; return sourceMap; } - snowcrash::SourceMap operator()(const NodeInfo& typeSection) - { + snowcrash::SourceMap operator()(const NodeInfo& typeSection) { snowcrash::SourceMap sourceMap = *NodeInfo::NullSourceMap(); sourceMap.sourceMap = typeSection.sourceMap->value.sourceMap; return sourceMap; } }; - template - struct Append { - typedef T ElementType; - typedef V ValueType; - ElementType*& element; - typedef typename ElementData::ElementInfo ElementInfo; - - Append(ElementType*& e) : element(e) - { - } - - void operator()(const NodeInfo& value) - { - // FIXME: snowcrash warn about "Primitive type can not have member" - // but in real it create "empty" member - // - // solution for now: set if element has no already value, otherwise silently ignore - // - // throw snowcrash::Error("can not append to primitive type", snowcrash::MSONError); - - if (element->empty()) { - element->set(*value.node); - AttachSourceMap(element, value); - } - } - - void operator()(const ElementInfo& value) - { - std::pair result = LiteralTo(std::get<0>(value)); - - const NodeInfo nodeInfo = MakeNodeInfo(std::get<1>(result), std::get<1>(value)); - (*this)(nodeInfo); - } - }; - - template - struct Append > { - typedef T ElementType; - typedef typename T::ValueType ValueType; - ElementType*& element; - typedef typename ElementData::ElementInfo ElementInfo; - - Append(ElementType*& e) : element(e) - { - } - - void operator()(const NodeInfo& value) - { - std::for_each(value.node->begin(), - value.node->end(), - std::bind(&ElementType::push_back, element, std::placeholders::_1)); - } - - void operator()(const ElementInfo& value) - { - const NodeInfo nodeInfo = MakeNodeInfo(std::get<0>(value), std::get<1>(value)); - (*this)(nodeInfo); - } - }; - template struct CheckValueValidity { @@ -179,8 +92,7 @@ namespace drafter } } - static mson::BaseTypeName NamedTypeFromElement(const refract::IElement* element) - { + static mson::BaseTypeName NamedTypeFromElement(const refract::IElement* element) { refract::TypeQueryVisitor type; refract::Visit(type, *element); @@ -210,9 +122,8 @@ namespace drafter return mson::UndefinedTypeName; } - template - static mson::BaseTypeName GetType(const T& type, ConversionContext& context) - { + template + static mson::BaseTypeName GetType(const T& type, ConversionContext& context) { mson::BaseTypeName nameType = type.typeDefinition.typeSpecification.name.base; const std::string& parent = type.typeDefinition.typeSpecification.name.symbol.literal; @@ -258,28 +169,21 @@ namespace drafter return attr; } - static refract::IElement* MsonElementToRefract(const NodeInfo& mse, - ConversionContext& context, - mson::BaseTypeName defaultNestedType = mson::StringTypeName); + static refract::IElement* MsonElementToRefract(const NodeInfo& mse, ConversionContext& context, mson::BaseTypeName defaultNestedType = mson::StringTypeName); - RefractElements MsonElementsToRefract(const NodeInfo& elements, - ConversionContext& context, - mson::BaseTypeName defaultNestedType = mson::StringTypeName) + RefractElements MsonElementsToRefract(const NodeInfo& elements, ConversionContext& context, mson::BaseTypeName defaultNestedType = mson::StringTypeName) { RefractElements result; NodeInfoCollection elementsNodeInfo(elements); - std::transform(elementsNodeInfo.begin(), - elementsNodeInfo.end(), - std::back_inserter(result), - std::bind(MsonElementToRefract, std::placeholders::_1, std::ref(context), defaultNestedType)); + std::transform(elementsNodeInfo.begin(), elementsNodeInfo.end(), + std::back_inserter(result), + std::bind(MsonElementToRefract, std::placeholders::_1, std::ref(context), defaultNestedType)); return result; } - static mson::BaseTypeName SelectNestedTypeSpecification( - const mson::TypeNames& nestedTypes, const mson::BaseTypeName defaultNestedType = mson::StringTypeName) - { + static mson::BaseTypeName SelectNestedTypeSpecification(const mson::TypeNames& nestedTypes, const mson::BaseTypeName defaultNestedType = mson::StringTypeName) { mson::BaseTypeName type = defaultNestedType; // Found if type of element is specified. // if more types is used - fallback to "StringType" @@ -289,11 +193,20 @@ namespace drafter return type; } + /** + * Extract mson definitions like + * - value + * - ts1 + * - ts2 + */ + template class ExtractTypeSection { - typedef typename T::ValueType ValueType; - typedef typename ElementData::ElementInfo ElementInfo; + using ElementType = T; + using ValueType = typename T::ValueType; + using ElementInfo = typename ElementData::ElementInfo; + ElementData& data; ConversionContext& context; @@ -301,77 +214,95 @@ namespace drafter mson::BaseTypeName elementTypeName; mson::BaseTypeName defaultNestedType; - /** - * Fetch<> is intended to extract value from TypeSection. - * Generalized type is for primitive types - * Specialized is for (Array|Object)Element because of underlying type. - * `dummy` param is used because of specialization inside another struct - */ - template - struct Fetch { + template ::IsPrimitive> struct Fetch; + + template + struct Fetch { ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { - snowcrash::SourceMap sourceMap = FetchSourceMap()(typeSection); + snowcrash::SourceMap sourceMap = FetchSourceMap()(typeSection); return std::make_tuple(typeSection.node->content.value, sourceMap); } }; - template - struct Fetch { + template + struct Fetch { ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { return std::make_tuple(MsonElementsToRefract(MakeNodeInfo(typeSection.node->content.elements(), typeSection.sourceMap->elements()), context, defaultNestedType), - FetchSourceMap()(typeSection) + FetchSourceMap()(typeSection) ); } }; + template ::IsPrimitive, bool dummy = true> struct Store; + + template + struct Store { + void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + // do nothing + + // Primitives should not contain members + // this is to avoid push "empty" elements to primitives + // it is related to test/fixtures/mson/primitive-with-members.apib + + } + }; + + template + struct Store { + void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + + data.values.push_back(Fetch()(typeSection, context, defaultNestedType)); + } + }; + +#ifdef ENUM_REIMPL + template + struct Store::IsPrimitive, dummy> { + void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + + data.enumerations.push_back(Fetch()(typeSection, context, defaultNestedType)); + } + }; +#endif + template struct TypeDefinition; - template + template struct TypeDefinition { - const mson::TypeDefinition& operator()(const snowcrash::DataStructure& dataStructure) - { + const mson::TypeDefinition& operator()(const snowcrash::DataStructure& dataStructure) { return dataStructure.typeDefinition; } }; - template + template struct TypeDefinition { - const mson::TypeDefinition& operator()(const mson::ValueMember& valueMember) - { + const mson::TypeDefinition& operator()(const mson::ValueMember& valueMember) { return valueMember.valueDefinition.typeDefinition; } }; public: - template + + template ExtractTypeSection(ElementData& data, ConversionContext& context, const NodeInfo& sectionHolder) - : data(data) - , context(context) - , elementTypeName(TypeDefinition()(*sectionHolder.node).typeSpecification.name.base) - , defaultNestedType( - SelectNestedTypeSpecification(TypeDefinition()(*sectionHolder.node).typeSpecification.nestedTypes)) - { - } + : data(data), + context(context), + elementTypeName(TypeDefinition()(*sectionHolder.node).typeSpecification.name.base), + defaultNestedType(SelectNestedTypeSpecification(TypeDefinition()(*sectionHolder.node).typeSpecification.nestedTypes)) + {} - void operator()(const NodeInfo& typeSection) - { - Fetch fetch; + void operator()(const NodeInfo& typeSection) { + Fetch fetch; switch (typeSection.node->klass) { - case mson::TypeSection::MemberTypeClass: - // Primitives should not contain members - // this is to avoid push "empty" elements to primitives - // it is related to test/fixtures/mson/primitive-with-members.apib - if (!typeSection.node->content.elements().empty()) { - data.values.push_back(fetch(typeSection, context, defaultNestedType)); - } + Store()(data, typeSection, context, defaultNestedType); break; case mson::TypeSection::SampleClass: @@ -383,8 +314,14 @@ namespace drafter break; case mson::TypeSection::BlockDescriptionClass: - data.descriptions.push_back(typeSection.node->content.description); - data.descriptionsSourceMap.push_back(typeSection.sourceMap->description); + //data.descriptions.push_back(typeSection.node->content.description); + //data.descriptionsSourceMap.push_back(typeSection.sourceMap->description); + + data.descriptions.push_back( + std::make_tuple( + typeSection.node->content.description, + typeSection.sourceMap->description + )); break; default: @@ -397,8 +334,7 @@ namespace drafter } }; - static mson::BaseTypeName RefractElementTypeToMsonType(refract::TypeQueryVisitor::ElementType type) - { + static mson::BaseTypeName RefractElementTypeToMsonType(refract::TypeQueryVisitor::ElementType type) { switch (type) { case refract::TypeQueryVisitor::String: return mson::StringTypeName; @@ -441,27 +377,25 @@ namespace drafter return RefractElementTypeToMsonType(query.get()); } + /** + * Extract mson definitions like + * - value enum[td1, td2] + */ + template struct ExtractTypeDefinition { - typedef T ElementType; - typedef typename ElementData::ElementInfoContainer ElementInfoContainer; + using ElementType = T; + using ElementInfo = typename ElementData::ElementInfo; ElementData& data; const ConversionContext& context; template ::IsPrimitive> struct Fetch; - template - struct Fetch { - void operator()(const mson::TypeNames&, const ConversionContext&, ElementInfoContainer&) { - // do nothing - } - }; - template struct Fetch { - void operator()(const mson::TypeNames& typeNames, const ConversionContext& context, ElementInfoContainer& values) { + ElementInfo operator()(const mson::TypeNames& typeNames, const ConversionContext& context) { RefractElements types; for (mson::TypeNames::const_iterator it = typeNames.begin(); it != typeNames.end(); ++it) { @@ -471,56 +405,87 @@ namespace drafter if (typeName == mson::UndefinedTypeName && !it->symbol.literal.empty()) { typeName = GetMsonTypeFromName(it->symbol.literal, context); method = it->symbol.variable ? eSample : eElement; - } + } const RefractElementFactory& f = FactoryFromType(typeName); types.push_back(f.Create(it->symbol.literal, method)); } - values.push_back(std::make_tuple(types, *NodeInfo::NullSourceMap())); + return std::make_tuple(types, *NodeInfo::NullSourceMap()); + } + }; + + + template ::IsPrimitive, bool dummy = true> struct Store; + + template + struct Store { + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + // do nothing + } + }; + + template + struct Store { + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + data.values.push_back(Fetch()(typeNames, context)); + } + }; + +#ifdef ENUM_REIMPL + template + struct Store::IsPrimitive, dummy> { + using E = refract::EnumElement; + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + data.enumerations.push_back(Fetch()(typeNames, context)); } }; +#endif ExtractTypeDefinition(ElementData& data, const ConversionContext& context) : data(data), context(context) {} void operator()(const NodeInfo& typeDefinition) { - Fetch()(typeDefinition.node->typeSpecification.nestedTypes, context, data.values); + Store()(data, typeDefinition.node->typeSpecification.nestedTypes, context); } }; + /** + * Extract mson definitions like + * - value: vm1, vm2 + */ template - struct ExtractValueMember { - typedef T ElementType; - typedef typename ElementData::ElementInfo ElementInfo; + struct ExtractValueMember + { + using ElementType = T; + using ElementInfo = typename ElementData::ElementInfo; ElementData& data; ConversionContext& context; - template - struct Fetch { // primitive values + template ::IsPrimitive> struct Fetch; + + template + struct Fetch { // primitive values ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { if (valueMember.node->valueDefinition.values.size() > 1) { - throw snowcrash::Error("only one value is supported for primitive types", - snowcrash::MSONError, - valueMember.sourceMap->sourceMap); + throw snowcrash::Error("only one value is supported for primitive types", snowcrash::MSONError, valueMember.sourceMap->sourceMap); } const mson::Value& value = *valueMember.node->valueDefinition.values.begin(); - snowcrash::SourceMap sourceMap = FetchSourceMap()(valueMember); + snowcrash::SourceMap sourceMap = FetchSourceMap()(valueMember); return std::make_tuple(value.literal, sourceMap); } }; - template - struct Fetch { // Array|Object + template + struct Fetch { // Array|Object ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { - const mson::BaseTypeName type = SelectNestedTypeSpecification( - valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); + const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); const RefractElementFactory& f = FactoryFromType(type); const mson::Values& values = valueMember.node->valueDefinition.values; @@ -531,45 +496,62 @@ namespace drafter elements.push_back(f.Create(it->literal, it->variable ? eSample : eValue)); } - return std::make_tuple(elements, FetchSourceMap()(valueMember)); + return std::make_tuple(elements, FetchSourceMap()(valueMember)); } }; - template + template struct IsValueVariable { - bool operator()(const mson::Value& value) - { + bool operator()(const mson::Value& value) { return value.variable; } }; - template - struct IsValueVariable { + template + struct IsValueVariable{ - bool operator()(const mson::Value&) - { + bool operator()(const mson::Value&) { return false; } }; - ExtractValueMember(ElementData& data, ConversionContext& context, const mson::BaseTypeName) - : data(data), context(context) - { - } + template + struct Store { + void operator()(ElementData&data, const ElementInfo& info) { + data.values.push_back(info); + } + }; - void operator()(const NodeInfo& valueMember) +#ifdef ENUM_REIMPL + template + struct Store { + void operator()(ElementData&data, const ElementInfo& info) { + if (std::get<0>(info).size() == 1) { + data.values.push_back(info); + } + else { + data.enumerations.push_back(info); + } + } + }; +#endif + + + ExtractValueMember(ElementData& data, ConversionContext& context, const mson::BaseTypeName) : data(data), context(context) {} + + void operator ()(const NodeInfo& valueMember) { // silently ignore "value" for ObjectElement e.g. // # A (array) // - key (object) // warning is attached while creating ValueMember in snowcrash - if (valueMember.node->valueDefinition.typeDefinition.baseType == mson::ImplicitObjectBaseType - || valueMember.node->valueDefinition.typeDefinition.baseType == mson::ObjectBaseType) { + if (valueMember.node->valueDefinition.typeDefinition.baseType == mson::ImplicitObjectBaseType || + valueMember.node->valueDefinition.typeDefinition.baseType == mson::ObjectBaseType) { return; } - Fetch fetch; + Fetch fetch; mson::TypeAttributes attrs = valueMember.node->valueDefinition.typeDefinition.attributes; if (!valueMember.node->valueDefinition.values.empty()) { @@ -579,29 +561,49 @@ namespace drafter if (attrs & mson::DefaultTypeAttribute) { data.defaults.push_back(parsed); - } else if ((attrs & mson::SampleTypeAttribute) || IsValueVariable()(value)) { + } + else if ((attrs & mson::SampleTypeAttribute) || IsValueVariable()(value)) { data.samples.push_back(parsed); - } else { - data.values.push_back(parsed); } - } else { + else { + Store()(data, parsed); + } + } + else { if (attrs & mson::DefaultTypeAttribute) { - context.warn(snowcrash::Warning("no value present when 'default' is specified")); + context.warn(snowcrash::Warning("no value present when 'default' is specified" +#ifdef ENUM_REIMPL + ,snowcrash::MSONError, valueMember.sourceMap->sourceMap +#endif + )); } + if (attrs & mson::SampleTypeAttribute) { - context.warn(snowcrash::Warning("no value present when 'sample' is specified")); + context.warn(snowcrash::Warning("no value present when 'sample' is specified" +#ifdef ENUM_REIMPL + ,snowcrash::MSONError, valueMember.sourceMap->sourceMap +#endif + )); } } if (!valueMember.node->description.empty()) { - data.descriptions.push_back(valueMember.node->description); - data.descriptionsSourceMap.push_back(valueMember.sourceMap->description); + //data.descriptions.push_back(valueMember.node->description); + //data.descriptionsSourceMap.push_back(valueMember.sourceMap->description); + data.descriptions.push_back( + std::make_tuple( + valueMember.node->description, + valueMember.sourceMap->description + )); } - if ((valueMember.node->valueDefinition.values.empty() - || (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1)) - && (GetType(valueMember.node->valueDefinition, context) != mson::EnumTypeName)) { + if ((valueMember.node->valueDefinition.values.empty() || + (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1)) +#ifndef ENUM_REIMPL + && (GetType(valueMember.node->valueDefinition, context) != mson::EnumTypeName) +#endif + ) { ExtractTypeDefinition extd(data, context); extd(MakeNodeInfoWithoutSourceMap(valueMember.node->valueDefinition.typeDefinition)); @@ -611,12 +613,6 @@ namespace drafter namespace { - template - void Deleter(T* ptr) - { - delete ptr; - } - struct Join { std::string& base; Join(std::string& str) : base(str) @@ -654,107 +650,177 @@ namespace drafter } }; - //template <> - //struct ElementInfoToElement::IsPrimitive> { - // refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { - // } - //}; + template ::IsPrimitive> struct Merge; + + template + struct Merge { + using ElementInfo = typename ElementData::ElementInfo; + using Container = typename ElementData::ElementInfoContainer; + using StoredType = typename ElementData::StoredType; + using SourceMap = typename ElementData::ValueSourceMapType; + + ElementInfo operator()(const Container& container) const { + + return container.empty() + ? ElementInfo() + : container.front(); + } + }; + + template + struct Merge { + using ElementInfo = typename ElementData::ElementInfo; + using Container = typename ElementData::ElementInfoContainer; + using StoredType = typename ElementData::StoredType; + using SourceMap = typename ElementData::ValueSourceMapType; + + ElementInfo operator()(const Container& container) const { + + StoredType value; + SourceMap sourceMap; + + for (const auto& info : container) { + auto iValue = std::get<0>(info); + + std::copy(iValue.begin(), iValue.end(), std::back_inserter(value)); + + // FIXME: merge source map? + // it is not used later, + // every element in vector has it own map + } + + return std::make_tuple(value, sourceMap) ; + } + }; + + template ::IsPrimitive> struct SaveValue; template - struct SaveSamples { + struct SaveValue { + using ElementInfo = typename ElementData::ElementInfo; + using ValueType = typename T::ValueType; template - void operator()(const U& samples, refract::IElement* element) - { - if (samples.empty()) { + void operator()(const U& values, T* element) { + if (values.empty()) { return; } - refract::ArrayElement* a = new refract::ArrayElement; + ElementInfo value = Merge()(values); + std::pair result = LiteralTo(std::get<0>(value)); - ElementInfoToElement fetch; + element->set(std::get<1>(result)); - for (auto sample : samples) { - a->push_back(fetch(sample)); - } + // refactoring adept - AttachSourceMap require NodeInfo, let it pass for now + AttachSourceMap(element, MakeNodeInfo(std::get<1>(result), std::get<1>(value))); + } + }; + + template + struct SaveValue { + using ElementInfo = typename ElementData::ElementInfo; + + template + void operator()(const U& values, T* element) { + ElementInfo value = Merge()(values); - element->attributes[SerializeKey::Samples] = a; + if (!std::get<0>(value).empty()) { + element->set(std::get<0>(value)); + } } }; template - struct SaveDefault { + struct AllElementsToAtribute { template - void operator()(const U& defaults, refract::IElement* element) - { - if (defaults.empty()) { + void operator()(const U& values, const std::string& key, refract::IElement* element) { + if (values.empty()) { return; } + refract::ArrayElement* a = new refract::ArrayElement; + ElementInfoToElement fetch; - T* defaultElement = fetch(*defaults.rbegin()); - element->attributes[SerializeKey::Default] = defaultElement; + for (auto const& value : values) { + a->push_back(fetch(value)); + } + + element->attributes[key] = a; } + }; template - struct MakeNodeInfoFunctor { - NodeInfo operator()(std::pair v, const snowcrash::SourceMap& sm) - { - return MakeNodeInfo(v.second, sm); + struct LastElementToAttribute { + + template + void operator()(const U& values, const std::string& key, refract::IElement* element) { + + if (values.empty()) { + return; + } + + ElementInfoToElement fetch; + T* value = fetch(*values.rbegin()); + + element->attributes[key] = value; } + }; template - void ElementDataToElement(T* element, const ElementData& data, ConversionContext& context) { + void ElementDataToElement (T* element, const ElementData& data, ConversionContext& context) { - for (auto collection : { data.values, data.samples, data.defaults } ) { + for (auto collection : {data.values, data.samples, data.defaults, data.enumerations} ) { std::for_each(collection.begin(), collection.end(), - std::bind(CheckValueValidity(),std::placeholders::_1, std::ref(context))); + std::bind(CheckValueValidity(),std::placeholders::_1, std::ref(context))); } - std::for_each(data.values.begin(), data.values.end(), Append(element)); - SaveSamples()(data.samples, element); - SaveDefault()(data.defaults, element); + SaveValue()(data.values, element); + AllElementsToAtribute()(data.samples, SerializeKey::Samples, element); + AllElementsToAtribute()(data.enumerations, SerializeKey::Enumerations, element); + LastElementToAttribute()(data.defaults, SerializeKey::Default, element); } + } - template - refract::IElement* DescriptionToRefract(const ElementData& data) + template + refract::IElement* DescriptionToRefract(const T& descriptions) { - if (data.descriptions.empty()) { + if (descriptions.empty()) { return NULL; } std::string description; Join join(description); - - for_each(data.descriptions.begin(), data.descriptions.end(), join); - snowcrash::SourceMap sourceMap; - typedef typename std::vector >::const_iterator Iterator; - for (Iterator it = data.descriptionsSourceMap.begin(); it != data.descriptionsSourceMap.end(); ++it) { - sourceMap.sourceMap.append(it->sourceMap); + for (const auto& item: descriptions) { + join(std::get<0>(item)); + sourceMap.sourceMap.append(std::get<1>(item).sourceMap); + } + + if (description.empty()) { + return NULL; } return PrimitiveToRefract(NodeInfo(&description, &sourceMap)); } +#ifndef ENUM_REIMPL template struct MoveFirstValueToSample { - void operator()(const NodeInfo& value, ElementData& data) - { - } + void operator() (const NodeInfo& value, ElementData& data) + { + } }; template <> struct MoveFirstValueToSample { typedef refract::EnumElement T; - void operator()(const NodeInfo& value, ElementData& data) - { + void operator()(const NodeInfo& value, ElementData& data) { if (value.node->valueDefinition.values.empty() || data.values.empty()) { return; } @@ -763,39 +829,40 @@ namespace drafter data.values.erase(data.values.begin()); } }; +#endif template - refract::IElement* RefractElementFromValue(const NodeInfo& value, - ConversionContext& context, - const mson::BaseTypeName defaultNestedType) + refract::IElement* RefractElementFromValue(const NodeInfo& value, ConversionContext& context, const mson::BaseTypeName defaultNestedType, typename ElementData::DescriptionInfoContainer& descriptions) { using namespace refract; - typedef T ElementType; + using ElementType = T; ElementData data; ElementType* element = new ElementType; ExtractValueMember(data, context, defaultNestedType)(value); - +#ifndef ENUM_REIMPL size_t valuesCount = data.values.size(); +#endif - if (!data.descriptions.empty()) { - element->meta[SerializeKey::Description] = DescriptionToRefract(data); - } SetElementType(element, value.node->valueDefinition.typeDefinition); - AttachSourceMap(element, MakeNodeInfo(value.node, value.sourceMap)); + AttachSourceMap(element, value); NodeInfoCollection typeSections(MAKE_NODE_INFO(value, sections)); std::for_each(typeSections.begin(), typeSections.end(), ExtractTypeSection(data, context, value)); +#ifndef ENUM_REIMPL if (valuesCount != data.values.size()) { // there are some values coming from TypeSections -> move first value into examples - MoveFirstValueToSample()(value, data); + MoveFirstValueToSample()(value, data); } +#endif + + ElementDataToElement(element, data, context); - ElementDataToElement(element, data, context); + descriptions = data.descriptions; return element; } @@ -806,8 +873,7 @@ namespace drafter return true; } - if (refract::TypeQueryVisitor::as(FindRootAncestor( - variable.typeDefinition.typeSpecification.name.symbol.literal, context.GetNamedTypesRegistry()))) { + if (refract::TypeQueryVisitor::as(FindRootAncestor(variable.typeDefinition.typeSpecification.name.symbol.literal, context.GetNamedTypesRegistry()))) { return true; } @@ -825,21 +891,22 @@ namespace drafter if (property.node->name.variable.values.size() > 1) { // FIXME: is there example for multiple variables? - context.warn(snowcrash::Warning("multiple variables in property definition is not implemented", - snowcrash::MSONError, - sourceMap.sourceMap)); + context.warn( + snowcrash::Warning( + "multiple variables in property definition is not implemented", + snowcrash::MSONError, + sourceMap.sourceMap)); } // variable containt type definition if (!property.node->name.variable.typeDefinition.empty()) { if (!VariablePropertyIsString(property.node->name.variable, context)) { delete key; - throw snowcrash::Error("'variable named property' must be string or its sub-type", - snowcrash::MSONError, - sourceMap.sourceMap); + throw snowcrash::Error("'variable named property' must be string or its sub-type", snowcrash::MSONError, sourceMap.sourceMap); } SetElementType(key, property.node->name.variable.typeDefinition); + } key->attributes[SerializeKey::Variable] = refract::IElement::Create(true); @@ -859,13 +926,14 @@ namespace drafter } template - refract::MemberElement* RefractElementFromProperty(const NodeInfo& property, - ConversionContext& context, - const mson::BaseTypeName defaultNestedType) + refract::MemberElement* RefractElementFromProperty(const NodeInfo& property, ConversionContext& context, const mson::BaseTypeName defaultNestedType) { + + typename ElementData::DescriptionInfoContainer dummy; // we need no this + typename ElementData::DescriptionInfoContainer descriptions; + refract::IElement* key = GetPropertyKey(property, context); - refract::IElement* value = RefractElementFromValue( - NodeInfo(property.node, property.sourceMap), context, defaultNestedType); + refract::IElement* value = RefractElementFromValue(NodeInfo(property.node, property.sourceMap), context, defaultNestedType, dummy); refract::MemberElement* element = new refract::MemberElement(key, value); mson::TypeAttributes attrs = property.node->valueDefinition.typeDefinition.attributes; @@ -875,47 +943,33 @@ namespace drafter element->attributes[SerializeKey::TypeAttributes] = attributes; } - std::string description; - Join join(std::ref(description)); - snowcrash::SourceMap sourceMap; - - refract::IElement::MemberElementCollection::iterator iterator = value->meta.find(SerializeKey::Description); - if (iterator != value->meta.end()) { - // There is already setted description to "value" as result of `RefractElementFromValue()` - // so we need to move this atribute from "value" up to MemberElement - // - // NOTE: potentionaly unsafe, but we set it already to StringElement - // most safe is check it via refract::TypeQueryVisitor - description = (static_cast((*iterator)->value.second)->value); - element->meta.push_back(*iterator); - value->meta.erase(iterator); - // FIXME: extract source map - } else { - join(property.node->description); - sourceMap.sourceMap.append(property.sourceMap->description.sourceMap); - } - - bool addNewLine = false; - if (!description.empty()) { - addNewLine = true; + if (!property.node->description.empty()) { + descriptions.push_back( + std::make_tuple( + property.node->description, + property.sourceMap->description + )); } NodeInfoCollection typeSections(MAKE_NODE_INFO(property, sections)); - for (NodeInfoCollection::const_iterator it = typeSections.begin(); it != typeSections.end(); ++it) { - if (it->node->klass == mson::TypeSection::BlockDescriptionClass) { - if (addNewLine) { - description.append("\n"); - addNewLine = false; - } + for (const auto& typeSection: typeSections) { + if (typeSection.node->klass == mson::TypeSection::BlockDescriptionClass) { + descriptions.push_back( + std::make_tuple( + typeSection.node->content.description, + typeSection.sourceMap->description + )); - join(it->node->content.description); - sourceMap.sourceMap.append(it->sourceMap->description.sourceMap); } } - if (!description.empty()) { - element->meta[SerializeKey::Description] = PrimitiveToRefract(MakeNodeInfo(description, sourceMap)); + if (!property.node->description.empty() && (descriptions.size() > 1)) { + std::get<0>(descriptions[0]).append("\n"); + } + + if (refract::IElement* description = DescriptionToRefract(descriptions)) { + element->meta[SerializeKey::Description] = description; } return element; @@ -945,10 +999,7 @@ namespace drafter typedef refract::MemberElement ElementType; typedef NodeInfo InputType; - template - static ElementType* Invoke( - const InputType& prop, ConversionContext& context, const mson::BaseTypeName defaultNestedType) - { + template static ElementType* Invoke(const InputType& prop, ConversionContext& context, const mson::BaseTypeName defaultNestedType) { return RefractElementFromProperty(prop, context, defaultNestedType); } }; @@ -957,11 +1008,10 @@ namespace drafter typedef refract::IElement ElementType; typedef NodeInfo InputType; - template - static ElementType* Invoke( - const InputType& val, ConversionContext& context, const mson::BaseTypeName defaultNestedType) - { - refract::IElement* element = RefractElementFromValue(val, context, defaultNestedType); + template static ElementType* Invoke (const InputType& val, ConversionContext& context, const mson::BaseTypeName defaultNestedType) { + typename ElementData::DescriptionInfoContainer descriptions; + + refract::IElement* element = RefractElementFromValue(val, context, defaultNestedType, descriptions); mson::TypeAttributes attrs = val.node->valueDefinition.typeDefinition.attributes; @@ -970,34 +1020,41 @@ namespace drafter element->attributes[SerializeKey::TypeAttributes] = attributes; } + if (refract::IElement* description = DescriptionToRefract(descriptions)) { + element->meta[SerializeKey::Description] = description; + } + return element; } }; static void CheckTypeAttributesClash(const mson::TypeAttributes& attributes, - const snowcrash::SourceMap& sourceMap, - ConversionContext& context) - { + const snowcrash::SourceMap& sourceMap, + ConversionContext& context) { - if ((attributes & mson::FixedTypeAttribute) != 0 && (attributes & mson::OptionalTypeAttribute) != 0) { + if ((attributes & mson::FixedTypeAttribute) != 0 && + (attributes & mson::OptionalTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'fixed' and 'optional' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::RequiredTypeAttribute) != 0 && (attributes & mson::OptionalTypeAttribute) != 0) { + if ((attributes & mson::RequiredTypeAttribute) != 0 && + (attributes & mson::OptionalTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'required' and 'optional' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::DefaultTypeAttribute) != 0 && (attributes & mson::SampleTypeAttribute) != 0) { + if ((attributes & mson::DefaultTypeAttribute) != 0 && + (attributes & mson::SampleTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'default' and 'sample' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::FixedTypeAttribute) != 0 && (attributes & mson::FixedTypeTypeAttribute) != 0) { + if ((attributes & mson::FixedTypeAttribute) != 0 && + (attributes & mson::FixedTypeTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'fixed' and 'fixed-type' together", snowcrash::MSONError, sourceMap.sourceMap)); @@ -1006,15 +1063,13 @@ namespace drafter template static refract::IElement* MsonMemberToRefract(const typename Trait::InputType& input, - ConversionContext& context, - const mson::BaseTypeName nameType, - const mson::BaseTypeName defaultNestedType, - bool checkTypeAttributes = true) - { + ConversionContext& context, + const mson::BaseTypeName nameType, + const mson::BaseTypeName defaultNestedType, + bool checkTypeAttributes = true) { if (checkTypeAttributes) { - CheckTypeAttributesClash( - input.node->valueDefinition.typeDefinition.attributes, input.sourceMap->valueDefinition, context); + CheckTypeAttributesClash(input.node->valueDefinition.typeDefinition.attributes, input.sourceMap->valueDefinition, context); } switch (nameType) { @@ -1036,11 +1091,13 @@ namespace drafter case mson::ObjectTypeName: return Trait::template Invoke(input, context, defaultNestedType); - case mson::UndefinedTypeName: { + case mson::UndefinedTypeName: + { if (ValueHasChildren(input.node)) { // FIXME: what about EnumElement return Trait::template Invoke(input, context, defaultNestedType); - } else if (ValueHasName(input.node) || ValueHasMembers(input.node)) { + } + else if (ValueHasName(input.node) || ValueHasMembers(input.node)) { return Trait::template Invoke(input, context, defaultNestedType); } else if (nameType != defaultNestedType) { return MsonMemberToRefract(input, context, defaultNestedType, defaultNestedType, false); @@ -1059,17 +1116,16 @@ namespace drafter NodeInfoCollection oneOfNodeInfo(oneOf); - for (NodeInfoCollection::const_iterator it = oneOfNodeInfo.begin(); it != oneOfNodeInfo.end(); - ++it) { + for (NodeInfoCollection::const_iterator it = oneOfNodeInfo.begin(); it != oneOfNodeInfo.end(); ++it) { refract::OptionElement* option = new refract::OptionElement; // we can not use MsonElementToRefract() for groups, // "option" element handles directly all elements in group if (it->node->klass == mson::Element::GroupClass) { - option->set(MsonElementsToRefract( - MakeNodeInfo(it->node->content.elements(), it->sourceMap->elements()), context)); - } else { + option->set(MsonElementsToRefract(MakeNodeInfo(it->node->content.elements(), it->sourceMap->elements()), context)); + } + else { option->push_back(MsonElementToRefract(*it, context, mson::StringTypeName)); } @@ -1089,23 +1145,20 @@ namespace drafter return ref; } - static refract::IElement* MsonElementToRefract(const NodeInfo& mse, - ConversionContext& context, - const mson::BaseTypeName defaultNestedType /* = mson::StringTypeName */) + static refract::IElement* MsonElementToRefract(const NodeInfo& mse, ConversionContext& context, const mson::BaseTypeName defaultNestedType/* = mson::StringTypeName */) { switch (mse.node->klass) { case mson::Element::PropertyClass: - return MsonMemberToRefract( - MakeNodeInfo(mse.node->content.property, mse.sourceMap->property), - context, - GetType(mse.node->content.property.valueDefinition, context), - defaultNestedType); + return MsonMemberToRefract(MakeNodeInfo(mse.node->content.property, mse.sourceMap->property), + context, + GetType(mse.node->content.property.valueDefinition, context), + defaultNestedType); case mson::Element::ValueClass: return MsonMemberToRefract(MakeNodeInfo(mse.node->content.value, mse.sourceMap->value), - context, - GetType(mse.node->content.value.valueDefinition, context), - defaultNestedType); + context, + GetType(mse.node->content.value.valueDefinition, context), + defaultNestedType); case mson::Element::MixinClass: return MsonMixinToRefract(MakeNodeInfo(mse.node->content.mixin, mse.sourceMap->mixin)); @@ -1121,7 +1174,7 @@ namespace drafter } } - template + template refract::IElement* RefractElementFromMSON(const NodeInfo& ds, ConversionContext& context) { using namespace refract; @@ -1152,17 +1205,16 @@ namespace drafter std::for_each(typeSections.begin(), typeSections.end(), ExtractTypeSection(data, context, ds)); - ElementDataToElement(element, data, context); + ElementDataToElement(element, data, context); - if (refract::IElement* description = DescriptionToRefract(data)) { + if (refract::IElement* description = DescriptionToRefract(data.descriptions)) { element->meta[SerializeKey::Description] = description; } return element; } - refract::IElement* MSONToRefract( - const NodeInfo& dataStructure, ConversionContext& context) + refract::IElement* MSONToRefract(const NodeInfo& dataStructure, ConversionContext& context) { if (dataStructure.node->empty()) { return NULL; diff --git a/src/RefractElementFactory.cc b/src/RefractElementFactory.cc index ce2e4f215..82a6ef1a8 100644 --- a/src/RefractElementFactory.cc +++ b/src/RefractElementFactory.cc @@ -1,5 +1,6 @@ #include "RefractElementFactory.h" #include "refract/Element.h" +#include "ElementData.h" #include "Serialize.h" // LiteralTo<> #include "SourceAnnotation.h" // mson::Error @@ -7,12 +8,15 @@ namespace drafter { - template - struct RefractElementFactoryImpl : RefractElementFactory { + template ::IsPrimitive> struct RefractElementFactoryImpl; - RefractElementFactoryImpl() - { - } + template + struct RefractElementFactoryImpl : RefractElementFactory + { + + typedef typename E::ValueType ValueType; + + RefractElementFactoryImpl() {} virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const { @@ -24,20 +28,22 @@ namespace drafter switch (method) { case eSample: { - refract::ArrayElement* samples = new refract::ArrayElement; - std::pair value = LiteralTo(literal); - if (value.first) { - samples->push_back(refract::IElement::Create(value.second)); + refract::ArrayElement* samples = new refract::ArrayElement; + std::pair value = LiteralTo(literal); + if (value.first) { + samples->push_back(refract::IElement::Create(value.second)); + } + element->attributes[SerializeKey::Samples] = samples; } - element->attributes[SerializeKey::Samples] = samples; - } break; + break; case eValue: { - std::pair value = LiteralTo(literal); - if (value.first) { - element->set(value.second); + std::pair value = LiteralTo(literal); + if (value.first) { + element->set(value.second); + } } - } break; + break; case eElement: element->element(literal); @@ -49,11 +55,10 @@ namespace drafter }; template - struct RefractElementFactoryImpl : RefractElementFactory { + struct RefractElementFactoryImpl : RefractElementFactory + { - RefractElementFactoryImpl() - { - } + RefractElementFactoryImpl() {} virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const { @@ -84,22 +89,23 @@ namespace drafter static const RefractElementFactoryImpl arrayFactory; static const RefractElementFactoryImpl objectFactory; - switch (typeName) { - case mson::BooleanTypeName: + switch (typeName) { + case mson::BooleanTypeName: return boolFactory; - case mson::NumberTypeName: + case mson::NumberTypeName: return numberFactory; - case mson::StringTypeName: + case mson::StringTypeName: return stringFactory; case mson::ArrayTypeName: return arrayFactory; case mson::EnumTypeName: return enumFactory; - case mson::ObjectTypeName: - case mson::UndefinedTypeName: + case mson::ObjectTypeName: + case mson::UndefinedTypeName: return objectFactory; - default:; // do nothing - } + default: + ; // do nothing + } throw snowcrash::Error("unknown mson type", snowcrash::ApplicationError); } diff --git a/src/Serialize.cc b/src/Serialize.cc index f593f1b95..9405a1660 100644 --- a/src/Serialize.cc +++ b/src/Serialize.cc @@ -56,6 +56,7 @@ const std::string SerializeKey::Parameters = "parameters"; const std::string SerializeKey::Type = "type"; const std::string SerializeKey::Required = "required"; const std::string SerializeKey::Default = "default"; +const std::string SerializeKey::Enumerations = "enumerations"; const std::string SerializeKey::Nullable = "nullable"; const std::string SerializeKey::Example = "example"; const std::string SerializeKey::Values = "values"; diff --git a/src/Serialize.h b/src/Serialize.h index 0d965a076..0c6aca918 100644 --- a/src/Serialize.h +++ b/src/Serialize.h @@ -95,6 +95,7 @@ namespace drafter static const std::string Type; static const std::string Required; static const std::string Default; + static const std::string Enumerations; static const std::string Nullable; static const std::string Example; static const std::string Values; diff --git a/src/refract/AppendDecorator.h b/src/refract/AppendDecorator.h deleted file mode 100644 index e5b78f08d..000000000 --- a/src/refract/AppendDecorator.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// refract/AppendDecorator.h -// librefract -// -// Created by Jiri Kratochvil on 17/06/15. -// Copyright (c) 2015 Apiary Inc. All rights reserved. -// -#ifndef REFRACT_APPENDDECORATOR_H -#define REFRACT_APPENDDECORATOR_H - -#include - -namespace refract -{ - - // Forward declarations of Elements - struct IElement; - - template - struct AppendDecorator { - typedef T ElementType; - typedef V ValueType; - ElementType*& element; - AppendDecorator(ElementType*& e) : element(e) - { - } - - void operator()(const V& value) - { - // FIXME: snowcrash warn about "Primitive type can not have member" - // but in real it create "empty" member - // - // solution for now: set if element has no already value, otherwise silently ignore - if (element->empty()) { - element->set(value); - } - } - }; - - template - struct AppendDecorator > { - typedef T ElementType; - typedef typename T::ValueType ValueType; - ElementType*& element; - - AppendDecorator(ElementType*& e) : element(e) - { - } - - void operator()(const ValueType& value) - { - std::transform(value.begin(), value.end(), std::back_inserter(element)); - } - }; - -}; // namespace refract - -#endif // #ifndef REFRACT_APPENDDECORATOR_H diff --git a/test/fixtures/api/data-structure.sourcemap.json b/test/fixtures/api/data-structure.sourcemap.json index a5eac6d6a..8ba26b8bb 100644 --- a/test/fixtures/api/data-structure.sourcemap.json +++ b/test/fixtures/api/data-structure.sourcemap.json @@ -161,6 +161,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 64 + }, + { + "element": "number", + "content": 32 + } + ] + } + ] + } + ] + } + }, "content": "Username of the user" } }, diff --git a/test/fixtures/api/mson.sourcemap.json b/test/fixtures/api/mson.sourcemap.json index a78ad881e..cfe2f93a8 100644 --- a/test/fixtures/api/mson.sourcemap.json +++ b/test/fixtures/api/mson.sourcemap.json @@ -191,6 +191,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 99 + }, + { + "element": "number", + "content": 32 + } + ] + } + ] + } + ] + } + }, "content": "Id of the user" } }, @@ -444,6 +469,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 171 + }, + { + "element": "number", + "content": 37 + } + ] + } + ] + } + ] + } + }, "content": "zip description" } }, @@ -584,6 +634,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 236 + }, + { + "element": "number", + "content": 34 + } + ] + } + ] + } + ] + } + }, "content": "array description" } }, @@ -741,6 +816,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 296 + }, + { + "element": "number", + "content": 35 + } + ] + } + ] + } + ] + } + }, "content": "desc" } }, @@ -830,6 +930,19 @@ { "element": "sourceMap", "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 333 + }, + { + "element": "number", + "content": 42 + } + ] + }, { "element": "array", "content": [ From 45f8c6a733e7bc29f3673bbe23a90f08033e4c7c Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Mon, 21 Aug 2017 08:02:01 +0200 Subject: [PATCH 03/12] Enum implementation - enum holds IElemet as value - refactoring on building elements in RefractDataStructure.cc --- src/RefractDataStructure.cc | 200 +++++++++++++------------ src/refract/Element.h | 43 ++++-- src/refract/ExpandVisitor.cc | 33 ++-- src/refract/JSONSchemaVisitor.cc | 34 +++-- src/refract/PrintVisitor.cc | 2 +- src/refract/RenderJSONVisitor.cc | 84 +++++++++-- src/refract/SerializeCompactVisitor.cc | 9 +- src/refract/SerializeVisitor.cc | 4 +- src/refract/VisitorUtils.h | 28 ---- 9 files changed, 261 insertions(+), 176 deletions(-) diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 5b9ec3d8b..29a68eb67 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -20,10 +20,6 @@ #include "ElementData.h" -#include - -//#define ENUM_REIMPL 1 - namespace drafter { template @@ -259,7 +255,6 @@ namespace drafter { } }; -#ifdef ENUM_REIMPL template struct Store::IsPrimitive, dummy> { void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { @@ -267,7 +262,6 @@ namespace drafter { data.enumerations.push_back(Fetch()(typeSection, context, defaultNestedType)); } }; -#endif template struct TypeDefinition; @@ -314,9 +308,6 @@ namespace drafter { break; case mson::TypeSection::BlockDescriptionClass: - //data.descriptions.push_back(typeSection.node->content.description); - //data.descriptionsSourceMap.push_back(typeSection.sourceMap->description); - data.descriptions.push_back( std::make_tuple( typeSection.node->content.description, @@ -432,7 +423,6 @@ namespace drafter { } }; -#ifdef ENUM_REIMPL template struct Store::IsPrimitive, dummy> { using E = refract::EnumElement; @@ -440,7 +430,6 @@ namespace drafter { data.enumerations.push_back(Fetch()(typeNames, context)); } }; -#endif ExtractTypeDefinition(ElementData& data, const ConversionContext& context) : data(data), context(context) {} @@ -462,10 +451,10 @@ namespace drafter { ElementData& data; ConversionContext& context; - template ::IsPrimitive> struct Fetch; + template ::IsPrimitive, bool dummy = true> struct Fetch; - template - struct Fetch { // primitive values + template + struct Fetch { // primitive values ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { if (valueMember.node->valueDefinition.values.size() > 1) { @@ -480,8 +469,8 @@ namespace drafter { } }; - template - struct Fetch { // Array|Object + template + struct Fetch { // Array|Object ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { @@ -500,6 +489,26 @@ namespace drafter { } }; + template + struct Fetch::IsPrimitive, dummy> { // Enum + + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { + + const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); + + const RefractElementFactory& f = FactoryFromType(type); + const mson::Values& values = valueMember.node->valueDefinition.values; + + RefractElements elements; + + for (mson::Values::const_iterator it = values.begin(); it != values.end(); ++it) { + elements.push_back(f.Create(it->literal, eValue)); + } + + return std::make_tuple(elements, FetchSourceMap()(valueMember)); + } + }; + template struct IsValueVariable { @@ -523,7 +532,6 @@ namespace drafter { } }; -#ifdef ENUM_REIMPL template struct Store { void operator()(ElementData&data, const ElementInfo& info) { @@ -535,8 +543,6 @@ namespace drafter { } } }; -#endif - ExtractValueMember(ElementData& data, ConversionContext& context, const mson::BaseTypeName) : data(data), context(context) {} @@ -571,26 +577,20 @@ namespace drafter { } else { if (attrs & mson::DefaultTypeAttribute) { - context.warn(snowcrash::Warning("no value present when 'default' is specified" -#ifdef ENUM_REIMPL - ,snowcrash::MSONError, valueMember.sourceMap->sourceMap -#endif - )); + context.warn(snowcrash::Warning("no value present when 'default' is specified", + snowcrash::MSONError, valueMember.sourceMap->sourceMap) + ); } if (attrs & mson::SampleTypeAttribute) { - context.warn(snowcrash::Warning("no value present when 'sample' is specified" -#ifdef ENUM_REIMPL - ,snowcrash::MSONError, valueMember.sourceMap->sourceMap -#endif - )); + context.warn(snowcrash::Warning("no value present when 'sample' is specified", + snowcrash::MSONError, valueMember.sourceMap->sourceMap) + ); } } if (!valueMember.node->description.empty()) { - //data.descriptions.push_back(valueMember.node->description); - //data.descriptionsSourceMap.push_back(valueMember.sourceMap->description); data.descriptions.push_back( std::make_tuple( valueMember.node->description, @@ -599,11 +599,7 @@ namespace drafter { } if ((valueMember.node->valueDefinition.values.empty() || - (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1)) -#ifndef ENUM_REIMPL - && (GetType(valueMember.node->valueDefinition, context) != mson::EnumTypeName) -#endif - ) { + (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1))) { ExtractTypeDefinition extd(data, context); extd(MakeNodeInfoWithoutSourceMap(valueMember.node->valueDefinition.typeDefinition)); @@ -633,22 +629,6 @@ namespace drafter { } }; - template ::IsPrimitive> struct ElementInfoToElement; - - template - struct ElementInfoToElement { - E* operator()(const typename ElementData::ElementInfo& value) { - std::pair result = LiteralTo(std::get<0>(value)); - return new E(std::get<1>(result)); - } - }; - - template - struct ElementInfoToElement { - E* operator()(const typename ElementData::ElementInfo& value) { - return new E(std::get<0>(value)); - } - }; template ::IsPrimitive> struct Merge; @@ -693,6 +673,41 @@ namespace drafter { } }; + template ::IsPrimitive> struct ElementInfoToElement; + + template + struct ElementInfoToElement { + E* operator()(const typename ElementData::ElementInfo& value) { + std::pair result = LiteralTo(std::get<0>(value)); + return new E(std::get<1>(result)); + } + }; + + template + struct ElementInfoToElement { + E* operator()(const typename ElementData::ElementInfo& value) { + return new E(std::get<0>(value)); + } + }; + + template <> + struct ElementInfoToElement::IsPrimitive> { + refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { + + auto v = std::get<0>(value); + + refract::EnumElement* e = new refract::EnumElement; + + if (v.size() == 1) { + e->set(v.front()); + } else if (v.size() > 1) { + e->attributes[SerializeKey::Enumerations] = new refract::ArrayElement(v); + } + + return e; + } + }; + template ::IsPrimitive> struct SaveValue; template @@ -700,18 +715,17 @@ namespace drafter { using ElementInfo = typename ElementData::ElementInfo; using ValueType = typename T::ValueType; - template - void operator()(const U& values, T* element) { - if (values.empty()) { + void operator()(const ElementData& data, T* element) { + if (data.values.empty()) { return; } - ElementInfo value = Merge()(values); + ElementInfo value = Merge()(data.values); std::pair result = LiteralTo(std::get<0>(value)); element->set(std::get<1>(result)); - // refactoring adept - AttachSourceMap require NodeInfo, let it pass for now + // FIXME: refactoring adept - AttachSourceMap require NodeInfo, let it pass for now AttachSourceMap(element, MakeNodeInfo(std::get<1>(result), std::get<1>(value))); } }; @@ -720,9 +734,8 @@ namespace drafter { struct SaveValue { using ElementInfo = typename ElementData::ElementInfo; - template - void operator()(const U& values, T* element) { - ElementInfo value = Merge()(values); + void operator()(const ElementData& data, T* element) { + ElementInfo value = Merge()(data.values); if (!std::get<0>(value).empty()) { element->set(std::get<0>(value)); @@ -730,6 +743,26 @@ namespace drafter { } }; + template <> + struct SaveValue::IsPrimitive> { + using ElementInfo = typename ElementData::ElementInfo; + + void operator()(const ElementData& data, refract::EnumElement* element) { + ElementInfo values = Merge()(data.values); + ElementInfo enumerations = Merge()(data.enumerations); + + if (!std::get<0>(values).empty()) { + element->set(std::get<0>(values).front()); + // FIXME: relese rest of elements + // it can leak if more values wil be in `values` + } + + if (!std::get<0>(enumerations).empty()) { + element->attributes[SerializeKey::Enumerations]= new refract::ArrayElement(std::get<0>(enumerations)); + } + } + }; + template struct AllElementsToAtribute { @@ -764,6 +797,9 @@ namespace drafter { ElementInfoToElement fetch; T* value = fetch(*values.rbegin()); + + // FIXME: relese rest of elements + // it can leak if more values wil be in `values` element->attributes[key] = value; } @@ -778,12 +814,10 @@ namespace drafter { std::bind(CheckValueValidity(),std::placeholders::_1, std::ref(context))); } - SaveValue()(data.values, element); + SaveValue()(data, element); AllElementsToAtribute()(data.samples, SerializeKey::Samples, element); - AllElementsToAtribute()(data.enumerations, SerializeKey::Enumerations, element); LastElementToAttribute()(data.defaults, SerializeKey::Default, element); } - } template @@ -809,30 +843,13 @@ namespace drafter { return PrimitiveToRefract(NodeInfo(&description, &sourceMap)); } -#ifndef ENUM_REIMPL - template - struct MoveFirstValueToSample { - void operator() (const NodeInfo& value, ElementData& data) - { - } - }; - - template <> - struct MoveFirstValueToSample { - typedef refract::EnumElement T; - void operator()(const NodeInfo& value, ElementData& data) { - if (value.node->valueDefinition.values.empty() || data.values.empty()) { - return; - } - - data.samples.insert(data.samples.begin(), data.values.front()); - data.values.erase(data.values.begin()); - } - }; -#endif - + // FIXME: refactoring - description is not used while calling from + // `RefractElementFromProperty()` template - refract::IElement* RefractElementFromValue(const NodeInfo& value, ConversionContext& context, const mson::BaseTypeName defaultNestedType, typename ElementData::DescriptionInfoContainer& descriptions) + refract::IElement* RefractElementFromValue(const NodeInfo& value, + ConversionContext& context, + const mson::BaseTypeName defaultNestedType, + typename ElementData::DescriptionInfoContainer& descriptions) { using namespace refract; using ElementType = T; @@ -841,10 +858,6 @@ namespace drafter { ElementType* element = new ElementType; ExtractValueMember(data, context, defaultNestedType)(value); -#ifndef ENUM_REIMPL - size_t valuesCount = data.values.size(); -#endif - SetElementType(element, value.node->valueDefinition.typeDefinition); AttachSourceMap(element, value); @@ -853,13 +866,6 @@ namespace drafter { std::for_each(typeSections.begin(), typeSections.end(), ExtractTypeSection(data, context, value)); -#ifndef ENUM_REIMPL - if (valuesCount != data.values.size()) { - // there are some values coming from TypeSections -> move first value into examples - MoveFirstValueToSample()(value, data); - } -#endif - ElementDataToElement(element, data, context); descriptions = data.descriptions; diff --git a/src/refract/Element.h b/src/refract/Element.h index 023d57f5d..8cf41e4aa 100644 --- a/src/refract/Element.h +++ b/src/refract/Element.h @@ -244,7 +244,6 @@ namespace refract const Type* self = static_cast(this); Type* element = new Type; - element->hasContent = self->hasContent; if (flags & cElement) { element->element_ = self->element_; @@ -263,6 +262,7 @@ namespace refract } if (flags & cValue) { + element->hasContent = self->hasContent; TraitType::cloneValue(value, element->value); } @@ -508,27 +508,52 @@ namespace refract } }; - struct EnumElementTrait : public ElementCollectionTrait<> { - static const std::string element() + struct EnumElementTrait + { + + typedef IElement* ValueType; + + static ValueType init() { return NULL; } + static const std::string element() { return "enum"; } + + static void release(ValueType& value) { - return "enum"; + if (value) { + delete value; + value = NULL; + } + } + + static void cloneValue(const ValueType& self, ValueType& other) + { + other = self ? self->clone() : NULL; } }; - struct EnumElement : Element { + // + // FIXME: what about `empty()`? should it reflect "enumeration" attribute? + // + + struct EnumElement : Element + { EnumElement() : Type() { } - EnumElement(const TraitType::ValueType& value) : Type() + EnumElement(const TraitType::ValueType& val) : Type() { - set(value); + set(val); } - void push_back(IElement* e) + void set(const ValueType& val) { hasContent = true; - value.push_back(e); + value = val; + } + + const ValueType& get() const + { + return value; } }; diff --git a/src/refract/ExpandVisitor.cc b/src/refract/ExpandVisitor.cc index c471b0fed..c9d10ccbd 100644 --- a/src/refract/ExpandVisitor.cc +++ b/src/refract/ExpandVisitor.cc @@ -21,11 +21,7 @@ #include "TypeQueryVisitor.h" #include "VisitorUtils.h" -#define VISIT_IMPL(ELEMENT) \ - void ExpandVisitor::operator()(const ELEMENT##Element& e) \ - { \ - result = Expand(e, context); \ - } +#define VISIT_IMPL( ELEMENT ) void ExpandVisitor::operator()(const ELEMENT ## Element& e) { result = Expand(e, context); } namespace refract { @@ -68,6 +64,20 @@ namespace refract } }; + // + // FIXME: it seem it is not required for implemetation + // maybe there is no EnumElement expansion in samples? + // + + //template <> + //struct ExpandValueImpl { + + // template + // IElement* const operator()(const IElement* value, Functor& expand) { + // return expand(value); + // } + //}; + template <> struct ExpandValueImpl { @@ -76,8 +86,8 @@ namespace refract { RefractElements members; - for (RefractElements::const_iterator it = value.begin(); it != value.end(); ++it) { - members.push_back(expand(*it)); + for (auto const& item: value) { + members.push_back(expand(item)); } return members; @@ -91,8 +101,9 @@ namespace refract // FIXME: add check against recursive inheritance // walk recursive in registry and expand inheritance tree - for (const IElement *parent = registry.find(en); parent && !isReserved(en); - en = parent->element(), parent = registry.find(en)) { + for (const IElement* parent = registry.find(en) + ; parent && !isReserved(en) + ; en = parent->element(), parent = registry.find(en)) { inheritance.push(parent->clone((IElement::cAll ^ IElement::cElement) | IElement::cNoMetaId)); inheritance.top()->meta["ref"] = IElement::Create(en); @@ -121,9 +132,7 @@ namespace refract const Registry& registry; ExpandVisitor* expand; - Context(const Registry& registry, ExpandVisitor* expand) : registry(registry), expand(expand) - { - } + Context(const Registry& registry, ExpandVisitor* expand) : registry(registry), expand(expand) {} IElement* ExpandOrClone(const IElement* e) { diff --git a/src/refract/JSONSchemaVisitor.cc b/src/refract/JSONSchemaVisitor.cc index 7f63576ff..42d3da80d 100644 --- a/src/refract/JSONSchemaVisitor.cc +++ b/src/refract/JSONSchemaVisitor.cc @@ -422,18 +422,24 @@ namespace refract } } - void JSONSchemaVisitor::operator()(const EnumElement& e) - { - const EnumElement::ValueType* val = GetValue(e); + void JSONSchemaVisitor::operator()(const EnumElement& e) { - if (!val || val->empty()) { + const auto& it = e.attributes.find("enumerations"); + if (it == e.attributes.end()) { + return; + } + + ArrayElement* enums = TypeQueryVisitor::as((*it)->value.second); + if (!enums) { return; } std::map > types; std::vector typesOrder; - for (ArrayElement::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { + for (ArrayElement::ValueType::const_iterator it = enums->value.begin(); + it != enums->value.end(); + ++it) { if (*it) { std::vector& items = types[(*it)->element()]; @@ -450,9 +456,9 @@ namespace refract anyOf(types, typesOrder); } else { const EnumElement* def = GetDefault(e); - if (!e.empty() || (def && !def->empty())) { - ArrayElement* a = new ArrayElement; - CloneMembers(a, val); + if (!enums->empty() || (def && !def->empty())) { + ArrayElement *a = new ArrayElement; + CloneMembers(a, &enums->value); setSchemaType(types.begin()->first); addMember("enum", a); } @@ -460,8 +466,10 @@ namespace refract const EnumElement* def = GetDefault(e); - if (def && !def->empty() && !def->value.empty()) { - IElement* d = def->value.front()->clone(); + // this works because "default" is everytime set by value + // if value will be moved into "enumerations" it need aditional check + if (def && !def->empty() && !def->value->empty()) { + IElement *d = def->value->clone(); addMember("default", d); } } @@ -601,7 +609,8 @@ namespace refract } } } - } break; + } + break; case TypeQueryVisitor::Select: { SelectElement* sel = static_cast(*it); @@ -614,7 +623,8 @@ namespace refract VisitBy(*(*it), v); oneOfMembers.push_back(v.getOwnership()); } - } break; + } + break; default: throw LogicError("Invalid member type of object in MSON definition"); diff --git a/src/refract/PrintVisitor.cc b/src/refract/PrintVisitor.cc index 85fd79021..ea1afc2a2 100644 --- a/src/refract/PrintVisitor.cc +++ b/src/refract/PrintVisitor.cc @@ -132,7 +132,7 @@ namespace refract void PrintVisitor::operator()(const EnumElement& e) { - printValues(e, "Enum"); + //printValues(e, "Enum"); } void PrintVisitor::operator()(const ObjectElement& e) diff --git a/src/refract/RenderJSONVisitor.cc b/src/refract/RenderJSONVisitor.cc index 1f67a790a..b9facaf5e 100644 --- a/src/refract/RenderJSONVisitor.cc +++ b/src/refract/RenderJSONVisitor.cc @@ -19,7 +19,18 @@ namespace refract namespace { - IElement* getEnumValue(const ExtendElement& extend) + const ArrayElement* GetEnumerations(const EnumElement& e) { + + IElement::MemberElementCollection::const_iterator i = e.attributes.find("enumerations"); + + if (i == e.attributes.end()) { + return NULL; + } + + return TypeQueryVisitor::as((*i)->value.second); + } + + IElement* GetEnumValue(const ExtendElement& extend) { if (extend.empty()) { return NULL; @@ -34,16 +45,58 @@ namespace refract continue; } - const ArrayElement::ValueType* items = GetValue(*element); + const EnumElement::ValueType* item = GetValue(*element); - if (!items->empty()) { - return *items->begin(); + if (item) { + return *item; } } return NULL; } + const IElement* GetEnumValue(const EnumElement& element) { + if (const EnumElement* s = GetSample(element)) { + return GetEnumValue(*s); + } + + if (const EnumElement* d = GetDefault(element)) { + return GetEnumValue(*d); + } + + if (!element.empty()) { + return element.value; + } + + if (const ArrayElement* e = GetEnumerations(element)) { + if (e && !e->empty()) { + for (const auto& item : e->value) { + if (!item) { + continue; + } + + // We need hadle Enum individualy because of attr["enumerations"] + if (EnumElement* val = TypeQueryVisitor::as(item)) { + const IElement* ret = GetEnumValue(*val); + if (ret) { + return ret; + } + } + + if (!item->empty()) { + return item; + } + } + } + } + + if (element.empty() && IsTypeAttribute(element, "nullable")) { + return NULL; + } + + return element.value; + } + template void FetchMembers(const T& element, typename T::ValueType& members) { @@ -116,18 +169,23 @@ namespace refract RenderJSONVisitor renderer; if (e.value.second) { - if (IsTypeAttribute(e, "nullable") && e.value.second->empty()) { + if (EnumElement* enm = TypeQueryVisitor::as(e.value.second)) { + // We nned nadle Enum individualy because of attr["enumerations"] + Visit(renderer, *enm); + } + else if (IsTypeAttribute(e, "nullable") && e.value.second->empty()) { renderer.result = new NullElement; } else if (IsTypeAttribute(e, "optional") && e.value.second->empty()) { return; } else { Visit(renderer, *e.value.second); - if (!renderer.result) { - return; - } } } + if (!renderer.result) { + return; + } + result = new MemberElement(key, renderer.result ? renderer.getOwnership() : new StringElement); } @@ -145,13 +203,15 @@ namespace refract if (!enumValue) { // there is no enumValue injected from ExtendElement,try to pick value directly - const EnumElement::ValueType* val = GetEnumValue(e); + const IElement* val = GetEnumValue(e); if (val && !val->empty()) { - enumValue = val->front()->clone(); - } else { + enumValue = val->clone(); + } + else { enumValue = new StringElement; } } + RenderJSONVisitor renderer; VisitBy(*enumValue, renderer); @@ -215,7 +275,7 @@ namespace refract } if (TypeQueryVisitor::as(merged)) { - renderer.enumValue = getEnumValue(e); + renderer.enumValue = GetEnumValue(e); if (renderer.enumValue) { renderer.enumValue = renderer.enumValue->clone(); } diff --git a/src/refract/SerializeCompactVisitor.cc b/src/refract/SerializeCompactVisitor.cc index 8d35cf408..1944c0bcd 100644 --- a/src/refract/SerializeCompactVisitor.cc +++ b/src/refract/SerializeCompactVisitor.cc @@ -59,9 +59,12 @@ namespace refract void SosSerializeCompactVisitor::operator()(const EnumElement& e) { - sos::Array array; - SerializeValues(array, e.value, generateSourceMap); - value_ = array; + IElement::MemberElementCollection::const_iterator enums = e.attributes.find("enumerations"); + if (enums == e.attributes.end() || !(*enums)->value.second) { + return; + } + + VisitBy(*(*enums)->value.second, *this); } void SosSerializeCompactVisitor::operator()(const ArrayElement& e) diff --git a/src/refract/SerializeVisitor.cc b/src/refract/SerializeVisitor.cc index 1b82c9db3..ebac8f98d 100644 --- a/src/refract/SerializeVisitor.cc +++ b/src/refract/SerializeVisitor.cc @@ -168,8 +168,8 @@ namespace refract void SosSerializeVisitor::operator()(const EnumElement& e) { - sos::Array array = SerializeValueList(e, generateSourceMap); - SetSerializerValue(*this, array); + sos::Object object = ElementToObject(e.value, generateSourceMap); + SetSerializerValue(*this, object); } void SosSerializeVisitor::operator()(const ObjectElement& e) diff --git a/src/refract/VisitorUtils.h b/src/refract/VisitorUtils.h index 43cadfda1..a30a8bc80 100644 --- a/src/refract/VisitorUtils.h +++ b/src/refract/VisitorUtils.h @@ -131,34 +131,6 @@ namespace refract } }; - struct GetEnumValue { - const EnumElement& element; - - GetEnumValue(const EnumElement& e) : element(e) - { - } - - operator const EnumElement::ValueType*() - { - if (const EnumElement* s = GetSample(element)) { - return &s->value; - } - - if (const EnumElement* d = GetDefault(element)) { - return &d->value; - } - - if (!element.empty()) { - return &element.value; - } - - if (element.empty() && IsTypeAttribute(element, "nullable")) { - return NULL; - } - - return &element.value; - } - }; // will be moved into different header (as part of drafter instead of refract) template From 7beec4bce7d025a32f22035a2b1eeb8713166252 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Mon, 21 Aug 2017 08:02:46 +0200 Subject: [PATCH 04/12] Update test outputs according to new structure of EnumElement --- .../mson/check-default-without-value.json | 18 +- .../mson/check-sample-without-value.json | 18 +- .../mson/enum-members-description.json | 59 +- test/fixtures/mson/enum-sample.json | 218 +++--- test/fixtures/mson/enum-variants.apib | 46 +- test/fixtures/mson/enum-variants.json | 639 +++++++++++------- test/fixtures/mson/enum.json | 34 +- test/fixtures/mson/named-with-types.json | 15 +- test/fixtures/render/enum-default.json | 33 +- test/fixtures/render/enum-sample.json | 43 +- test/fixtures/render/mixin-override.json | 50 +- test/fixtures/schema/default-attribute.json | 31 +- test/fixtures/schema/default-section.json | 25 +- .../fixtures/schema/enum-containing-enum.json | 54 +- .../schema/enum-containing-object.json | 61 +- .../schema/enum-containing-sample.json | 39 +- test/fixtures/schema/enum-nullable.json | 18 +- test/fixtures/schema/enum-of-strings.json | 23 +- test/fixtures/schema/enum-with-type.json | 34 +- test/fixtures/schema/object-very-complex.json | 23 +- .../schema/sample-inline-attribute.json | 23 +- .../schema/sample-inline-variable.json | 23 +- test/fixtures/schema/sample.json | 23 +- 23 files changed, 928 insertions(+), 622 deletions(-) diff --git a/test/fixtures/mson/check-default-without-value.json b/test/fixtures/mson/check-default-without-value.json index 22cd7411f..1efd78ce5 100644 --- a/test/fixtures/mson/check-default-without-value.json +++ b/test/fixtures/mson/check-default-without-value.json @@ -131,14 +131,28 @@ "attributes": { "code": { "element": "number", - "content": 0 + "content": 4 }, "sourceMap": { "element": "array", "content": [ { "element": "sourceMap", - "content": [] + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 50 + }, + { + "element": "number", + "content": 15 + } + ] + } + ] } ] } diff --git a/test/fixtures/mson/check-sample-without-value.json b/test/fixtures/mson/check-sample-without-value.json index ed209dd31..9993267d3 100644 --- a/test/fixtures/mson/check-sample-without-value.json +++ b/test/fixtures/mson/check-sample-without-value.json @@ -131,14 +131,28 @@ "attributes": { "code": { "element": "number", - "content": 0 + "content": 4 }, "sourceMap": { "element": "array", "content": [ { "element": "sourceMap", - "content": [] + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 50 + }, + { + "element": "number", + "content": 14 + } + ] + } + ] } ] } diff --git a/test/fixtures/mson/enum-members-description.json b/test/fixtures/mson/enum-members-description.json index 55010b4a0..e16e3cee8 100644 --- a/test/fixtures/mson/enum-members-description.json +++ b/test/fixtures/mson/enum-members-description.json @@ -59,38 +59,43 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "meta": { - "description": { + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { "element": "string", - "content": "red" - } - }, - "content": "#ff0000" - }, - { - "element": "string", - "meta": { - "description": { + "meta": { + "description": { + "element": "string", + "content": "red" + } + }, + "content": "#ff0000" + }, + { "element": "string", - "content": "green" - } - }, - "content": "#00ff00" - }, - { - "element": "string", - "meta": { - "description": { + "meta": { + "description": { + "element": "string", + "content": "green" + } + }, + "content": "#00ff00" + }, + { "element": "string", - "content": "blue" + "meta": { + "description": { + "element": "string", + "content": "blue" + } + }, + "content": "#0000ff" } - }, - "content": "#0000ff" + ] } - ] + } } } } diff --git a/test/fixtures/mson/enum-sample.json b/test/fixtures/mson/enum-sample.json index 9160ace03..2a9bc86ad 100644 --- a/test/fixtures/mson/enum-sample.json +++ b/test/fixtures/mson/enum-sample.json @@ -53,16 +53,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "3" + }, + { + "element": "string", + "content": "4" + } + ] } - ] + } } } }, @@ -81,16 +86,21 @@ "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "3" + }, + { + "element": "string", + "content": "4" + } + ] } - ] + } } ] } @@ -113,16 +123,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "*3" - }, - { - "element": "string", - "content": "4*" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "*3" + }, + { + "element": "string", + "content": "4*" + } + ] } - ] + } } } }, @@ -147,16 +162,21 @@ "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "3" + }, + { + "element": "string", + "content": "4" + } + ] } - ] + } } ] } @@ -180,45 +200,61 @@ "value": { "element": "enum", "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number" + } + ] + }, "samples": { "element": "array", "content": [ { "element": "enum", - "content": [ - { - "element": "number", - "content": 3 - }, - { - "element": "number", - "content": 4 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number", + "content": 3 + }, + { + "element": "number", + "content": 4 + } + ] } - ] + } }, { "element": "enum", - "content": [ - { - "element": "number", - "content": 5 - }, - { - "element": "number", - "content": 6 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number", + "content": 5 + }, + { + "element": "number", + "content": 6 + } + ] } - ] + } } ] }, "default": { "element": "enum", - "content": [ - { - "element": "number", - "content": 1 - } - ] + "content": { + "element": "number", + "content": 1 + } } } } @@ -239,16 +275,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "pavan" - }, - { - "element": "number", - "content": 4 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "pavan" + }, + { + "element": "number", + "content": 4 + } + ] } - ] + } } } }, @@ -267,26 +308,31 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "pavan" - }, - { - "element": "number", - "attributes": { - "samples": { - "element": "array", - "content": [ - { - "element": "number", - "content": 4 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "pavan" + }, + { + "element": "number", + "attributes": { + "samples": { + "element": "array", + "content": [ + { + "element": "number", + "content": 4 + } + ] } - ] + } } - } + ] } - ] + } } } } diff --git a/test/fixtures/mson/enum-variants.apib b/test/fixtures/mson/enum-variants.apib index 9aa16e4a6..456832d33 100644 --- a/test/fixtures/mson/enum-variants.apib +++ b/test/fixtures/mson/enum-variants.apib @@ -2,24 +2,24 @@ # Data Structures # Enum behavior (object) -- size1: L (enum) - content ['L'] +- size1: L (enum) - C: 'L' -- size2: S, M, L, XL (enum) - content ['S','M','L','XL'] +- size2: S, M, L, XL (enum) - E: ['S','M','L','XL'] -- size3: L (enum) - sample [['L']], content ['S','M','L','XL'] +- size3: L (enum) - C: 'L', E: ['S','M','L','XL'] - S - M - L - XL -- size4: L (enum) - sample [['L']], content [ 'S, M, L, XL' ] - FIXME: from snowcrash we receive "enum of strings" should be string "S, M, L, XL" +- size4: L (enum) - C: 'L', E: [ 'S, M, L, XL' ] - FIXME: from snowcrash we receive "enum of strings" should be string "S, M, L, XL" - S, M, L, XL -- size5: *L* (enum) - sample [['L']] +- size5: *L* (enum) - S: [C:'L'] -- size6: L (enum, sample) - sample [['L']] +- size6: L (enum, sample) - S: [C:'L'] -- size7 (enum) - content ['S','M','L','XL','XXL','XXXL'] +- size7 (enum) - E: ['S','M','L','XL','XXL','XXXL'] - S - M - L @@ -29,38 +29,54 @@ - XXL - XXXL -- size8: S (enum) - content ['T'], samples [[ 'S' ],[ 'U']] +- size8: S (enum) - C: 'S', E: ['T'] S: [C:'U'] - T - sample - U -- size9: L (enum, sample) - sample [['L'],['M','N']] +- size9: L (enum, sample) - E: ['M','N'], S: [C:'L'] - M - N -- size10: L (enum, sample) - sample [['L'],['M','N']] +- size10: L (enum, sample) - E: ['M','N'], S: [C:'L'] - items - M - M -- size11 (enum[string, number]) - content['M','N'] +- size11 (enum[string, number]) - E:[,,'M','N'] - M - N -- size12: L (enum,default) - default['M','N'] - FIXME: current default['L'], sample[['M','N']] +- size12: L (enum,default) - D: {C:'L'}, E: ['M','N'] - M - N -- size13: L (enum,default) - default['M','N'] - FIXME: current default['L'], sample[['M','N']] +- size13: L (enum,default) - D: {C:'L'}, E: ['M','N'] - items - M - N -- size14 (enum,sample) - sample[['M','N']] - FIXME: curent content[['M','N']] +- size14 (enum,sample) - E: ['M','N'] - M - N -- size15 (enum,default) - default['M','N'] - FIXME: curent content[['M','N']] +- size15 (enum,default) - E: ['M','N'] - M - N + +- size16: A (enum) - C: 'A', E: ['D','E'], S: {E: ['F','G']} + - D + - E + + - sample + - F + - G + + - default + - H + +- size17: A,B,C (enum) - E: ['A','B','C','D','E','F'] + - D + - E + - F diff --git a/test/fixtures/mson/enum-variants.json b/test/fixtures/mson/enum-variants.json index 303c844a2..0d24085be 100644 --- a/test/fixtures/mson/enum-variants.json +++ b/test/fixtures/mson/enum-variants.json @@ -49,7 +49,7 @@ "meta": { "description": { "element": "string", - "content": "content ['L']" + "content": "C: 'L'" } }, "content": { @@ -59,12 +59,10 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "content": { + "element": "string", + "content": "L" + } } } }, @@ -73,7 +71,7 @@ "meta": { "description": { "element": "string", - "content": "content ['S','M','L','XL']" + "content": "E: ['S','M','L','XL']" } }, "content": { @@ -83,24 +81,29 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "S" - }, - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "L" - }, - { - "element": "string", - "content": "XL" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "S" + }, + { + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "L" + }, + { + "element": "string", + "content": "XL" + } + ] } - ] + } } } }, @@ -109,7 +112,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L']], content ['S','M','L','XL']" + "content": "C: 'L', E: ['S','M','L','XL']" } }, "content": { @@ -120,39 +123,32 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "element": "string", + "content": "S" + }, + { + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "L" + }, + { + "element": "string", + "content": "XL" } ] } }, - "content": [ - { - "element": "string", - "content": "S" - }, - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "L" - }, - { - "element": "string", - "content": "XL" - } - ] + "content": { + "element": "string", + "content": "L" + } } } }, @@ -161,7 +157,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L']], content [ 'S, M, L, XL' ] - FIXME: from snowcrash we receive \"enum of strings\" should be string \"S, M, L, XL\"" + "content": "C: 'L', E: [ 'S, M, L, XL' ] - FIXME: from snowcrash we receive \"enum of strings\" should be string \"S, M, L, XL\"" } }, "content": { @@ -172,44 +168,37 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", + "element": "array", "content": [ + { + "element": "string", + "content": "S" + }, + { + "element": "string", + "content": "M" + }, { "element": "string", "content": "L" + }, + { + "element": "string", + "content": "XL" } ] } ] } }, - "content": [ - { - "element": "array", - "content": [ - { - "element": "string", - "content": "S" - }, - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "L" - }, - { - "element": "string", - "content": "XL" - } - ] - } - ] + "content": { + "element": "string", + "content": "L" + } } } }, @@ -218,7 +207,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L']]" + "content": "S: [C:'L']" } }, "content": { @@ -228,22 +217,20 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "attributes": { - "samples": { - "element": "array", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "attributes": { + "samples": { + "element": "array", + "content": [ + { + "element": "enum", + "content": { + "element": "string", + "content": "L" + } } - } + ] } - ] + } } } }, @@ -252,7 +239,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L']]" + "content": "S: [C:'L']" } }, "content": { @@ -268,12 +255,10 @@ "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "content": { + "element": "string", + "content": "L" + } } ] } @@ -286,7 +271,7 @@ "meta": { "description": { "element": "string", - "content": "content ['S','M','L','XL','XXL','XXXL']" + "content": "E: ['S','M','L','XL','XXL','XXXL']" } }, "content": { @@ -296,32 +281,37 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "S" - }, - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "L" - }, - { - "element": "string", - "content": "XL" - }, - { - "element": "string", - "content": "XXL" - }, - { - "element": "string", - "content": "XXXL" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "S" + }, + { + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "L" + }, + { + "element": "string", + "content": "XL" + }, + { + "element": "string", + "content": "XXL" + }, + { + "element": "string", + "content": "XXXL" + } + ] } - ] + } } } }, @@ -330,7 +320,7 @@ "meta": { "description": { "element": "string", - "content": "content ['T'], samples [[ 'S' ],[ 'U']]" + "content": "C: 'S', E: ['T'] S: [C:'U']" } }, "content": { @@ -341,36 +331,32 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "S" - } - ] - }, + "element": "string", + "content": "T" + } + ] + }, + "samples": { + "element": "array", + "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "U" - } - ] + "content": { + "element": "string", + "content": "U" + } } ] } }, - "content": [ - { - "element": "string", - "content": "T" - } - ] + "content": { + "element": "string", + "content": "S" + } } } }, @@ -379,7 +365,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L'],['M','N']]" + "content": "E: ['M','N'], S: [C:'L']" } }, "content": { @@ -390,30 +376,28 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "N" - } - ] + "element": "string", + "content": "M" }, + { + "element": "string", + "content": "N" + } + ] + }, + "samples": { + "element": "array", + "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "content": { + "element": "string", + "content": "L" + } } ] } @@ -426,7 +410,7 @@ "meta": { "description": { "element": "string", - "content": "sample [['L'],['M','N']]" + "content": "E: ['M','N'], S: [C:'L']" } }, "content": { @@ -437,30 +421,28 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "M" - } - ] + "element": "string", + "content": "M" }, + { + "element": "string", + "content": "M" + } + ] + }, + "samples": { + "element": "array", + "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "L" - } - ] + "content": { + "element": "string", + "content": "L" + } } ] } @@ -473,7 +455,7 @@ "meta": { "description": { "element": "string", - "content": "content['M','N']" + "content": "E:[,,'M','N']" } }, "content": { @@ -483,16 +465,27 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "N" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string" + }, + { + "element": "number" + }, + { + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "N" + } + ] } - ] + } } } }, @@ -501,7 +494,7 @@ "meta": { "description": { "element": "string", - "content": "default['M','N'] - FIXME: current default['L'], sample[['M','N']]" + "content": "D: {C:'L'}, E: ['M','N']" } }, "content": { @@ -512,32 +505,65 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "N" - } - ] + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "N" } ] }, "default": { "element": "enum", + "content": { + "element": "string", + "content": "L" + } + } + } + } + } + }, + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "D: {C:'L'}, E: ['M','N']" + } + }, + "content": { + "key": { + "element": "string", + "content": "size13" + }, + "value": { + "element": "enum", + "attributes": { + "enumerations": { + "element": "array", "content": [ { "element": "string", - "content": "L" + "content": "M" + }, + { + "element": "string", + "content": "N" } ] + }, + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "L" + } } } } @@ -548,41 +574,60 @@ "meta": { "description": { "element": "string", - "content": "default['M','N'] - FIXME: current default['L'], sample[['M','N']]" + "content": "E: ['M','N']" } }, "content": { "key": { "element": "string", - "content": "size13" + "content": "size14" }, "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "N" - } - ] + "element": "string", + "content": "M" + }, + { + "element": "string", + "content": "N" } ] - }, - "default": { - "element": "enum", + } + } + } + } + }, + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "E: ['M','N']" + } + }, + "content": { + "key": { + "element": "string", + "content": "size15" + }, + "value": { + "element": "enum", + "attributes": { + "enumerations": { + "element": "array", "content": [ { "element": "string", - "content": "L" + "content": "M" + }, + { + "element": "string", + "content": "N" } ] } @@ -595,26 +640,65 @@ "meta": { "description": { "element": "string", - "content": "sample[['M','N']] - FIXME: curent content[['M','N']]" + "content": "C: 'A', E: ['D','E'], S: {E: ['F','G']}" } }, "content": { "key": { "element": "string", - "content": "size14" + "content": "size16" }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "M" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "D" + }, + { + "element": "string", + "content": "E" + } + ] + }, + "samples": { + "element": "array", + "content": [ + { + "element": "enum", + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "F" + }, + { + "element": "string", + "content": "G" + } + ] + } + } + } + ] }, - { - "element": "string", - "content": "N" + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "H" + } } - ] + }, + "content": { + "element": "string", + "content": "A" + } } } }, @@ -623,26 +707,47 @@ "meta": { "description": { "element": "string", - "content": "default['M','N'] - FIXME: curent content[['M','N']]" + "content": "E: ['A','B','C','D','E','F']" } }, "content": { "key": { "element": "string", - "content": "size15" + "content": "size17" }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "M" - }, - { - "element": "string", - "content": "N" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "A" + }, + { + "element": "string", + "content": "B" + }, + { + "element": "string", + "content": "C" + }, + { + "element": "string", + "content": "D" + }, + { + "element": "string", + "content": "E" + }, + { + "element": "string", + "content": "F" + } + ] } - ] + } } } } @@ -669,14 +774,28 @@ "attributes": { "code": { "element": "number", - "content": 0 + "content": 4 }, "sourceMap": { "element": "array", "content": [ { "element": "sourceMap", - "content": [] + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 1062 + }, + { + "element": "number", + "content": 36 + } + ] + } + ] } ] } @@ -699,14 +818,28 @@ "attributes": { "code": { "element": "number", - "content": 0 + "content": 4 }, "sourceMap": { "element": "array", "content": [ { "element": "sourceMap", - "content": [] + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 1117 + }, + { + "element": "number", + "content": 38 + } + ] + } + ] } ] } diff --git a/test/fixtures/mson/enum.json b/test/fixtures/mson/enum.json index 82a55d35a..ce2362254 100644 --- a/test/fixtures/mson/enum.json +++ b/test/fixtures/mson/enum.json @@ -57,20 +57,28 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "red" - }, - { - "element": "string", - "content": "yellow" - }, - { - "element": "string", - "content": "green" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string" + }, + { + "element": "string", + "content": "red" + }, + { + "element": "string", + "content": "yellow" + }, + { + "element": "string", + "content": "green" + } + ] } - ] + } } } } diff --git a/test/fixtures/mson/named-with-types.json b/test/fixtures/mson/named-with-types.json index 233c566a4..261694965 100644 --- a/test/fixtures/mson/named-with-types.json +++ b/test/fixtures/mson/named-with-types.json @@ -47,12 +47,17 @@ "content": "EnumType" } }, - "content": [ - { - "element": "string", - "content": "m1" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "m1" + } + ] } - ] + } } }, { diff --git a/test/fixtures/render/enum-default.json b/test/fixtures/render/enum-default.json index 73cdb0adb..6916c6767 100644 --- a/test/fixtures/render/enum-default.json +++ b/test/fixtures/render/enum-default.json @@ -116,30 +116,31 @@ "value": { "element": "enum", "attributes": { - "default": { - "element": "enum", + "enumerations": { + "element": "array", "content": [ + { + "element": "string", + "content": "a" + }, + { + "element": "string", + "content": "b" + }, { "element": "string", "content": "c" } ] - } - }, - "content": [ - { - "element": "string", - "content": "a" - }, - { - "element": "string", - "content": "b" }, - { - "element": "string", - "content": "c" + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "c" + } } - ] + } } } } diff --git a/test/fixtures/render/enum-sample.json b/test/fixtures/render/enum-sample.json index e4eb7caab..7fe24d1b4 100644 --- a/test/fixtures/render/enum-sample.json +++ b/test/fixtures/render/enum-sample.json @@ -116,35 +116,36 @@ "value": { "element": "enum", "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "a" + }, + { + "element": "string", + "content": "b" + }, + { + "element": "string", + "content": "c" + } + ] + }, "samples": { "element": "array", "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "c" - } - ] + "content": { + "element": "string", + "content": "c" + } } ] } - }, - "content": [ - { - "element": "string", - "content": "a" - }, - { - "element": "string", - "content": "b" - }, - { - "element": "string", - "content": "c" - } - ] + } } } } diff --git a/test/fixtures/render/mixin-override.json b/test/fixtures/render/mixin-override.json index dd13e8f3b..96d3699e9 100644 --- a/test/fixtures/render/mixin-override.json +++ b/test/fixtures/render/mixin-override.json @@ -288,28 +288,36 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "CREATED" - }, - { - "element": "string", - "content": "QUEUED" - }, - { - "element": "string", - "content": "RUNNING" - }, - { - "element": "string", - "content": "FINISHED" - }, - { - "element": "string", - "content": "ERROR" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string" + }, + { + "element": "string", + "content": "CREATED" + }, + { + "element": "string", + "content": "QUEUED" + }, + { + "element": "string", + "content": "RUNNING" + }, + { + "element": "string", + "content": "FINISHED" + }, + { + "element": "string", + "content": "ERROR" + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/default-attribute.json b/test/fixtures/schema/default-attribute.json index 38085333c..87a143618 100644 --- a/test/fixtures/schema/default-attribute.json +++ b/test/fixtures/schema/default-attribute.json @@ -116,32 +116,25 @@ "value": { "element": "enum", "attributes": { - "samples": { + "enumerations": { "element": "array", "content": [ { - "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" - } - ] - } - ] - }, - "default": { - "element": "enum", - "content": [ + "element": "string", + "content": "3" + }, { "element": "string", "content": "4" } ] + }, + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "4" + } } } } @@ -169,7 +162,7 @@ "content": "application/json" } }, - "content": "{\n \"list\": \"3\"\n}" + "content": "{\n \"list\": \"4\"\n}" }, { "element": "asset", diff --git a/test/fixtures/schema/default-section.json b/test/fixtures/schema/default-section.json index 06c4b1291..87a143618 100644 --- a/test/fixtures/schema/default-section.json +++ b/test/fixtures/schema/default-section.json @@ -116,26 +116,27 @@ "value": { "element": "enum", "attributes": { - "default": { - "element": "enum", + "enumerations": { + "element": "array", "content": [ + { + "element": "string", + "content": "3" + }, { "element": "string", "content": "4" } ] - } - }, - "content": [ - { - "element": "string", - "content": "3" }, - { - "element": "string", - "content": "4" + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "4" + } } - ] + } } } } diff --git a/test/fixtures/schema/enum-containing-enum.json b/test/fixtures/schema/enum-containing-enum.json index 3b6c7e649..e49bbfaee 100644 --- a/test/fixtures/schema/enum-containing-enum.json +++ b/test/fixtures/schema/enum-containing-enum.json @@ -115,37 +115,47 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "enum", + "attributes": { + "enumerations": { + "element": "array", "content": [ { - "element": "number", - "content": 1 + "element": "enum", + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number", + "content": 1 + }, + { + "element": "number", + "content": 2 + }, + { + "element": "number", + "content": 3 + }, + { + "element": "number", + "content": 4 + } + ] + } + } }, { - "element": "number", - "content": 2 + "element": "string", + "content": "something" }, { - "element": "number", - "content": 3 - }, - { - "element": "number", - "content": 4 + "element": "string", + "content": "anything" } ] - }, - { - "element": "string", - "content": "something" - }, - { - "element": "string", - "content": "anything" } - ] + } } } } diff --git a/test/fixtures/schema/enum-containing-object.json b/test/fixtures/schema/enum-containing-object.json index fc436150e..c0b8433a8 100644 --- a/test/fixtures/schema/enum-containing-object.json +++ b/test/fixtures/schema/enum-containing-object.json @@ -115,43 +115,48 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "green" - }, - { - "element": "object", + "attributes": { + "enumerations": { + "element": "array", "content": [ { - "element": "member", - "content": { - "key": { - "element": "string", - "content": "tag_id" - }, - "value": { - "element": "string", - "content": "1" - } - } + "element": "string", + "content": "green" }, { - "element": "member", - "content": { - "key": { - "element": "string", - "content": "label" + "element": "object", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "tag_id" + }, + "value": { + "element": "string", + "content": "1" + } + } }, - "value": { - "element": "string", - "content": "green" + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "label" + }, + "value": { + "element": "string", + "content": "green" + } + } } - } + ] } ] } - ] + } } } } diff --git a/test/fixtures/schema/enum-containing-sample.json b/test/fixtures/schema/enum-containing-sample.json index 2894273a1..151b275f3 100644 --- a/test/fixtures/schema/enum-containing-sample.json +++ b/test/fixtures/schema/enum-containing-sample.json @@ -115,26 +115,31 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "green" - }, - { - "element": "number", - "attributes": { - "samples": { - "element": "array", - "content": [ - { - "element": "number", - "content": 5 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "green" + }, + { + "element": "number", + "attributes": { + "samples": { + "element": "array", + "content": [ + { + "element": "number", + "content": 5 + } + ] } - ] + } } - } + ] } - ] + } } } } diff --git a/test/fixtures/schema/enum-nullable.json b/test/fixtures/schema/enum-nullable.json index fb2278d4f..c2090ae6b 100644 --- a/test/fixtures/schema/enum-nullable.json +++ b/test/fixtures/schema/enum-nullable.json @@ -126,12 +126,20 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "number", - "content": 4 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number" + }, + { + "element": "number", + "content": 4 + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/enum-of-strings.json b/test/fixtures/schema/enum-of-strings.json index 92a9242ef..40872d926 100644 --- a/test/fixtures/schema/enum-of-strings.json +++ b/test/fixtures/schema/enum-of-strings.json @@ -115,16 +115,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "male" - }, - { - "element": "string", - "content": "female" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "male" + }, + { + "element": "string", + "content": "female" + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/enum-with-type.json b/test/fixtures/schema/enum-with-type.json index 860e846cc..295d895e4 100644 --- a/test/fixtures/schema/enum-with-type.json +++ b/test/fixtures/schema/enum-with-type.json @@ -115,20 +115,28 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "number", - "content": 4 - }, - { - "element": "number", - "content": 2 - }, - { - "element": "number", - "content": 42 + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "number" + }, + { + "element": "number", + "content": 4 + }, + { + "element": "number", + "content": 2 + }, + { + "element": "number", + "content": 42 + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/object-very-complex.json b/test/fixtures/schema/object-very-complex.json index 1b8df761e..8f8ab1278 100644 --- a/test/fixtures/schema/object-very-complex.json +++ b/test/fixtures/schema/object-very-complex.json @@ -352,16 +352,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "Czech Republic" - }, - { - "element": "string", - "content": "United States of America" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "Czech Republic" + }, + { + "element": "string", + "content": "United States of America" + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/sample-inline-attribute.json b/test/fixtures/schema/sample-inline-attribute.json index b13bc3450..1cb5882dd 100644 --- a/test/fixtures/schema/sample-inline-attribute.json +++ b/test/fixtures/schema/sample-inline-attribute.json @@ -121,16 +121,21 @@ "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "3" + }, + { + "element": "string", + "content": "4" + } + ] } - ] + } } ] } diff --git a/test/fixtures/schema/sample-inline-variable.json b/test/fixtures/schema/sample-inline-variable.json index 3f7ade4f9..57f547a6c 100644 --- a/test/fixtures/schema/sample-inline-variable.json +++ b/test/fixtures/schema/sample-inline-variable.json @@ -115,16 +115,21 @@ }, "value": { "element": "enum", - "content": [ - { - "element": "string", - "content": "*3" - }, - { - "element": "string", - "content": "4*" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "*3" + }, + { + "element": "string", + "content": "4*" + } + ] } - ] + } } } } diff --git a/test/fixtures/schema/sample.json b/test/fixtures/schema/sample.json index b13bc3450..1cb5882dd 100644 --- a/test/fixtures/schema/sample.json +++ b/test/fixtures/schema/sample.json @@ -121,16 +121,21 @@ "content": [ { "element": "enum", - "content": [ - { - "element": "string", - "content": "3" - }, - { - "element": "string", - "content": "4" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "3" + }, + { + "element": "string", + "content": "4" + } + ] } - ] + } } ] } From 920359f9ee3307360c4786e2b6ddd4ac7a991bbb Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Mon, 4 Sep 2017 15:42:07 +0200 Subject: [PATCH 05/12] Enum impementation with "enumeration" attribute --- src/ElementData.h | 7 +- src/RefractAPI.cc | 1 + src/RefractDataStructure.cc | 91 ++++++--- src/RefractElementFactory.cc | 6 +- src/refract/Element.cc | 139 +++++++------ src/refract/ExpandVisitor.cc | 21 +- src/refract/JSONSchemaVisitor.cc | 31 +-- src/refract/PrintVisitor.cc | 5 +- src/refract/RenderJSONVisitor.cc | 147 +++----------- src/refract/RenderJSONVisitor.h | 2 - src/refract/VisitorUtils.h | 61 ++++++ test/fixtures/mson/enum-empty-default.json | 40 ++-- test/fixtures/mson/enum-variants.apib | 2 +- test/fixtures/mson/enum-variants.json | 2 +- .../render/enum-default-multiple.apib | 8 + .../render/enum-default-multiple.json | 188 ++++++++++++++++++ test/test-RenderTest.cc | 1 + 17 files changed, 473 insertions(+), 279 deletions(-) create mode 100644 test/fixtures/render/enum-default-multiple.apib create mode 100644 test/fixtures/render/enum-default-multiple.json diff --git a/src/ElementData.h b/src/ElementData.h index 5c8356526..38aecf4cb 100644 --- a/src/ElementData.h +++ b/src/ElementData.h @@ -19,16 +19,17 @@ namespace drafter { typedef typename ElementType::ValueType ValueType; typedef snowcrash::SourceMap ValueSourceMapType; - static const bool IsPrimitive = std::conditional< + typedef typename std::conditional< std::is_same::value || std::is_same::value, // check for primitive values - std::false_type, std::true_type>::type::value; + std::false_type, std::true_type>::type + IsPrimitive; // This is required because snowcrash internal stuctures holds data // for primitive types as "string" for complex types as "element array" // it will be converted into apropriated element typer once all required data are colected typedef typename std::conditional< - IsPrimitive, + IsPrimitive::value, std::string, // for primitive values, we will hold data as string refract::RefractElements // for complex types, we will hold elements >::type StoredType; diff --git a/src/RefractAPI.cc b/src/RefractAPI.cc index aa573413c..f5708a6f1 100644 --- a/src/RefractAPI.cc +++ b/src/RefractAPI.cc @@ -102,6 +102,7 @@ namespace drafter refract::IElement* msonElement = MSONToRefract(dataStructure, context); if (context.options.expandMSON) { + //if (true) { refract::IElement* msonExpanded = ExpandRefract(msonElement, context); msonElement = msonExpanded; } diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 29a68eb67..ef02ad70f 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -22,6 +22,9 @@ namespace drafter { + using PrimitiveType = std::true_type; + using ComplexType = std::false_type; + template struct FetchSourceMap { @@ -210,10 +213,10 @@ namespace drafter { mson::BaseTypeName elementTypeName; mson::BaseTypeName defaultNestedType; - template ::IsPrimitive> struct Fetch; + template ::IsPrimitive> struct Fetch; template - struct Fetch { + struct Fetch { ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { snowcrash::SourceMap sourceMap = FetchSourceMap()(typeSection); @@ -222,7 +225,7 @@ namespace drafter { }; template - struct Fetch { + struct Fetch { ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { return std::make_tuple(MsonElementsToRefract(MakeNodeInfo(typeSection.node->content.elements(), typeSection.sourceMap->elements()), @@ -233,10 +236,10 @@ namespace drafter { } }; - template ::IsPrimitive, bool dummy = true> struct Store; + template ::IsPrimitive, bool dummy = true> struct Store; template - struct Store { + struct Store { void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { // do nothing @@ -248,7 +251,7 @@ namespace drafter { }; template - struct Store { + struct Store { void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { data.values.push_back(Fetch()(typeSection, context, defaultNestedType)); @@ -256,7 +259,7 @@ namespace drafter { }; template - struct Store::IsPrimitive, dummy> { + struct Store::IsPrimitive, dummy> { void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { data.enumerations.push_back(Fetch()(typeSection, context, defaultNestedType)); @@ -382,10 +385,10 @@ namespace drafter { ElementData& data; const ConversionContext& context; - template ::IsPrimitive> struct Fetch; + template ::IsPrimitive> struct Fetch; template - struct Fetch { + struct Fetch { ElementInfo operator()(const mson::TypeNames& typeNames, const ConversionContext& context) { RefractElements types; @@ -407,24 +410,24 @@ namespace drafter { }; - template ::IsPrimitive, bool dummy = true> struct Store; + template ::IsPrimitive, bool dummy = true> struct Store; template - struct Store { + struct Store { void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ // do nothing } }; template - struct Store { + struct Store { void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ data.values.push_back(Fetch()(typeNames, context)); } }; template - struct Store::IsPrimitive, dummy> { + struct Store::IsPrimitive, dummy> { using E = refract::EnumElement; void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ data.enumerations.push_back(Fetch()(typeNames, context)); @@ -451,10 +454,10 @@ namespace drafter { ElementData& data; ConversionContext& context; - template ::IsPrimitive, bool dummy = true> struct Fetch; + template ::IsPrimitive, bool dummy = true> struct Fetch; template - struct Fetch { // primitive values + struct Fetch { // primitive values ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { if (valueMember.node->valueDefinition.values.size() > 1) { @@ -470,7 +473,7 @@ namespace drafter { }; template - struct Fetch { // Array|Object + struct Fetch { // Array|Object ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { @@ -490,7 +493,7 @@ namespace drafter { }; template - struct Fetch::IsPrimitive, dummy> { // Enum + struct Fetch::IsPrimitive, dummy> { // Enum ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { @@ -630,10 +633,10 @@ namespace drafter { }; - template ::IsPrimitive> struct Merge; + template ::IsPrimitive> struct Merge; template - struct Merge { + struct Merge { using ElementInfo = typename ElementData::ElementInfo; using Container = typename ElementData::ElementInfoContainer; using StoredType = typename ElementData::StoredType; @@ -648,7 +651,7 @@ namespace drafter { }; template - struct Merge { + struct Merge { using ElementInfo = typename ElementData::ElementInfo; using Container = typename ElementData::ElementInfoContainer; using StoredType = typename ElementData::StoredType; @@ -673,10 +676,10 @@ namespace drafter { } }; - template ::IsPrimitive> struct ElementInfoToElement; + template ::IsPrimitive> struct ElementInfoToElement; template - struct ElementInfoToElement { + struct ElementInfoToElement { E* operator()(const typename ElementData::ElementInfo& value) { std::pair result = LiteralTo(std::get<0>(value)); return new E(std::get<1>(result)); @@ -684,14 +687,14 @@ namespace drafter { }; template - struct ElementInfoToElement { + struct ElementInfoToElement { E* operator()(const typename ElementData::ElementInfo& value) { return new E(std::get<0>(value)); } }; template <> - struct ElementInfoToElement::IsPrimitive> { + struct ElementInfoToElement::IsPrimitive> { refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { auto v = std::get<0>(value); @@ -708,10 +711,10 @@ namespace drafter { } }; - template ::IsPrimitive> struct SaveValue; + template ::IsPrimitive> struct SaveValue; template - struct SaveValue { + struct SaveValue { using ElementInfo = typename ElementData::ElementInfo; using ValueType = typename T::ValueType; @@ -731,7 +734,7 @@ namespace drafter { }; template - struct SaveValue { + struct SaveValue { using ElementInfo = typename ElementData::ElementInfo; void operator()(const ElementData& data, T* element) { @@ -744,7 +747,7 @@ namespace drafter { }; template <> - struct SaveValue::IsPrimitive> { + struct SaveValue::IsPrimitive> { using ElementInfo = typename ElementData::ElementInfo; void operator()(const ElementData& data, refract::EnumElement* element) { @@ -785,6 +788,28 @@ namespace drafter { }; + template ::IsPrimitive> struct ReleaseStoredData; + + template + struct ReleaseStoredData { + void operator()(const typename ElementData::ElementInfoContainer& data) { + // do nothing + } + }; + + template + struct ReleaseStoredData { + void operator()(const typename ElementData::ElementInfoContainer& data) { + std::for_each(data.begin(), data.end(), + [](const typename ElementData::ElementInfo& info){ + const auto& elements = std::get<0>(info); + for_each(elements.begin(), elements.end(), + [](const refract::IElement* e) { delete e; } + ); + }); + } + }; + template struct LastElementToAttribute { @@ -796,10 +821,12 @@ namespace drafter { } ElementInfoToElement fetch; - T* value = fetch(*values.rbegin()); - - // FIXME: relese rest of elements - // it can leak if more values wil be in `values` + refract::IElement* value = fetch(*values.rbegin()); + + if (values.size() > 1) { + value = value->clone(); + ReleaseStoredData()(values); + } element->attributes[key] = value; } diff --git a/src/RefractElementFactory.cc b/src/RefractElementFactory.cc index 82a6ef1a8..27f596b87 100644 --- a/src/RefractElementFactory.cc +++ b/src/RefractElementFactory.cc @@ -8,10 +8,10 @@ namespace drafter { - template ::IsPrimitive> struct RefractElementFactoryImpl; + template ::IsPrimitive> struct RefractElementFactoryImpl; template - struct RefractElementFactoryImpl : RefractElementFactory + struct RefractElementFactoryImpl : RefractElementFactory { typedef typename E::ValueType ValueType; @@ -55,7 +55,7 @@ namespace drafter }; template - struct RefractElementFactoryImpl : RefractElementFactory + struct RefractElementFactoryImpl : RefractElementFactory { RefractElementFactoryImpl() {} diff --git a/src/refract/Element.cc b/src/refract/Element.cc index 98eb537b6..317916e33 100644 --- a/src/refract/Element.cc +++ b/src/refract/Element.cc @@ -18,28 +18,26 @@ namespace refract { - bool isReserved(const std::string& element) - { - static std::set reserved; - if (reserved.empty()) { - reserved.insert("null"); - reserved.insert("boolean"); - reserved.insert("number"); - reserved.insert("string"); + bool isReserved(const std::string& element) { + static const std::set reserved = { + "null", + "boolean", + "number", + "string", - reserved.insert("member"); + "member", - reserved.insert("array"); - reserved.insert("enum"); - reserved.insert("object"); + "array", + "enum", + "object", - reserved.insert("ref"); - reserved.insert("select"); - reserved.insert("option"); - reserved.insert("extend"); + "ref", + "select", + "option", + "extend", - reserved.insert("generic"); - } + "generic" + }; return reserved.find(element) != reserved.end(); } @@ -116,17 +114,17 @@ namespace refract return true; } - TypeQueryVisitor v; - Visit(v, *values.front()); + TypeQueryVisitor visitor; + Visit(visitor, *values.front()); + + const TypeQueryVisitor::ElementType base = visitor.get(); + + return std::all_of(values.begin(), values.end(), + [&visitor, base](const IElement* e) { + Visit(visitor,*e); + return base == visitor.get(); + }); - const TypeQueryVisitor::ElementType base = v.get(); - for (ExtendElement::ValueType::const_iterator i = values.begin(); i != values.end(); ++i) { - Visit(v, *(*i)); - if (base != v.get()) { - return false; - } - } - return true; } } @@ -192,6 +190,19 @@ namespace refract } }; + template + struct ValueMerge { + IElement*& value; + ValueMerge(T& element) : value(element.value) {} + + void operator()(const T& merge) { + if (!value && merge.value) { + value = merge.value->clone(); + } + } + }; + + /** * Merge stategy for objects/array * - if member @@ -217,19 +228,20 @@ namespace refract MapKeyToMember keysBase; MapNameToRef refBase; - for (RefractElements::iterator it = value.begin(); it != value.end(); ++it) { - if (MemberElement* member = TypeQueryVisitor::as(*it)) { + for (auto& it: value) { + if (MemberElement* member = TypeQueryVisitor::as(it)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { keysBase[key->value] = member; } - } else if (RefElement* ref = TypeQueryVisitor::as(*it)) { + } + else if (RefElement* ref = TypeQueryVisitor::as(it)) { refBase[ref->value] = ref; } } - for (RefractElements::const_iterator it = merge.value.begin(); it != merge.value.end(); ++it) { - if (MemberElement* member = TypeQueryVisitor::as(*it)) { + for (auto const& it: merge.value) { + if (MemberElement* member = TypeQueryVisitor::as(it)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { MapKeyToMember::iterator iKey = keysBase.find(key->value); @@ -237,52 +249,50 @@ namespace refract delete iKey->second->value.second; iKey->second->value.second = member->value.second->clone(); - std::set emptySet; - InfoMerge(iKey->second->meta, emptySet)(member->meta); - InfoMerge(iKey->second->attributes, emptySet)(member->attributes); - } else { // unknown key, append value + CollectionMerge(iKey->second->meta, {})(member->meta); + CollectionMerge(iKey->second->attributes, {})(member->attributes); + } + else { // unknown key, append value MemberElement* clone = static_cast(member->clone()); value.push_back(clone); keysBase[key->value] = clone; } } - } else if (RefElement* ref = TypeQueryVisitor::as(*it)) { + } + else if (RefElement* ref = TypeQueryVisitor::as(it)) { if (refBase.find(ref->value) == refBase.end()) { RefElement* clone = static_cast(member->clone()); value.push_back(clone); refBase[ref->value] = clone; } - } else if (!(*it)->empty()) { // merge member is not MemberElement, append value - value.push_back((*it)->clone()); + } + else if(!(it)->empty()) { // merge member is not MemberElement, append value + value.push_back(it->clone()); } } } }; template - class InfoMerge - { + class CollectionMerge { + using KeySet = std::set; IElement::MemberElementCollection& info; - const std::set& noMergeKeys; + const KeySet& noMergeKeys; public: - InfoMerge(IElement::MemberElementCollection& info, const std::set& noMergeKeys) - : info(info), noMergeKeys(noMergeKeys) - { - } - void operator()(const IElement::MemberElementCollection& append) - { + CollectionMerge(IElement::MemberElementCollection& info, const KeySet& noMergeKeys) : info(info), noMergeKeys(noMergeKeys) {} + + void operator()(const IElement::MemberElementCollection& append) { IElement::MemberElementCollection toAppend; - for (IElement::MemberElementCollection::const_iterator it = append.begin(); it != append.end(); - ++it) { + for (const auto& it: append) { - if (!*it) { + if (!it) { continue; } - if (StringElement* key = TypeQueryVisitor::as((*it)->value.first)) { + if (StringElement* key = TypeQueryVisitor::as(it->value.first)) { if (noMergeKeys.find(key->value) != noMergeKeys.end()) { // this key should not be merged continue; @@ -292,17 +302,16 @@ namespace refract if (item != info.end()) { // this key alrady exist, replace value delete (*item)->value.second; - (*item)->value.second = (*it)->value.second->clone(); + (*item)->value.second = it->value.second->clone(); continue; } } - toAppend.push_back(static_cast((*it)->clone())); + toAppend.push_back(static_cast(it->clone())); } - for (IElement::MemberElementCollection::const_iterator it = toAppend.begin(); it != toAppend.end(); - ++it) { - info.push_back(*it); + for (const auto& it: toAppend) { + info.push_back(it); } toAppend.clear(); @@ -318,18 +327,8 @@ namespace refract { typedef T ElementType; - // FIXME: static initialization on C++11 - static std::set noMeta; - static std::set noAttributes; - - if (noMeta.empty()) { - noMeta.insert("id"); - noMeta.insert("prefix"); - noMeta.insert("namespace"); - } - - InfoMerge(target->meta, noMeta)(append->meta); - InfoMerge(target->attributes, noAttributes)(append->attributes); + CollectionMerge(target->meta, { "id", "prefix", "namespace" })(append->meta); + CollectionMerge(target->attributes, {})(append->attributes); ValueMerge(static_cast(*target))(static_cast(*append)); } diff --git a/src/refract/ExpandVisitor.cc b/src/refract/ExpandVisitor.cc index c9d10ccbd..f1f9416f0 100644 --- a/src/refract/ExpandVisitor.cc +++ b/src/refract/ExpandVisitor.cc @@ -64,19 +64,14 @@ namespace refract } }; - // - // FIXME: it seem it is not required for implemetation - // maybe there is no EnumElement expansion in samples? - // - - //template <> - //struct ExpandValueImpl { + template <> + struct ExpandValueImpl { - // template - // IElement* const operator()(const IElement* value, Functor& expand) { - // return expand(value); - // } - //}; + template + IElement* operator()(const IElement* value, Functor& expand) { + return expand(value); + } + }; template <> struct ExpandValueImpl { @@ -134,7 +129,7 @@ namespace refract Context(const Registry& registry, ExpandVisitor* expand) : registry(registry), expand(expand) {} - IElement* ExpandOrClone(const IElement* e) + IElement* ExpandOrClone(const IElement* e) const { IElement* result = NULL; if (!e) { diff --git a/src/refract/JSONSchemaVisitor.cc b/src/refract/JSONSchemaVisitor.cc index 42d3da80d..e27085690 100644 --- a/src/refract/JSONSchemaVisitor.cc +++ b/src/refract/JSONSchemaVisitor.cc @@ -424,31 +424,36 @@ namespace refract void JSONSchemaVisitor::operator()(const EnumElement& e) { + RefractElements elms; + const auto& it = e.attributes.find("enumerations"); - if (it == e.attributes.end()) { - return; + if (it != e.attributes.end()) { + if (ArrayElement* enums = TypeQueryVisitor::as((*it)->value.second)) { + elms.insert(elms.end(), enums->value.begin(), enums->value.end()); + } + } + + if (e.value) { + elms.push_back(e.value); } - ArrayElement* enums = TypeQueryVisitor::as((*it)->value.second); - if (!enums) { + if (elms.empty()) { return; } std::map > types; std::vector typesOrder; - for (ArrayElement::ValueType::const_iterator it = enums->value.begin(); - it != enums->value.end(); - ++it) { + for (const auto& it: elms) { - if (*it) { - std::vector& items = types[(*it)->element()]; + if (it) { + std::vector& items = types[(it)->element()]; if (items.empty()) { - typesOrder.push_back((*it)->element()); + typesOrder.push_back((it)->element()); } - items.push_back(*it); + items.push_back(it); } } @@ -456,9 +461,9 @@ namespace refract anyOf(types, typesOrder); } else { const EnumElement* def = GetDefault(e); - if (!enums->empty() || (def && !def->empty())) { + if (!elms.empty() || (def && !def->empty())) { ArrayElement *a = new ArrayElement; - CloneMembers(a, &enums->value); + CloneMembers(a, &elms); setSchemaType(types.begin()->first); addMember("enum", a); } diff --git a/src/refract/PrintVisitor.cc b/src/refract/PrintVisitor.cc index ea1afc2a2..a295c88ce 100644 --- a/src/refract/PrintVisitor.cc +++ b/src/refract/PrintVisitor.cc @@ -132,7 +132,10 @@ namespace refract void PrintVisitor::operator()(const EnumElement& e) { - //printValues(e, "Enum"); + indented() << "- EnumElement " << "\n"; + if (e.value) { + PrintVisitor{indent + 1, os, ommitSourceMap}(*e.value); + } } void PrintVisitor::operator()(const ObjectElement& e) diff --git a/src/refract/RenderJSONVisitor.cc b/src/refract/RenderJSONVisitor.cc index b9facaf5e..16201aad1 100644 --- a/src/refract/RenderJSONVisitor.cc +++ b/src/refract/RenderJSONVisitor.cc @@ -16,86 +16,7 @@ namespace refract { - namespace - { - - const ArrayElement* GetEnumerations(const EnumElement& e) { - - IElement::MemberElementCollection::const_iterator i = e.attributes.find("enumerations"); - - if (i == e.attributes.end()) { - return NULL; - } - - return TypeQueryVisitor::as((*i)->value.second); - } - - IElement* GetEnumValue(const ExtendElement& extend) - { - if (extend.empty()) { - return NULL; - } - - for (ExtendElement::ValueType::const_reverse_iterator it = extend.value.rbegin(); it != extend.value.rend(); - ++it) { - - const EnumElement* element = TypeQueryVisitor::as(*it); - - if (!element) { - continue; - } - - const EnumElement::ValueType* item = GetValue(*element); - - if (item) { - return *item; - } - } - - return NULL; - } - - const IElement* GetEnumValue(const EnumElement& element) { - if (const EnumElement* s = GetSample(element)) { - return GetEnumValue(*s); - } - - if (const EnumElement* d = GetDefault(element)) { - return GetEnumValue(*d); - } - - if (!element.empty()) { - return element.value; - } - - if (const ArrayElement* e = GetEnumerations(element)) { - if (e && !e->empty()) { - for (const auto& item : e->value) { - if (!item) { - continue; - } - - // We need hadle Enum individualy because of attr["enumerations"] - if (EnumElement* val = TypeQueryVisitor::as(item)) { - const IElement* ret = GetEnumValue(*val); - if (ret) { - return ret; - } - } - - if (!item->empty()) { - return item; - } - } - } - } - - if (element.empty() && IsTypeAttribute(element, "nullable")) { - return NULL; - } - - return element.value; - } + namespace { template void FetchMembers(const T& element, typename T::ValueType& members) @@ -106,7 +27,9 @@ namespace refract return; } - for (typename T::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { + for (typename T::ValueType::const_iterator it = val->begin(); + it != val->end(); + ++it) { if (!(*it) || (*it)->empty()) { continue; @@ -115,7 +38,8 @@ namespace refract if (RefElement* ref = TypeQueryVisitor::as(*it)) { HandleRefWhenFetchingMembers(ref, members, FetchMembers); continue; - } else if (SelectElement* select = TypeQueryVisitor::as(*it)) { + } + else if (SelectElement* select = TypeQueryVisitor::as(*it)) { if (select->value.empty() || !(*select->value.begin())) { continue; } @@ -135,21 +59,15 @@ namespace refract members.push_back(e); } } - } - RenderJSONVisitor::RenderJSONVisitor() : result(NULL), enumValue(NULL) - { } - RenderJSONVisitor::~RenderJSONVisitor() - { + RenderJSONVisitor::RenderJSONVisitor() : result(nullptr) {} + + RenderJSONVisitor::~RenderJSONVisitor() { if (result) { delete result; } - - if (enumValue) { - delete enumValue; - } } void RenderJSONVisitor::operator()(const IElement& e) @@ -189,8 +107,7 @@ namespace refract result = new MemberElement(key, renderer.result ? renderer.getOwnership() : new StringElement); } - void RenderJSONVisitor::operator()(const ObjectElement& e) - { + void RenderJSONVisitor::operator()(const ObjectElement& e) { ObjectElement::ValueType members; FetchMembers(e, members); ObjectElement* o = new ObjectElement; @@ -198,27 +115,21 @@ namespace refract result = o; } - void RenderJSONVisitor::operator()(const EnumElement& e) - { + void RenderJSONVisitor::operator()(const EnumElement& e) { - if (!enumValue) { // there is no enumValue injected from ExtendElement,try to pick value directly - - const IElement* val = GetEnumValue(e); - if (val && !val->empty()) { - enumValue = val->clone(); - } - else { - enumValue = new StringElement; - } + const IElement* val = GetValue(e); + if (val && !val->empty()) { + val = val->clone(); + } + else { + val = new StringElement; } - RenderJSONVisitor renderer; - VisitBy(*enumValue, renderer); + VisitBy(*val, renderer); result = renderer.getOwnership(); - delete enumValue; - enumValue = NULL; + delete val; } void RenderJSONVisitor::operator()(const ArrayElement& e) @@ -241,7 +152,7 @@ namespace refract const typename T::ValueType* v = GetValue(e); if (!v) { - return NULL; + return nullptr; } T* result = IElement::Create(*v); @@ -274,25 +185,17 @@ namespace refract return; } - if (TypeQueryVisitor::as(merged)) { - renderer.enumValue = GetEnumValue(e); - if (renderer.enumValue) { - renderer.enumValue = renderer.enumValue->clone(); - } - } - Visit(renderer, *merged); result = renderer.getOwnership(); delete merged; } - IElement* RenderJSONVisitor::getOwnership() - { - IElement* ret = result; - result = NULL; - return ret; - } + IElement* RenderJSONVisitor::getOwnership() { + IElement* ret = result; + result = nullptr; + return ret; + } std::string RenderJSONVisitor::getString() const { diff --git a/src/refract/RenderJSONVisitor.h b/src/refract/RenderJSONVisitor.h index 4392e3fbc..7b17d1e8d 100644 --- a/src/refract/RenderJSONVisitor.h +++ b/src/refract/RenderJSONVisitor.h @@ -20,8 +20,6 @@ namespace refract class RenderJSONVisitor { IElement* result; - IElement* enumValue; - public: RenderJSONVisitor(); virtual ~RenderJSONVisitor(); diff --git a/src/refract/VisitorUtils.h b/src/refract/VisitorUtils.h index a30a8bc80..0569b8d99 100644 --- a/src/refract/VisitorUtils.h +++ b/src/refract/VisitorUtils.h @@ -131,6 +131,67 @@ namespace refract } }; + template<> + struct GetValue { + using EnumElement = refract::EnumElement; + const EnumElement& element; + + GetValue(const EnumElement& e) : element(e) {} + + operator const IElement*() { + return GetEnumValue(element); + } + + IElement* GetEnumValue(const EnumElement& element) { + if (const EnumElement* s = GetSample(element)) { + return GetEnumValue(*s); + } + + if (const EnumElement* d = GetDefault(element)) { + return GetEnumValue(*d); + } + + if (element.value) { + return element.value; + } + + if (const ArrayElement* e = GetEnumerations(element)) { + if (e && !e->empty()) { + for (const auto& item : e->value) { + if (!item) { + continue; + } + + // We need hadle Enum individualy because of attr["enumerations"] + if (EnumElement* val = TypeQueryVisitor::as(item)) { + IElement* ret = GetEnumValue(*val); + if (ret) { + return ret; + } + } + + if (!item->empty()) { + return item; + } + } + } + } + + return element.value; + } + + const ArrayElement* GetEnumerations(const EnumElement& e) { + + IElement::MemberElementCollection::const_iterator i = e.attributes.find("enumerations"); + + if (i == e.attributes.end()) { + return nullptr; + } + + return TypeQueryVisitor::as((*i)->value.second); + } + }; + // will be moved into different header (as part of drafter instead of refract) template diff --git a/test/fixtures/mson/enum-empty-default.json b/test/fixtures/mson/enum-empty-default.json index b53bca21e..d8cadec44 100644 --- a/test/fixtures/mson/enum-empty-default.json +++ b/test/fixtures/mson/enum-empty-default.json @@ -125,17 +125,19 @@ "value": { "element": "enum", "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "regular" + } + ] + }, "default": { - "element": "enum", - "content": [] + "element": "enum" } - }, - "content": [ - { - "element": "string", - "content": "regular" - } - ] + } } } } @@ -234,17 +236,19 @@ "value": { "element": "enum", "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "regular" + } + ] + }, "default": { - "element": "enum", - "content": [] + "element": "enum" } - }, - "content": [ - { - "element": "string", - "content": "regular" - } - ] + } } } } diff --git a/test/fixtures/mson/enum-variants.apib b/test/fixtures/mson/enum-variants.apib index 456832d33..7de8a8656 100644 --- a/test/fixtures/mson/enum-variants.apib +++ b/test/fixtures/mson/enum-variants.apib @@ -65,7 +65,7 @@ - M - N -- size16: A (enum) - C: 'A', E: ['D','E'], S: {E: ['F','G']} +- size16: A (enum) - C: 'A', E: ['D','E'], S: {E: ['F','G']}, D: 'H' - D - E diff --git a/test/fixtures/mson/enum-variants.json b/test/fixtures/mson/enum-variants.json index 0d24085be..089486ea4 100644 --- a/test/fixtures/mson/enum-variants.json +++ b/test/fixtures/mson/enum-variants.json @@ -640,7 +640,7 @@ "meta": { "description": { "element": "string", - "content": "C: 'A', E: ['D','E'], S: {E: ['F','G']}" + "content": "C: 'A', E: ['D','E'], S: {E: ['F','G']}, D: 'H'" } }, "content": { diff --git a/test/fixtures/render/enum-default-multiple.apib b/test/fixtures/render/enum-default-multiple.apib new file mode 100644 index 000000000..ffa73c927 --- /dev/null +++ b/test/fixtures/render/enum-default-multiple.apib @@ -0,0 +1,8 @@ +# GET / + ++ Response 200 (application/json) + + Attributes + + enumField (enum) + + Default: e + + Default: f + + Default: g diff --git a/test/fixtures/render/enum-default-multiple.json b/test/fixtures/render/enum-default-multiple.json new file mode 100644 index 000000000..5a80cc093 --- /dev/null +++ b/test/fixtures/render/enum-default-multiple.json @@ -0,0 +1,188 @@ +{ + "element": "parseResult", + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "api" + } + ] + }, + "title": { + "element": "string", + "content": "" + } + }, + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "resourceGroup" + } + ] + }, + "title": { + "element": "string", + "content": "" + } + }, + "content": [ + { + "element": "resource", + "meta": { + "title": { + "element": "string", + "content": "" + } + }, + "attributes": { + "href": { + "element": "string", + "content": "/" + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + }, + "content": [] + }, + { + "element": "httpResponse", + "attributes": { + "statusCode": { + "element": "string", + "content": "200" + }, + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "Content-Type" + }, + "value": { + "element": "string", + "content": "application/json" + } + } + } + ] + } + }, + "content": [ + { + "element": "dataStructure", + "content": { + "element": "object", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "enumField" + }, + "value": { + "element": "enum", + "attributes": { + "default": { + "element": "enum", + "content": { + "element": "string", + "content": "g" + } + } + } + } + } + } + ] + } + }, + { + "element": "asset", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "messageBody" + } + ] + } + }, + "attributes": { + "contentType": { + "element": "string", + "content": "application/json" + } + }, + "content": "{\n \"enumField\": \"g\"\n}" + }, + { + "element": "asset", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "messageBodySchema" + } + ] + } + }, + "attributes": { + "contentType": { + "element": "string", + "content": "application/schema+json" + } + }, + "content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"enumField\": {}\n }\n}" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/test-RenderTest.cc b/test/test-RenderTest.cc index 153cf8195..97004e795 100644 --- a/test/test-RenderTest.cc +++ b/test/test-RenderTest.cc @@ -35,6 +35,7 @@ TEST_REFRACT("render", "override"); TEST_REFRACT("render", "action-request-attributes"); TEST_REFRACT("render", "object-array-string"); TEST_REFRACT("render", "enum-default"); +TEST_REFRACT("render", "enum-default-multiple"); TEST_REFRACT("render", "enum-sample"); TEST_REFRACT("render", "array-fixed-values"); From 52c8f52bebce11f7cf948fe9dc6b7f1387b650c0 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Mon, 4 Sep 2017 15:51:37 +0200 Subject: [PATCH 06/12] Enum update fixture outputs according to enum "enumertations" impl --- .../attributes-named-type-enum-reference.json | 25 +++++++------ test/fixtures/circular/array-in-object.json | 2 +- test/fixtures/circular/array.json | 2 +- test/fixtures/circular/enum.json | 21 ++++++----- test/fixtures/extend/circular.json | 36 ++++++++++++------- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/test/fixtures/api/attributes-named-type-enum-reference.json b/test/fixtures/api/attributes-named-type-enum-reference.json index 30236fcd1..d76a8cc73 100644 --- a/test/fixtures/api/attributes-named-type-enum-reference.json +++ b/test/fixtures/api/attributes-named-type-enum-reference.json @@ -64,12 +64,10 @@ }, "value": { "element": "B", - "content": [ - { - "element": "string", - "content": "valueA" - } - ] + "content": { + "element": "string", + "content": "valueA" + } } } } @@ -86,12 +84,17 @@ "content": "B" } }, - "content": [ - { - "element": "string", - "content": "valueB" + "attributes": { + "enumerations": { + "element": "array", + "content": [ + { + "element": "string", + "content": "valueB" + } + ] } - ] + } } } ] diff --git a/test/fixtures/circular/array-in-object.json b/test/fixtures/circular/array-in-object.json index 7195b7eb7..7c961669d 100644 --- a/test/fixtures/circular/array-in-object.json +++ b/test/fixtures/circular/array-in-object.json @@ -126,7 +126,7 @@ "content": "application/json" } }, - "content": "{\n \"id\": \"1\",\n \"data\": [\n {}\n ]\n}" + "content": "{\n \"id\": \"1\",\n \"data\": []\n}" }, { "element": "asset", diff --git a/test/fixtures/circular/array.json b/test/fixtures/circular/array.json index 6840b2371..6b7afe948 100644 --- a/test/fixtures/circular/array.json +++ b/test/fixtures/circular/array.json @@ -126,7 +126,7 @@ "content": "application/json" } }, - "content": "[\n \"1\",\n []\n]" + "content": "[\n \"1\"\n]" }, { "element": "asset", diff --git a/test/fixtures/circular/enum.json b/test/fixtures/circular/enum.json index 3edb7bc22..913bdae5c 100644 --- a/test/fixtures/circular/enum.json +++ b/test/fixtures/circular/enum.json @@ -126,7 +126,7 @@ "content": "application/json" } }, - "content": "{\n \"id\": \"1\",\n \"data\": {}\n}" + "content": "{\n \"id\": \"1\",\n \"data\": []\n}" }, { "element": "asset", @@ -147,7 +147,7 @@ "content": "application/schema+json" } }, - "content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"data\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {}\n },\n {\n \"type\": \"array\",\n \"enum\": [\n [\n {}\n ]\n ]\n }\n ]\n }\n }\n}" + "content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"data\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {}\n },\n {\n \"type\": \"array\",\n \"enum\": [\n []\n ]\n }\n ]\n }\n }\n}" } ] } @@ -183,19 +183,24 @@ "content": "E" } }, - "content": [ - { - "element": "A" - }, - { + "attributes": { + "enumerations": { "element": "array", "content": [ { "element": "A" + }, + { + "element": "array", + "content": [ + { + "element": "A" + } + ] } ] } - ] + } } }, { diff --git a/test/fixtures/extend/circular.json b/test/fixtures/extend/circular.json index ac6f5194c..e2d4d5e9a 100644 --- a/test/fixtures/extend/circular.json +++ b/test/fixtures/extend/circular.json @@ -134,7 +134,7 @@ "content": "application/json" } }, - "content": "[\n \"\",\n \"\"\n]" + "content": "[\n [],\n []\n]" }, { "element": "asset", @@ -191,19 +191,24 @@ "content": "A" } }, - "content": [ - { - "element": "B" - }, - { + "attributes": { + "enumerations": { "element": "array", "content": [ { "element": "B" + }, + { + "element": "array", + "content": [ + { + "element": "B" + } + ] } ] } - ] + } } }, { @@ -216,19 +221,24 @@ "content": "B" } }, - "content": [ - { - "element": "A" - }, - { + "attributes": { + "enumerations": { "element": "array", "content": [ { "element": "A" + }, + { + "element": "array", + "content": [ + { + "element": "A" + } + ] } ] } - ] + } } } ] From a80d79d749c553d23527a00b3934789f3057dad0 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Tue, 5 Sep 2017 17:34:27 +0200 Subject: [PATCH 07/12] Fix memory leak --- src/RefractDataStructure.cc | 55 +++++++++++-------- .../check-bool-number-value-validity.json | 6 +- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index ef02ad70f..1cf7399ed 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -682,7 +682,9 @@ namespace drafter { struct ElementInfoToElement { E* operator()(const typename ElementData::ElementInfo& value) { std::pair result = LiteralTo(std::get<0>(value)); - return new E(std::get<1>(result)); + return result.first + ? new E(std::get<1>(result)) + : new E; } }; @@ -766,6 +768,31 @@ namespace drafter { } }; + + template ::IsPrimitive> struct ReleaseStoredData; + + template + struct ReleaseStoredData { + template + void operator()(const I1& begin, const I2& end) { + // do nothing + } + }; + + template + struct ReleaseStoredData { + template + void operator()(const I1& begin, const I2& end) { + std::for_each(begin, end, + [](const typename ElementData::ElementInfo& info){ + const auto& elements = std::get<0>(info); + for_each(elements.begin(), elements.end(), + [](const refract::IElement* e) { delete e; } + ); + }); + } + }; + template struct AllElementsToAtribute { @@ -784,30 +811,9 @@ namespace drafter { } element->attributes[key] = a; - } - }; - - template ::IsPrimitive> struct ReleaseStoredData; - - template - struct ReleaseStoredData { - void operator()(const typename ElementData::ElementInfoContainer& data) { - // do nothing } - }; - template - struct ReleaseStoredData { - void operator()(const typename ElementData::ElementInfoContainer& data) { - std::for_each(data.begin(), data.end(), - [](const typename ElementData::ElementInfo& info){ - const auto& elements = std::get<0>(info); - for_each(elements.begin(), elements.end(), - [](const refract::IElement* e) { delete e; } - ); - }); - } }; template @@ -824,8 +830,9 @@ namespace drafter { refract::IElement* value = fetch(*values.rbegin()); if (values.size() > 1) { - value = value->clone(); - ReleaseStoredData()(values); + auto begin = values.rbegin(); + begin++; // avoid last one + ReleaseStoredData()(begin, values.rend()); } element->attributes[key] = value; diff --git a/test/fixtures/mson/check-bool-number-value-validity.json b/test/fixtures/mson/check-bool-number-value-validity.json index 1bd2dac57..ca3e869c5 100644 --- a/test/fixtures/mson/check-bool-number-value-validity.json +++ b/test/fixtures/mson/check-bool-number-value-validity.json @@ -79,8 +79,7 @@ "element": "array", "content": [ { - "element": "number", - "content": 0 + "element": "number" } ] } @@ -117,8 +116,7 @@ "content": 3 }, { - "element": "number", - "content": 0 + "element": "number" } ] } From 3bae76b4760f652ea137ef0a14b9f6f33715a362 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Wed, 6 Sep 2017 10:17:30 +0200 Subject: [PATCH 08/12] Commit missing file --- test/test-ElementDataTest.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/test-ElementDataTest.cc diff --git a/test/test-ElementDataTest.cc b/test/test-ElementDataTest.cc new file mode 100644 index 000000000..7df63f727 --- /dev/null +++ b/test/test-ElementDataTest.cc @@ -0,0 +1,29 @@ +#include "catch.hpp" + +#include "ElementData.h" + +using namespace refract; +using namespace drafter; + +TEST_CASE("Check Complex/Primitive data","[ElementData]") { + + REQUIRE(ElementData::IsPrimitive::value == true); + + REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE(ElementData::IsPrimitive::value == true); + + REQUIRE(ElementData::IsPrimitive::value == true); // probably invalid, but not used while conversion (maybe static assert?) + + REQUIRE(ElementData::IsPrimitive::value == true); + + REQUIRE(ElementData::IsPrimitive::value == false); + REQUIRE(ElementData::IsPrimitive::value == false); + REQUIRE(ElementData::IsPrimitive::value == false); + + REQUIRE(ElementData::IsPrimitive::value == false); + REQUIRE(ElementData::IsPrimitive::value == true); + + REQUIRE(ElementData::IsPrimitive::value == false); + +} From e5fb8a795e3cbb299cc2f2f56fac1b392f8a6c65 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Thu, 7 Sep 2017 11:19:01 +0200 Subject: [PATCH 09/12] Review requests --- src/ElementData.h | 5 +---- src/RefractAPI.cc | 1 - src/RefractDataStructure.cc | 11 +++++------ src/refract/ExpandVisitor.cc | 7 +++---- src/refract/RenderJSONVisitor.cc | 2 +- src/refract/VisitorUtils.h | 2 +- test/test-ElementDataTest.cc | 24 ++++++++++++------------ 7 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/ElementData.h b/src/ElementData.h index 38aecf4cb..247245726 100644 --- a/src/ElementData.h +++ b/src/ElementData.h @@ -26,7 +26,7 @@ namespace drafter { // This is required because snowcrash internal stuctures holds data // for primitive types as "string" for complex types as "element array" - // it will be converted into apropriated element typer once all required data are colected + // it will be converted into apropriated element type once all required data are colected typedef typename std::conditional< IsPrimitive::value, @@ -46,9 +46,6 @@ namespace drafter { ElementInfoContainer enumerations; DescriptionInfoContainer descriptions; - - //std::vector descriptions; - //std::vector > descriptionsSourceMap; }; } // namespace drafter diff --git a/src/RefractAPI.cc b/src/RefractAPI.cc index f5708a6f1..aa573413c 100644 --- a/src/RefractAPI.cc +++ b/src/RefractAPI.cc @@ -102,7 +102,6 @@ namespace drafter refract::IElement* msonElement = MSONToRefract(dataStructure, context); if (context.options.expandMSON) { - //if (true) { refract::IElement* msonExpanded = ExpandRefract(msonElement, context); msonElement = msonExpanded; } diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 1cf7399ed..72f062f51 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -415,7 +415,7 @@ namespace drafter { template struct Store { void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ - // do nothing + // do nothing - Primitive types does not contain TypeDefinitions } }; @@ -479,14 +479,13 @@ namespace drafter { const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); - const RefractElementFactory& f = FactoryFromType(type); + const RefractElementFactory& factory = FactoryFromType(type); const mson::Values& values = valueMember.node->valueDefinition.values; RefractElements elements; - - for (mson::Values::const_iterator it = values.begin(); it != values.end(); ++it) { - elements.push_back(f.Create(it->literal, it->variable ? eSample : eValue)); - } + std::transform(values.begin(), values.end(), + std::back_inserter(elements), + [&factory](const mson::Value& value){ return factory.Create(value.literal, value.variable ? eSample : eValue); }); return std::make_tuple(elements, FetchSourceMap()(valueMember)); } diff --git a/src/refract/ExpandVisitor.cc b/src/refract/ExpandVisitor.cc index f1f9416f0..c605dfb68 100644 --- a/src/refract/ExpandVisitor.cc +++ b/src/refract/ExpandVisitor.cc @@ -80,10 +80,9 @@ namespace refract RefractElements operator()(const RefractElements& value, Functor& expand) { RefractElements members; - - for (auto const& item: value) { - members.push_back(expand(item)); - } + std::transform(value.begin(), value.end(), + std::back_inserter(members), + expand); return members; } diff --git a/src/refract/RenderJSONVisitor.cc b/src/refract/RenderJSONVisitor.cc index 16201aad1..4d0c1174d 100644 --- a/src/refract/RenderJSONVisitor.cc +++ b/src/refract/RenderJSONVisitor.cc @@ -88,7 +88,7 @@ namespace refract if (e.value.second) { if (EnumElement* enm = TypeQueryVisitor::as(e.value.second)) { - // We nned nadle Enum individualy because of attr["enumerations"] + // We need to handle Enum individualy because of attr["enumerations"] Visit(renderer, *enm); } else if (IsTypeAttribute(e, "nullable") && e.value.second->empty()) { diff --git a/src/refract/VisitorUtils.h b/src/refract/VisitorUtils.h index 0569b8d99..6cd8ee802 100644 --- a/src/refract/VisitorUtils.h +++ b/src/refract/VisitorUtils.h @@ -162,7 +162,7 @@ namespace refract continue; } - // We need hadle Enum individualy because of attr["enumerations"] + // We need to hadle Enum individualy because of attr["enumerations"] if (EnumElement* val = TypeQueryVisitor::as(item)) { IElement* ret = GetEnumValue(*val); if (ret) { diff --git a/test/test-ElementDataTest.cc b/test/test-ElementDataTest.cc index 7df63f727..42c0a83a3 100644 --- a/test/test-ElementDataTest.cc +++ b/test/test-ElementDataTest.cc @@ -7,23 +7,23 @@ using namespace drafter; TEST_CASE("Check Complex/Primitive data","[ElementData]") { - REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value == true); - REQUIRE(ElementData::IsPrimitive::value == true); - REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE(ElementData::IsPrimitive::value); + REQUIRE(ElementData::IsPrimitive::value); + REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value == true); // probably invalid, but not used while conversion (maybe static assert?) + REQUIRE(ElementData::IsPrimitive::value); // probably invalid, but not used while conversion (maybe static assert?) - REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value == false); - REQUIRE(ElementData::IsPrimitive::value == false); - REQUIRE(ElementData::IsPrimitive::value == false); + REQUIRE_FALSE(ElementData::IsPrimitive::value); + REQUIRE_FALSE(ElementData::IsPrimitive::value); + REQUIRE_FALSE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value == false); - REQUIRE(ElementData::IsPrimitive::value == true); + REQUIRE_FALSE(ElementData::IsPrimitive::value); + REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value == false); + REQUIRE_FALSE(ElementData::IsPrimitive::value); } From cae28cd8fd697d38fefe6cff6a9d7f91702ddbb6 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Thu, 7 Sep 2017 11:19:53 +0200 Subject: [PATCH 10/12] Update integration test fixtures --- features/fixtures/refract.sourcemap.json | 50 ++++++++++++++++++++++++ features/fixtures/refract.sourcemap.yaml | 32 +++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/features/fixtures/refract.sourcemap.json b/features/fixtures/refract.sourcemap.json index a6477db45..bb1ab01a8 100644 --- a/features/fixtures/refract.sourcemap.json +++ b/features/fixtures/refract.sourcemap.json @@ -609,6 +609,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 200 + }, + { + "element": "number", + "content": 102 + } + ] + } + ] + } + ] + } + }, "content": "" } }, @@ -3086,6 +3111,31 @@ "meta": { "description": { "element": "string", + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "content": 1647 + }, + { + "element": "number", + "content": 117 + } + ] + } + ] + } + ] + } + }, "content": "" } }, diff --git a/features/fixtures/refract.sourcemap.yaml b/features/fixtures/refract.sourcemap.yaml index bbdaaa48f..048a3fc13 100644 --- a/features/fixtures/refract.sourcemap.yaml +++ b/features/fixtures/refract.sourcemap.yaml @@ -400,6 +400,22 @@ content: meta: description: element: "string" + attributes: + sourceMap: + element: "array" + content: + - + element: "sourceMap" + content: + - + element: "array" + content: + - + element: "number" + content: 200 + - + element: "number" + content: 102 content: "" content: key: @@ -2013,6 +2029,22 @@ content: meta: description: element: "string" + attributes: + sourceMap: + element: "array" + content: + - + element: "sourceMap" + content: + - + element: "array" + content: + - + element: "number" + content: 1647 + - + element: "number" + content: 117 content: "" content: key: From 68f0aae21bf19c7ea1025f14018e3d4cbf51c01e Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Wed, 13 Sep 2017 12:10:01 +0200 Subject: [PATCH 11/12] Reformat according to clang-format --- src/ConversionContext.h | 10 +- src/ElementData.h | 23 +- src/RefractDataStructure.cc | 519 +++++++++++++++++-------------- src/RefractElementFactory.cc | 56 ++-- src/refract/Element.cc | 65 ++-- src/refract/Element.h | 17 +- src/refract/ExpandVisitor.cc | 22 +- src/refract/JSONSchemaVisitor.cc | 15 +- src/refract/PrintVisitor.cc | 5 +- src/refract/RenderJSONVisitor.cc | 41 +-- src/refract/RenderJSONVisitor.h | 1 + src/refract/VisitorUtils.h | 18 +- 12 files changed, 437 insertions(+), 355 deletions(-) diff --git a/src/ConversionContext.h b/src/ConversionContext.h index 04c3adbbc..c555beee9 100644 --- a/src/ConversionContext.h +++ b/src/ConversionContext.h @@ -24,8 +24,14 @@ namespace drafter const WrapperOptions& options; std::vector warnings; - inline refract::Registry& GetNamedTypesRegistry() { return registry; } - inline const refract::Registry& GetNamedTypesRegistry() const { return registry; } + inline refract::Registry& GetNamedTypesRegistry() + { + return registry; + } + inline const refract::Registry& GetNamedTypesRegistry() const + { + return registry; + } ConversionContext(const WrapperOptions& options) : options(options) { diff --git a/src/ElementData.h b/src/ElementData.h index 247245726..62d261551 100644 --- a/src/ElementData.h +++ b/src/ElementData.h @@ -10,7 +10,8 @@ #include "RefractSourceMap.h" -namespace drafter { +namespace drafter +{ template struct ElementData { @@ -19,22 +20,21 @@ namespace drafter { typedef typename ElementType::ValueType ValueType; typedef snowcrash::SourceMap ValueSourceMapType; - typedef typename std::conditional< - std::is_same::value || std::is_same::value, // check for primitive values - std::false_type, std::true_type>::type - IsPrimitive; + typedef typename std::conditional::value + || std::is_same::value, // check for primitive values + std::false_type, + std::true_type>::type IsPrimitive; - // This is required because snowcrash internal stuctures holds data + // This is required because snowcrash internal stuctures holds data // for primitive types as "string" for complex types as "element array" // it will be converted into apropriated element type once all required data are colected - - typedef typename std::conditional< - IsPrimitive::value, - std::string, // for primitive values, we will hold data as string + + typedef typename std::conditional::type StoredType; - typedef std::tuple ElementInfo; // [value, sourceMap] + typedef std::tuple ElementInfo; // [value, sourceMap] typedef std::tuple > DescriptionInfo; // [description, sourceMap] typedef std::vector ElementInfoContainer; @@ -51,4 +51,3 @@ namespace drafter { } // namespace drafter #endif // #ifndef DRAFTER_ELEMENTDATA_H - diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 72f062f51..0bab5646a 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -20,7 +20,8 @@ #include "ElementData.h" -namespace drafter { +namespace drafter +{ using PrimitiveType = std::true_type; using ComplexType = std::false_type; @@ -28,13 +29,15 @@ namespace drafter { template struct FetchSourceMap { - snowcrash::SourceMap operator()(const NodeInfo& valueMember) { + snowcrash::SourceMap operator()(const NodeInfo& valueMember) + { snowcrash::SourceMap sourceMap = *NodeInfo::NullSourceMap(); sourceMap.sourceMap = valueMember.sourceMap->valueDefinition.sourceMap; return sourceMap; } - snowcrash::SourceMap operator()(const NodeInfo& typeSection) { + snowcrash::SourceMap operator()(const NodeInfo& typeSection) + { snowcrash::SourceMap sourceMap = *NodeInfo::NullSourceMap(); sourceMap.sourceMap = typeSection.sourceMap->value.sourceMap; return sourceMap; @@ -46,7 +49,8 @@ namespace drafter { typedef typename ElementData::ElementInfo ElementInfo; - void operator()(const ElementInfo&, ConversionContext&) { + void operator()(const ElementInfo&, ConversionContext&) + { // do nothing } }; @@ -57,12 +61,16 @@ namespace drafter { typedef typename ElementData::ElementInfo ElementInfo; typedef typename refract::NumberElement::ValueType ValueType; - void operator()(const ElementInfo& value, ConversionContext& context) { + void operator()(const ElementInfo& value, ConversionContext& context) + { std::pair result = LiteralTo(std::get<0>(value)); if (!std::get<0>(result)) { - context.warn(snowcrash::Warning("invalid value format for 'number' type. please check mson specification for valid format", snowcrash::MSONError, std::get<1>(value).sourceMap)); + context.warn(snowcrash::Warning( + "invalid value format for 'number' type. please check mson specification for valid format", + snowcrash::MSONError, + std::get<1>(value).sourceMap)); } } }; @@ -73,11 +81,15 @@ namespace drafter { typedef typename ElementData::ElementInfo ElementInfo; typedef typename refract::BooleanElement::ValueType ValueType; - void operator()(const ElementInfo& value, ConversionContext& context) { + void operator()(const ElementInfo& value, ConversionContext& context) + { std::pair result = LiteralTo(std::get<0>(value)); if (!std::get<0>(result)) { - context.warn(snowcrash::Warning("invalid value for 'boolean' type. allowed values are 'true' or 'false'", snowcrash::MSONError, std::get<1>(value).sourceMap)); + context.warn( + snowcrash::Warning("invalid value for 'boolean' type. allowed values are 'true' or 'false'", + snowcrash::MSONError, + std::get<1>(value).sourceMap)); } } }; @@ -91,7 +103,8 @@ namespace drafter { } } - static mson::BaseTypeName NamedTypeFromElement(const refract::IElement* element) { + static mson::BaseTypeName NamedTypeFromElement(const refract::IElement* element) + { refract::TypeQueryVisitor type; refract::Visit(type, *element); @@ -121,8 +134,9 @@ namespace drafter { return mson::UndefinedTypeName; } - template - static mson::BaseTypeName GetType(const T& type, ConversionContext& context) { + template + static mson::BaseTypeName GetType(const T& type, ConversionContext& context) + { mson::BaseTypeName nameType = type.typeDefinition.typeSpecification.name.base; const std::string& parent = type.typeDefinition.typeSpecification.name.symbol.literal; @@ -168,21 +182,28 @@ namespace drafter { return attr; } - static refract::IElement* MsonElementToRefract(const NodeInfo& mse, ConversionContext& context, mson::BaseTypeName defaultNestedType = mson::StringTypeName); + static refract::IElement* MsonElementToRefract(const NodeInfo& mse, + ConversionContext& context, + mson::BaseTypeName defaultNestedType = mson::StringTypeName); - RefractElements MsonElementsToRefract(const NodeInfo& elements, ConversionContext& context, mson::BaseTypeName defaultNestedType = mson::StringTypeName) + RefractElements MsonElementsToRefract(const NodeInfo& elements, + ConversionContext& context, + mson::BaseTypeName defaultNestedType = mson::StringTypeName) { RefractElements result; NodeInfoCollection elementsNodeInfo(elements); - std::transform(elementsNodeInfo.begin(), elementsNodeInfo.end(), - std::back_inserter(result), - std::bind(MsonElementToRefract, std::placeholders::_1, std::ref(context), defaultNestedType)); + std::transform(elementsNodeInfo.begin(), + elementsNodeInfo.end(), + std::back_inserter(result), + std::bind(MsonElementToRefract, std::placeholders::_1, std::ref(context), defaultNestedType)); return result; } - static mson::BaseTypeName SelectNestedTypeSpecification(const mson::TypeNames& nestedTypes, const mson::BaseTypeName defaultNestedType = mson::StringTypeName) { + static mson::BaseTypeName SelectNestedTypeSpecification( + const mson::TypeNames& nestedTypes, const mson::BaseTypeName defaultNestedType = mson::StringTypeName) + { mson::BaseTypeName type = defaultNestedType; // Found if type of element is specified. // if more types is used - fallback to "StringType" @@ -206,61 +227,78 @@ namespace drafter { using ValueType = typename T::ValueType; using ElementInfo = typename ElementData::ElementInfo; - ElementData& data; ConversionContext& context; mson::BaseTypeName elementTypeName; mson::BaseTypeName defaultNestedType; - template ::IsPrimitive> struct Fetch; + template ::IsPrimitive> + struct Fetch; template struct Fetch { - ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { + ElementInfo operator()(const NodeInfo& typeSection, + ConversionContext& context, + const mson::BaseTypeName& defaultNestedType) + { snowcrash::SourceMap sourceMap = FetchSourceMap()(typeSection); return std::make_tuple(typeSection.node->content.value, sourceMap); } }; - template + template struct Fetch { - ElementInfo operator()(const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType) { + ElementInfo operator()(const NodeInfo& typeSection, + ConversionContext& context, + const mson::BaseTypeName& defaultNestedType) + { return std::make_tuple(MsonElementsToRefract(MakeNodeInfo(typeSection.node->content.elements(), - typeSection.sourceMap->elements()), - context, - defaultNestedType), - FetchSourceMap()(typeSection) - ); + typeSection.sourceMap->elements()), + context, + defaultNestedType), + FetchSourceMap()(typeSection)); } }; - template ::IsPrimitive, bool dummy = true> struct Store; + template ::IsPrimitive, bool dummy = true> + struct Store; - template + template struct Store { - void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + void operator()(ElementData& data, + const NodeInfo& typeSection, + ConversionContext& context, + const mson::BaseTypeName& defaultNestedType) + { // do nothing // Primitives should not contain members // this is to avoid push "empty" elements to primitives // it is related to test/fixtures/mson/primitive-with-members.apib - } }; - template + template struct Store { - void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + void operator()(ElementData& data, + const NodeInfo& typeSection, + ConversionContext& context, + const mson::BaseTypeName& defaultNestedType) + { data.values.push_back(Fetch()(typeSection, context, defaultNestedType)); } }; - template + template struct Store::IsPrimitive, dummy> { - void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, const mson::BaseTypeName& defaultNestedType ) { + void operator()(ElementData& data, + const NodeInfo& typeSection, + ConversionContext& context, + const mson::BaseTypeName& defaultNestedType) + { data.enumerations.push_back(Fetch()(typeSection, context, defaultNestedType)); } @@ -269,31 +307,35 @@ namespace drafter { template struct TypeDefinition; - template + template struct TypeDefinition { - const mson::TypeDefinition& operator()(const snowcrash::DataStructure& dataStructure) { + const mson::TypeDefinition& operator()(const snowcrash::DataStructure& dataStructure) + { return dataStructure.typeDefinition; } }; - template + template struct TypeDefinition { - const mson::TypeDefinition& operator()(const mson::ValueMember& valueMember) { + const mson::TypeDefinition& operator()(const mson::ValueMember& valueMember) + { return valueMember.valueDefinition.typeDefinition; } }; public: - - template + template ExtractTypeSection(ElementData& data, ConversionContext& context, const NodeInfo& sectionHolder) - : data(data), - context(context), - elementTypeName(TypeDefinition()(*sectionHolder.node).typeSpecification.name.base), - defaultNestedType(SelectNestedTypeSpecification(TypeDefinition()(*sectionHolder.node).typeSpecification.nestedTypes)) - {} + : data(data) + , context(context) + , elementTypeName(TypeDefinition()(*sectionHolder.node).typeSpecification.name.base) + , defaultNestedType( + SelectNestedTypeSpecification(TypeDefinition()(*sectionHolder.node).typeSpecification.nestedTypes)) + { + } - void operator()(const NodeInfo& typeSection) { + void operator()(const NodeInfo& typeSection) + { Fetch fetch; switch (typeSection.node->klass) { @@ -312,10 +354,7 @@ namespace drafter { case mson::TypeSection::BlockDescriptionClass: data.descriptions.push_back( - std::make_tuple( - typeSection.node->content.description, - typeSection.sourceMap->description - )); + std::make_tuple(typeSection.node->content.description, typeSection.sourceMap->description)); break; default: @@ -328,7 +367,8 @@ namespace drafter { } }; - static mson::BaseTypeName RefractElementTypeToMsonType(refract::TypeQueryVisitor::ElementType type) { + static mson::BaseTypeName RefractElementTypeToMsonType(refract::TypeQueryVisitor::ElementType type) + { switch (type) { case refract::TypeQueryVisitor::String: return mson::StringTypeName; @@ -354,13 +394,13 @@ namespace drafter { case refract::TypeQueryVisitor::Ref: case refract::TypeQueryVisitor::Extend: case refract::TypeQueryVisitor::Option: - case refract::TypeQueryVisitor::Select: - ; + case refract::TypeQueryVisitor::Select:; }; return mson::UndefinedTypeName; } - static mson::BaseTypeName GetMsonTypeFromName(const std::string& name, const ConversionContext& context) { + static mson::BaseTypeName GetMsonTypeFromName(const std::string& name, const ConversionContext& context) + { refract::IElement* e = FindRootAncestor(name, context.GetNamedTypesRegistry()); if (!e) { return mson::UndefinedTypeName; @@ -385,11 +425,13 @@ namespace drafter { ElementData& data; const ConversionContext& context; - template ::IsPrimitive> struct Fetch; + template ::IsPrimitive> + struct Fetch; - template + template struct Fetch { - ElementInfo operator()(const mson::TypeNames& typeNames, const ConversionContext& context) { + ElementInfo operator()(const mson::TypeNames& typeNames, const ConversionContext& context) + { RefractElements types; for (mson::TypeNames::const_iterator it = typeNames.begin(); it != typeNames.end(); ++it) { @@ -399,7 +441,7 @@ namespace drafter { if (typeName == mson::UndefinedTypeName && !it->symbol.literal.empty()) { typeName = GetMsonTypeFromName(it->symbol.literal, context); method = it->symbol.variable ? eSample : eElement; - } + } const RefractElementFactory& f = FactoryFromType(typeName); types.push_back(f.Create(it->symbol.literal, method)); @@ -409,34 +451,41 @@ namespace drafter { } }; + template ::IsPrimitive, bool dummy = true> + struct Store; - template ::IsPrimitive, bool dummy = true> struct Store; - - template + template struct Store { - void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context) + { // do nothing - Primitive types does not contain TypeDefinitions } }; - template + template struct Store { - void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context) + { data.values.push_back(Fetch()(typeNames, context)); } }; - template + template struct Store::IsPrimitive, dummy> { using E = refract::EnumElement; - void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context){ + void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context) + { data.enumerations.push_back(Fetch()(typeNames, context)); } }; - ExtractTypeDefinition(ElementData& data, const ConversionContext& context) : data(data), context(context) {} + ExtractTypeDefinition(ElementData& data, const ConversionContext& context) + : data(data), context(context) + { + } - void operator()(const NodeInfo& typeDefinition) { + void operator()(const NodeInfo& typeDefinition) + { Store()(data, typeDefinition.node->typeSpecification.nestedTypes, context); } }; @@ -446,57 +495,64 @@ namespace drafter { * - value: vm1, vm2 */ template - struct ExtractValueMember - { + struct ExtractValueMember { using ElementType = T; using ElementInfo = typename ElementData::ElementInfo; ElementData& data; ConversionContext& context; - template ::IsPrimitive, bool dummy = true> struct Fetch; + template ::IsPrimitive, bool dummy = true> + struct Fetch; template - struct Fetch { // primitive values + struct Fetch { // primitive values - ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) + { if (valueMember.node->valueDefinition.values.size() > 1) { - throw snowcrash::Error("only one value is supported for primitive types", snowcrash::MSONError, valueMember.sourceMap->sourceMap); + throw snowcrash::Error("only one value is supported for primitive types", + snowcrash::MSONError, + valueMember.sourceMap->sourceMap); } const mson::Value& value = *valueMember.node->valueDefinition.values.begin(); snowcrash::SourceMap sourceMap = FetchSourceMap()(valueMember); return std::make_tuple(value.literal, sourceMap); - } }; - template + template struct Fetch { // Array|Object - ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) + { - const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); + const mson::BaseTypeName type = SelectNestedTypeSpecification( + valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); const RefractElementFactory& factory = FactoryFromType(type); const mson::Values& values = valueMember.node->valueDefinition.values; RefractElements elements; - std::transform(values.begin(), values.end(), - std::back_inserter(elements), - [&factory](const mson::Value& value){ return factory.Create(value.literal, value.variable ? eSample : eValue); }); + std::transform( + values.begin(), values.end(), std::back_inserter(elements), [&factory](const mson::Value& value) { + return factory.Create(value.literal, value.variable ? eSample : eValue); + }); return std::make_tuple(elements, FetchSourceMap()(valueMember)); } }; - template + template struct Fetch::IsPrimitive, dummy> { // Enum - ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { + ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) + { - const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); + const mson::BaseTypeName type = SelectNestedTypeSpecification( + valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes); const RefractElementFactory& f = FactoryFromType(type); const mson::Values& values = valueMember.node->valueDefinition.values; @@ -511,51 +567,57 @@ namespace drafter { } }; - template + template struct IsValueVariable { - bool operator()(const mson::Value& value) { + bool operator()(const mson::Value& value) + { return value.variable; } }; - template - struct IsValueVariable{ + template + struct IsValueVariable { - bool operator()(const mson::Value&) { + bool operator()(const mson::Value&) + { return false; } }; template struct Store { - void operator()(ElementData&data, const ElementInfo& info) { + void operator()(ElementData& data, const ElementInfo& info) + { data.values.push_back(info); } }; template struct Store { - void operator()(ElementData&data, const ElementInfo& info) { + void operator()(ElementData& data, const ElementInfo& info) + { if (std::get<0>(info).size() == 1) { data.values.push_back(info); - } - else { + } else { data.enumerations.push_back(info); } } }; - ExtractValueMember(ElementData& data, ConversionContext& context, const mson::BaseTypeName) : data(data), context(context) {} + ExtractValueMember(ElementData& data, ConversionContext& context, const mson::BaseTypeName) + : data(data), context(context) + { + } - void operator ()(const NodeInfo& valueMember) + void operator()(const NodeInfo& valueMember) { // silently ignore "value" for ObjectElement e.g. // # A (array) // - key (object) // warning is attached while creating ValueMember in snowcrash - if (valueMember.node->valueDefinition.typeDefinition.baseType == mson::ImplicitObjectBaseType || - valueMember.node->valueDefinition.typeDefinition.baseType == mson::ObjectBaseType) { + if (valueMember.node->valueDefinition.typeDefinition.baseType == mson::ImplicitObjectBaseType + || valueMember.node->valueDefinition.typeDefinition.baseType == mson::ObjectBaseType) { return; } @@ -569,39 +631,32 @@ namespace drafter { if (attrs & mson::DefaultTypeAttribute) { data.defaults.push_back(parsed); - } - else if ((attrs & mson::SampleTypeAttribute) || IsValueVariable()(value)) { + } else if ((attrs & mson::SampleTypeAttribute) || IsValueVariable()(value)) { data.samples.push_back(parsed); - } - else { + } else { Store()(data, parsed); } - } - else { + } else { if (attrs & mson::DefaultTypeAttribute) { context.warn(snowcrash::Warning("no value present when 'default' is specified", - snowcrash::MSONError, valueMember.sourceMap->sourceMap) - ); + snowcrash::MSONError, + valueMember.sourceMap->sourceMap)); } - if (attrs & mson::SampleTypeAttribute) { context.warn(snowcrash::Warning("no value present when 'sample' is specified", - snowcrash::MSONError, valueMember.sourceMap->sourceMap) - ); + snowcrash::MSONError, + valueMember.sourceMap->sourceMap)); } } if (!valueMember.node->description.empty()) { data.descriptions.push_back( - std::make_tuple( - valueMember.node->description, - valueMember.sourceMap->description - )); + std::make_tuple(valueMember.node->description, valueMember.sourceMap->description)); } - if ((valueMember.node->valueDefinition.values.empty() || - (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1))) { + if ((valueMember.node->valueDefinition.values.empty() + || (valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes.size() > 1))) { ExtractTypeDefinition extd(data, context); extd(MakeNodeInfoWithoutSourceMap(valueMember.node->valueDefinition.typeDefinition)); @@ -631,8 +686,8 @@ namespace drafter { } }; - - template ::IsPrimitive> struct Merge; + template ::IsPrimitive> + struct Merge; template struct Merge { @@ -641,11 +696,10 @@ namespace drafter { using StoredType = typename ElementData::StoredType; using SourceMap = typename ElementData::ValueSourceMapType; - ElementInfo operator()(const Container& container) const { + ElementInfo operator()(const Container& container) const + { - return container.empty() - ? ElementInfo() - : container.front(); + return container.empty() ? ElementInfo() : container.front(); } }; @@ -656,7 +710,8 @@ namespace drafter { using StoredType = typename ElementData::StoredType; using SourceMap = typename ElementData::ValueSourceMapType; - ElementInfo operator()(const Container& container) const { + ElementInfo operator()(const Container& container) const + { StoredType value; SourceMap sourceMap; @@ -671,32 +726,34 @@ namespace drafter { // every element in vector has it own map } - return std::make_tuple(value, sourceMap) ; + return std::make_tuple(value, sourceMap); } }; - template ::IsPrimitive> struct ElementInfoToElement; + template ::IsPrimitive> + struct ElementInfoToElement; - template + template struct ElementInfoToElement { - E* operator()(const typename ElementData::ElementInfo& value) { - std::pair result = LiteralTo(std::get<0>(value)); - return result.first - ? new E(std::get<1>(result)) - : new E; + E* operator()(const typename ElementData::ElementInfo& value) + { + std::pair result = LiteralTo(std::get<0>(value)); + return result.first ? new E(std::get<1>(result)) : new E; } }; - template + template struct ElementInfoToElement { - E* operator()(const typename ElementData::ElementInfo& value) { + E* operator()(const typename ElementData::ElementInfo& value) + { return new E(std::get<0>(value)); } }; - template <> + template <> struct ElementInfoToElement::IsPrimitive> { - refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { + refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) + { auto v = std::get<0>(value); @@ -712,20 +769,22 @@ namespace drafter { } }; - template ::IsPrimitive> struct SaveValue; + template ::IsPrimitive> + struct SaveValue; template struct SaveValue { using ElementInfo = typename ElementData::ElementInfo; using ValueType = typename T::ValueType; - void operator()(const ElementData& data, T* element) { + void operator()(const ElementData& data, T* element) + { if (data.values.empty()) { return; } ElementInfo value = Merge()(data.values); - std::pair result = LiteralTo(std::get<0>(value)); + std::pair result = LiteralTo(std::get<0>(value)); element->set(std::get<1>(result)); @@ -738,7 +797,8 @@ namespace drafter { struct SaveValue { using ElementInfo = typename ElementData::ElementInfo; - void operator()(const ElementData& data, T* element) { + void operator()(const ElementData& data, T* element) + { ElementInfo value = Merge()(data.values); if (!std::get<0>(value).empty()) { @@ -751,7 +811,8 @@ namespace drafter { struct SaveValue::IsPrimitive> { using ElementInfo = typename ElementData::ElementInfo; - void operator()(const ElementData& data, refract::EnumElement* element) { + void operator()(const ElementData& data, refract::EnumElement* element) + { ElementInfo values = Merge()(data.values); ElementInfo enumerations = Merge()(data.enumerations); @@ -762,18 +823,20 @@ namespace drafter { } if (!std::get<0>(enumerations).empty()) { - element->attributes[SerializeKey::Enumerations]= new refract::ArrayElement(std::get<0>(enumerations)); + element->attributes[SerializeKey::Enumerations] + = new refract::ArrayElement(std::get<0>(enumerations)); } } }; + template ::IsPrimitive> + struct ReleaseStoredData; - template ::IsPrimitive> struct ReleaseStoredData; - template struct ReleaseStoredData { template - void operator()(const I1& begin, const I2& end) { + void operator()(const I1& begin, const I2& end) + { // do nothing } }; @@ -781,14 +844,12 @@ namespace drafter { template struct ReleaseStoredData { template - void operator()(const I1& begin, const I2& end) { - std::for_each(begin, end, - [](const typename ElementData::ElementInfo& info){ - const auto& elements = std::get<0>(info); - for_each(elements.begin(), elements.end(), - [](const refract::IElement* e) { delete e; } - ); - }); + void operator()(const I1& begin, const I2& end) + { + std::for_each(begin, end, [](const typename ElementData::ElementInfo& info) { + const auto& elements = std::get<0>(info); + for_each(elements.begin(), elements.end(), [](const refract::IElement* e) { delete e; }); + }); } }; @@ -796,7 +857,8 @@ namespace drafter { struct AllElementsToAtribute { template - void operator()(const U& values, const std::string& key, refract::IElement* element) { + void operator()(const U& values, const std::string& key, refract::IElement* element) + { if (values.empty()) { return; } @@ -810,16 +872,15 @@ namespace drafter { } element->attributes[key] = a; - } - }; template struct LastElementToAttribute { template - void operator()(const U& values, const std::string& key, refract::IElement* element) { + void operator()(const U& values, const std::string& key, refract::IElement* element) + { if (values.empty()) { return; @@ -829,22 +890,23 @@ namespace drafter { refract::IElement* value = fetch(*values.rbegin()); if (values.size() > 1) { - auto begin = values.rbegin(); + auto begin = values.rbegin(); begin++; // avoid last one ReleaseStoredData()(begin, values.rend()); } element->attributes[key] = value; } - }; - template - void ElementDataToElement (T* element, const ElementData& data, ConversionContext& context) { + template + void ElementDataToElement(T* element, const ElementData& data, ConversionContext& context) + { - for (auto collection : {data.values, data.samples, data.defaults, data.enumerations} ) { - std::for_each(collection.begin(), collection.end(), - std::bind(CheckValueValidity(),std::placeholders::_1, std::ref(context))); + for (auto collection : { data.values, data.samples, data.defaults, data.enumerations }) { + std::for_each(collection.begin(), + collection.end(), + std::bind(CheckValueValidity(), std::placeholders::_1, std::ref(context))); } SaveValue()(data, element); @@ -853,7 +915,7 @@ namespace drafter { } } - template + template refract::IElement* DescriptionToRefract(const T& descriptions) { if (descriptions.empty()) { @@ -864,7 +926,7 @@ namespace drafter { Join join(description); snowcrash::SourceMap sourceMap; - for (const auto& item: descriptions) { + for (const auto& item : descriptions) { join(std::get<0>(item)); sourceMap.sourceMap.append(std::get<1>(item).sourceMap); } @@ -877,12 +939,12 @@ namespace drafter { } // FIXME: refactoring - description is not used while calling from - // `RefractElementFromProperty()` + // `RefractElementFromProperty()` template refract::IElement* RefractElementFromValue(const NodeInfo& value, - ConversionContext& context, - const mson::BaseTypeName defaultNestedType, - typename ElementData::DescriptionInfoContainer& descriptions) + ConversionContext& context, + const mson::BaseTypeName defaultNestedType, + typename ElementData::DescriptionInfoContainer& descriptions) { using namespace refract; using ElementType = T; @@ -912,7 +974,8 @@ namespace drafter { return true; } - if (refract::TypeQueryVisitor::as(FindRootAncestor(variable.typeDefinition.typeSpecification.name.symbol.literal, context.GetNamedTypesRegistry()))) { + if (refract::TypeQueryVisitor::as(FindRootAncestor( + variable.typeDefinition.typeSpecification.name.symbol.literal, context.GetNamedTypesRegistry()))) { return true; } @@ -930,22 +993,21 @@ namespace drafter { if (property.node->name.variable.values.size() > 1) { // FIXME: is there example for multiple variables? - context.warn( - snowcrash::Warning( - "multiple variables in property definition is not implemented", - snowcrash::MSONError, - sourceMap.sourceMap)); + context.warn(snowcrash::Warning("multiple variables in property definition is not implemented", + snowcrash::MSONError, + sourceMap.sourceMap)); } // variable containt type definition if (!property.node->name.variable.typeDefinition.empty()) { if (!VariablePropertyIsString(property.node->name.variable, context)) { delete key; - throw snowcrash::Error("'variable named property' must be string or its sub-type", snowcrash::MSONError, sourceMap.sourceMap); + throw snowcrash::Error("'variable named property' must be string or its sub-type", + snowcrash::MSONError, + sourceMap.sourceMap); } SetElementType(key, property.node->name.variable.typeDefinition); - } key->attributes[SerializeKey::Variable] = refract::IElement::Create(true); @@ -965,14 +1027,17 @@ namespace drafter { } template - refract::MemberElement* RefractElementFromProperty(const NodeInfo& property, ConversionContext& context, const mson::BaseTypeName defaultNestedType) + refract::MemberElement* RefractElementFromProperty(const NodeInfo& property, + ConversionContext& context, + const mson::BaseTypeName defaultNestedType) { typename ElementData::DescriptionInfoContainer dummy; // we need no this typename ElementData::DescriptionInfoContainer descriptions; refract::IElement* key = GetPropertyKey(property, context); - refract::IElement* value = RefractElementFromValue(NodeInfo(property.node, property.sourceMap), context, defaultNestedType, dummy); + refract::IElement* value = RefractElementFromValue( + NodeInfo(property.node, property.sourceMap), context, defaultNestedType, dummy); refract::MemberElement* element = new refract::MemberElement(key, value); mson::TypeAttributes attrs = property.node->valueDefinition.typeDefinition.attributes; @@ -983,24 +1048,16 @@ namespace drafter { } if (!property.node->description.empty()) { - descriptions.push_back( - std::make_tuple( - property.node->description, - property.sourceMap->description - )); + descriptions.push_back(std::make_tuple(property.node->description, property.sourceMap->description)); } NodeInfoCollection typeSections(MAKE_NODE_INFO(property, sections)); - for (const auto& typeSection: typeSections) { - if (typeSection.node->klass == mson::TypeSection::BlockDescriptionClass) { - descriptions.push_back( - std::make_tuple( - typeSection.node->content.description, - typeSection.sourceMap->description - )); - - } + for (const auto& typeSection : typeSections) { + if (typeSection.node->klass == mson::TypeSection::BlockDescriptionClass) { + descriptions.push_back( + std::make_tuple(typeSection.node->content.description, typeSection.sourceMap->description)); + } } if (!property.node->description.empty() && (descriptions.size() > 1)) { @@ -1038,7 +1095,10 @@ namespace drafter { typedef refract::MemberElement ElementType; typedef NodeInfo InputType; - template static ElementType* Invoke(const InputType& prop, ConversionContext& context, const mson::BaseTypeName defaultNestedType) { + template + static ElementType* Invoke( + const InputType& prop, ConversionContext& context, const mson::BaseTypeName defaultNestedType) + { return RefractElementFromProperty(prop, context, defaultNestedType); } }; @@ -1047,7 +1107,10 @@ namespace drafter { typedef refract::IElement ElementType; typedef NodeInfo InputType; - template static ElementType* Invoke (const InputType& val, ConversionContext& context, const mson::BaseTypeName defaultNestedType) { + template + static ElementType* Invoke( + const InputType& val, ConversionContext& context, const mson::BaseTypeName defaultNestedType) + { typename ElementData::DescriptionInfoContainer descriptions; refract::IElement* element = RefractElementFromValue(val, context, defaultNestedType, descriptions); @@ -1068,32 +1131,29 @@ namespace drafter { }; static void CheckTypeAttributesClash(const mson::TypeAttributes& attributes, - const snowcrash::SourceMap& sourceMap, - ConversionContext& context) { + const snowcrash::SourceMap& sourceMap, + ConversionContext& context) + { - if ((attributes & mson::FixedTypeAttribute) != 0 && - (attributes & mson::OptionalTypeAttribute) != 0) { + if ((attributes & mson::FixedTypeAttribute) != 0 && (attributes & mson::OptionalTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'fixed' and 'optional' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::RequiredTypeAttribute) != 0 && - (attributes & mson::OptionalTypeAttribute) != 0) { + if ((attributes & mson::RequiredTypeAttribute) != 0 && (attributes & mson::OptionalTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'required' and 'optional' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::DefaultTypeAttribute) != 0 && - (attributes & mson::SampleTypeAttribute) != 0) { + if ((attributes & mson::DefaultTypeAttribute) != 0 && (attributes & mson::SampleTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'default' and 'sample' together", snowcrash::MSONError, sourceMap.sourceMap)); } - if ((attributes & mson::FixedTypeAttribute) != 0 && - (attributes & mson::FixedTypeTypeAttribute) != 0) { + if ((attributes & mson::FixedTypeAttribute) != 0 && (attributes & mson::FixedTypeTypeAttribute) != 0) { context.warn(snowcrash::Warning( "cannot use 'fixed' and 'fixed-type' together", snowcrash::MSONError, sourceMap.sourceMap)); @@ -1102,13 +1162,15 @@ namespace drafter { template static refract::IElement* MsonMemberToRefract(const typename Trait::InputType& input, - ConversionContext& context, - const mson::BaseTypeName nameType, - const mson::BaseTypeName defaultNestedType, - bool checkTypeAttributes = true) { + ConversionContext& context, + const mson::BaseTypeName nameType, + const mson::BaseTypeName defaultNestedType, + bool checkTypeAttributes = true) + { if (checkTypeAttributes) { - CheckTypeAttributesClash(input.node->valueDefinition.typeDefinition.attributes, input.sourceMap->valueDefinition, context); + CheckTypeAttributesClash( + input.node->valueDefinition.typeDefinition.attributes, input.sourceMap->valueDefinition, context); } switch (nameType) { @@ -1130,13 +1192,11 @@ namespace drafter { case mson::ObjectTypeName: return Trait::template Invoke(input, context, defaultNestedType); - case mson::UndefinedTypeName: - { + case mson::UndefinedTypeName: { if (ValueHasChildren(input.node)) { // FIXME: what about EnumElement return Trait::template Invoke(input, context, defaultNestedType); - } - else if (ValueHasName(input.node) || ValueHasMembers(input.node)) { + } else if (ValueHasName(input.node) || ValueHasMembers(input.node)) { return Trait::template Invoke(input, context, defaultNestedType); } else if (nameType != defaultNestedType) { return MsonMemberToRefract(input, context, defaultNestedType, defaultNestedType, false); @@ -1155,16 +1215,17 @@ namespace drafter { NodeInfoCollection oneOfNodeInfo(oneOf); - for (NodeInfoCollection::const_iterator it = oneOfNodeInfo.begin(); it != oneOfNodeInfo.end(); ++it) { + for (NodeInfoCollection::const_iterator it = oneOfNodeInfo.begin(); it != oneOfNodeInfo.end(); + ++it) { refract::OptionElement* option = new refract::OptionElement; // we can not use MsonElementToRefract() for groups, // "option" element handles directly all elements in group if (it->node->klass == mson::Element::GroupClass) { - option->set(MsonElementsToRefract(MakeNodeInfo(it->node->content.elements(), it->sourceMap->elements()), context)); - } - else { + option->set(MsonElementsToRefract( + MakeNodeInfo(it->node->content.elements(), it->sourceMap->elements()), context)); + } else { option->push_back(MsonElementToRefract(*it, context, mson::StringTypeName)); } @@ -1184,20 +1245,23 @@ namespace drafter { return ref; } - static refract::IElement* MsonElementToRefract(const NodeInfo& mse, ConversionContext& context, const mson::BaseTypeName defaultNestedType/* = mson::StringTypeName */) + static refract::IElement* MsonElementToRefract(const NodeInfo& mse, + ConversionContext& context, + const mson::BaseTypeName defaultNestedType /* = mson::StringTypeName */) { switch (mse.node->klass) { case mson::Element::PropertyClass: - return MsonMemberToRefract(MakeNodeInfo(mse.node->content.property, mse.sourceMap->property), - context, - GetType(mse.node->content.property.valueDefinition, context), - defaultNestedType); + return MsonMemberToRefract( + MakeNodeInfo(mse.node->content.property, mse.sourceMap->property), + context, + GetType(mse.node->content.property.valueDefinition, context), + defaultNestedType); case mson::Element::ValueClass: return MsonMemberToRefract(MakeNodeInfo(mse.node->content.value, mse.sourceMap->value), - context, - GetType(mse.node->content.value.valueDefinition, context), - defaultNestedType); + context, + GetType(mse.node->content.value.valueDefinition, context), + defaultNestedType); case mson::Element::MixinClass: return MsonMixinToRefract(MakeNodeInfo(mse.node->content.mixin, mse.sourceMap->mixin)); @@ -1213,7 +1277,7 @@ namespace drafter { } } - template + template refract::IElement* RefractElementFromMSON(const NodeInfo& ds, ConversionContext& context) { using namespace refract; @@ -1253,7 +1317,8 @@ namespace drafter { return element; } - refract::IElement* MSONToRefract(const NodeInfo& dataStructure, ConversionContext& context) + refract::IElement* MSONToRefract( + const NodeInfo& dataStructure, ConversionContext& context) { if (dataStructure.node->empty()) { return NULL; diff --git a/src/RefractElementFactory.cc b/src/RefractElementFactory.cc index 27f596b87..8735bec0b 100644 --- a/src/RefractElementFactory.cc +++ b/src/RefractElementFactory.cc @@ -8,15 +8,17 @@ namespace drafter { - template ::IsPrimitive> struct RefractElementFactoryImpl; + template ::IsPrimitive> + struct RefractElementFactoryImpl; template - struct RefractElementFactoryImpl : RefractElementFactory - { + struct RefractElementFactoryImpl : RefractElementFactory { typedef typename E::ValueType ValueType; - RefractElementFactoryImpl() {} + RefractElementFactoryImpl() + { + } virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const { @@ -28,22 +30,20 @@ namespace drafter switch (method) { case eSample: { - refract::ArrayElement* samples = new refract::ArrayElement; - std::pair value = LiteralTo(literal); - if (value.first) { - samples->push_back(refract::IElement::Create(value.second)); - } - element->attributes[SerializeKey::Samples] = samples; + refract::ArrayElement* samples = new refract::ArrayElement; + std::pair value = LiteralTo(literal); + if (value.first) { + samples->push_back(refract::IElement::Create(value.second)); } - break; + element->attributes[SerializeKey::Samples] = samples; + } break; case eValue: { - std::pair value = LiteralTo(literal); - if (value.first) { - element->set(value.second); - } + std::pair value = LiteralTo(literal); + if (value.first) { + element->set(value.second); } - break; + } break; case eElement: element->element(literal); @@ -55,10 +55,11 @@ namespace drafter }; template - struct RefractElementFactoryImpl : RefractElementFactory - { + struct RefractElementFactoryImpl : RefractElementFactory { - RefractElementFactoryImpl() {} + RefractElementFactoryImpl() + { + } virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const { @@ -89,23 +90,22 @@ namespace drafter static const RefractElementFactoryImpl arrayFactory; static const RefractElementFactoryImpl objectFactory; - switch (typeName) { - case mson::BooleanTypeName: + switch (typeName) { + case mson::BooleanTypeName: return boolFactory; - case mson::NumberTypeName: + case mson::NumberTypeName: return numberFactory; - case mson::StringTypeName: + case mson::StringTypeName: return stringFactory; case mson::ArrayTypeName: return arrayFactory; case mson::EnumTypeName: return enumFactory; - case mson::ObjectTypeName: - case mson::UndefinedTypeName: + case mson::ObjectTypeName: + case mson::UndefinedTypeName: return objectFactory; - default: - ; // do nothing - } + default:; // do nothing + } throw snowcrash::Error("unknown mson type", snowcrash::ApplicationError); } diff --git a/src/refract/Element.cc b/src/refract/Element.cc index 317916e33..50db2bd39 100644 --- a/src/refract/Element.cc +++ b/src/refract/Element.cc @@ -18,9 +18,9 @@ namespace refract { - bool isReserved(const std::string& element) { - static const std::set reserved = { - "null", + bool isReserved(const std::string& element) + { + static const std::set reserved = { "null", "boolean", "number", "string", @@ -36,8 +36,7 @@ namespace refract "option", "extend", - "generic" - }; + "generic" }; return reserved.find(element) != reserved.end(); } @@ -119,12 +118,10 @@ namespace refract const TypeQueryVisitor::ElementType base = visitor.get(); - return std::all_of(values.begin(), values.end(), - [&visitor, base](const IElement* e) { - Visit(visitor,*e); - return base == visitor.get(); - }); - + return std::all_of(values.begin(), values.end(), [&visitor, base](const IElement* e) { + Visit(visitor, *e); + return base == visitor.get(); + }); } } @@ -193,16 +190,18 @@ namespace refract template struct ValueMerge { IElement*& value; - ValueMerge(T& element) : value(element.value) {} + ValueMerge(T& element) : value(element.value) + { + } - void operator()(const T& merge) { - if (!value && merge.value) { - value = merge.value->clone(); - } + void operator()(const T& merge) + { + if (!value && merge.value) { + value = merge.value->clone(); + } } }; - /** * Merge stategy for objects/array * - if member @@ -228,19 +227,18 @@ namespace refract MapKeyToMember keysBase; MapNameToRef refBase; - for (auto& it: value) { + for (auto& it : value) { if (MemberElement* member = TypeQueryVisitor::as(it)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { keysBase[key->value] = member; } - } - else if (RefElement* ref = TypeQueryVisitor::as(it)) { + } else if (RefElement* ref = TypeQueryVisitor::as(it)) { refBase[ref->value] = ref; } } - for (auto const& it: merge.value) { + for (auto const& it : merge.value) { if (MemberElement* member = TypeQueryVisitor::as(it)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { MapKeyToMember::iterator iKey = keysBase.find(key->value); @@ -251,22 +249,19 @@ namespace refract CollectionMerge(iKey->second->meta, {})(member->meta); CollectionMerge(iKey->second->attributes, {})(member->attributes); - } - else { // unknown key, append value + } else { // unknown key, append value MemberElement* clone = static_cast(member->clone()); value.push_back(clone); keysBase[key->value] = clone; } } - } - else if (RefElement* ref = TypeQueryVisitor::as(it)) { + } else if (RefElement* ref = TypeQueryVisitor::as(it)) { if (refBase.find(ref->value) == refBase.end()) { RefElement* clone = static_cast(member->clone()); value.push_back(clone); refBase[ref->value] = clone; } - } - else if(!(it)->empty()) { // merge member is not MemberElement, append value + } else if (!(it)->empty()) { // merge member is not MemberElement, append value value.push_back(it->clone()); } } @@ -274,19 +269,23 @@ namespace refract }; template - class CollectionMerge { + class CollectionMerge + { using KeySet = std::set; IElement::MemberElementCollection& info; const KeySet& noMergeKeys; public: + CollectionMerge(IElement::MemberElementCollection& info, const KeySet& noMergeKeys) + : info(info), noMergeKeys(noMergeKeys) + { + } - CollectionMerge(IElement::MemberElementCollection& info, const KeySet& noMergeKeys) : info(info), noMergeKeys(noMergeKeys) {} - - void operator()(const IElement::MemberElementCollection& append) { + void operator()(const IElement::MemberElementCollection& append) + { IElement::MemberElementCollection toAppend; - for (const auto& it: append) { + for (const auto& it : append) { if (!it) { continue; @@ -310,7 +309,7 @@ namespace refract toAppend.push_back(static_cast(it->clone())); } - for (const auto& it: toAppend) { + for (const auto& it : toAppend) { info.push_back(it); } diff --git a/src/refract/Element.h b/src/refract/Element.h index 8cf41e4aa..7cc757c48 100644 --- a/src/refract/Element.h +++ b/src/refract/Element.h @@ -244,7 +244,6 @@ namespace refract const Type* self = static_cast(this); Type* element = new Type; - if (flags & cElement) { element->element_ = self->element_; } @@ -508,13 +507,18 @@ namespace refract } }; - struct EnumElementTrait - { + struct EnumElementTrait { typedef IElement* ValueType; - static ValueType init() { return NULL; } - static const std::string element() { return "enum"; } + static ValueType init() + { + return NULL; + } + static const std::string element() + { + return "enum"; + } static void release(ValueType& value) { @@ -534,8 +538,7 @@ namespace refract // FIXME: what about `empty()`? should it reflect "enumeration" attribute? // - struct EnumElement : Element - { + struct EnumElement : Element { EnumElement() : Type() { } diff --git a/src/refract/ExpandVisitor.cc b/src/refract/ExpandVisitor.cc index c605dfb68..6511b2b26 100644 --- a/src/refract/ExpandVisitor.cc +++ b/src/refract/ExpandVisitor.cc @@ -21,7 +21,11 @@ #include "TypeQueryVisitor.h" #include "VisitorUtils.h" -#define VISIT_IMPL( ELEMENT ) void ExpandVisitor::operator()(const ELEMENT ## Element& e) { result = Expand(e, context); } +#define VISIT_IMPL(ELEMENT) \ + void ExpandVisitor::operator()(const ELEMENT##Element& e) \ + { \ + result = Expand(e, context); \ + } namespace refract { @@ -68,7 +72,8 @@ namespace refract struct ExpandValueImpl { template - IElement* operator()(const IElement* value, Functor& expand) { + IElement* operator()(const IElement* value, Functor& expand) + { return expand(value); } }; @@ -80,9 +85,7 @@ namespace refract RefractElements operator()(const RefractElements& value, Functor& expand) { RefractElements members; - std::transform(value.begin(), value.end(), - std::back_inserter(members), - expand); + std::transform(value.begin(), value.end(), std::back_inserter(members), expand); return members; } @@ -95,9 +98,8 @@ namespace refract // FIXME: add check against recursive inheritance // walk recursive in registry and expand inheritance tree - for (const IElement* parent = registry.find(en) - ; parent && !isReserved(en) - ; en = parent->element(), parent = registry.find(en)) { + for (const IElement *parent = registry.find(en); parent && !isReserved(en); + en = parent->element(), parent = registry.find(en)) { inheritance.push(parent->clone((IElement::cAll ^ IElement::cElement) | IElement::cNoMetaId)); inheritance.top()->meta["ref"] = IElement::Create(en); @@ -126,7 +128,9 @@ namespace refract const Registry& registry; ExpandVisitor* expand; - Context(const Registry& registry, ExpandVisitor* expand) : registry(registry), expand(expand) {} + Context(const Registry& registry, ExpandVisitor* expand) : registry(registry), expand(expand) + { + } IElement* ExpandOrClone(const IElement* e) const { diff --git a/src/refract/JSONSchemaVisitor.cc b/src/refract/JSONSchemaVisitor.cc index e27085690..117370207 100644 --- a/src/refract/JSONSchemaVisitor.cc +++ b/src/refract/JSONSchemaVisitor.cc @@ -422,7 +422,8 @@ namespace refract } } - void JSONSchemaVisitor::operator()(const EnumElement& e) { + void JSONSchemaVisitor::operator()(const EnumElement& e) + { RefractElements elms; @@ -444,7 +445,7 @@ namespace refract std::map > types; std::vector typesOrder; - for (const auto& it: elms) { + for (const auto& it : elms) { if (it) { std::vector& items = types[(it)->element()]; @@ -462,7 +463,7 @@ namespace refract } else { const EnumElement* def = GetDefault(e); if (!elms.empty() || (def && !def->empty())) { - ArrayElement *a = new ArrayElement; + ArrayElement* a = new ArrayElement; CloneMembers(a, &elms); setSchemaType(types.begin()->first); addMember("enum", a); @@ -474,7 +475,7 @@ namespace refract // this works because "default" is everytime set by value // if value will be moved into "enumerations" it need aditional check if (def && !def->empty() && !def->value->empty()) { - IElement *d = def->value->clone(); + IElement* d = def->value->clone(); addMember("default", d); } } @@ -614,8 +615,7 @@ namespace refract } } } - } - break; + } break; case TypeQueryVisitor::Select: { SelectElement* sel = static_cast(*it); @@ -628,8 +628,7 @@ namespace refract VisitBy(*(*it), v); oneOfMembers.push_back(v.getOwnership()); } - } - break; + } break; default: throw LogicError("Invalid member type of object in MSON definition"); diff --git a/src/refract/PrintVisitor.cc b/src/refract/PrintVisitor.cc index a295c88ce..778782d67 100644 --- a/src/refract/PrintVisitor.cc +++ b/src/refract/PrintVisitor.cc @@ -132,9 +132,10 @@ namespace refract void PrintVisitor::operator()(const EnumElement& e) { - indented() << "- EnumElement " << "\n"; + indented() << "- EnumElement " + << "\n"; if (e.value) { - PrintVisitor{indent + 1, os, ommitSourceMap}(*e.value); + PrintVisitor{ indent + 1, os, ommitSourceMap }(*e.value); } } diff --git a/src/refract/RenderJSONVisitor.cc b/src/refract/RenderJSONVisitor.cc index 4d0c1174d..0386dde68 100644 --- a/src/refract/RenderJSONVisitor.cc +++ b/src/refract/RenderJSONVisitor.cc @@ -16,7 +16,8 @@ namespace refract { - namespace { + namespace + { template void FetchMembers(const T& element, typename T::ValueType& members) @@ -27,9 +28,7 @@ namespace refract return; } - for (typename T::ValueType::const_iterator it = val->begin(); - it != val->end(); - ++it) { + for (typename T::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { if (!(*it) || (*it)->empty()) { continue; @@ -38,8 +37,7 @@ namespace refract if (RefElement* ref = TypeQueryVisitor::as(*it)) { HandleRefWhenFetchingMembers(ref, members, FetchMembers); continue; - } - else if (SelectElement* select = TypeQueryVisitor::as(*it)) { + } else if (SelectElement* select = TypeQueryVisitor::as(*it)) { if (select->value.empty() || !(*select->value.begin())) { continue; } @@ -59,12 +57,14 @@ namespace refract members.push_back(e); } } - } - RenderJSONVisitor::RenderJSONVisitor() : result(nullptr) {} + RenderJSONVisitor::RenderJSONVisitor() : result(nullptr) + { + } - RenderJSONVisitor::~RenderJSONVisitor() { + RenderJSONVisitor::~RenderJSONVisitor() + { if (result) { delete result; } @@ -90,8 +90,7 @@ namespace refract if (EnumElement* enm = TypeQueryVisitor::as(e.value.second)) { // We need to handle Enum individualy because of attr["enumerations"] Visit(renderer, *enm); - } - else if (IsTypeAttribute(e, "nullable") && e.value.second->empty()) { + } else if (IsTypeAttribute(e, "nullable") && e.value.second->empty()) { renderer.result = new NullElement; } else if (IsTypeAttribute(e, "optional") && e.value.second->empty()) { return; @@ -107,7 +106,8 @@ namespace refract result = new MemberElement(key, renderer.result ? renderer.getOwnership() : new StringElement); } - void RenderJSONVisitor::operator()(const ObjectElement& e) { + void RenderJSONVisitor::operator()(const ObjectElement& e) + { ObjectElement::ValueType members; FetchMembers(e, members); ObjectElement* o = new ObjectElement; @@ -115,13 +115,13 @@ namespace refract result = o; } - void RenderJSONVisitor::operator()(const EnumElement& e) { + void RenderJSONVisitor::operator()(const EnumElement& e) + { const IElement* val = GetValue(e); if (val && !val->empty()) { val = val->clone(); - } - else { + } else { val = new StringElement; } @@ -191,11 +191,12 @@ namespace refract delete merged; } - IElement* RenderJSONVisitor::getOwnership() { - IElement* ret = result; - result = nullptr; - return ret; - } + IElement* RenderJSONVisitor::getOwnership() + { + IElement* ret = result; + result = nullptr; + return ret; + } std::string RenderJSONVisitor::getString() const { diff --git a/src/refract/RenderJSONVisitor.h b/src/refract/RenderJSONVisitor.h index 7b17d1e8d..956b806f5 100644 --- a/src/refract/RenderJSONVisitor.h +++ b/src/refract/RenderJSONVisitor.h @@ -20,6 +20,7 @@ namespace refract class RenderJSONVisitor { IElement* result; + public: RenderJSONVisitor(); virtual ~RenderJSONVisitor(); diff --git a/src/refract/VisitorUtils.h b/src/refract/VisitorUtils.h index 6cd8ee802..11ed8c8db 100644 --- a/src/refract/VisitorUtils.h +++ b/src/refract/VisitorUtils.h @@ -131,18 +131,22 @@ namespace refract } }; - template<> + template <> struct GetValue { using EnumElement = refract::EnumElement; const EnumElement& element; - GetValue(const EnumElement& e) : element(e) {} + GetValue(const EnumElement& e) : element(e) + { + } - operator const IElement*() { + operator const IElement*() + { return GetEnumValue(element); } - IElement* GetEnumValue(const EnumElement& element) { + IElement* GetEnumValue(const EnumElement& element) + { if (const EnumElement* s = GetSample(element)) { return GetEnumValue(*s); } @@ -171,7 +175,7 @@ namespace refract } if (!item->empty()) { - return item; + return item; } } } @@ -180,7 +184,8 @@ namespace refract return element.value; } - const ArrayElement* GetEnumerations(const EnumElement& e) { + const ArrayElement* GetEnumerations(const EnumElement& e) + { IElement::MemberElementCollection::const_iterator i = e.attributes.find("enumerations"); @@ -192,7 +197,6 @@ namespace refract } }; - // will be moved into different header (as part of drafter instead of refract) template void CheckMixinParent(refract::IElement* element) From b640f999eb27e0140a5531d63d1c78ccfcc2d472 Mon Sep 17 00:00:00 2001 From: Jiri Kratochvil Date: Mon, 18 Sep 2017 14:07:21 +0200 Subject: [PATCH 12/12] Polishing code --- src/ElementData.h | 35 +++++++----- src/RefractDataStructure.cc | 36 ++++++------ src/RefractElementFactory.cc | 2 +- src/refract/Element.cc | 33 ++++++----- src/refract/Element.h | 52 ++++++----------- src/refract/JSONSchemaVisitor.cc | 79 +++++++++++++------------- src/refract/RenderJSONVisitor.cc | 18 ++---- src/refract/RenderJSONVisitor.h | 4 +- src/refract/SerializeCompactVisitor.cc | 12 ++-- src/refract/VisitorUtils.cc | 2 +- src/refract/VisitorUtils.h | 34 +++++------ test/test-ElementDataTest.cc | 28 ++++----- 12 files changed, 160 insertions(+), 175 deletions(-) diff --git a/src/ElementData.h b/src/ElementData.h index 62d261551..f005fcc37 100644 --- a/src/ElementData.h +++ b/src/ElementData.h @@ -13,32 +13,41 @@ namespace drafter { + template + struct IsPrimitive { + using ValueType = typename T::ValueType; + using type = std::integral_constant::value + && !std::is_same::value>; + }; + template struct ElementData { - typedef T ElementType; + using ElementType = T; + + using ValueType = typename ElementType::ValueType; + using ValueSourceMapType = snowcrash::SourceMap; - typedef typename ElementType::ValueType ValueType; - typedef snowcrash::SourceMap ValueSourceMapType; - typedef typename std::conditional::value - || std::is_same::value, // check for primitive values - std::false_type, - std::true_type>::type IsPrimitive; + //typedef typename std::conditional::value + // || std::is_same::value, // check for primitive values + // std::false_type, + // std::true_type>::type IsPrimitive; // This is required because snowcrash internal stuctures holds data // for primitive types as "string" for complex types as "element array" // it will be converted into apropriated element type once all required data are colected - typedef typename std::conditional::type::value, std::string, // for primitive values, we will hold data as string refract::RefractElements // for complex types, we will hold elements - >::type StoredType; + >::type; - typedef std::tuple ElementInfo; // [value, sourceMap] - typedef std::tuple > DescriptionInfo; // [description, sourceMap] + using ElementInfo = std::tuple; // [value, sourceMap] + using DescriptionInfo = std::tuple >; // [description, sourceMap] - typedef std::vector ElementInfoContainer; - typedef std::vector DescriptionInfoContainer; + using ElementInfoContainer = std::vector; + using DescriptionInfoContainer = std::vector; ElementInfoContainer values; ElementInfoContainer defaults; diff --git a/src/RefractDataStructure.cc b/src/RefractDataStructure.cc index 0bab5646a..629af3d4c 100644 --- a/src/RefractDataStructure.cc +++ b/src/RefractDataStructure.cc @@ -23,8 +23,8 @@ namespace drafter { - using PrimitiveType = std::true_type; - using ComplexType = std::false_type; + auto const PrimitiveType = std::true_type::value; + auto const ComplexType = std::false_type::value; template struct FetchSourceMap { @@ -58,8 +58,8 @@ namespace drafter template struct CheckValueValidity { - typedef typename ElementData::ElementInfo ElementInfo; - typedef typename refract::NumberElement::ValueType ValueType; + using ElementInfo = typename ElementData::ElementInfo; + using ValueType = typename refract::NumberElement::ValueType; void operator()(const ElementInfo& value, ConversionContext& context) { @@ -233,7 +233,7 @@ namespace drafter mson::BaseTypeName elementTypeName; mson::BaseTypeName defaultNestedType; - template ::IsPrimitive> + template ::type::value> struct Fetch; template @@ -262,7 +262,7 @@ namespace drafter } }; - template ::IsPrimitive, bool dummy = true> + template ::type::value, bool dummy = true> struct Store; template @@ -293,7 +293,7 @@ namespace drafter }; template - struct Store::IsPrimitive, dummy> { + struct Store::type::value, dummy> { void operator()(ElementData& data, const NodeInfo& typeSection, ConversionContext& context, @@ -425,7 +425,7 @@ namespace drafter ElementData& data; const ConversionContext& context; - template ::IsPrimitive> + template ::type::value> struct Fetch; template @@ -451,7 +451,7 @@ namespace drafter } }; - template ::IsPrimitive, bool dummy = true> + template ::type::value, bool dummy = true> struct Store; template @@ -471,7 +471,7 @@ namespace drafter }; template - struct Store::IsPrimitive, dummy> { + struct Store::type::value, dummy> { using E = refract::EnumElement; void operator()(ElementData& data, const mson::TypeNames& typeNames, const ConversionContext& context) { @@ -502,7 +502,7 @@ namespace drafter ElementData& data; ConversionContext& context; - template ::IsPrimitive, bool dummy = true> + template ::type::value, bool dummy = true> struct Fetch; template @@ -546,7 +546,7 @@ namespace drafter }; template - struct Fetch::IsPrimitive, dummy> { // Enum + struct Fetch::type::value, dummy> { // Enum ElementInfo operator()(const NodeInfo& valueMember, ConversionContext& context) { @@ -686,7 +686,7 @@ namespace drafter } }; - template ::IsPrimitive> + template ::type::value> struct Merge; template @@ -730,7 +730,7 @@ namespace drafter } }; - template ::IsPrimitive> + template ::type::value> struct ElementInfoToElement; template @@ -751,7 +751,7 @@ namespace drafter }; template <> - struct ElementInfoToElement::IsPrimitive> { + struct ElementInfoToElement::type::value> { refract::EnumElement* operator()(const typename ElementData::ElementInfo& value) { @@ -769,7 +769,7 @@ namespace drafter } }; - template ::IsPrimitive> + template ::type::value> struct SaveValue; template @@ -808,7 +808,7 @@ namespace drafter }; template <> - struct SaveValue::IsPrimitive> { + struct SaveValue::type::value> { using ElementInfo = typename ElementData::ElementInfo; void operator()(const ElementData& data, refract::EnumElement* element) @@ -829,7 +829,7 @@ namespace drafter } }; - template ::IsPrimitive> + template ::type::value> struct ReleaseStoredData; template diff --git a/src/RefractElementFactory.cc b/src/RefractElementFactory.cc index 8735bec0b..e544c14ad 100644 --- a/src/RefractElementFactory.cc +++ b/src/RefractElementFactory.cc @@ -8,7 +8,7 @@ namespace drafter { - template ::IsPrimitive> + template ::type> struct RefractElementFactoryImpl; template diff --git a/src/refract/Element.cc b/src/refract/Element.cc index 50db2bd39..a3d05e026 100644 --- a/src/refract/Element.cc +++ b/src/refract/Element.cc @@ -227,19 +227,19 @@ namespace refract MapKeyToMember keysBase; MapNameToRef refBase; - for (auto& it : value) { - if (MemberElement* member = TypeQueryVisitor::as(it)) { + for (auto& element : value) { + if (MemberElement* member = TypeQueryVisitor::as(element)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { keysBase[key->value] = member; } - } else if (RefElement* ref = TypeQueryVisitor::as(it)) { + } else if (RefElement* ref = TypeQueryVisitor::as(element)) { refBase[ref->value] = ref; } } - for (auto const& it : merge.value) { - if (MemberElement* member = TypeQueryVisitor::as(it)) { + for (auto const& element : merge.value) { + if (MemberElement* member = TypeQueryVisitor::as(element)) { if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { MapKeyToMember::iterator iKey = keysBase.find(key->value); @@ -255,14 +255,14 @@ namespace refract keysBase[key->value] = clone; } } - } else if (RefElement* ref = TypeQueryVisitor::as(it)) { + } else if (RefElement* ref = TypeQueryVisitor::as(element)) { if (refBase.find(ref->value) == refBase.end()) { RefElement* clone = static_cast(member->clone()); value.push_back(clone); refBase[ref->value] = clone; } - } else if (!(it)->empty()) { // merge member is not MemberElement, append value - value.push_back(it->clone()); + } else if (!(element)->empty()) { // merge member is not MemberElement, append value + value.push_back(element->clone()); } } } @@ -285,13 +285,15 @@ namespace refract { IElement::MemberElementCollection toAppend; - for (const auto& it : append) { + for (const auto& member : append) { - if (!it) { + assert(member); + + if (!member) { continue; } - if (StringElement* key = TypeQueryVisitor::as(it->value.first)) { + if (StringElement* key = TypeQueryVisitor::as(member->value.first)) { if (noMergeKeys.find(key->value) != noMergeKeys.end()) { // this key should not be merged continue; @@ -301,16 +303,16 @@ namespace refract if (item != info.end()) { // this key alrady exist, replace value delete (*item)->value.second; - (*item)->value.second = it->value.second->clone(); + (*item)->value.second = member->value.second->clone(); continue; } } - toAppend.push_back(static_cast(it->clone())); + toAppend.push_back(static_cast(member->clone())); } - for (const auto& it : toAppend) { - info.push_back(it); + for (const auto& member : toAppend) { + info.push_back(member); } toAppend.clear(); @@ -409,4 +411,5 @@ namespace refract return std::for_each(value.begin(), value.end(), ElementMerger()); } + }; // namespace refract diff --git a/src/refract/Element.h b/src/refract/Element.h index 7cc757c48..3d33a1fae 100644 --- a/src/refract/Element.h +++ b/src/refract/Element.h @@ -405,7 +405,7 @@ namespace refract static ValueType init() { - return NULL; + return nullptr; } static const std::string element() { @@ -415,12 +415,12 @@ namespace refract static void release(ValueType& value) { delete value; - value = NULL; + value = nullptr; } static void cloneValue(const ValueType& self, ValueType& other) { - other = self ? self->clone() : NULL; + other = self ? self->clone() : nullptr; } }; @@ -466,7 +466,7 @@ namespace refract static typename ValueType::value_type typedMemberClone(IElement* element, const IElement::cloneFlags flags) { if (!element) { - return NULL; + return nullptr; } return static_cast(element->clone(flags)); @@ -513,7 +513,7 @@ namespace refract static ValueType init() { - return NULL; + return nullptr; } static const std::string element() { @@ -522,15 +522,13 @@ namespace refract static void release(ValueType& value) { - if (value) { - delete value; - value = NULL; - } + delete value; + value = nullptr; } static void cloneValue(const ValueType& self, ValueType& other) { - other = self ? self->clone() : NULL; + other = self ? self->clone() : nullptr; } }; @@ -574,22 +572,18 @@ namespace refract static void release(ValueType& member) { - if (member.first) { - delete member.first; - member.first = NULL; - } + delete member.first; + member.first = nullptr; - if (member.second) { - delete member.second; - member.second = NULL; - } + delete member.second; + member.second = nullptr; } static void cloneValue(const ValueType& self, ValueType& other) { - other.first = self.first ? self.first->clone() : NULL; + other.first = self.first ? self.first->clone() : nullptr; - other.second = self.second ? self.second->clone() : NULL; + other.second = self.second ? self.second->clone() : nullptr; } }; @@ -616,18 +610,10 @@ namespace refract void set(IElement* key, IElement* element) { - if (value.first != NULL) { - delete value.first; - value.first = NULL; - } - + delete value.first; value.first = key; - if (value.second != NULL) { - delete value.second; - value.second = NULL; - } - + delete value.second; value.second = element; hasContent = true; @@ -635,11 +621,7 @@ namespace refract MemberElement& operator=(IElement* element) { - if (value.second != NULL) { - delete value.second; - value.second = NULL; - } - + delete value.second; value.second = element; return *this; } diff --git a/src/refract/JSONSchemaVisitor.cc b/src/refract/JSONSchemaVisitor.cc index 117370207..7e9320065 100644 --- a/src/refract/JSONSchemaVisitor.cc +++ b/src/refract/JSONSchemaVisitor.cc @@ -16,20 +16,22 @@ #include "JSONSchemaVisitor.h" #include "SerializeCompactVisitor.h" +#include + namespace refract { template void CloneMembers(T* a, const RefractElements* val) { - for (RefractElements::const_iterator it = val->begin(); it != val->end(); ++it) { + for (const auto& value : *val) { - if ((*it)->empty()) { + if ((value)->empty()) { continue; } RenderJSONVisitor v; - Visit(v, *(*it)); + Visit(v, *value); IElement* e = v.getOwnership(); a->push_back(e); } @@ -44,23 +46,23 @@ namespace refract return; } - for (typename T::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { + for (auto const& value : *val) { - if (!(*it) || (*it)->empty()) { + if (!value || value->empty()) { continue; } - if ((*it)->element() == "ref") { - HandleRefWhenFetchingMembers(*it, members, IncludeMembers); + if (value->element() == "ref") { + HandleRefWhenFetchingMembers(value, members, IncludeMembers); continue; } - members.push_back(*it); + members.push_back(value); } } JSONSchemaVisitor::JSONSchemaVisitor( - ObjectElement* pDefinitions /*= NULL*/, bool _fixed /*= false*/, bool _fixedType /*= false*/) + ObjectElement* pDefinitions /*= nullptr*/, bool _fixed /*= false*/, bool _fixedType /*= false*/) : pDefs(pDefinitions), fixed(_fixed), fixedType(_fixedType) { pObj = new ObjectElement; @@ -72,7 +74,7 @@ namespace refract JSONSchemaVisitor::~JSONSchemaVisitor() { - if (NULL != pObj) { + if (nullptr != pObj) { delete pObj; } } @@ -213,8 +215,7 @@ namespace refract BooleanElement* boolSecond = TypeQueryVisitor::as(e.value.second); if (e.value.second && (strSecond || numSecond || boolSecond)) { - IElement::MemberElementCollection::const_iterator defaultIt - = e.value.second->attributes.find("default"); + auto defaultIt = e.value.second->attributes.find("default"); if (defaultIt != e.value.second->attributes.end()) { renderer.addMember("default", (*defaultIt)->clone()); @@ -247,14 +248,14 @@ namespace refract { ArrayElement* a = new ArrayElement; - for (std::vector::const_iterator i = props.begin(); i != props.end(); ++i) { + for (auto const& prop : props) { - StringElement* str = TypeQueryVisitor::as((*i)->value.first); + StringElement* str = TypeQueryVisitor::as(prop->value.first); if (str) { - bool fixedType = IsTypeAttribute(*(*i), "fixedType"); + bool fixedType = IsTypeAttribute(*prop, "fixedType"); JSONSchemaVisitor renderer(pDefs, fixed, fixedType); - Visit(renderer, *(*i)->value.second); + Visit(renderer, *prop->value.second); pDefs->push_back(new MemberElement(str->value, definitionFromVariableProperty(renderer))); @@ -339,9 +340,9 @@ namespace refract { ArrayElement* a = new ArrayElement; - for (std::vector::const_iterator i = typesOrder.begin(); i != typesOrder.end(); ++i) { + for (auto const& item : typesOrder) { - const std::vector& items = types[*i]; + const std::vector& items = types[item]; IElement* elm = items.front(); JSONSchemaVisitor v(pDefs); @@ -388,17 +389,20 @@ namespace refract ArrayElement::ValueType av; bool allEmpty = allItemsEmpty(val); - for (ArrayElement::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { + for (auto const& value : *val) { - if (*it) { - // if all items are just type items then we - // want them in the schema, otherwise skip - // empty ones - if (allEmpty || !(*it)->empty()) { - JSONSchemaVisitor v(pDefs, fixed); - Visit(v, *(*it)); - av.push_back(v.getOwnership()); - } + assert(value); + if (!value) { + continue; + } + + // if all items are just type items then we + // want them in the schema, otherwise skip + // empty ones + if (allEmpty || !value->empty()) { + JSONSchemaVisitor v(pDefs, fixed); + Visit(v, *value); + av.push_back(v.getOwnership()); } } @@ -445,16 +449,16 @@ namespace refract std::map > types; std::vector typesOrder; - for (const auto& it : elms) { + for (const auto& enumeration : elms) { - if (it) { - std::vector& items = types[(it)->element()]; + if (enumeration) { + std::vector& items = types[enumeration->element()]; if (items.empty()) { - typesOrder.push_back((it)->element()); + typesOrder.push_back(enumeration->element()); } - items.push_back(it); + items.push_back(enumeration); } } @@ -543,7 +547,7 @@ namespace refract IElement* JSONSchemaVisitor::getOwnership() { IElement* ret = pObj; - pObj = NULL; + pObj = nullptr; return ret; } @@ -578,7 +582,7 @@ namespace refract RefractElements& oneOfMembers, ObjectElement* o) { - for (std::vector::const_iterator it = begin; it != end; ++it) { + for (auto it = begin; it != end; ++it) { if (!*it) { continue; } @@ -622,10 +626,9 @@ namespace refract // FIXME: there is no valid solution for multiple "SelectElement" in one object. - for (SelectElement::ValueType::const_iterator it = sel->value.begin(); it != sel->value.end(); - ++it) { + for (auto const& select : sel->value) { JSONSchemaVisitor v(pDefs); - VisitBy(*(*it), v); + VisitBy(*select, v); oneOfMembers.push_back(v.getOwnership()); } } break; diff --git a/src/refract/RenderJSONVisitor.cc b/src/refract/RenderJSONVisitor.cc index 0386dde68..4646fe37e 100644 --- a/src/refract/RenderJSONVisitor.cc +++ b/src/refract/RenderJSONVisitor.cc @@ -28,16 +28,16 @@ namespace refract return; } - for (typename T::ValueType::const_iterator it = val->begin(); it != val->end(); ++it) { + for (auto const& item: *val) { - if (!(*it) || (*it)->empty()) { + if (!item || item->empty()) { continue; } - if (RefElement* ref = TypeQueryVisitor::as(*it)) { + if (RefElement* ref = TypeQueryVisitor::as(item)) { HandleRefWhenFetchingMembers(ref, members, FetchMembers); continue; - } else if (SelectElement* select = TypeQueryVisitor::as(*it)) { + } else if (SelectElement* select = TypeQueryVisitor::as(item)) { if (select->value.empty() || !(*select->value.begin())) { continue; } @@ -47,7 +47,7 @@ namespace refract } RenderJSONVisitor renderer; - Visit(renderer, *(*it)); + Visit(renderer, *item); IElement* e = renderer.getOwnership(); if (!e) { @@ -59,15 +59,9 @@ namespace refract } } - RenderJSONVisitor::RenderJSONVisitor() : result(nullptr) - { - } - RenderJSONVisitor::~RenderJSONVisitor() { - if (result) { - delete result; - } + delete result; } void RenderJSONVisitor::operator()(const IElement& e) diff --git a/src/refract/RenderJSONVisitor.h b/src/refract/RenderJSONVisitor.h index 956b806f5..db8bc707d 100644 --- a/src/refract/RenderJSONVisitor.h +++ b/src/refract/RenderJSONVisitor.h @@ -19,10 +19,10 @@ namespace refract class RenderJSONVisitor { - IElement* result; + IElement* result = nullptr; public: - RenderJSONVisitor(); + RenderJSONVisitor() = default; virtual ~RenderJSONVisitor(); void operator()(const IElement& e); diff --git a/src/refract/SerializeCompactVisitor.cc b/src/refract/SerializeCompactVisitor.cc index 1944c0bcd..ce8d74364 100644 --- a/src/refract/SerializeCompactVisitor.cc +++ b/src/refract/SerializeCompactVisitor.cc @@ -49,9 +49,9 @@ namespace refract void SerializeValues(sos::Array& array, const Values& values, bool generateSourceMap) { - for (typename Values::const_iterator it = values.begin(); it != values.end(); ++it) { + for (auto const& value : values) { SosSerializeCompactVisitor s(generateSourceMap); - VisitBy(*(*it), s); + VisitBy(*value, s); array.push(s.value()); } } @@ -59,7 +59,7 @@ namespace refract void SosSerializeCompactVisitor::operator()(const EnumElement& e) { - IElement::MemberElementCollection::const_iterator enums = e.attributes.find("enumerations"); + auto enums = e.attributes.find("enumerations"); if (enums == e.attributes.end() || !(*enums)->value.second) { return; } @@ -89,13 +89,11 @@ namespace refract void SosSerializeCompactVisitor::operator()(const ObjectElement& e) { - typedef ObjectElement::ValueType::const_iterator iterator; - sos::Object obj; - for (iterator it = e.value.begin(); it != e.value.end(); ++it) { + for (auto const& value : e.value) { SosSerializeCompactVisitor sv(generateSourceMap); - VisitBy(*(*it), sv); + VisitBy(*value, sv); obj.set(sv.key(), sv.value()); } diff --git a/src/refract/VisitorUtils.cc b/src/refract/VisitorUtils.cc index 0334d4601..e1bfddcf4 100644 --- a/src/refract/VisitorUtils.cc +++ b/src/refract/VisitorUtils.cc @@ -13,7 +13,7 @@ namespace refract StringElement* GetDescription(const IElement& e) { - IElement::MemberElementCollection::const_iterator i = e.meta.find("description"); + auto i = e.meta.find("description"); if (i == e.meta.end()) { return NULL; diff --git a/src/refract/VisitorUtils.h b/src/refract/VisitorUtils.h index 11ed8c8db..f7c15a8c8 100644 --- a/src/refract/VisitorUtils.h +++ b/src/refract/VisitorUtils.h @@ -22,7 +22,7 @@ namespace refract template bool IsTypeAttribute(const T& e, std::string typeAttribute) { - IElement::MemberElementCollection::const_iterator ta = e.attributes.find("typeAttributes"); + auto ta = e.attributes.find("typeAttributes"); if (ta == e.attributes.end()) { return false; @@ -34,8 +34,8 @@ namespace refract return false; } - for (ArrayElement::ValueType::const_iterator it = attrs->value.begin(); it != attrs->value.end(); ++it) { - StringElement* attr = TypeQueryVisitor::as(*it); + for (auto const& value: attrs->value) { + StringElement* attr = TypeQueryVisitor::as(value); if (!attr) { continue; } @@ -50,32 +50,32 @@ namespace refract template bool IsVariableProperty(const T& e) { - IElement::MemberElementCollection::const_iterator i = e.attributes.find("variable"); + auto const var = e.attributes.find("variable"); - if (i == e.attributes.end()) { + if (var == e.attributes.end()) { return false; } - BooleanElement* b = TypeQueryVisitor::as((*i)->value.second); + const BooleanElement* b = TypeQueryVisitor::as((*var)->value.second); return b ? b->value : false; } template const T* GetDefault(const T& e) { - IElement::MemberElementCollection::const_iterator i = e.attributes.find("default"); + auto const dflt = e.attributes.find("default"); - if (i == e.attributes.end()) { + if (dflt == e.attributes.end()) { return NULL; } - return TypeQueryVisitor::as((*i)->value.second); + return TypeQueryVisitor::as((*dflt)->value.second); } template const T* GetSample(const T& e) { - IElement::MemberElementCollection::const_iterator i = e.attributes.find("samples"); + auto const i = e.attributes.find("samples"); if (i == e.attributes.end()) { return NULL; @@ -187,7 +187,7 @@ namespace refract const ArrayElement* GetEnumerations(const EnumElement& e) { - IElement::MemberElementCollection::const_iterator i = e.attributes.find("enumerations"); + auto i = e.attributes.find("enumerations"); if (i == e.attributes.end()) { return nullptr; @@ -216,7 +216,7 @@ namespace refract void HandleRefWhenFetchingMembers( const refract::IElement* e, typename T::ValueType& members, const Functor& functor) { - IElement::MemberElementCollection::const_iterator found = e->attributes.find("resolved"); + auto const found = e->attributes.find("resolved"); if (found == e->attributes.end()) { return; @@ -242,13 +242,13 @@ namespace refract template MemberElement* FindMemberByKey(const T& e, const std::string& name) { - for (typename T::ValueType::const_iterator it = e.value.begin(); it != e.value.end(); ++it) { + for (auto const& value: e.value) { ComparableVisitor cmp(name, ComparableVisitor::key); - VisitBy(*(*it), cmp); + VisitBy(*value, cmp); - if (cmp.get()) { // key was recognized - it is save to cast to MemberElement - return static_cast(*it); + if (cmp.get()) { // key was recognized - it is safe to cast to MemberElement + return static_cast(value); } } @@ -258,7 +258,7 @@ namespace refract template T* FindCollectionMemberValue(const IElement::MemberElementCollection& collection, const std::string& key) { - IElement::MemberElementCollection::const_iterator i = collection.find(key); + auto const i = collection.find(key); if (i == collection.end()) { return NULL; } diff --git a/test/test-ElementDataTest.cc b/test/test-ElementDataTest.cc index 42c0a83a3..a36572b8e 100644 --- a/test/test-ElementDataTest.cc +++ b/test/test-ElementDataTest.cc @@ -1,29 +1,25 @@ -#include "catch.hpp" - #include "ElementData.h" using namespace refract; using namespace drafter; -TEST_CASE("Check Complex/Primitive data","[ElementData]") { - REQUIRE(ElementData::IsPrimitive::value); + static_assert(IsPrimitive::type::value, "NullElement must be primitive"); - REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value); + static_assert(IsPrimitive::type::value, "StringElement must be primitive"); + static_assert(IsPrimitive::type::value, "NumberElement must be primitive"); + static_assert(IsPrimitive::type::value, "BooleanElement must be primitive"); - REQUIRE(ElementData::IsPrimitive::value); // probably invalid, but not used while conversion (maybe static assert?) + static_assert(IsPrimitive::type::value, "MemeberElement should be primitive"); // probably invalid, but not used while conversion - REQUIRE(ElementData::IsPrimitive::value); + static_assert(IsPrimitive::type::value, "RefElement should be primitive"); - REQUIRE_FALSE(ElementData::IsPrimitive::value); - REQUIRE_FALSE(ElementData::IsPrimitive::value); - REQUIRE_FALSE(ElementData::IsPrimitive::value); + static_assert(!IsPrimitive::type::value, "ArrayElement must not be primitive"); + static_assert(!IsPrimitive::type::value, "EnumElement must not be primitive"); + static_assert(!IsPrimitive::type::value, "ObjectElement must not be primitive"); - REQUIRE_FALSE(ElementData::IsPrimitive::value); - REQUIRE(ElementData::IsPrimitive::value); + static_assert(!IsPrimitive::type::value, "OptionElement must not be primitive"); + static_assert(IsPrimitive::type::value, "SelectElement must be primitive"); - REQUIRE_FALSE(ElementData::IsPrimitive::value); + static_assert(!IsPrimitive::type::value, "HolderElement must not be primitive"); -}