11mod diagnostics;
22
3+ use clap:: builder:: Str ;
34use tucana:: shared:: { DataTypeIdentifier , DefinitionDataType , FlowType , RuntimeFunctionDefinition } ;
45use tucana:: shared:: data_type_identifier:: Type ;
56use tucana:: shared:: definition_data_type_rule:: Config ;
67use code0_definition_reader:: parser:: Parser ;
78use code0_definition_reader:: reader:: { MetaType , ParsableDefinition , Reader } ;
89use crate :: analyser:: diagnostics:: { Diagnose , DiagnosticKind , Reporter } ;
9- use crate :: analyser:: diagnostics:: DiagnosticKind :: { DuplicateDataTypeIdentifier , DuplicateFlowTypeIdentifier , NullField , UndefinedDataTypeIdentifier , UndefinedGenericKey , UndefinedTranslation , UnusedGenericKey } ;
10+ use crate :: analyser:: diagnostics:: DiagnosticKind :: { DuplicateDataTypeIdentifier , DuplicateFlowTypeIdentifier , DuplicateRuntimeParameterIdentifier , EmptyGenericMapper , GenericKeyNotInMappingTarget , NullField , UndefinedDataTypeIdentifier , UndefinedGenericKey , UndefinedTranslation , UnusedGenericKey } ;
1011
1112#[ derive( Clone ) ]
1213pub struct AnalysableDataType {
@@ -22,6 +23,7 @@ pub struct AnalysableFlowType {
2223 pub id : i16
2324}
2425
26+ #[ derive( Clone ) ]
2527pub struct AnalysableFunction {
2628 pub original_definition : ParsableDefinition ,
2729 pub function : RuntimeFunctionDefinition ,
@@ -156,6 +158,14 @@ impl Analyser {
156158 ) ) ;
157159 }
158160
161+ if generic. generic_mappers . is_empty ( ) {
162+ self . reporter . add_report ( Diagnose :: new (
163+ analysable_data_type. definition_data_type . clone ( ) . identifier ,
164+ analysable_data_type. original_definition . clone ( ) ,
165+ EmptyGenericMapper
166+ ) )
167+ }
168+
159169 for mapper in generic. generic_mappers {
160170 if data_type. generic_keys . contains ( & mapper. target ) {
161171 result. push ( mapper. target . clone ( ) )
@@ -397,7 +407,194 @@ impl Analyser {
397407 break ;
398408 }
399409 }
410+ }
411+
412+ pub fn analyse_runtime_function ( & mut self , analysable_function : AnalysableFunction ) {
413+ let name = analysable_function. function . runtime_name . clone ( ) ;
414+ let function = analysable_function. function ;
415+ let original = analysable_function. original_definition ;
416+ let id = analysable_function. id ;
417+
418+ // Check if at least one Translation is present
419+ if function. name . is_empty ( ) {
420+ self . reporter . add_report ( Diagnose :: new (
421+ name. clone ( ) ,
422+ original. clone ( ) ,
423+ UndefinedTranslation { translation_field : String :: from ( "name" ) }
424+ ) ) ;
425+ }
426+
427+ if function. description . is_empty ( ) {
428+ self . reporter . add_report ( Diagnose :: new (
429+ name. clone ( ) ,
430+ original. clone ( ) ,
431+ UndefinedTranslation { translation_field : String :: from ( "description" ) }
432+ ) ) ;
433+ }
434+
435+ if function. documentation . is_empty ( ) {
436+ self . reporter . add_report ( Diagnose :: new (
437+ name. clone ( ) ,
438+ original. clone ( ) ,
439+ UndefinedTranslation { translation_field : String :: from ( "documentation" ) }
440+ ) ) ;
441+ }
442+
443+ // Check if runtime function already exists
444+ for func in & self . functions {
445+ if func. id == id {
446+ continue
447+ }
448+
449+ if func. function . runtime_name . to_lowercase ( ) == name. clone ( ) . to_lowercase ( ) {
450+ self . reporter . add_report ( Diagnose :: new (
451+ name. clone ( ) ,
452+ original. clone ( ) ,
453+ DuplicateFlowTypeIdentifier { identifier : name. clone ( ) }
454+ ) ) ;
455+ break ;
456+ }
457+ }
458+
459+ let mut detected_generic_keys: Vec < String > = vec ! [ ] ;
460+ if let Some ( identifier) = function. return_type_identifier {
461+ detected_generic_keys. append ( & mut self . handle_function_data_type_identifier ( name. clone ( ) , original. clone ( ) , identifier) ) ;
462+ }
463+
464+ let mut parameter_names: Vec < String > = vec ! [ ] ;
465+ for parameter in function. runtime_parameter_definitions {
466+
467+ // Check if at least one Translation is present
468+ if parameter. name . is_empty ( ) {
469+ self . reporter . add_report ( Diagnose :: new (
470+ name. clone ( ) ,
471+ original. clone ( ) ,
472+ UndefinedTranslation { translation_field : String :: from ( "name" ) }
473+ ) ) ;
474+ }
475+
476+ if parameter. description . is_empty ( ) {
477+ self . reporter . add_report ( Diagnose :: new (
478+ name. clone ( ) ,
479+ original. clone ( ) ,
480+ UndefinedTranslation { translation_field : String :: from ( "description" ) }
481+ ) ) ;
482+ }
483+
484+ if parameter. documentation . is_empty ( ) {
485+ self . reporter . add_report ( Diagnose :: new (
486+ name. clone ( ) ,
487+ original. clone ( ) ,
488+ UndefinedTranslation { translation_field : String :: from ( "documentation" ) }
489+ ) ) ;
490+ }
491+
492+ // Check if data_type exists
493+ if let Some ( identifier) = parameter. data_type_identifier {
494+ detected_generic_keys. append ( & mut self . handle_function_data_type_identifier ( name. clone ( ) , original. clone ( ) , identifier) ) ;
495+ } else {
496+ self . reporter . add_report ( Diagnose :: new (
497+ name. clone ( ) ,
498+ original. clone ( ) ,
499+ NullField { field_name : String :: from ( "data_type" ) }
500+ ) ) ;
501+ }
502+
503+ if parameter_names. contains ( & parameter. runtime_name ) {
504+ self . reporter . add_report ( Diagnose :: new (
505+ name. clone ( ) ,
506+ original. clone ( ) ,
507+ DuplicateRuntimeParameterIdentifier { identifier : parameter. runtime_name . clone ( ) }
508+ ) ) ;
509+ }
510+
511+ parameter_names. push ( parameter. runtime_name ) ;
512+ }
513+
514+ let defined_but_unused = function. generic_keys . iter ( ) . filter ( |key| !detected_generic_keys. contains ( key) ) . collect :: < Vec < & String > > ( ) ;
515+ let used_but_undefined = detected_generic_keys. iter ( ) . filter ( |key| !function. generic_keys . contains ( key) ) . collect :: < Vec < & String > > ( ) ;
516+
517+ for key in defined_but_unused {
518+ self . reporter . add_report ( Diagnose :: new (
519+ name. clone ( ) ,
520+ original. clone ( ) ,
521+ UnusedGenericKey { key : key. clone ( ) }
522+ ) ) ;
523+ }
524+
525+ for key in used_but_undefined {
526+ self . reporter . add_report ( Diagnose :: new (
527+ name. clone ( ) ,
528+ original. clone ( ) ,
529+ UndefinedGenericKey { key : key. clone ( ) }
530+ ) ) ;
531+ }
532+ }
533+
534+ fn handle_function_data_type_identifier ( & mut self , name : String , original : ParsableDefinition , identifier : DataTypeIdentifier ) -> Vec < String > {
535+ let mut result: Vec < String > = vec ! [ ] ;
536+ if let Some ( r#type) = identifier. r#type {
537+ match r#type {
538+ Type :: DataTypeIdentifier ( data_type) => {
539+ if !self . data_type_identifier_exists ( data_type. clone ( ) , -1 ) {
540+ self . reporter . add_report ( Diagnose :: new (
541+ name. clone ( ) ,
542+ original. clone ( ) ,
543+ UndefinedDataTypeIdentifier { identifier : data_type. clone ( ) }
544+ ) )
545+ } ;
546+ } ,
547+ Type :: GenericType ( generic_type) => {
548+ if !self . data_type_identifier_exists ( generic_type. data_type_identifier . clone ( ) , -1 ) {
549+ self . reporter . add_report ( Diagnose :: new (
550+ name. clone ( ) ,
551+ original. clone ( ) ,
552+ UndefinedDataTypeIdentifier { identifier : generic_type. data_type_identifier . clone ( ) }
553+ ) )
554+ }
555+
556+ if generic_type. generic_mappers . is_empty ( ) {
557+ self . reporter . add_report ( Diagnose :: new (
558+ name. clone ( ) ,
559+ original. clone ( ) ,
560+ EmptyGenericMapper
561+ ) )
562+ }
563+
564+ for mapper in & generic_type. generic_mappers {
565+ for source in mapper. source . clone ( ) {
566+ result. append ( & mut self . handle_function_data_type_identifier ( name. clone ( ) , original. clone ( ) , source) )
567+ }
568+
569+ if !self . generic_key_in_target ( mapper. target . clone ( ) , generic_type. data_type_identifier . clone ( ) ) {
570+ self . reporter . add_report ( Diagnose :: new (
571+ name. clone ( ) ,
572+ original. clone ( ) ,
573+ GenericKeyNotInMappingTarget { key : mapper. target . clone ( ) , target : generic_type. data_type_identifier . clone ( ) }
574+ ) )
575+ }
576+ }
577+ } ,
578+ Type :: GenericKey ( key) => {
579+ result. push ( key. clone ( ) )
580+ } ,
581+ }
582+ }
583+
584+ result
585+ }
400586
587+ fn generic_key_in_target ( & mut self , key : String , target : String ) -> bool {
588+ let data_types: Vec < DefinitionDataType > = self . data_types . iter ( ) . map ( |d| d. definition_data_type . clone ( ) ) . collect ( ) ;
589+ for data_type in data_types {
590+ if target. to_lowercase ( ) != data_type. identifier . to_lowercase ( ) {
591+ continue ;
592+ }
593+
594+ return data_type. generic_keys . contains ( & key) ;
595+ }
596+
597+ false
401598 }
402599
403600 pub fn report ( & self ) {
0 commit comments