@@ -60,12 +60,6 @@ impl diagnostics::AsDiagnostic for LexicalError {
6060 }
6161}
6262
63- impl From < ParseFloatError > for LexicalError {
64- fn from ( value : ParseFloatError ) -> Self {
65- LexicalError :: InvalidNumber ( value)
66- }
67- }
68-
6963#[ derive( Debug , Clone , Error , PartialEq ) ]
7064pub enum SyntaxError {
7165 #[ error( "extraneous input: {token:?}" ) ]
@@ -486,7 +480,10 @@ pub mod diagnostics {
486480
487481 #[ cfg( test) ]
488482 mod error_to_diagnostics_tests {
489- use crate :: errors:: { CompileError , ExprError , LexicalError } ;
483+ use crate :: {
484+ errors:: { CompileError , ExprError , LexicalError , RuntimeError , SyntaxError } ,
485+ types:: Type ,
486+ } ;
490487
491488 use super :: * ;
492489 use std:: ops:: Range ;
@@ -552,5 +549,250 @@ pub mod diagnostics {
552549 assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
553550 assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
554551 }
552+
553+ #[ test]
554+ fn it_converts_compileerror_no_callee_to_diagnostic ( ) {
555+ let source = dummy_source ( ) ;
556+ let range = dummy_range ( ) ;
557+ let error = ExprError :: CompileError ( CompileError :: NoCallee ) ;
558+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
559+
560+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
561+ let diagnostic = & diagnostics[ 0 ] ;
562+ assert_eq ! ( diagnostic. code, Some ( "compiler" . to_string( ) ) ) ;
563+ assert_eq ! (
564+ diagnostic. message,
565+ "call expression without a callee" . to_string( )
566+ ) ;
567+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
568+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
569+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
570+ }
571+
572+ #[ test]
573+ fn it_converts_compileerror_type_mismatch_to_diagnostic ( ) {
574+ let source = dummy_source ( ) ;
575+ let range = dummy_range ( ) ;
576+ let error = ExprError :: CompileError ( CompileError :: TypeMismatch {
577+ expected : Type :: String ,
578+ actual : Type :: Bool ,
579+ } ) ;
580+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
581+
582+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
583+ let diagnostic = & diagnostics[ 0 ] ;
584+ assert_eq ! ( diagnostic. code, Some ( "compiler" . to_string( ) ) ) ;
585+ assert_eq ! (
586+ diagnostic. message,
587+ "expected type String but received Bool" . to_string( )
588+ ) ;
589+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
590+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
591+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
592+ }
593+
594+ #[ test]
595+ fn it_converts_compileerror_invalid_lookup_type_to_diagnostic ( ) {
596+ let source = dummy_source ( ) ;
597+ let range = dummy_range ( ) ;
598+ let error = ExprError :: CompileError ( CompileError :: InvalidLookupType ( 99 ) ) ;
599+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
600+
601+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
602+ let diagnostic = & diagnostics[ 0 ] ;
603+ assert_eq ! ( diagnostic. code, Some ( "compiler" . to_string( ) ) ) ;
604+ assert_eq ! ( diagnostic. message, "invalid lookup type: 99" . to_string( ) ) ;
605+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
606+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
607+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
608+ }
609+
610+ #[ test]
611+ fn it_converts_runtimeerror_undefined_to_diagnostic ( ) {
612+ let source = dummy_source ( ) ;
613+ let range = dummy_range ( ) ;
614+ let error = ExprError :: RuntimeError ( RuntimeError :: TypeMismatch {
615+ expected : Type :: Bool ,
616+ actual : Type :: String ,
617+ } ) ;
618+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
619+
620+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
621+ let diagnostic = & diagnostics[ 0 ] ;
622+ assert_eq ! ( diagnostic. code, Some ( "runtime" . to_string( ) ) ) ;
623+ assert_eq ! (
624+ diagnostic. message,
625+ "expected type Bool but received String" . to_string( )
626+ ) ;
627+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
628+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
629+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
630+ }
631+
632+ #[ test]
633+ fn it_converts_runtimeerror_empty_stack_to_diagnostic ( ) {
634+ let source = dummy_source ( ) ;
635+ let range = dummy_range ( ) ;
636+ let error = ExprError :: RuntimeError ( RuntimeError :: EmptyStack ) ;
637+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
638+
639+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
640+ let diagnostic = & diagnostics[ 0 ] ;
641+ assert_eq ! ( diagnostic. code, Some ( "runtime" . to_string( ) ) ) ;
642+ assert_eq ! (
643+ diagnostic. message,
644+ "attempting to pop from an empty stack" . to_string( )
645+ ) ;
646+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
647+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
648+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
649+ }
650+
651+ #[ test]
652+ fn it_converts_syntaxerror_unrecognized_eof_to_diagnostic ( ) {
653+ let source = dummy_source ( ) ;
654+ let range = dummy_range ( ) ;
655+ let error = ExprError :: SyntaxError ( SyntaxError :: UnrecognizedEOF {
656+ expected : vec ! [ "string" . to_string( ) ] ,
657+ } ) ;
658+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
659+
660+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
661+ let diagnostic = & diagnostics[ 0 ] ;
662+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
663+ assert_eq ! (
664+ diagnostic. message,
665+ "unexpected end of file; expected: [\" string\" ]" . to_string( )
666+ ) ;
667+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
668+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
669+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
670+ }
671+
672+ #[ test]
673+ fn it_converts_syntaxerror_invalid_token_to_diagnostic ( ) {
674+ let source = dummy_source ( ) ;
675+ let range = dummy_range ( ) ;
676+ let error = ExprError :: SyntaxError ( SyntaxError :: InvalidToken ) ;
677+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
678+
679+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
680+ let diagnostic = & diagnostics[ 0 ] ;
681+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
682+ assert_eq ! ( diagnostic. message, "invalid input" . to_string( ) ) ;
683+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
684+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
685+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
686+ }
687+
688+ #[ test]
689+ fn it_converts_syntaxerror_unexpected_input_to_diagnostic ( ) {
690+ let source = dummy_source ( ) ;
691+ let range = dummy_range ( ) ;
692+ let error = ExprError :: SyntaxError ( SyntaxError :: UnexpectedInput {
693+ token : "number" . to_string ( ) ,
694+ } ) ;
695+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
696+
697+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
698+ let diagnostic = & diagnostics[ 0 ] ;
699+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
700+ assert_eq ! (
701+ diagnostic. message,
702+ "unexpected input: \" number\" " . to_string( )
703+ ) ;
704+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
705+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
706+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
707+ }
708+
709+ #[ test]
710+ fn it_converts_syntaxerror_unrecognized_token_to_diagnostic ( ) {
711+ let source = dummy_source ( ) ;
712+ let range = dummy_range ( ) ;
713+ let error = ExprError :: SyntaxError ( SyntaxError :: UnrecognizedToken {
714+ token : "number" . to_string ( ) ,
715+ expected : vec ! [ "," . to_string( ) , "number" . to_string( ) , "]" . to_string( ) ] ,
716+ } ) ;
717+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
718+
719+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
720+ let diagnostic = & diagnostics[ 0 ] ;
721+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
722+ assert_eq ! (
723+ diagnostic. message,
724+ "unexpected \" number\" ; expected: [\" ,\" , \" number\" , \" ]\" ]" . to_string( )
725+ ) ;
726+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
727+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
728+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
729+ }
730+
731+ #[ test]
732+ fn it_converts_syntaxerror_unterminated_string_to_diagnostic ( ) {
733+ let source = dummy_source ( ) ;
734+ let range = dummy_range ( ) ;
735+ let error = ExprError :: SyntaxError ( SyntaxError :: UnterminatedString ) ;
736+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
737+
738+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
739+ let diagnostic = & diagnostics[ 0 ] ;
740+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
741+ assert_eq ! ( diagnostic. message, "unterminated string" . to_string( ) ) ;
742+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
743+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
744+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
745+ }
746+
747+ #[ test]
748+ fn it_converts_syntaxerror_extra_token_to_diagnostic ( ) {
749+ let source = dummy_source ( ) ;
750+ let range = dummy_range ( ) ;
751+ let error = ExprError :: SyntaxError ( SyntaxError :: ExtraToken {
752+ token : "," . to_string ( ) ,
753+ } ) ;
754+ let diagnostics = get_diagnostics ( & [ ( error, range. clone ( ) ) ] , source) ;
755+
756+ assert_eq ! ( diagnostics. len( ) , 1 ) ;
757+ let diagnostic = & diagnostics[ 0 ] ;
758+ assert_eq ! ( diagnostic. code, Some ( "syntax" . to_string( ) ) ) ;
759+ assert_eq ! ( diagnostic. message, "extraneous input: \" ,\" " . to_string( ) ) ;
760+ assert_eq ! ( diagnostic. severity, Severity :: Error ) ;
761+ assert_eq ! ( diagnostic. labels. len( ) , 1 ) ;
762+ assert_eq ! ( diagnostic. labels[ 0 ] , Label :: primary( ( ) , range) ) ;
763+ }
764+ }
765+ #[ cfg( test) ]
766+ mod to_severity_tests {
767+ use codespan_reporting:: diagnostic:: Severity ;
768+
769+ use crate :: errors:: diagnostics:: ExprDiagnosisSeverity ;
770+
771+ #[ test]
772+ fn from_hint ( ) {
773+ assert_eq ! ( Severity :: Help , ExprDiagnosisSeverity :: HINT . to_severity( ) ) ;
774+ }
775+
776+ #[ test]
777+ fn from_information ( ) {
778+ assert_eq ! (
779+ Severity :: Note ,
780+ ExprDiagnosisSeverity :: INFORMATION . to_severity( )
781+ ) ;
782+ }
783+
784+ #[ test]
785+ fn from_warning ( ) {
786+ assert_eq ! (
787+ Severity :: Warning ,
788+ ExprDiagnosisSeverity :: WARNING . to_severity( )
789+ ) ;
790+ }
791+
792+ #[ test]
793+ #[ should_panic( expected = "Invalid diagnosis severity: 99" ) ]
794+ fn from_invalid ( ) {
795+ ExprDiagnosisSeverity ( 99 ) . to_severity ( ) ;
796+ }
555797 }
556798}
0 commit comments