diff --git a/.travis.yml b/.travis.yml index 96158aab..22b50341 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,6 @@ compiler: script: ./configure && make test before_install: - git submodule update --init --recursive -branches: - only: - - master notifications: email: recipients: diff --git a/configure b/configure index 14b22f9d..4359d889 100755 --- a/configure +++ b/configure @@ -26,6 +26,11 @@ parser.add_option("--debug", dest="debug", help="Also build debug build") +parser.add_option("--dest-cpu", + action="store", + dest="dest_cpu", + help="CPU architecture to build for. Valid values are: ia32, x64") + (options, args) = parser.parse_args() def write(filename, data): diff --git a/src/Blueprint.h b/src/Blueprint.h index abf16f17..bdc83c24 100644 --- a/src/Blueprint.h +++ b/src/Blueprint.h @@ -13,32 +13,43 @@ #include #include +/** + * API Blueprint Abstract Syntaxt Tree + * ----------------------------------- + * + * Data types in this documents define the API Blueprint AST. + */ + namespace snowcrash { - // - // Generic types - // - - // Name of section / element. Plain text + /** Name of a an API Blueprint entity. */ typedef std::string Name; - // Section Description. Rendered HTML from Markdown + /** + * \brief An API Blueprint entity Description. + * + * Depending on parser setting the description might be + * rendered HTML from Markdown or raw Markdown. + */ typedef std::string Description; - // URI + /** URI */ typedef std::string URI; - // URI template + /** URI template */ typedef std::string URITemplate; - // HTTP Method + /** HTTP Method */ typedef std::string HTTPMethod; - // Key:Value pair + /** A generic key - value pair */ typedef std::pair KeyValuePair; - // Default Container for collections - // FIXME: C++11 template aliases + /** + * Default Container for collections. + * + * FIXME: Use C++11 template aliases when migrating to C++11. + */ template struct Collection { typedef std::vector type; @@ -46,138 +57,160 @@ namespace snowcrash { typedef typename std::vector::const_iterator const_iterator; }; - // - // API Blueprint sections - // - - // Asset data + /** An asset data */ typedef std::string Asset; - // Metadata key-value pair, e.g. "HOST: http://acme.com" + /** + * \brief Metadata key-value pair, + * + * E.g. "HOST: http://acme.com" + */ typedef KeyValuePair Metadata; - // Header key-value pair, e.g. "Content-Type: application/json" + /** + * \brief Header key-value pair. + * + * E.g. "Content-Type: application/json" + */ typedef KeyValuePair Header; - // Parameter + /** Parameter */ struct Parameter { - // Parameter Name + /** Parameter Name */ Name name; - // Parameter Description + /** Parameter Description */ Description description; // TODO: type, optional, default value }; - // Payload + /** + * Payload + */ struct Payload { - // Payload Name + /** A Payload Name */ Name name; - // Payload Description + /** Payload Description */ Description description; - // Parameters + /** Payload-specific Parameters */ Collection::type parameters; - // Headers + /** Payload-specific Headers */ Collection
::type headers; - // Body + /** Body */ Asset body; - // Schema + /** Schema */ Asset schema; }; - // Resource Object + /** Resource Object */ typedef Payload ResourceObject; - // Request + /** Request */ typedef Payload Request; - // Response, a payload where name is HTTP status code + /** + * \brief Response + * + * A payload returned in a response to an action. + * Payload's name represents the HTTP status code. + */ typedef Payload Response; - // Method + /** + * Method + */ struct Method { - // HTTP method + /** HTTP method */ HTTPMethod method; - // Method name + /** A Method name */ Name name; - // Description + /** Description */ Description description; - // Parameters + /** Method-specfic Parameters */ Collection::type parameters; - // Headers + /** Method-specific HTTP headers */ Collection
::type headers; - // Requests + /** Requests */ Collection::type requests; - // Responses + /** Responses */ Collection::type responses; }; - // Resource + /** + * API Resource + */ struct Resource { - // URI template + /** URI template */ URITemplate uriTemplate; - // Resource Name + /** A Resource Name */ Name name; - // Description + /** Description of the resource */ Description description; - // Object represented by this resource + /** Object model representing this Resource */ ResourceObject object; - // Parameters + /** Parameters */ Collection::type parameters; - // Headers + /** Resource-specific HTTP Headers */ Collection
::type headers; - // Methods + /** A set of HTTP Methods specified for this Resource */ Collection::type methods; }; - // Group of resources + /** + * Group of API Resources + */ struct ResourceGroup { - // Group Name + /** A Group Name */ Name name; - // Group Description + /** Group description */ Description description; - // Resources + /** Resources */ Collection::type resources; }; - // API Blueprint + /** + * \brief API Blueprint AST + * + * This is top-level (or root if you prefer) of API Blueprint abstract syntax tree. + * Start reading a parsed API here. + */ struct Blueprint { - // Metadata + /** Metadata */ Collection::type metadata; - // API Name + /** The API Name */ Name name; - // API Overview + /** An API Overview description */ Description description; - // Resource Groups + /** The set of API Resource Groups */ Collection::type resourceGroups; }; } diff --git a/src/BlueprintParserCore.h b/src/BlueprintParserCore.h index e0634fa4..c47ccb94 100644 --- a/src/BlueprintParserCore.h +++ b/src/BlueprintParserCore.h @@ -112,18 +112,20 @@ namespace snowcrash { } }; - // - // Blueprint Parser Options - // + /** + * \brief Blueprint Parser Options. + * + * Controls blueprint parser behavi + */ enum BlueprintParserOption { - RenderDescriptionsOption = (1 << 0), // Render Markdown in description - RequireBlueprintNameOption = (1 << 1) // Treat missing blueprint name as error + RenderDescriptionsOption = (1 << 0), /// < Render Markdown in description. + RequireBlueprintNameOption = (1 << 1) /// < Treat missing blueprint name as error }; typedef unsigned int BlueprintParserOptions; - // - // Parser Core Data - // + /** + * Parser Core Data + */ struct BlueprintParserCore { BlueprintParserCore(BlueprintParserOptions opts, const SourceData& src, @@ -261,12 +263,14 @@ namespace snowcrash { return (!keyValuePair.first.empty() && !keyValuePair.second.empty()); } - ///! \brief Checks cursor validity within its container. - ///! \param cur an iterator to be checked - ///! \param bounds boundaries to check against - ///! \param parent cursor's parent block to be used in case of error reporting - ///! \param result error result output, an error object is added in case of failed check - ///! \returns true if cursor appears to be valid false otherwise + /** + * \brief Checks cursor validity within its container. + * \param cur an iterator to be checked + * \param bounds boundaries to check against + * \param parent cursor's parent block to be used in case of error reporting + * \param result error result output, an error object is added in case of failed check + * \returns true if cursor appears to be valid false otherwise + */ FORCEINLINE bool CheckCursor(const BlockIterator& cur, const SectionBounds& bounds, const BlockIterator& parent, diff --git a/src/MarkdownParser.cc b/src/MarkdownParser.cc index cdfa360a..dc686c42 100644 --- a/src/MarkdownParser.cc +++ b/src/MarkdownParser.cc @@ -22,7 +22,7 @@ static std::string BufText(const struct buf *text) const size_t MarkdownParser::OutputUnitSize = 64; const size_t MarkdownParser::MaxNesting = 16; -const int MarkdownParser::ParserExtensions = MKDEXT_FENCED_CODE | MKDEXT_NO_INTRA_EMPHASIS /*| MKDEXT_TABLES */; +const int MarkdownParser::ParserExtensions = MKDEXT_FENCED_CODE | MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_LAX_SPACING /*| MKDEXT_TABLES */; void MarkdownParser::parse(const SourceData& source, Result& result, MarkdownBlock::Stack& markdown) { diff --git a/src/ParserCore.h b/src/ParserCore.h index 4de34773..fd7c09b2 100644 --- a/src/ParserCore.h +++ b/src/ParserCore.h @@ -15,43 +15,50 @@ namespace snowcrash { - // - // Source (string) data - // + /** + * \brief Textual source data. A markdown-formatted text. + */ typedef std::string SourceData; - // - // Interval of Source data - // + /** + * \brief A range of data within the source data buffer. + */ struct SourceDataRange { size_t location; size_t length; }; - - // - // Block of Source Data, set of intervals - // + + /** + * \brief A block of source data. + * + * NOTE: The block does not have to be continuous. + */ typedef std::vector SourceDataBlock; - // Create SourceDataBlock - SourceDataBlock MakeSourceDataBlock(size_t loc, size_t len); - - // Append SourceDataBlock to existign blog, merging continuous blocks - void AppendSourceDataBlock(SourceDataBlock& destination, const SourceDataBlock& append); - - // Split source data block at len - typedef std::pair SourceDataBlockPair; - SourceDataBlockPair SplitSourceDataBlock(const SourceDataBlock& block, size_t len); - - // - // Source module line anotation - // + /** + * \brief A source data annotation. + * + * Annotation bound to a source data block. Includes an + * annotation code and an optional message. + */ struct SourceAnnotation { + /** + * \brief Default annotation code representing success. + */ static const int OK; + /** + * \brief %SourceAnnotation default constructor. + * + * Creates an empty anotation with the default annotation code. + */ SourceAnnotation() : code(OK) {} + /** + * \brief %SourceAnnotation copy constructor. + * \param rhs An anotation to be copied. + */ SourceAnnotation(const SourceAnnotation& rhs) { this->message = rhs.message; @@ -59,6 +66,12 @@ namespace snowcrash { this->location = rhs.location; } + /** + * \brief %SourceAnnotation constructor. + * \param message An annotation message. + * \param code Annotation code. + * \param location A location of the annotation. + */ SourceAnnotation(const std::string& message, int code = OK, const SourceDataBlock& location = SourceDataBlock()) { @@ -68,8 +81,13 @@ namespace snowcrash { this->location = location; } + /** \brief %SourceAnnotation destructor. */ ~SourceAnnotation() {} + /** + * \brief %SourceAnnotation assignment operator + * \param rhs An anotation to be assigned to this annotation. + */ SourceAnnotation& operator=(const SourceAnnotation& rhs) { this->message = rhs.message; this->code = rhs.code; @@ -77,35 +95,94 @@ namespace snowcrash { return *this; } - // Location of this annotation + /** The location of this annotation within the source data buffer. */ SourceDataBlock location; - // Annotation code + /** An annotation code. */ int code; - // Annotation message + /** A annotation message. */ std::string message; }; + /** + * Error source annotation. + */ typedef SourceAnnotation Error; + + /** + * Warning source annotation. + */ typedef SourceAnnotation Warning; + + /** + * A set of warning source annotations. + */ typedef std::vector Warnings; - // - // Module parsing report - // + /** + * \brief A parsing result Report. + * + * Resulte of a source data parsing operation. + * Composed of ONE error source annotation + * and a set of warning source annotations. + */ struct Result { - // Append another result to this one, replacing error. + /** + * \brief Append a result to this one, replacing the error source annotation. + * + * NOTE: A binding does not need to wrap this method. + */ Result& operator+=(const Result& rhs) { error = rhs.error; warnings.insert(warnings.end(), rhs.warnings.begin(), rhs.warnings.end()); return *this; } - + + /** Result error source annotation */ Error error; + + /** Result warning source annotations */ Warnings warnings; }; + + /** + * \brief Create a %SourceDataBlock with a range. + * \param loc A location in source data buffer. + * \param len Length of the range. + * + * NOTE: A binding does not need to wrap this function. + */ + SourceDataBlock MakeSourceDataBlock(size_t loc, size_t len); + + // Append SourceDataBlock to existign blog, merging continuous blocks + + /** + * \brief Append %SourceDataBlock to existign block, merging continuous blocks. + * \param destination A block to append to. + * \param append A block to be appended. + * + * NOTE: A binding does not need to wrap this function. + */ + void AppendSourceDataBlock(SourceDataBlock& destination, const SourceDataBlock& append); + + + /** + * \brief A generic pair of two blocks + * + * NOTE: A binding does not need to wrap this data type. + */ + typedef std::pair SourceDataBlockPair; + + /** + * \brief Splits %SourceDataBlock into two blocks. + * \param block A block to be split. + * \param len The length of first block after which the split occurs. + * + * NOTE: A binding does not need to wrap this function. + */ + SourceDataBlockPair SplitSourceDataBlock(const SourceDataBlock& block, size_t len); } #endif diff --git a/src/Serialize.cc b/src/Serialize.cc index 1e8a7147..b62521c5 100644 --- a/src/Serialize.cc +++ b/src/Serialize.cc @@ -11,6 +11,7 @@ #include #include #include "Serialize.h" +#include "StringUtility.h" using namespace snowcrash; @@ -32,11 +33,10 @@ const std::string SerializeKey::Object = "object"; std::string snowcrash::EscapeNewlines(const std::string& input) { - std::ostringstream oss; - std::istringstream iss(input); - std::string line; - while (std::getline(iss, line)) - oss << line << "\\n"; - - return oss.str(); + return ReplaceString(input, "\n", "\\n"); +} + +std::string snowcrash::EscapeDoubleQuotes(const std::string& input) +{ + return ReplaceString(input, "\"", "\\\""); } diff --git a/src/Serialize.h b/src/Serialize.h index 76b9e225..9e50739f 100644 --- a/src/Serialize.h +++ b/src/Serialize.h @@ -13,8 +13,25 @@ namespace snowcrash { + /** + * \brief Escape new lines in input string. + * \param input A string to escape its new lines. + * \return A new string with lines escaped. + * + * This function replaces all occurences of "\n" with "\\n". + */ std::string EscapeNewlines(const std::string& input); + /** + * \brief Escape every double quote in input string. + * \param input A string to escape its double quotes. + * \return A new string with double quotes escaped. + */ + std::string EscapeDoubleQuotes(const std::string& input); + + /** + * AST entities serialization keys + */ struct SerializeKey { static const std::string Metadata; static const std::string Name; diff --git a/src/SerializeJSON.cc b/src/SerializeJSON.cc index 6273f8b5..0f269560 100644 --- a/src/SerializeJSON.cc +++ b/src/SerializeJSON.cc @@ -50,10 +50,11 @@ static void serialize(const std::string& key, const std::string& value, size_t l serialize(key, os); os << ": "; - if (value.find("\n") != std::string::npos) - serialize(EscapeNewlines(value), os); + std::string normValue = EscapeDoubleQuotes(value); + if (normValue.find("\n") != std::string::npos) + serialize(EscapeNewlines(normValue), os); else - serialize(value, os); + serialize(normValue, os); if (object) { os << "\n"; diff --git a/src/SerializeYAML.cc b/src/SerializeYAML.cc index b2cbb8e8..5de57392 100644 --- a/src/SerializeYAML.cc +++ b/src/SerializeYAML.cc @@ -24,8 +24,15 @@ static void serialize(const std::string& key, const std::string& value, size_t l os << key << ": "; + std::string normalizedValue = value; + if (normalizedValue.find("\"") != std::string::npos) + normalizedValue = EscapeDoubleQuotes(normalizedValue); + if (value.find("\n") != std::string::npos) - os << "\"" << EscapeNewlines(value) << "\""; + normalizedValue = EscapeNewlines(normalizedValue); + + if (normalizedValue != value) + os << "\"" << normalizedValue << "\""; else os << value; diff --git a/src/StringUtility.h b/src/StringUtility.h index 3c3a81a0..77200f81 100644 --- a/src/StringUtility.h +++ b/src/StringUtility.h @@ -76,7 +76,27 @@ namespace snowcrash { elems.push_back(s.substr(pos + 1, std::string::npos)); } return elems; - } + } + + + /** + * \brief Replace all occurences of a string. + * \param s A string to search in. + * \param find A string to look for. + * \param replace A string to replace with. + * \return A copy of %s with all occurences of %find replaced by %replace. + */ + inline std::string ReplaceString(const std::string& s, + const std::string& find, + const std::string& replace) { + size_t pos = 0; + std::string target(s); + while ((pos = target.find(find, pos)) != std::string::npos) { + target.replace(pos, find.length(), replace); + pos += replace.length(); + } + return target; + } } #endif diff --git a/src/snowcrash.cc b/src/snowcrash.cc index e024bb73..57315d66 100644 --- a/src/snowcrash.cc +++ b/src/snowcrash.cc @@ -10,8 +10,9 @@ using namespace snowcrash; -void snowcrash::parse(const SourceData& source, BlueprintParserOptions options, Result& result, Blueprint& blueprint) +int snowcrash::parse(const SourceData& source, BlueprintParserOptions options, Result& result, Blueprint& blueprint) { Parser p; p.parse(source, options, result, blueprint); + return result.error.code; } diff --git a/src/snowcrash.h b/src/snowcrash.h index e70c602b..eda7aaab 100644 --- a/src/snowcrash.h +++ b/src/snowcrash.h @@ -11,10 +11,31 @@ #include "Parser.h" +/** + * API Blueprint Parser Interface + * ------------------------------ + * + * This is the parser's entry point. + * + * For Snow Crash users, this is the only interface to use. + * + * For binding writers, this is the point to start wrapping. + * Refer to https://github.com/apiaryio/snowcrash/wiki/Writing-a-binding + * for details on how to write a Snow Crash binding. + */ + namespace snowcrash { - // Convenience wrapper for Parser's parse method - void parse(const SourceData& source, BlueprintParserOptions options, Result& result, Blueprint& blueprint); + /** + * \brief Parse the source data into a blueprint abstract source tree (AST). + * + * \param source A textual source data to be parsed. + * \param options Parser options. Use 0 for no addtional options. + * \param result Parsing result report. + * \param blueprint Parsed blueprint AST. + * \return Error status code. Zero represents success, non-zero a failure. + */ + int parse(const SourceData& source, BlueprintParserOptions options, Result& result, Blueprint& blueprint); } #endif diff --git a/test/test-BlueprintParser.cc b/test/test-BlueprintParser.cc index 815ef5b0..2c6dcb78 100644 --- a/test/test-BlueprintParser.cc +++ b/test/test-BlueprintParser.cc @@ -467,10 +467,8 @@ TEST_CASE("bpparser/metadatarequired-name", "Test required blueprint name on blu CHECK(result.warnings.empty()); } -TEST_CASE("bparser/incorrect-duplicity-warn", "Issue: fix incorrect warning about duplicity") +TEST_CASE("Incorrect warning about duplicate resources", "[blueprint][issue][3]") { - //https://github.com/apiaryio/snowcrash/issues/3 - // Blueprint in question: //R"( //FORMAT: X-1A @@ -513,3 +511,62 @@ TEST_CASE("bparser/incorrect-duplicity-warn", "Issue: fix incorrect warning abou REQUIRE(blueprint.resourceGroups.size() == 2); } + +TEST_CASE("Fail to parse nested lists in description", "[blueprint][issue][#16]") +{ + // Blueprint in question: + //R"( + //# API + //+ List + // + Nested Item + //"); + + const std::string source = \ +"# API\n\ ++ List\n\ + + Nested Item\n\ +"; + + MarkdownBlock::Stack markdown; + markdown.push_back(MarkdownBlock(HeaderBlockType, "API", 1, MakeSourceDataBlock(0, 6))); + + markdown.push_back(MarkdownBlock(ListBlockBeginType, SourceData(), 0, SourceDataBlock())); + markdown.push_back(MarkdownBlock(ListItemBlockBeginType, SourceData(), 0, SourceDataBlock())); + + markdown.push_back(MarkdownBlock(ListBlockBeginType, SourceData(), 0, SourceDataBlock())); + markdown.push_back(MarkdownBlock(ListItemBlockBeginType, SourceData(), 0, SourceDataBlock())); + + markdown.push_back(MarkdownBlock(ListItemBlockEndType, "Nested Item\n", 0, MakeSourceDataBlock(19, 12))); + markdown.push_back(MarkdownBlock(ListBlockEndType, SourceData(), 0, MakeSourceDataBlock(17, 14))); + + SourceDataBlock block; + SourceDataRange r; + r.location = 8; + r.length = 5; + block.push_back(r); + + r.location = 17; + r.length = 14; + block.push_back(r); + + markdown.push_back(MarkdownBlock(ListItemBlockEndType, "List\n", 0, block)); + markdown.push_back(MarkdownBlock(ListBlockEndType, SourceData(), 0, MakeSourceDataBlock(6, 25))); + + Blueprint blueprint; + BlueprintParserCore parser(0, source, Blueprint()); + ParseSectionResult result = BlueprintParserInner::Parse(markdown.begin(), markdown.end(), parser, blueprint); + + REQUIRE(result.first.error.code == Error::OK); + CHECK(result.first.warnings.empty()); + + const MarkdownBlock::Stack &blocks = markdown; + REQUIRE(std::distance(blocks.begin(), result.second) == 9); + + REQUIRE(blueprint.name == "API"); + REQUIRE(blueprint.description == \ +"+ List\n\ + + Nested Item\n\ +"); + REQUIRE(blueprint.resourceGroups.empty()); +} + diff --git a/test/test-MarkdownParser.cc b/test/test-MarkdownParser.cc index 89f652ff..d292f020 100644 --- a/test/test-MarkdownParser.cc +++ b/test/test-MarkdownParser.cc @@ -612,3 +612,63 @@ TEST_CASE("mdparser/parse-header-only", "parsing asserting header one liner") REQUIRE(markdown[0].data == 1); } +TEST_CASE("Missing nested list item", "[markdown][issue][#12]") +{ + MarkdownParser parser; + Result result; + MarkdownBlock::Stack markdown; + + const std::string source = \ +"\n\ ++ Parent\n\ +\n\ + + Item1\n\ +\n\ + Para1\n\ +\n\ + + Item2\n\ +"; + + parser.parse(source, result, markdown); + + REQUIRE(result.error.code == Error::OK); + REQUIRE(result.warnings.empty()); + + REQUIRE(markdown.size() == 14); + + REQUIRE(markdown[0].type == ListBlockBeginType); + REQUIRE(markdown[0].content.empty()); + REQUIRE(markdown[1].type == ListItemBlockBeginType); + REQUIRE(markdown[1].content.empty()); + + REQUIRE(markdown[2].type == ParagraphBlockType); + REQUIRE(markdown[2].content == "Parent"); + + REQUIRE(markdown[3].type == ListBlockBeginType); + REQUIRE(markdown[3].content.empty()); + REQUIRE(markdown[4].type == ListItemBlockBeginType); + REQUIRE(markdown[4].content.empty()); + + REQUIRE(markdown[5].type == ListItemBlockEndType); + REQUIRE(markdown[5].content == "Item1\n"); + REQUIRE(markdown[6].type == ListBlockEndType); + REQUIRE(markdown[6].content.empty()); + + REQUIRE(markdown[7].type == ParagraphBlockType); + REQUIRE(markdown[7].content == "Para1"); + + REQUIRE(markdown[8].type == ListBlockBeginType); + REQUIRE(markdown[8].content.empty()); + REQUIRE(markdown[9].type == ListItemBlockBeginType); + REQUIRE(markdown[9].content.empty()); + + REQUIRE(markdown[10].type == ListItemBlockEndType); + REQUIRE(markdown[10].content == "Item2\n"); + REQUIRE(markdown[11].type == ListBlockEndType); + REQUIRE(markdown[11].content.empty()); + + REQUIRE(markdown[12].type == ListItemBlockEndType); + REQUIRE(markdown[12].content.empty()); + REQUIRE(markdown[13].type == ListBlockEndType); + REQUIRE(markdown[13].content.empty()); +} diff --git a/test/test-PayloadParser.cc b/test/test-PayloadParser.cc index 6ee55c91..96edcab3 100644 --- a/test/test-PayloadParser.cc +++ b/test/test-PayloadParser.cc @@ -65,7 +65,7 @@ MarkdownBlock::Stack snowcrashtest::CanonicalPayloadFixture() return markdown; } -TEST_CASE("pldparser/classifier", "Payload block classifier") +TEST_CASE("Payload block classifier", "[payload]") { MarkdownBlock::Stack markdown = CanonicalPayloadFixture(); @@ -127,7 +127,7 @@ TEST_CASE("pldparser/classifier", "Payload block classifier") } -TEST_CASE("pldparser/parse", "Parse canonical payload") +TEST_CASE("Parse canonical payload", "[payload]") { MarkdownBlock::Stack markdown = CanonicalPayloadFixture(); Payload payload; @@ -152,7 +152,7 @@ TEST_CASE("pldparser/parse", "Parse canonical payload") REQUIRE(payload.schema == "Code 2"); } -TEST_CASE("pldparser/parse-list-description", "Parse description with list") +TEST_CASE("Parse description with list", "[payload]") { // Blueprint in question: //R"( @@ -187,7 +187,7 @@ TEST_CASE("pldparser/parse-list-description", "Parse description with list") REQUIRE(result.first.error.code != Error::OK); } -TEST_CASE("pldparser/parse-one", "Parse just one payload in a list with multiple payloads") +TEST_CASE("Parse just one payload in a list with multiple payloads", "[payload]") { // Blueprint in question: //R"( @@ -222,7 +222,7 @@ TEST_CASE("pldparser/parse-one", "Parse just one payload in a list with multiple REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-one-foreign", "Parse just one payload in a list with multiple items") +TEST_CASE("Parse just one payload in a list with multiple items", "[payload]") { // Blueprint in question: //R"( @@ -257,7 +257,7 @@ TEST_CASE("pldparser/parse-one-foreign", "Parse just one payload in a list with REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-payload-foreign-listitem", "Parse payload with foreign list item") +TEST_CASE("Parse payload with foreign list item", "[payload]") { // Blueprint in question: //R"( @@ -309,7 +309,7 @@ TEST_CASE("pldparser/parse-payload-foreign-listitem", "Parse payload with foreig REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-payload-foreign-block", "Parse payload with foreign block") +TEST_CASE("Parse payload with foreign block", "[payload]") { // Blueprint in question: //R"( @@ -360,7 +360,7 @@ TEST_CASE("pldparser/parse-payload-foreign-block", "Parse payload with foreign b } -TEST_CASE("pldparser/parse-abbrev-body", "Parse abbreviated payload body") +TEST_CASE("Parse abbreviated payload body", "[payload]") { // Blueprint in question: //R"( @@ -396,7 +396,7 @@ TEST_CASE("pldparser/parse-abbrev-body", "Parse abbreviated payload body") REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-abbrev-inline", "Parse abbreviated inline payload body") +TEST_CASE("Parse abbreviated inline payload body", "[payload]") { // Blueprint in question: //R"( @@ -429,7 +429,7 @@ TEST_CASE("pldparser/parse-abbrev-inline", "Parse abbreviated inline payload bod REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-symbol-inline-reference", "Parse inline payload with symbol reference") +TEST_CASE("Parse inline payload with symbol reference", "[payload]") { // Blueprint in question: //R"( @@ -469,7 +469,7 @@ TEST_CASE("pldparser/parse-symbol-inline-reference", "Parse inline payload with REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/parse-symbol-reference", "Parse payload with symbol reference") +TEST_CASE("Parse payload with symbol reference", "[payload]") { // Blueprint in question: //R"( @@ -515,10 +515,8 @@ TEST_CASE("pldparser/parse-symbol-reference", "Parse payload with symbol referen REQUIRE(payload.schema.empty()); } -TEST_CASE("pldparser/fix-missing-source-map", "Issue: Fix missing source map") +TEST_CASE("Missing 'expected pre-formatted code block' warning source map", "[payload][issue][#2]") { - // https://github.com/apiaryio/snowcrash/issues/2 - // // Blueprint in question: //R"( //# GET /res @@ -552,4 +550,3 @@ TEST_CASE("pldparser/fix-missing-source-map", "Issue: Fix missing source map") REQUIRE(result.first.warnings[0].location.size() == 1); } - diff --git a/vcbuild.bat b/vcbuild.bat index 1ed92352..13dd6405 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -7,10 +7,52 @@ cd %~dp0 +if /i "%1"=="help" goto help +if /i "%1"=="--help" goto help +if /i "%1"=="-help" goto help +if /i "%1"=="/help" goto help +if /i "%1"=="?" goto help +if /i "%1"=="-?" goto help +if /i "%1"=="--?" goto help +if /i "%1"=="/?" goto help + +@rem Process arguments. +set config=Release +set target=Build +set target_arch=ia32 +set noprojgen= +set nobuild= +set test= + +:next-arg +if "%1"=="" goto args-done +if /i "%1"=="debug" set config=Debug&goto arg-ok +if /i "%1"=="release" set config=Release&goto arg-ok +if /i "%1"=="clean" set target=Clean&goto arg-ok +if /i "%1"=="ia32" set target_arch=ia32&goto arg-ok +if /i "%1"=="x86" set target_arch=ia32&goto arg-ok +if /i "%1"=="x64" set target_arch=x64&goto arg-ok +if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok +if /i "%1"=="nobuild" set nobuild=1&goto arg-ok +if /i "%1"=="test" set test=test&goto arg-ok + +echo Warning: ignoring invalid command line option `%1`. + +:arg-ok +shift +goto next-arg + +:args-done +if "%config%"=="Debug" set debug_arg=--debug + +:project-gen +@rem Skip project generation if requested. +if defined noprojgen goto msbuild + @rem Generate the VS project. SETLOCAL if defined VS100COMNTOOLS call "%VS100COMNTOOLS%\VCVarsQueryRegistry.bat" - python configure + python configure %debug_arg% --dest-cpu=%target_arch% if errorlevel 1 goto create-msvs-files-failed if not exist build/snowcrash.sln goto create-msvs-files-failed echo Project files generated. @@ -20,6 +62,9 @@ ENDLOCAL @rem goto exit :msbuild +@rem Skip project generation if requested. +if defined nobuild goto exit + @rem Look for Visual Studio 2012 if not defined VS110COMNTOOLS goto vc-set-2010 if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 @@ -45,6 +90,12 @@ echo Building Snow Crash... msbuild build/snowcrash.sln /m /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo if errorlevel 1 goto exit +:run +@rem Run tests if requested. +if "%test%"=="" goto exit +echo Running tests... +.\build\Debug\test-snowcrash.exe + @rem All Done goto exit @@ -52,5 +103,14 @@ goto exit echo Failed to create vc project files. goto exit +:help +echo vcbuild.bat [debug/release] [test] [clean] [noprojgen] [nobuild] [x86/x64] +echo Examples: +echo vcbuild.bat : builds release build +echo vcbuild.bat nobuild : generate MSVS project files only +echo vcbuild.bat debug : builds debug build +echo vcbuild.bat test : builds debug build and runs tests +goto exit + :exit goto :EOF