diff --git a/CHANGELOG.md b/CHANGELOG.md index de9811ec..089fb0d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Single arity functions can be tagged with `^:allow-unsafe-names` to preserve their parameter names (#1212) ### Fixed - * Fix an issue where the compiler would generate an illegal `return` statement for asynchronous generators (#1180) + * Fix an issue where the compiler would generate an illegal `return` statement for asynchronous generators (#1180) + * Fix an issue where consecutive reader comment forms would not be ignored (#1207) ## [v0.3.7] ### Fixed diff --git a/src/basilisp/lang/reader.py b/src/basilisp/lang/reader.py index 1f50fb0f..d9a532d7 100644 --- a/src/basilisp/lang/reader.py +++ b/src/basilisp/lang/reader.py @@ -1667,7 +1667,7 @@ def _read_reader_macro(ctx: ReaderContext) -> LispReaderForm: # noqa: MC0001 return _read_regex(ctx) elif char == "_": ctx.reader.advance() - _read_next(ctx) # Ignore the entire next form + _read_next_consuming_comment(ctx) # Ignore the entire next form return COMMENT elif char == "!": return _read_comment(ctx) diff --git a/tests/basilisp/reader_test.py b/tests/basilisp/reader_test.py index a089d2a8..72d579f9 100644 --- a/tests/basilisp/reader_test.py +++ b/tests/basilisp/reader_test.py @@ -1524,65 +1524,61 @@ def test_syntax_error_attaching_metadata_to_unsupported_type(self, s: str): read_str_first(s) -def test_comment_reader_macro(): - with pytest.raises(EOFError): - read_str_first("#_ (a list)", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_1", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first('#_"string"', is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_:keyword", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_symbol", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_[]", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_{}", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_()", is_eof_error=True) - - with pytest.raises(EOFError): - read_str_first("#_#{}", is_eof_error=True) - - assert kw.keyword("kw2") == read_str_first("#_:kw1 :kw2") - - assert llist.EMPTY == read_str_first("(#_sym)") - assert llist.l(sym.symbol("inc"), 5) == read_str_first("(inc #_counter 5)") - assert llist.l(sym.symbol("dec"), 8) == read_str_first("(#_inc dec #_counter 8)") - - assert vec.EMPTY == read_str_first("[#_m]") - assert vec.v(1) == read_str_first("[#_m 1]") - assert vec.v(1) == read_str_first("[#_m 1 #_2]") - assert vec.v(1, 2) == read_str_first("[#_m 1 2]") - assert vec.v(1, 4) == read_str_first("[#_m 1 #_2 4]") - assert vec.v(1, 4) == read_str_first("[#_m 1 #_2 4 #_5]") - - assert lset.EMPTY == read_str_first("#{#_m}") - assert lset.s(1) == read_str_first("#{#_m 1}") - assert lset.s(1) == read_str_first("#{#_m 1 #_2}") - assert lset.s(1, 2) == read_str_first("#{#_m 1 2}") - assert lset.s(1, 4) == read_str_first("#{#_m 1 #_2 4}") - assert lset.s(1, 4) == read_str_first("#{#_m 1 #_2 4 #_5}") - - assert lmap.EMPTY == read_str_first("{#_:key}") - assert lmap.EMPTY == read_str_first('{#_:key #_"value"}') - assert lmap.map({kw.keyword("key"): "value"}) == read_str_first( - '{:key #_"other" "value"}' +class TestCommentReaderMacro: + @pytest.mark.parametrize( + "s", + [ + "#_ (a list)", + "#_1", + '#_"string"', + "#_:keyword", + "#_symbol", + "#_[]", + "#_{}", + "#_()", + "#_#{}", + "#_ #_ {} {}", + ], ) - assert lmap.map({kw.keyword("key"): "value"}) == read_str_first( - '{:key "value" #_"other"}' + def test_comment_suppresses_form_with_eof(self, s: str): + with pytest.raises(EOFError): + read_str_first(s, is_eof_error=True) + + @pytest.mark.parametrize( + "s,v", + [ + ("#_:kw1 :kw2", kw.keyword("kw2")), + ("#_ #_ :kw1 :kw2 :kw3", kw.keyword("kw3")), + ("(#_sym)", llist.EMPTY), + ("(#_ #_ sym 1)", llist.EMPTY), + ("(inc #_counter 5)", llist.l(sym.symbol("inc"), 5)), + ("(#_inc dec #_counter 8)", llist.l(sym.symbol("dec"), 8)), + ("[#_m]", vec.EMPTY), + ("[#_m 1]", vec.v(1)), + ("[#_m 1 #_2]", vec.v(1)), + ("[#_m 1 2]", vec.v(1, 2)), + ("[#_m 1 #_2 4]", vec.v(1, 4)), + ("[#_m 1 #_2 4 #_5]", vec.v(1, 4)), + ("#{#_m}", lset.EMPTY), + ("#{#_m 1}", lset.s(1)), + ("#{#_m 1 #_2}", lset.s(1)), + ("#{#_m 1 2}", lset.s(1, 2)), + ("#{#_m 1 #_2 4}", lset.s(1, 4)), + ("#{#_m 1 #_2 4 #_5}", lset.s(1, 4)), + ("{#_:key}", lmap.EMPTY), + ('{#_:key #_"value"}', lmap.EMPTY), + ('{#_ #_:key "value"}', lmap.EMPTY), + ('{:key #_"other" "value"}', lmap.map({kw.keyword("key"): "value"})), + ('{:key "value" #_"other"}', lmap.map({kw.keyword("key"): "value"})), + ("{#_ #_:a 3 :b 5}", lmap.map({kw.keyword("b"): 5})), + ], ) + def test_comment_suppresses_form_in_other_form(self, s: str, v): + assert v == read_str_first(s) - with pytest.raises(reader.SyntaxError): - read_str_first('{:key #_"value"}') + def test_comment_creates_syntax_error(self): + with pytest.raises(reader.SyntaxError): + read_str_first('{:key #_"value"}') def test_comment_line():