Skip to content

Commit

Permalink
Merge pull request #7724 from bcardiff/fix/deprecated-named-args
Browse files Browse the repository at this point in the history
Detect deprecation on initialize methods and methods with named args
  • Loading branch information
asterite authored May 2, 2019
2 parents c8505ce + 7730e99 commit 4e1e9cb
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 0 deletions.
37 changes: 37 additions & 0 deletions spec/compiler/codegen/warnings_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,43 @@ 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 "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
Expand Down
6 changes: 6 additions & 0 deletions src/compiler/crystal/codegen/warnings.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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}" }
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/compiler/crystal/semantic/default_arguments.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/crystal/semantic/new.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 4e1e9cb

Please sign in to comment.