From 5fcc66c1d502fa552c3c1ddb66024f4b0e055186 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Mon, 29 Jan 2024 17:27:07 +0800 Subject: [PATCH] Fix name locations of `FunDef` and `External` nodes --- spec/compiler/parser/parser_spec.cr | 18 ++++++++++++++++++ .../crystal/semantic/top_level_visitor.cr | 1 + src/compiler/crystal/syntax/ast.cr | 9 ++++++++- src/compiler/crystal/syntax/parser.cr | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 2fa1a5b4c4a7..9f4ec5faccf7 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2505,6 +2505,24 @@ module Crystal name_location.column_number.should eq(12) end + it "sets location of top-level fun name" do + parser = Parser.new("fun foo; end") + node = parser.parse.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(5) + end + + it "sets location of lib fun name" do + parser = Parser.new("lib Foo; fun foo; end") + node = parser.parse.as(LibDef).body.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(14) + end + it "sets correct location of proc literal" do parser = Parser.new("->(\n x : Int32,\n y : String\n) { }") node = parser.parse.as(ProcLiteral) diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 05d8918f8383..11c5707b19fa 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -918,6 +918,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor end external = External.new(node.name, external_args, node.body, node.real_name).at(node) + external.name_location = node.name_location call_convention = nil process_def_annotations(external, annotations) do |annotation_type, ann| diff --git a/src/compiler/crystal/syntax/ast.cr b/src/compiler/crystal/syntax/ast.cr index d0be18606714..9c0ffcf0d7e5 100644 --- a/src/compiler/crystal/syntax/ast.cr +++ b/src/compiler/crystal/syntax/ast.cr @@ -1954,6 +1954,7 @@ module Crystal property real_name : String property doc : String? property? varargs : Bool + property name_location : Location? def initialize(@name, @args = [] of Arg, @return_type = nil, @varargs = false, @body = nil, @real_name = name) end @@ -1965,7 +1966,13 @@ module Crystal end def clone_without_location - FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone = FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone.name_location = name_location + clone + end + + def name_size + @name.size end def_equals_and_hash @name, @args, @return_type, @varargs, @body, @real_name diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index f14399212e65..e3f4c2605ed6 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -5732,6 +5732,7 @@ module Crystal with_isolated_var_scope(require_body) do next_token_skip_space_or_newline + name_location = @token.location name = if top_level check_ident else @@ -5835,6 +5836,7 @@ module Crystal end fun_def = FunDef.new name, params, return_type, varargs, body, real_name + fun_def.name_location = name_location fun_def.doc = doc fun_def.at(location).at_end(end_location) end