1+ use fxhash:: FxHashMap ;
12use serde:: ser:: { SerializeStruct , Serializer } ;
23use serde:: Serialize ;
34use std:: fmt;
@@ -123,65 +124,28 @@ pub trait Cognitive
123124where
124125 Self : Checker ,
125126{
126- fn compute ( _node : & Node , _stats : & mut Stats ) { }
127+ fn compute (
128+ _node : & Node ,
129+ _stats : & mut Stats ,
130+ _nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ,
131+ ) {
132+ }
127133}
128134
129- macro_rules! compute_booleans {
130- ( $node: ident, $stats: ident, $( $typs: pat_param ) |* ) => {
131- let mut cursor = $node. object( ) . walk( ) ;
132- for child in $node. object( ) . children( & mut cursor) {
133- if let $( $typs ) |* = child. kind_id( ) . into( ) {
134- $stats. structural = $stats
135- . boolean_seq
136- . eval_based_on_prev( child. kind_id( ) , $stats. structural) ;
137- }
135+ fn compute_booleans < T : std:: cmp:: PartialEq + std:: convert:: From < u16 > > (
136+ node : & Node ,
137+ stats : & mut Stats ,
138+ typs1 : T ,
139+ typs2 : T ,
140+ ) {
141+ let mut cursor = node. object ( ) . walk ( ) ;
142+ for child in node. object ( ) . children ( & mut cursor) {
143+ if typs1 == child. kind_id ( ) . into ( ) || typs2 == child. kind_id ( ) . into ( ) {
144+ stats. structural = stats
145+ . boolean_seq
146+ . eval_based_on_prev ( child. kind_id ( ) , stats. structural )
138147 }
139- } ;
140- }
141-
142- macro_rules! nesting_levels {
143- ( $node: ident, $stats: ident, [ $nest_func: pat_param => $nest_func_stop: pat_param] ,
144- [ $lambdas: pat => $( $lambdas_stop: pat_param ) |* ] ,
145- [ $( $nest_level: pat_param ) |* => $( $nest_level_stop: pat_param ) |* ] ) => {
146- // Find the depth of a function (the most external function is
147- // not considered)
148- $stats. nesting = count_specific_ancestors!( $node, $nest_func, $nest_func_stop) . max( 1 ) - 1 ;
149-
150- // Find the depth of a lambda
151- let lambda_depth = count_specific_ancestors!( $node, $lambdas, $( $lambdas_stop ) |* ) ;
152-
153- // Find the nesting operator level
154- $stats. nesting += lambda_depth
155- + count_specific_ancestors!(
156- $node,
157- $( $nest_level ) |* ,
158- $( $nest_level_stop) |*
159- ) ;
160-
161- // Reset the boolean sequence
162- $stats. boolean_seq. reset( ) ;
163-
164- increment( $stats) ;
165- } ;
166- ( $node: ident, $stats: ident,
167- [ $lambdas: pat_param => $( $lambdas_stop: pat_param ) |* ] ,
168- [ $( $nest_level: pat_param ) |* => $( $nest_level_stop: pat_param ) |* ] ) => {
169- // Find the depth of a lambda
170- let lambda_depth = count_specific_ancestors!( $node, $lambdas, $( $lambdas_stop ) |* ) ;
171-
172- // Find the nesting operator level
173- $stats. nesting = lambda_depth
174- + count_specific_ancestors!(
175- $node,
176- $( $nest_level ) |* ,
177- $( $nest_level_stop) |*
178- ) ;
179-
180- // Reset the boolean sequence
181- $stats. boolean_seq. reset( ) ;
182-
183- increment( $stats) ;
184- } ;
148+ }
185149}
186150
187151#[ derive( Debug , Default , Clone ) ]
@@ -228,18 +192,59 @@ fn increment_by_one(stats: &mut Stats) {
228192 stats. structural += 1 ;
229193}
230194
195+ fn get_nesting_from_map (
196+ node : & Node ,
197+ nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ,
198+ ) -> ( usize , usize , usize ) {
199+ if let Some ( parent) = node. object ( ) . parent ( ) {
200+ if let Some ( n) = nesting_map. get ( & parent. id ( ) ) {
201+ * n
202+ } else {
203+ ( 0 , 0 , 0 )
204+ }
205+ } else {
206+ ( 0 , 0 , 0 )
207+ }
208+ }
209+
210+ fn increment_function_depth < T : std:: cmp:: PartialEq + std:: convert:: From < u16 > > (
211+ depth : & mut usize ,
212+ node : & Node ,
213+ stop : T ,
214+ ) {
215+ // Increase depth function nesting if needed
216+ let mut child = node. object ( ) ;
217+ while let Some ( parent) = child. parent ( ) {
218+ if stop == parent. kind_id ( ) . into ( ) {
219+ * depth += 1 ;
220+ break ;
221+ }
222+ child = parent;
223+ }
224+ }
225+
226+ #[ inline( always) ]
227+ fn increase_nesting ( stats : & mut Stats , nesting : & mut usize , depth : usize , lambda : usize ) {
228+ stats. nesting = * nesting + depth + lambda;
229+ increment ( stats) ;
230+ * nesting += 1 ;
231+ stats. boolean_seq . reset ( ) ;
232+ }
233+
231234impl Cognitive for PythonCode {
232- fn compute ( node : & Node , stats : & mut Stats ) {
235+ fn compute (
236+ node : & Node ,
237+ stats : & mut Stats ,
238+ nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ,
239+ ) {
233240 use Python :: * ;
234241
242+ // Get nesting of the parent
243+ let ( mut nesting, mut depth, mut lambda) = get_nesting_from_map ( node, nesting_map) ;
244+
235245 match node. object ( ) . kind_id ( ) . into ( ) {
236246 IfStatement | ForStatement | WhileStatement | ConditionalExpression => {
237- nesting_levels ! (
238- node, stats,
239- [ FunctionDefinition => Module ] ,
240- [ Lambda => FunctionDefinition | Module ] ,
241- [ IfStatement | ForStatement | WhileStatement | ExceptClause => FunctionDefinition ]
242- ) ;
247+ increase_nesting ( stats, & mut nesting, depth, lambda) ;
243248 }
244249 ElifClause => {
245250 // No nesting increment for them because their cost has already
@@ -254,6 +259,7 @@ impl Cognitive for PythonCode {
254259 increment_by_one ( stats) ;
255260 }
256261 ExceptClause => {
262+ nesting += 1 ;
257263 increment ( stats) ;
258264 }
259265 ExpressionList | ExpressionStatement | Tuple => {
@@ -270,38 +276,46 @@ impl Cognitive for PythonCode {
270276 ExpressionList | IfStatement | ForStatement | WhileStatement
271277 ) ;
272278 }
273- compute_booleans ! ( node, stats, And | Or ) ;
279+ compute_booleans :: < language_python:: Python > ( node, stats, And , Or ) ;
280+ }
281+ Lambda => {
282+ // Increase lambda nesting
283+ lambda += 1 ;
284+ }
285+ FunctionDefinition => {
286+ // Increase depth function nesting if needed
287+ increment_function_depth :: < language_python:: Python > (
288+ & mut depth,
289+ node,
290+ FunctionDefinition ,
291+ ) ;
274292 }
275293 _ => { }
276294 }
295+ // Add node to nesting map
296+ nesting_map. insert ( node. object ( ) . id ( ) , ( nesting, depth, lambda) ) ;
277297 }
278298}
279299
280300impl Cognitive for RustCode {
281- fn compute ( node : & Node , stats : & mut Stats ) {
301+ fn compute (
302+ node : & Node ,
303+ stats : & mut Stats ,
304+ nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ,
305+ ) {
282306 use Rust :: * ;
283-
284307 //TODO: Implement macros
308+ let ( mut nesting, mut depth, mut lambda) = get_nesting_from_map ( node, nesting_map) ;
285309
286310 match node. object ( ) . kind_id ( ) . into ( ) {
287311 IfExpression | IfLetExpression => {
288312 // Check if a node is not an else-if
289313 if !Self :: is_else_if ( node) {
290- nesting_levels ! (
291- node, stats,
292- [ FunctionItem => SourceFile ] ,
293- [ ClosureExpression => SourceFile ] ,
294- [ IfExpression | IfLetExpression | ForExpression | WhileExpression | MatchExpression => FunctionItem ]
295- ) ;
314+ increase_nesting ( stats, & mut nesting, depth, lambda) ;
296315 }
297316 }
298317 ForExpression | WhileExpression | MatchExpression => {
299- nesting_levels ! (
300- node, stats,
301- [ FunctionItem => SourceFile ] ,
302- [ ClosureExpression => SourceFile ] ,
303- [ IfExpression | IfLetExpression | ForExpression | WhileExpression | MatchExpression => FunctionItem ]
304- ) ;
318+ increase_nesting ( stats, & mut nesting, depth, lambda) ;
305319 }
306320 Else /*else-if also */ => {
307321 increment_by_one ( stats) ;
@@ -317,45 +331,41 @@ impl Cognitive for RustCode {
317331 stats. boolean_seq . not_operator ( node. object ( ) . kind_id ( ) ) ;
318332 }
319333 BinaryExpression => {
320- compute_booleans ! ( node, stats, AMPAMP | PIPEPIPE ) ;
334+ compute_booleans :: < language_rust:: Rust > ( node, stats, AMPAMP , PIPEPIPE ) ;
335+ }
336+ FunctionItem => {
337+ nesting = 0 ;
338+ // Increase depth function nesting if needed
339+ increment_function_depth :: < language_rust:: Rust > ( & mut depth, node, FunctionItem ) ;
340+ }
341+ ClosureExpression => {
342+ lambda += 1 ;
321343 }
322344 _ => { }
323345 }
346+ nesting_map. insert ( node. object ( ) . id ( ) , ( nesting, depth, lambda) ) ;
324347 }
325348}
326349
327350impl Cognitive for CppCode {
328- fn compute ( node : & Node , stats : & mut Stats ) {
351+ fn compute (
352+ node : & Node ,
353+ stats : & mut Stats ,
354+ nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ,
355+ ) {
329356 use Cpp :: * ;
330357
331358 //TODO: Implement macros
359+ let ( mut nesting, depth, mut lambda) = get_nesting_from_map ( node, nesting_map) ;
332360
333361 match node. object ( ) . kind_id ( ) . into ( ) {
334362 IfStatement => {
335363 if !Self :: is_else_if ( node) {
336- nesting_levels ! (
337- node, stats,
338- [ LambdaExpression => TranslationUnit ] ,
339- [ IfStatement
340- | ForStatement
341- | WhileStatement
342- | DoStatement
343- | SwitchStatement
344- | CatchClause => FunctionDefinition ]
345- ) ;
364+ increase_nesting ( stats, & mut nesting, depth, lambda) ;
346365 }
347366 }
348367 ForStatement | WhileStatement | DoStatement | SwitchStatement | CatchClause => {
349- nesting_levels ! (
350- node, stats,
351- [ LambdaExpression => TranslationUnit ] ,
352- [ IfStatement
353- | ForStatement
354- | WhileStatement
355- | DoStatement
356- | SwitchStatement
357- | CatchClause => FunctionDefinition ]
358- ) ;
368+ increase_nesting ( stats, & mut nesting, depth, lambda) ;
359369 }
360370 GotoStatement | Else /* else-if also */ => {
361371 increment_by_one ( stats) ;
@@ -364,50 +374,31 @@ impl Cognitive for CppCode {
364374 stats. boolean_seq . not_operator ( node. object ( ) . kind_id ( ) ) ;
365375 }
366376 BinaryExpression2 => {
367- compute_booleans ! ( node, stats, AMPAMP | PIPEPIPE ) ;
377+ compute_booleans :: < language_cpp:: Cpp > ( node, stats, AMPAMP , PIPEPIPE ) ;
378+ }
379+ LambdaExpression => {
380+ lambda += 1 ;
368381 }
369382 _ => { }
370383 }
384+ nesting_map. insert ( node. object ( ) . id ( ) , ( nesting, depth, lambda) ) ;
371385 }
372386}
373387
374388macro_rules! js_cognitive {
375389 ( $lang: ident) => {
376- fn compute( node: & Node , stats: & mut Stats ) {
390+ fn compute( node: & Node , stats: & mut Stats , nesting_map : & mut FxHashMap < usize , ( usize , usize , usize ) > ) {
377391 use $lang:: * ;
392+ let ( mut nesting, mut depth, mut lambda) = get_nesting_from_map( node, nesting_map) ;
378393
379394 match node. object( ) . kind_id( ) . into( ) {
380395 IfStatement => {
381396 if !Self :: is_else_if( & node) {
382- nesting_levels!(
383- node, stats,
384- [ FunctionDeclaration => Program ] ,
385- [ ArrowFunction => FunctionDeclaration | Program ] ,
386- [ IfStatement
387- | ForStatement
388- | ForInStatement
389- | WhileStatement
390- | DoStatement
391- | SwitchStatement
392- | CatchClause
393- | TernaryExpression => FunctionDeclaration ]
394- ) ;
397+ increase_nesting( stats, & mut nesting, depth, lambda) ;
395398 }
396399 }
397400 ForStatement | ForInStatement | WhileStatement | DoStatement | SwitchStatement | CatchClause | TernaryExpression => {
398- nesting_levels!(
399- node, stats,
400- [ FunctionDeclaration => Program ] ,
401- [ ArrowFunction => FunctionDeclaration | Program ] ,
402- [ IfStatement
403- | ForStatement
404- | ForInStatement
405- | WhileStatement
406- | DoStatement
407- | SwitchStatement
408- | CatchClause
409- | TernaryExpression => FunctionDeclaration ]
410- ) ;
401+ increase_nesting( stats, & mut nesting, depth, lambda) ;
411402 }
412403 Else /* else-if also */ => {
413404 increment_by_one( stats) ;
@@ -420,10 +411,21 @@ macro_rules! js_cognitive {
420411 stats. boolean_seq. not_operator( node. object( ) . kind_id( ) ) ;
421412 }
422413 BinaryExpression => {
423- compute_booleans!( node, stats, AMPAMP | PIPEPIPE ) ;
414+ compute_booleans:: <$lang>( node, stats, AMPAMP , PIPEPIPE ) ;
415+ }
416+ FunctionDeclaration => {
417+ // Reset lambda nesting at function for JS
418+ nesting = 0 ;
419+ lambda = 0 ;
420+ // Increase depth function nesting if needed
421+ increment_function_depth:: <$lang>( & mut depth, node, FunctionDeclaration ) ;
422+ }
423+ ArrowFunction => {
424+ lambda += 1 ;
424425 }
425426 _ => { }
426427 }
428+ nesting_map. insert( node. object( ) . id( ) , ( nesting, depth, lambda) ) ;
427429 }
428430 } ;
429431}
0 commit comments