@@ -758,7 +758,18 @@ pub struct Comment {
758
758
pub multi_line : bool ,
759
759
}
760
760
761
+ impl Comment {
762
+ pub ( crate ) fn is_start_of_ignored_region ( & self ) -> bool {
763
+ self . value . trim ( ) == "vhdl_ls off"
764
+ }
765
+
766
+ pub ( crate ) fn is_end_of_ignored_region ( & self ) -> bool {
767
+ self . value . trim ( ) == "vhdl_ls on"
768
+ }
769
+ }
770
+
761
771
use crate :: standard:: VHDLStandard ;
772
+ use itertools:: Itertools ;
762
773
use std:: convert:: AsRef ;
763
774
use std:: fmt:: { Debug , Display , Formatter } ;
764
775
use std:: ops:: { Add , AddAssign , Sub } ;
@@ -889,6 +900,45 @@ impl Token {
889
900
pub fn equal_format ( & self , other : & Token ) -> bool {
890
901
self . kind == other. kind && self . value == other. value
891
902
}
903
+
904
+ pub ( crate ) fn leading_is_start_of_ignored_region ( & self ) -> bool {
905
+ let Some ( comments) = & self . comments else {
906
+ return false ;
907
+ } ;
908
+ if let Some ( ( index, _) ) = comments
909
+ . leading
910
+ . iter ( )
911
+ . find_position ( |comment| comment. is_start_of_ignored_region ( ) )
912
+ {
913
+ // This construct guards against the case where we have a `vhdl_ls on` in the same
914
+ // comment block after a a `vhdl_ls off`
915
+ !comments. leading [ index..]
916
+ . iter ( )
917
+ . any ( Comment :: is_end_of_ignored_region)
918
+ } else {
919
+ false
920
+ }
921
+ }
922
+
923
+ pub ( crate ) fn leading_is_end_of_ignored_region ( & self ) -> bool {
924
+ let Some ( comments) = & self . comments else {
925
+ return false ;
926
+ } ;
927
+ comments
928
+ . leading
929
+ . iter ( )
930
+ . any ( Comment :: is_end_of_ignored_region)
931
+ }
932
+
933
+ pub ( crate ) fn trailing_is_end_of_ignored_region ( & self ) -> bool {
934
+ let Some ( comments) = & self . comments else {
935
+ return false ;
936
+ } ;
937
+ comments
938
+ . trailing
939
+ . as_ref ( )
940
+ . is_some_and ( Comment :: is_end_of_ignored_region)
941
+ }
892
942
}
893
943
894
944
impl Operator {
@@ -1973,7 +2023,38 @@ impl<'a> Tokenizer<'a> {
1973
2023
1974
2024
pub fn pop ( & mut self ) -> DiagnosticResult < Option < Token > > {
1975
2025
match self . pop_raw ( ) {
1976
- Ok ( token) => Ok ( token) ,
2026
+ Ok ( None ) => Ok ( None ) ,
2027
+ Ok ( Some ( token) ) => {
2028
+ if token. leading_is_start_of_ignored_region ( ) {
2029
+ if !token. trailing_is_end_of_ignored_region ( ) {
2030
+ loop {
2031
+ match self . pop_raw ( ) {
2032
+ Ok ( None ) => {
2033
+ // Note: we should probably emit an unterminated error here
2034
+ // instead of silently failing.
2035
+ return Ok ( None ) ;
2036
+ }
2037
+ Ok ( Some ( tok) ) => {
2038
+ if tok. trailing_is_end_of_ignored_region ( ) {
2039
+ break ;
2040
+ } else if tok. leading_is_end_of_ignored_region ( ) {
2041
+ // Note: to be pedantic, the 'vhdl_ls on' should be
2042
+ // removed from the comments. However, because we have
2043
+ // no public API and the comments don't really play
2044
+ // a crucial role in the language server or binary,
2045
+ // we just emit the token for simplicity.
2046
+ return Ok ( Some ( tok) ) ;
2047
+ }
2048
+ }
2049
+ Err ( _) => { }
2050
+ }
2051
+ }
2052
+ }
2053
+ self . pop ( )
2054
+ } else {
2055
+ Ok ( Some ( token) )
2056
+ }
2057
+ }
1977
2058
Err ( err) => {
1978
2059
self . state . start = self . reader . state ( ) ;
1979
2060
Err ( Diagnostic :: syntax_error (
@@ -3106,4 +3187,63 @@ entity -- €
3106
3187
vec![ View , Default ]
3107
3188
) ;
3108
3189
}
3190
+
3191
+ #[ test]
3192
+ fn ignore_code_in_between_explicitly_ignored_regions ( ) {
3193
+ let tokens = kinds_tokenize (
3194
+ "\
3195
+ entity foo is
3196
+ --vhdl_ls off
3197
+ I am ignored cod€
3198
+ --vhdl_ls on
3199
+ end foo;
3200
+ " ,
3201
+ ) ;
3202
+ assert_eq ! (
3203
+ & tokens,
3204
+ & [ Entity , Identifier , Is , End , Identifier , SemiColon ]
3205
+ ) ;
3206
+
3207
+ let tokens = kinds_tokenize (
3208
+ "\
3209
+ before Is
3210
+ --vhdl_ls off
3211
+ single_token
3212
+ --vhdl_ls on
3213
+ End after
3214
+ " ,
3215
+ ) ;
3216
+ assert_eq ! ( & tokens, & [ Identifier , Is , End , After ] ) ;
3217
+ }
3218
+
3219
+ #[ test]
3220
+ fn ignore_code_without_on ( ) {
3221
+ // This should potentially emit a warning, but for now we just silently
3222
+ // ignore that there should be a `vhdl_ls on` at some point.
3223
+ let tokens = kinds_tokenize (
3224
+ "\
3225
+ before Is
3226
+ --vhdl_ls off
3227
+ single_token
3228
+ End after
3229
+ " ,
3230
+ ) ;
3231
+ assert_eq ! ( & tokens, & [ Identifier , Is ] ) ;
3232
+ }
3233
+
3234
+ #[ test]
3235
+ fn on_directly_after_off ( ) {
3236
+ // This should potentially emit a warning, but for now we just silently
3237
+ // ignore that there should be a `vhdl_ls on` at some point.
3238
+ let tokens = kinds_tokenize (
3239
+ "\
3240
+ before Is
3241
+ --vhdl_ls off
3242
+ --vhdl_ls on
3243
+ single_token
3244
+ End after
3245
+ " ,
3246
+ ) ;
3247
+ assert_eq ! ( & tokens, & [ Identifier , Is , Identifier , End , After ] ) ;
3248
+ }
3109
3249
}
0 commit comments