@@ -24,23 +24,44 @@ pub struct UMPLParentFunction {
24
24
25
25
impl fmt:: Display for UMPLFunction {
26
26
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
27
- todo ! ( )
27
+ for i in & self . parents {
28
+ write ! ( f, "{}\n ...\n " , i. top) ?;
29
+ }
30
+ write ! ( f, "{}" , self . body) ?;
31
+ for i in & self . parents {
32
+ write ! ( f, "\n ...\n {}" , i. bottom) ?;
33
+ }
34
+ Ok ( ( ) )
28
35
}
29
36
}
30
37
31
38
impl FunctionTrait for UMPLFunction {
32
39
impl_function_trait ! ( UMPLFunction ) ;
33
40
34
41
fn get_total_lines ( & self ) -> ( usize , usize ) {
35
- todo ! ( )
42
+ let mut start = self . lines . 0 ;
43
+ let mut end = self . lines . 1 ;
44
+ for parent in & self . parents {
45
+ if parent. lines . 0 < start {
46
+ start = parent. lines . 0 ;
47
+ end = parent. lines . 1 ;
48
+ }
49
+ }
50
+ ( start, end)
36
51
}
37
52
38
53
fn get_tops ( & self ) -> Vec < ( String , usize ) > {
39
- todo ! ( )
54
+ self . parents
55
+ . iter ( )
56
+ . map ( |f| ( f. top . clone ( ) , f. lines . 0 ) )
57
+ . collect ( )
40
58
}
41
59
42
60
fn get_bottoms ( & self ) -> Vec < ( String , usize ) > {
43
- todo ! ( )
61
+ self . parents
62
+ . iter ( )
63
+ . map ( |f| ( f. bottom . clone ( ) , f. lines . 1 ) )
64
+ . collect ( )
44
65
}
45
66
}
46
67
@@ -53,53 +74,104 @@ pub(crate) fn find_function_in_file(
53
74
let tokens = lexed. scan_tokens ( ) ;
54
75
let mut parsed = umpl:: parser:: Parser :: new ( tokens) ;
55
76
let ast = parsed. parse ( ) ;
56
- let res = find_function_recurse ( name, ast, & vec ! [ ] ) ;
57
- if res. len ( ) > 0 {
77
+ let res = find_function_recurse ( name, file_contents , ast, & vec ! [ ] ) ;
78
+ if ! res. is_empty ( ) {
58
79
return Ok ( res) ;
59
80
}
60
81
Err ( "no function found" ) ?
61
82
}
62
83
63
84
fn find_function_recurse (
64
85
name : & str ,
86
+ file_contents : & str ,
65
87
ast : Vec < Thing > ,
66
88
current : & Vec < UMPLParentFunction > ,
67
- ) -> Vec < ( UMPLFunction ) > {
89
+ ) -> Vec < UMPLFunction > {
68
90
let mut results = Vec :: new ( ) ;
69
91
for node in ast {
70
92
match node {
71
93
Thing :: Function ( fns) => {
72
94
if fns. name . to_string ( ) == name {
95
+ let lines = ( fns. line as usize , fns. end_line as usize ) ;
96
+ let body = file_contents
97
+ . lines ( )
98
+ . enumerate ( )
99
+ . filter ( |line| line. 0 >= lines. 0 - 1 && line. 0 < lines. 1 )
100
+ . map ( |line| format ! ( "{}\n " , line. 1 ) )
101
+ . collect :: < String > ( ) ;
73
102
let new_fn = UMPLFunction {
74
- lines : ( fns . line as usize , fns . end_line as usize ) ,
103
+ lines,
75
104
name : fns. name . to_string ( ) ,
76
- // TODO: get the function body
77
- body : String :: new ( ) ,
105
+ body : super :: make_lined ( & body, lines. 0 ) ,
78
106
args_count : fns. num_arguments as usize ,
79
107
parents : current. clone ( ) ,
80
108
} ;
81
109
results. push ( new_fn) ;
82
110
} else {
83
111
let mut new_current = current. clone ( ) ;
84
112
// turn into a parent function
113
+ let lines = ( fns. line as usize , fns. end_line as usize ) ;
114
+ let bottom = if let Some ( line) = file_contents. lines ( ) . nth ( lines. 1 - 1 ) {
115
+ super :: make_lined ( line, lines. 1 )
116
+ } else {
117
+ results. append ( & mut find_function_recurse (
118
+ name,
119
+ file_contents,
120
+ fns. body ,
121
+ & new_current,
122
+ ) ) ;
123
+ continue ;
124
+ } ;
125
+ // FIXME: this should find the last line of the `top` by looking at its first element of is ast instead of finding the the first `⧼` (which could be commented out)
126
+ let Some ( top_end) = file_contents. lines ( ) . enumerate ( ) . skip ( lines. 0 -1 ) . find_map ( |line| {
127
+ line. 1 . contains ( '⧼' ) . then_some ( line. 0 )
128
+ } ) else {
129
+ results. append ( & mut find_function_recurse ( name, file_contents, fns. body , & new_current) ) ;
130
+ continue ;
131
+ } ;
132
+ let top = file_contents
133
+ . lines ( )
134
+ . enumerate ( )
135
+ . filter ( |line| line. 0 >= lines. 0 - 1 && line. 0 <= top_end)
136
+ . map ( |line| format ! ( "{}\n " , line. 1 ) )
137
+ . collect :: < String > ( ) ;
85
138
let pfn = UMPLParentFunction {
86
- lines : ( fns . line as usize , fns . end_line as usize ) ,
139
+ lines,
87
140
name : fns. name . to_string ( ) ,
88
- // TODO: get the top and bottom lines
89
- top : String :: new ( ) ,
90
- bottom : String :: new ( ) ,
141
+ top : super :: make_lined ( & top, lines. 0 ) ,
142
+ bottom,
91
143
args_count : fns. num_arguments as usize ,
92
144
} ;
93
145
new_current. push ( pfn) ;
94
- results. append ( & mut find_function_recurse ( name, fns. body , & new_current) ) ;
146
+ results. append ( & mut find_function_recurse (
147
+ name,
148
+ file_contents,
149
+ fns. body ,
150
+ & new_current,
151
+ ) ) ;
95
152
}
96
153
}
97
154
Thing :: LoopStatement ( loops) => {
98
- results. append ( & mut find_function_recurse ( name, loops. body , current) ) ;
155
+ results. append ( & mut find_function_recurse (
156
+ name,
157
+ file_contents,
158
+ loops. body ,
159
+ current,
160
+ ) ) ;
99
161
}
100
162
Thing :: IfStatement ( ifs) => {
101
- results. append ( & mut find_function_recurse ( name, ifs. body_true , current) ) ;
102
- results. append ( & mut find_function_recurse ( name, ifs. body_false , current) ) ;
163
+ results. append ( & mut find_function_recurse (
164
+ name,
165
+ file_contents,
166
+ ifs. body_true ,
167
+ current,
168
+ ) ) ;
169
+ results. append ( & mut find_function_recurse (
170
+ name,
171
+ file_contents,
172
+ ifs. body_false ,
173
+ current,
174
+ ) ) ;
103
175
}
104
176
_ => { }
105
177
}
@@ -108,10 +180,22 @@ fn find_function_recurse(
108
180
}
109
181
110
182
#[ derive( Debug , Clone , PartialEq , Eq ) ]
111
- pub enum UMPLFilter { }
183
+ pub enum UMPLFilter {
184
+ HasParameterCount ( usize ) ,
185
+ HasParentWithParamCount ( usize ) ,
186
+ HasParentWithName ( String ) ,
187
+ HasParents ,
188
+ }
112
189
113
190
impl UMPLFilter {
114
191
pub fn matches ( & self , function : & UMPLFunction ) -> bool {
115
- false
192
+ match self {
193
+ Self :: HasParameterCount ( count) => function. args_count == * count,
194
+ Self :: HasParentWithParamCount ( count) => {
195
+ function. parents . iter ( ) . any ( |p| p. args_count == * count)
196
+ }
197
+ Self :: HasParentWithName ( name) => function. parents . iter ( ) . any ( |p| p. name == * name) ,
198
+ Self :: HasParents => !function. parents . is_empty ( ) ,
199
+ }
116
200
}
117
201
}
0 commit comments