diff --git a/spec/compiler/semantic/doc_spec.cr b/spec/compiler/semantic/doc_spec.cr index 05f6772b6aa8..831db038bf3a 100644 --- a/spec/compiler/semantic/doc_spec.cr +++ b/spec/compiler/semantic/doc_spec.cr @@ -135,6 +135,33 @@ describe "Semantic: doc" do bar.doc.should eq("Hello") end + {% for def_type in %w[def macro].map &.id %} + it "overwrites doc for {{def_type}} when redefining" do + result = semantic %( + module Foo + # Doc 1 + {{def_type}} bar + end + end + + module Foo + # Doc 2 + {{def_type}} bar + end + end + + module Foo + {{def_type}} bar + end + end + ), wants_doc: true + program = result.program + foo = program.types["Foo"] + bar = foo.lookup_{{def_type}}s("bar").as(Array).first + bar.doc.should eq("Doc 2") + end + {% end %} + it "stores doc for macro" do result = semantic %( class Foo @@ -295,34 +322,42 @@ describe "Semantic: doc" do foo.doc.should eq("Hello") end - it "stores doc for class if reopening" do - result = semantic %( - class Foo - end + {% for module_type in %w[class struct module enum].map &.id %} + it "stores doc for {{module_type}} when reopening" do + result = semantic %( + {{module_type}} Foo + A = 1 + end - # Hello - class Foo - end - ), wants_doc: true - program = result.program - foo = program.types["Foo"] - foo.doc.should eq("Hello") - foo.locations.not_nil!.size.should eq(2) - end + # Hello + {{module_type}} Foo + end + ), wants_doc: true + program = result.program + foo = program.types["Foo"] + foo.doc.should eq("Hello") + foo.locations.not_nil!.size.should eq(2) + end + + it "overwrites doc for {{module_type}} when reopening" do + result = semantic %( + # Doc 1 + {{module_type}} Foo + A = 1 + end - it "stores doc for module if reopening" do - result = semantic %( - module Foo - end + # Doc 2 + {{module_type}} Foo + end - # Hello - module Foo - end - ), wants_doc: true - program = result.program - foo = program.types["Foo"] - foo.doc.should eq("Hello") - end + {{module_type}} Foo + end + ), wants_doc: true + program = result.program + foo = program.types["Foo"] + foo.doc.should eq("Doc 2") + end + {% end %} it "stores locations for auto-generated module" do result = semantic %( diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index a763a4801e6f..d40154229d32 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -47,9 +47,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor def visit(node : ClassDef) check_outside_exp node, "declare class" - scope, name = lookup_type_def_name(node) - - type = scope.types[name]? + scope, name, type = lookup_type_def(node) created_new_type = false extern = false @@ -185,9 +183,8 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor def visit(node : ModuleDef) check_outside_exp node, "declare module" - scope, name = lookup_type_def_name(node) + scope, name, type = lookup_type_def(node) - type = scope.types[name]? if type type = type.remove_alias @@ -450,9 +447,8 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor attributes = check_valid_attributes node, ValidEnumDefAttributes, "enum" attributes_doc = attributes_doc() - scope, name = lookup_type_def_name(node) + scope, name, enum_type = lookup_type_def(node) - enum_type = scope.types[name]? if enum_type unless enum_type.is_a?(EnumType) node.raise "#{name} is not a enum, it's a #{enum_type.type_desc}" @@ -985,6 +981,15 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor {extern, extern_union, packed} end + def lookup_type_def(node : ASTNode) + scope, name = lookup_type_def_name(node) + type = scope.types[name]? + if type && node.doc + type.doc = node.doc + end + {scope, name, type} + end + def lookup_type_def_name(node : ASTNode) scope, name = lookup_type_def_name(node.name) if current_type.is_a?(Program) diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index 562957aae4ba..79c06de8f57e 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -748,6 +748,7 @@ module Crystal if ex_item.restriction_of?(item, self) list[i] = item a_def.previous = ex_item + a_def.doc ||= ex_item.def.doc ex_item.def.next = a_def return ex_item.def else @@ -781,6 +782,7 @@ module Crystal array = (macros[a_def.name] ||= [] of Macro) index = array.index { |existing_macro| a_def.overrides?(existing_macro) } if index + a_def.doc ||= array[index].doc array[index] = a_def else array.push a_def