@@ -11,28 +11,22 @@ use petgraph::stable_graph::NodeIndex;
1111
1212use crate :: graph:: CachedStableGraph ;
1313
14- /// FilialTuple represents a tuple with a parent at index 0
15- /// and a child at index 1. Parent can be nullable in the case of
14+ /// FilialTuple represents a tuple with a child at index 0
15+ /// and a parent at index 1. Parent can be nullable in the case of
1616/// the child being a top level node in the tree.
17- #[ derive( PartialEq , Eq , Hash ) ]
18- struct FilialTuple ( Option < NodeIndex > , NodeIndex ) ;
17+ pub type FilialTuple = ( NodeIndex , Option < NodeIndex > ) ;
1918
20- impl From < ( Option < & NodeIndex > , NodeIndex ) > for FilialTuple {
21- fn from ( tuple : ( Option < & NodeIndex > , NodeIndex ) ) -> Self {
22- FilialTuple ( tuple. 0 . copied ( ) , tuple. 1 )
23- }
24- }
25-
26- pub fn generate_merge_list < ' a > (
27- nodes : & ' a [ ( NodeIndex , Option < NodeIndex > ) ] , sources : & ' a HashMap < PathBuf , String > , graph : & ' a CachedStableGraph ,
28- ) -> String {
29- let mut line_directives: Vec < String > = Vec :: new ( ) ;
19+ pub fn generate_merge_list < ' a > ( nodes : & ' a [ FilialTuple ] , sources : & ' a HashMap < PathBuf , String > , graph : & ' a CachedStableGraph ) -> String {
20+ // contains additionally inserted lines such as #line and other directives, preamble defines etc
21+ let mut extra_lines: Vec < String > = Vec :: new ( ) ;
22+ extra_lines. reserve ( ( nodes. len ( ) * 2 ) + 2 ) ;
3023
3124 // list of source code views onto the below sources
3225 let mut merge_list: LinkedList < & ' a str > = LinkedList :: new ( ) ;
3326
34- line_directives. reserve ( nodes. len ( ) * 2 ) ;
35-
27+ // holds the offset into the child which has been added to the merge list for a parent.
28+ // A child can have multiple parents for a given tree, hence we have to track it for
29+ // a (child, parent) tuple instead of just the child.
3630 let mut last_offset_set: HashMap < FilialTuple , usize > = HashMap :: new ( ) ;
3731
3832 let mut nodes_iter = nodes. iter ( ) . peekable ( ) ;
@@ -41,7 +35,7 @@ pub fn generate_merge_list<'a>(
4135 let first = nodes_iter. next ( ) . unwrap ( ) . 0 ;
4236 let first_path = graph. get_node ( first) ;
4337
44- last_offset_set. insert ( FilialTuple ( None , first ) , 0 ) ;
38+ last_offset_set. insert ( ( first , None ) , 0 ) ;
4539
4640 // stack to keep track of the depth first traversal
4741 let mut stack = VecDeque :: < NodeIndex > :: new ( ) ;
@@ -52,30 +46,27 @@ pub fn generate_merge_list<'a>(
5246 & mut last_offset_set,
5347 graph,
5448 sources,
55- & mut line_directives ,
49+ & mut extra_lines ,
5650 & mut stack,
5751 ) ;
5852
5953 // now we add a view of the remainder of the root file
60- let offset = * last_offset_set. get ( & FilialTuple ( None , first ) ) . unwrap ( ) ;
54+ let offset = * last_offset_set. get ( & ( first , None ) ) . unwrap ( ) ;
6155
6256 let len = sources. get ( & first_path) . unwrap ( ) . len ( ) ;
6357 merge_list. push_back ( & sources. get ( & first_path) . unwrap ( ) [ min ( offset, len) ..] ) ;
6458
6559 let total_len = merge_list. iter ( ) . fold ( 0 , |a, b| a + b. len ( ) ) ;
6660
6761 let mut merged = String :: with_capacity ( total_len) ;
68- for slice in merge_list {
69- merged. push_str ( slice) ;
70- }
62+ merged. extend ( merge_list) ;
7163
7264 merged
7365}
7466
7567fn create_merge_views < ' a > (
76- nodes : & mut Peekable < Iter < ( NodeIndex , Option < NodeIndex > ) > > , merge_list : & mut LinkedList < & ' a str > ,
77- last_offset_set : & mut HashMap < FilialTuple , usize > , graph : & ' a CachedStableGraph , sources : & ' a HashMap < PathBuf , String > ,
78- line_directives : & mut Vec < String > , stack : & mut VecDeque < NodeIndex > ,
68+ nodes : & mut Peekable < Iter < FilialTuple > > , merge_list : & mut LinkedList < & ' a str > , last_offset_set : & mut HashMap < FilialTuple , usize > ,
69+ graph : & ' a CachedStableGraph , sources : & ' a HashMap < PathBuf , String > , extra_lines : & mut Vec < String > , stack : & mut VecDeque < NodeIndex > ,
7970) {
8071 loop {
8172 let n = match nodes. next ( ) {
@@ -94,10 +85,10 @@ fn create_merge_views<'a>(
9485 let ( char_for_line, char_following_line) = char_offset_for_line ( edge. line , parent_source) ;
9586
9687 let offset = * last_offset_set
97- . insert ( ( stack. back ( ) , parent ) . into ( ) , char_following_line)
88+ . insert ( ( parent , stack. back ( ) . copied ( ) ) , char_following_line)
9889 . get_or_insert ( 0 ) ;
9990 merge_list. push_back ( & parent_source[ offset..char_for_line] ) ;
100- add_opening_line_directive ( & child_path, merge_list, line_directives ) ;
91+ add_opening_line_directive ( & child_path, merge_list, extra_lines ) ;
10192
10293 match nodes. peek ( ) {
10394 Some ( next) => {
@@ -113,9 +104,9 @@ fn create_merge_views<'a>(
113104 }
114105 } ;
115106 merge_list. push_back ( & child_source[ ..offset] ) ;
116- last_offset_set. insert ( FilialTuple ( Some ( parent) , child ) , 0 ) ;
107+ last_offset_set. insert ( ( child , Some ( parent) ) , 0 ) ;
117108 // +2 because edge.line is 0 indexed but #line is 1 indexed and references the *following* line
118- add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, line_directives ) ;
109+ add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, extra_lines ) ;
119110 // if the next pair's parent is not the current pair's parent, we need to bubble up
120111 if stack. contains ( & next. 1 . unwrap ( ) ) {
121112 return ;
@@ -124,26 +115,24 @@ fn create_merge_views<'a>(
124115 }
125116
126117 stack. push_back ( parent) ;
127- create_merge_views ( nodes, merge_list, last_offset_set, graph, sources, line_directives , stack) ;
118+ create_merge_views ( nodes, merge_list, last_offset_set, graph, sources, extra_lines , stack) ;
128119 stack. pop_back ( ) ;
129120
130- let offset = * last_offset_set. get ( & FilialTuple ( Some ( parent) , child ) ) . unwrap ( ) ;
121+ let offset = * last_offset_set. get ( & ( child , Some ( parent) ) ) . unwrap ( ) ;
131122 let child_source = sources. get ( & child_path) . unwrap ( ) ;
132123 // this evaluates to false once the file contents have been exhausted aka offset = child_source.len() + 1
133- let end_offset = {
134- match child_source. ends_with ( '\n' ) {
135- true => 1 , /* child_source.len()-1 */
136- false => 0 , /* child_source.len() */
137- }
124+ let end_offset = match child_source. ends_with ( '\n' ) {
125+ true => 1 , /* child_source.len()-1 */
126+ false => 0 , /* child_source.len() */
138127 } ;
139128 if offset < child_source. len ( ) - end_offset {
140129 // if ends in \n\n, we want to exclude the last \n for some reason. Ask optilad
141130 merge_list. push_back ( & child_source[ offset../* std::cmp::max( */ child_source. len ( ) -end_offset/* , offset) */ ] ) ;
142- last_offset_set. insert ( FilialTuple ( Some ( parent) , child ) , 0 ) ;
131+ last_offset_set. insert ( ( child , Some ( parent) ) , 0 ) ;
143132 }
144133
145134 // +2 because edge.line is 0 indexed but #line is 1 indexed and references the *following* line
146- add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, line_directives ) ;
135+ add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, extra_lines ) ;
147136
148137 // we need to check the next item at the point of original return further down the callstack
149138 if nodes. peek ( ) . is_some ( ) && stack. contains ( & nodes. peek ( ) . unwrap ( ) . 1 . unwrap ( ) ) {
@@ -153,16 +142,14 @@ fn create_merge_views<'a>(
153142 None => {
154143 let child_source = sources. get ( & child_path) . unwrap ( ) ;
155144 // if ends in \n\n, we want to exclude the last \n for some reason. Ask optilad
156- let offset = {
157- match child_source. ends_with ( '\n' ) {
158- true => child_source. len ( ) - 1 ,
159- false => child_source. len ( ) ,
160- }
145+ let offset = match child_source. ends_with ( '\n' ) {
146+ true => child_source. len ( ) - 1 ,
147+ false => child_source. len ( ) ,
161148 } ;
162149 merge_list. push_back ( & child_source[ ..offset] ) ;
163- last_offset_set. insert ( FilialTuple ( Some ( parent) , child ) , 0 ) ;
150+ last_offset_set. insert ( ( child , Some ( parent) ) , 0 ) ;
164151 // +2 because edge.line is 0 indexed but #line is 1 indexed and references the *following* line
165- add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, line_directives ) ;
152+ add_closing_line_directive ( edge. line + 2 , & parent_path, merge_list, extra_lines ) ;
166153 }
167154 }
168155 }
@@ -184,13 +171,13 @@ fn char_offset_for_line(line_num: usize, source: &str) -> (usize, usize) {
184171 ( char_for_line, char_following_line)
185172}
186173
187- fn add_opening_line_directive ( path : & Path , merge_list : & mut LinkedList < & str > , line_directives : & mut Vec < String > ) {
174+ fn add_opening_line_directive ( path : & Path , merge_list : & mut LinkedList < & str > , extra_lines : & mut Vec < String > ) {
188175 let line_directive = format ! ( "#line 1 \" {}\" \n " , path. to_str( ) . unwrap( ) . replace( '\\' , "\\ \\ " ) ) ;
189- line_directives . push ( line_directive) ;
190- unsafe_get_and_insert ( merge_list, line_directives ) ;
176+ extra_lines . push ( line_directive) ;
177+ unsafe_get_and_insert ( merge_list, extra_lines ) ;
191178}
192179
193- fn add_closing_line_directive ( line : usize , path : & Path , merge_list : & mut LinkedList < & str > , line_directives : & mut Vec < String > ) {
180+ fn add_closing_line_directive ( line : usize , path : & Path , merge_list : & mut LinkedList < & str > , extra_lines : & mut Vec < String > ) {
194181 // Optifine doesn't seem to add a leading newline if the previous line was a #line directive
195182 let line_directive = if let Some ( l) = merge_list. back ( ) {
196183 if l. trim ( ) . starts_with ( "#line" ) {
@@ -202,14 +189,14 @@ fn add_closing_line_directive(line: usize, path: &Path, merge_list: &mut LinkedL
202189 format ! ( "\n #line {} \" {}\" \n " , line, path. to_str( ) . unwrap( ) . replace( '\\' , "\\ \\ " ) )
203190 } ;
204191
205- line_directives . push ( line_directive) ;
206- unsafe_get_and_insert ( merge_list, line_directives ) ;
192+ extra_lines . push ( line_directive) ;
193+ unsafe_get_and_insert ( merge_list, extra_lines ) ;
207194}
208195
209- fn unsafe_get_and_insert ( merge_list : & mut LinkedList < & str > , line_directives : & [ String ] ) {
196+ fn unsafe_get_and_insert ( merge_list : & mut LinkedList < & str > , extra_lines : & [ String ] ) {
210197 // :^)
211198 unsafe {
212- let vec_ptr_offset = line_directives . as_ptr ( ) . add ( line_directives . len ( ) - 1 ) ;
199+ let vec_ptr_offset = extra_lines . as_ptr ( ) . add ( extra_lines . len ( ) - 1 ) ;
213200 merge_list. push_back ( & vec_ptr_offset. as_ref ( ) . unwrap ( ) [ ..] ) ;
214201 }
215202}
0 commit comments