From fa67a6a571d93c2d810b6a88b2d01568ce4e6dfc Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Sun, 28 Apr 2019 08:22:03 -0500 Subject: [PATCH 1/2] Compiler: keep annotations when expanding named/default arguments --- spec/compiler/codegen/warnings_spec.cr | 11 +++++++++++ src/compiler/crystal/semantic/default_arguments.cr | 1 + 2 files changed, 12 insertions(+) diff --git a/spec/compiler/codegen/warnings_spec.cr b/spec/compiler/codegen/warnings_spec.cr index a02be4789941..312f94ef9ddc 100644 --- a/spec/compiler/codegen/warnings_spec.cr +++ b/spec/compiler/codegen/warnings_spec.cr @@ -88,6 +88,17 @@ describe "Code gen: warnings" do inject_primitives: false end + it "detects deprecated methods with named arguments" do + assert_warning %( + @[Deprecated] + def foo(*, a) + end + + foo(a: 2) + ), "Warning in line 6: Deprecated top-level foo:a.", + inject_primitives: false + end + it "informs warnings once per call site location (a)" do warning_failures = warnings_result %( class Foo diff --git a/src/compiler/crystal/semantic/default_arguments.cr b/src/compiler/crystal/semantic/default_arguments.cr index 85112317edff..cb53ec4afe33 100644 --- a/src/compiler/crystal/semantic/default_arguments.cr +++ b/src/compiler/crystal/semantic/default_arguments.cr @@ -103,6 +103,7 @@ class Crystal::Def expansion.yields = yields expansion.raises = raises? expansion.free_vars = free_vars + expansion.annotations = annotations if owner = self.owner? expansion.owner = owner end From 7730e99aeb00e500c2aa90b811c8ae478b5d4636 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Sun, 28 Apr 2019 08:43:31 -0500 Subject: [PATCH 2/2] Compiler: keep annotations when expanding initialize --- spec/compiler/codegen/warnings_spec.cr | 26 ++++++++++++++++++++++++ src/compiler/crystal/codegen/warnings.cr | 6 ++++++ src/compiler/crystal/semantic/new.cr | 3 +++ 3 files changed, 35 insertions(+) diff --git a/spec/compiler/codegen/warnings_spec.cr b/spec/compiler/codegen/warnings_spec.cr index 312f94ef9ddc..85cf6866746f 100644 --- a/spec/compiler/codegen/warnings_spec.cr +++ b/spec/compiler/codegen/warnings_spec.cr @@ -99,6 +99,32 @@ describe "Code gen: warnings" do inject_primitives: false end + it "detects deprecated initialize" do + assert_warning %( + class Foo + @[Deprecated] + def initialize + end + end + + Foo.new + ), "Warning in line 8: Deprecated Foo.new.", + inject_primitives: false + end + + it "detects deprecated initialize with named arguments" do + assert_warning %( + class Foo + @[Deprecated] + def initialize(*, a) + end + end + + Foo.new(a: 2) + ), "Warning in line 8: Deprecated Foo.new:a.", + inject_primitives: false + end + it "informs warnings once per call site location (a)" do warning_failures = warnings_result %( class Foo diff --git a/src/compiler/crystal/codegen/warnings.cr b/src/compiler/crystal/codegen/warnings.cr index 08e0356043a0..7c37cd898dc8 100644 --- a/src/compiler/crystal/codegen/warnings.cr +++ b/src/compiler/crystal/codegen/warnings.cr @@ -53,6 +53,7 @@ module Crystal if (ann = node.target_def.annotation(@program.deprecated_annotation)) && (deprecated_annotation = DeprecatedAnnotation.from(ann)) + return if compiler_expanded_call(node) return if ignore_warning_due_to_location(node.location) short_reference = node.target_def.short_reference warning_key = node.location.try { |l| "#{short_reference} #{l}" } @@ -81,6 +82,11 @@ module Crystal filename.starts_with?(path) end end + + private def compiler_expanded_call(node : Call) + # Compiler generates a `_.initialize` call in `new` + node.obj.as?(Var).try { |v| v.name == "_" } && node.name == "initialize" + end end class Command diff --git a/src/compiler/crystal/semantic/new.cr b/src/compiler/crystal/semantic/new.cr index 588935f03c3d..8281c5ca7109 100644 --- a/src/compiler/crystal/semantic/new.cr +++ b/src/compiler/crystal/semantic/new.cr @@ -141,6 +141,7 @@ module Crystal new_def.new = true new_def.doc = doc new_def.free_vars = free_vars + new_def.annotations = annotations # Forward block argument if any if uses_block_arg? @@ -288,6 +289,8 @@ module Crystal expansion = Def.new(name, def_args, Nop.new, splat_index: splat_index).at(self) expansion.yields = yields expansion.visibility = visibility + expansion.annotations = annotations + if uses_block_arg? block_arg = self.block_arg.not_nil! expansion.block_arg = block_arg.clone