From 4596dc840eef20a9b70d00b3594c086ee3cc50e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:47:05 -0800 Subject: [PATCH 1/5] Add `focus` parameter to `assert_end_location` --- spec/compiler/parser/parser_spec.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index ab8b1e9edfca..b25b0a774a94 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -40,8 +40,8 @@ private def node_source(string, node) source_between(string, node.location, node.end_location) end -private def assert_end_location(source, line_number = 1, column_number = source.size, file = __FILE__, line = __LINE__) - it "gets corrects end location for #{source.inspect}", file, line do +private def assert_end_location(source, line_number = 1, column_number = source.size, file = __FILE__, line = __LINE__, *, focus : Bool = false) + it "gets corrects end location for #{source.inspect}", file, line, focus: focus do string = "#{source}; 1" parser = Parser.new(string) node = parser.parse.as(Expressions).expressions[0] From 1fdc246d30311c553060d902617638584f943e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:47:31 -0800 Subject: [PATCH 2/5] Add end location to `Case` --- spec/compiler/parser/parser_spec.cr | 1 + src/compiler/crystal/syntax/parser.cr | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index b25b0a774a94..c448cdc5f9fa 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2371,6 +2371,7 @@ module Crystal assert_end_location "1 rescue 2" assert_end_location "1 ensure 2" assert_end_location "foo.bar= *baz" + assert_end_location "case :foo; when :bar; 2; end" assert_syntax_error %({"a" : 1}), "space not allowed between named argument name and ':'" assert_syntax_error %({"a": 1, "b" : 2}), "space not allowed between named argument name and ':'" diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 60a3ec6414a7..f7556bb2fdad 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -2844,9 +2844,11 @@ module Crystal a_else = parse_expressions skip_statement_end check_ident :end + end_location = token_end_location next_token break when Keyword::END + end_location = token_end_location next_token break else @@ -2854,7 +2856,7 @@ module Crystal end end - Case.new(cond, whens, a_else, exhaustive.nil? ? false : exhaustive) + Case.new(cond, whens, a_else, exhaustive.nil? ? false : exhaustive).at_end(end_location) end def check_valid_exhaustive_expression(exp) From 064b06db7ff667da90040092f2a3ac4f6156a89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:50:47 -0800 Subject: [PATCH 3/5] Avoid using `token_end_location` as a variable name --- src/compiler/crystal/syntax/parser.cr | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index f7556bb2fdad..f233fe40aa2d 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -2084,7 +2084,7 @@ module Crystal pieces = [] of Piece has_interpolation = false - delimiter_state, has_interpolation, options, token_end_location = consume_delimiter pieces, delimiter_state, has_interpolation + delimiter_state, has_interpolation, options, end_location = consume_delimiter pieces, delimiter_state, has_interpolation if want_skip_space && delimiter_state.kind.string? while true @@ -2094,7 +2094,7 @@ module Crystal if passed_backslash_newline && @token.type.delimiter_start? && @token.delimiter_state.kind.string? next_string_token(delimiter_state) delimiter_state = @token.delimiter_state - delimiter_state, has_interpolation, options, token_end_location = consume_delimiter pieces, delimiter_state, has_interpolation + delimiter_state, has_interpolation, options, end_location = consume_delimiter pieces, delimiter_state, has_interpolation else break end @@ -2122,7 +2122,7 @@ module Crystal # no special treatment end - result.end_location = token_end_location + result.end_location = end_location result end @@ -2149,7 +2149,7 @@ module Crystal def consume_delimiter(pieces, delimiter_state, has_interpolation) options = Regex::CompileOptions::None - token_end_location = nil + end_location = nil while true case @token.type when .string? @@ -2161,7 +2161,7 @@ module Crystal if delimiter_state.kind.regex? options = consume_regex_options end - token_end_location = token_end_location() + end_location = token_end_location next_token break when .eof? @@ -2204,7 +2204,7 @@ module Crystal end end - {delimiter_state, has_interpolation, options, token_end_location} + {delimiter_state, has_interpolation, options, end_location} end def consume_regex_options @@ -2246,19 +2246,19 @@ module Crystal pieces = [] of Piece has_interpolation = false - delimiter_state, has_interpolation, options, token_end_location = consume_delimiter pieces, delimiter_state, has_interpolation + delimiter_state, has_interpolation, options, end_location = consume_delimiter pieces, delimiter_state, has_interpolation if has_interpolation pieces = combine_interpolation_pieces(pieces, delimiter_state) node.expressions.concat(pieces) else string = combine_pieces(pieces, delimiter_state) - node.expressions.push(StringLiteral.new(string).at(node).at_end(token_end_location)) + node.expressions.push(StringLiteral.new(string).at(node).at_end(end_location)) end node.heredoc_indent = delimiter_state.heredoc_indent - node.end_location = token_end_location + node.end_location = end_location end def needs_heredoc_indent_removed?(delimiter_state) From 35fc6d69ec2b36f2ffe5f2d25f2c89604ce677b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:55:50 -0800 Subject: [PATCH 4/5] Add end location to `Asm` --- spec/compiler/parser/parser_spec.cr | 1 + src/compiler/crystal/syntax/parser.cr | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index c448cdc5f9fa..c97e5c6d6712 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2372,6 +2372,7 @@ module Crystal assert_end_location "1 ensure 2" assert_end_location "foo.bar= *baz" assert_end_location "case :foo; when :bar; 2; end" + assert_end_location %(asm("nop" ::)) assert_syntax_error %({"a" : 1}), "space not allowed between named argument name and ':'" assert_syntax_error %({"a": 1, "b" : 2}), "space not allowed between named argument name and ':'" diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index f233fe40aa2d..b73ee2afbf68 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -5500,9 +5500,11 @@ module Crystal check :OP_RPAREN + end_location = token_end_location + next_token_skip_space - Asm.new(text, outputs, inputs, clobbers, volatile, alignstack, intel, can_throw) + Asm.new(text, outputs, inputs, clobbers, volatile, alignstack, intel, can_throw).at_end(end_location) end def parse_asm_operands From 673353c7f3d9157af2a5b6de72973def41d38a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Tue, 11 Feb 2025 10:58:30 -0800 Subject: [PATCH 5/5] Add end location to `Select` --- spec/compiler/parser/parser_spec.cr | 1 + src/compiler/crystal/syntax/parser.cr | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index c97e5c6d6712..f4c6cf7799cf 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2373,6 +2373,7 @@ module Crystal assert_end_location "foo.bar= *baz" assert_end_location "case :foo; when :bar; 2; end" assert_end_location %(asm("nop" ::)) + assert_end_location "select; when foo; 2; end" assert_syntax_error %({"a" : 1}), "space not allowed between named argument name and ':'" assert_syntax_error %({"a": 1, "b" : 2}), "space not allowed between named argument name and ':'" diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index b73ee2afbf68..2b3727d681c5 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -3001,12 +3001,14 @@ module Crystal a_else = parse_expressions skip_statement_end check_ident :end + end_location = token_end_location next_token break when Keyword::END if whens.empty? unexpected_token "expecting when, else or end" end + end_location = token_end_location next_token break else @@ -3014,7 +3016,7 @@ module Crystal end end - Select.new(whens, a_else) + Select.new(whens, a_else).at_end(end_location) end def valid_select_when?(node)