13
13
#include " swift-c/SyntaxParser/SwiftSyntaxParser.h"
14
14
#include " swift/Basic/LLVM.h"
15
15
#include " llvm/ADT/StringRef.h"
16
+ #include " swift/Syntax/Serialization/SyntaxSerialization.h"
16
17
#include < vector>
17
18
#include " gtest/gtest.h"
18
19
19
20
using namespace swift ;
21
+ using namespace swift ::syntax;
22
+ using namespace serialization ;
20
23
21
24
static swiftparse_client_node_t
22
25
parse (StringRef source, swiftparse_node_handler_t node_handler,
@@ -29,63 +32,110 @@ parse(StringRef source, swiftparse_node_handler_t node_handler,
29
32
return top;
30
33
}
31
34
35
+ static bool containsChild (swiftparse_layout_data_t layout_data, void *child) {
36
+ for (size_t i = 0 ; i < layout_data.nodes_count ; i++) {
37
+ if (layout_data.nodes [i] == child) {
38
+ return true ;
39
+ }
40
+ }
41
+ return false ;
42
+ }
43
+
32
44
TEST (SwiftSyntaxParserTests, IncrementalParsing) {
33
45
StringRef source1 =
34
46
" func t1() { }\n "
35
- " func t2() { }\n " ;
47
+ " func t2() { }\n "
48
+ " func t3() { }\n " ;
49
+
36
50
StringRef source2 =
37
51
" func t1renamed() { }\n "
38
- " func t2() { }\n " ;
52
+ " func t2() { }\n "
53
+ " func t3() { }\n " ;
54
+
55
+ swiftparse_syntax_kind_t token = getNumericValue (SyntaxKind::Token);
56
+ swiftparse_syntax_kind_t functionDecl = getNumericValue (SyntaxKind::FunctionDecl);
57
+ swiftparse_syntax_kind_t codeBlockItem = getNumericValue (SyntaxKind::CodeBlockItem);
58
+ swiftparse_syntax_kind_t codeBlockItemList = getNumericValue (SyntaxKind::CodeBlockItemList);
59
+
60
+ // Set up a bunch of node ids that we can later use.
61
+ void *t1Token = &t1Token;
62
+ void *t1Func = &t1Func;
63
+ void *t1CodeBlockItem = &t1CodeBlockItem;
64
+ void *t2Token = &t2Token;
65
+ void *t2Func = &t2Func;
66
+ void *t2CodeBlockItem = &t2CodeBlockItem;
67
+ void *t3Token = &t3Token;
68
+ void *t3Func = &t3Func;
69
+ void *t3CodeBlockItem = &t3CodeBlockItem;
39
70
40
- // FIXME: Use the syntax kind directly instead of the serialization number.
41
- swiftparse_syntax_kind_t codeBlockItemList = 163 ;
42
- swiftparse_syntax_kind_t codeBlockItem = 92 ;
71
+ // Find the t1/t2/t3 tokens in the source
72
+ size_t t1TokenOffset = StringRef (source1).find (" t1" );
73
+ size_t t2TokenOffset = StringRef (source1).find (" t2" );
74
+ size_t t3TokenOffset = StringRef (source1).find (" t3" );
43
75
44
- // Assign id numbers to codeBlockItem nodes and collect the ids that are
45
- // listed as members of a codeBlockItemList node into a vector.
46
- // When we reparse, check that we got the parser to resuse the node id from
47
- // the previous parse.
76
+ // The length of the t2/t3 code block items
77
+ size_t t2CodeBlockItemLength = 14 ;
78
+ size_t t3CodeBlockItemLength = 14 ;
79
+
80
+ // Collect the node ids of the code block items in this list and verify that
81
+ // t2 and t3 get reused after the edit from source1 to source2.
82
+ __block std::vector<void *> codeBlockItemIds;
48
83
49
- __block std::vector<int > nodeids;
50
- __block int idcounter = 0 ;
51
- size_t t2Offset = StringRef (source1).find (" \n func t2" );
52
- __block int t2NodeId = 0 ;
53
- __block size_t t2NodeLength = 0 ;
54
84
swiftparse_node_handler_t nodeHandler =
55
85
^swiftparse_client_node_t (const swiftparse_syntax_node_t *raw_node) {
56
- if (raw_node->kind == codeBlockItem) {
57
- int nodeid = ++idcounter;
58
- if (raw_node->range .offset == t2Offset) {
59
- t2NodeId = nodeid;
60
- t2NodeLength = raw_node->range .length ;
86
+ if (raw_node->kind == token) {
87
+ if (raw_node->token_data .range .offset == t1TokenOffset) {
88
+ return t1Token;
89
+ } else if (raw_node->token_data .range .offset == t2TokenOffset) {
90
+ return t2Token;
91
+ } else if (raw_node->token_data .range .offset == t3TokenOffset) {
92
+ return t3Token;
61
93
}
62
- return (void *)(intptr_t )nodeid;
63
- }
64
- if (raw_node->kind == codeBlockItemList) {
94
+ } else if (raw_node->kind == functionDecl) {
95
+ if (containsChild (raw_node->layout_data , t1Token)) {
96
+ return t1Func;
97
+ } else if (containsChild (raw_node->layout_data , t2Token)) {
98
+ return t2Func;
99
+ } else if (containsChild (raw_node->layout_data , t3Token)) {
100
+ return t3Func;
101
+ }
102
+ } else if (raw_node->kind == codeBlockItem) {
103
+ if (containsChild (raw_node->layout_data , t1Func)) {
104
+ return t1CodeBlockItem;
105
+ } else if (containsChild (raw_node->layout_data , t2Func)) {
106
+ return t2CodeBlockItem;
107
+ } else if (containsChild (raw_node->layout_data , t3Func)) {
108
+ return t3CodeBlockItem;
109
+ }
110
+ } else if (raw_node->kind == codeBlockItemList) {
65
111
for (unsigned i = 0 , e = raw_node->layout_data .nodes_count ;
66
112
i != e; ++i) {
67
- nodeids .push_back (( int )( intptr_t ) raw_node->layout_data .nodes [i]);
113
+ codeBlockItemIds .push_back (raw_node->layout_data .nodes [i]);
68
114
}
69
115
}
70
116
return nullptr ;
71
117
};
72
- parse (source1, nodeHandler, nullptr );
73
- EXPECT_EQ (t2NodeId, 2 );
74
- ASSERT_NE (t2NodeLength, size_t (0 ));
75
- EXPECT_EQ (nodeids, (std::vector<int >{1 , 2 }));
118
+ parse (source1, nodeHandler, /* node_lookup=*/ nullptr );
119
+ ASSERT_NE (t2CodeBlockItemLength, size_t (0 ));
120
+ EXPECT_EQ (codeBlockItemIds, (std::vector<void *>{t1CodeBlockItem, t2CodeBlockItem, t3CodeBlockItem}));
76
121
77
- nodeids .clear ();
78
- idcounter = 1000 ;
79
- t2Offset = StringRef (source2).find (" \n func t2 " );
122
+ codeBlockItemIds .clear ();
123
+ size_t t2CodeBlockItemOffset = StringRef (source2). find ( " \n func t2 " ) ;
124
+ size_t t3CodeBlockItemOffset = StringRef (source2).find (" \n func t3 " );
80
125
swiftparse_node_lookup_t nodeLookup =
81
126
^swiftparse_lookup_result_t (size_t offset, swiftparse_syntax_kind_t kind) {
82
- if (offset == t2Offset && kind == codeBlockItem) {
83
- return { t2NodeLength, (void *)(intptr_t )t2NodeId };
84
- } else {
85
- return {0 , nullptr };
127
+ if (kind == codeBlockItem) {
128
+ if (offset == t2CodeBlockItemOffset) {
129
+ return { t2CodeBlockItemLength, t2CodeBlockItem };
130
+ } else if (offset == t3CodeBlockItemOffset) {
131
+ return { t3CodeBlockItemLength, t3CodeBlockItem };
132
+ }
86
133
}
134
+ return {0 , nullptr };
87
135
};
88
136
89
137
parse (source2, nodeHandler, nodeLookup);
90
- EXPECT_EQ (nodeids, (std::vector<int >{1001 , 2 }));
138
+ // Assert that t2 and t3 get reused.
139
+ EXPECT_EQ (codeBlockItemIds[1 ], t2CodeBlockItem);
140
+ EXPECT_EQ (codeBlockItemIds[2 ], t3CodeBlockItem);
91
141
}
0 commit comments