//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift-c/SyntaxParser/SwiftSyntaxParser.h" #include "swift/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include #include "gtest/gtest.h" using namespace swift; static swiftparse_client_node_t parse(StringRef source, swiftparse_node_handler_t node_handler, swiftparse_node_lookup_t node_lookup) { swiftparse_parser_t parser = swiftparse_parser_create(); swiftparse_parser_set_node_handler(parser, node_handler); swiftparse_parser_set_node_lookup(parser, node_lookup); swiftparse_client_node_t top = swiftparse_parse_string(parser, source.data(), source.size()); swiftparse_parser_dispose(parser); return top; } TEST(SwiftSyntaxParserTests, IncrementalParsing) { StringRef source1 = "func t1() { }\n" "func t2() { }\n"; StringRef source2 = "func t1renamed() { }\n" "func t2() { }\n"; // FIXME: Use the syntax kind directly instead of the serialization number. swiftparse_syntax_kind_t codeBlockItemList = 163; swiftparse_syntax_kind_t codeBlockItem = 92; // Assign id numbers to codeBlockItem nodes and collect the ids that are // listed as members of a codeBlockItemList node into a vector. // When we reparse, check that we got the parser to resuse the node id from // the previous parse. __block std::vector nodeids; __block int idcounter = 0; size_t t2Offset = StringRef(source1).find("\nfunc t2"); __block int t2NodeId = 0; __block size_t t2NodeLength = 0; swiftparse_node_handler_t nodeHandler = ^swiftparse_client_node_t(const swiftparse_syntax_node_t *raw_node) { if (raw_node->kind == codeBlockItem) { int nodeid = ++idcounter; if (raw_node->range.offset == t2Offset) { t2NodeId = nodeid; t2NodeLength = raw_node->range.length; } return (void*)(intptr_t)nodeid; } if (raw_node->kind == codeBlockItemList) { for (unsigned i = 0, e = raw_node->layout_data.nodes_count; i != e; ++i) { nodeids.push_back((int)(intptr_t)raw_node->layout_data.nodes[i]); } } return nullptr; }; parse(source1, nodeHandler, nullptr); EXPECT_EQ(t2NodeId, 2); ASSERT_NE(t2NodeLength, size_t(0)); EXPECT_EQ(nodeids, (std::vector{1, 2})); nodeids.clear(); idcounter = 1000; t2Offset = StringRef(source2).find("\nfunc t2"); swiftparse_node_lookup_t nodeLookup = ^swiftparse_lookup_result_t(size_t offset, swiftparse_syntax_kind_t kind) { if (offset == t2Offset && kind == codeBlockItem) { return { t2NodeLength, (void*)(intptr_t)t2NodeId }; } else { return {0, nullptr}; } }; parse(source2, nodeHandler, nodeLookup); EXPECT_EQ(nodeids, (std::vector{1001, 2})); }