Skip to content
This repository has been archived by the owner on Jun 15, 2020. It is now read-only.

Commit

Permalink
Rubocop
Browse files Browse the repository at this point in the history
  • Loading branch information
yuku committed Dec 11, 2015
1 parent d4b8bc9 commit 5c3605a
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 94 deletions.
6 changes: 6 additions & 0 deletions .rubocop.yml
Expand Up @@ -4,6 +4,12 @@ Style/StringLiterals:
Metrics/LineLength:
Max: 100

Metrics/MethodLength:
Max: 25

# Document classes and non-namespace modules.
Style/Documentation:
Enabled: false

Style/TrailingComma:
Enabled: false
26 changes: 24 additions & 2 deletions lib/duck_testing/yard.rb
Expand Up @@ -6,8 +6,6 @@ module YARD
# The default glob of files to be parsed.
DEFAULT_PATH_GLOB = ["{lib,app}/**/*.rb"]

module_function

# Parses a path or set of paths then prepend them into corresponding classes..
#
# @param paths [String, Array<String>] a path, glob or list of paths to parse
Expand All @@ -25,5 +23,29 @@ def apply(paths: DEFAULT_PATH_GLOB, excluded: [])
klass.singleton_class.send(:prepend, builder.build(:class))
end
end

# @param types [Array<String>]
# @return [Array<DuckTesting::Type::Base>]
def expected_types(types)
types.map do |type|
if type == "Boolean"
[
DuckTesting::Type::Constant.new(true),
DuckTesting::Type::Constant.new(false),
]
elsif DuckTesting::Type::Constant::CONSTANTS.include?(type)
DuckTesting::Type::Constant.new(type)
elsif type == "void"
nil
elsif type.start_with?("Array")
# TODO: Support specifing types of array elements.
DuckTesting::Type::ClassInstance.new(Array)
else
DuckTesting::Type::ClassInstance.new(Object.const_get(type))
end
end.flatten.compact
end

module_function :apply, :expected_types
end
end
66 changes: 34 additions & 32 deletions lib/duck_testing/yard/builder.rb
Expand Up @@ -11,7 +11,7 @@ def initialize(class_object)
# @param scope [Symbol] `:instance` or `:class`
# @return [Module] duck testing module of `class_object` in the `scope`.
def build(scope = :instance)
@building_module = Module.new
@building_module = prepare_module
@class_object.method_objects.each do |method_object|
next unless method_object.scope == scope
handle_method_object(method_object)
Expand All @@ -21,47 +21,49 @@ def build(scope = :instance)
remove_instance_variable :@building_module
end

# rubocop:disable Lint/NestedMethodDefinition, Metrics/AbcSize

private

# @param method_object [DuckTesting::YARD::MethodObject]
def handle_method_object(method_object)
@building_module.module_eval do
define_method method_object.name do |*args|
tester = DuckTesting::Tester.new(self, method_object.name)
if method_object.keyword_parameters.any? && args.last.is_a?(Hash)
# Normal parameters
args[0...-1].each_with_index do |arg, index|
method_parameter = method_object.method_parameters[index]
tester.test_param(arg, method_parameter.expected_types)
end
def prepare_module
Module.new do
private

# Keyword parameters
hash = args.last
method_object.keyword_parameters.each do |method_parameter|
next unless hash.key?(method_parameter.key_name)
value = hash[method_parameter.key_name]
tester.test_param(value, method_parameter.expected_types)
end
else
args.each_with_index do |arg, index|
method_parameter = method_object.method_parameters[index]
tester.test_param(arg, method_parameter.expected_types)
end
def __dk_test_normal_parameters(tester, method_object, parameters)
parameters.each_with_index do |parameter, index|
tester.test_param(
parameter,
method_object.method_parameters[index].expected_types
)
end
end

tester.test_return(super(*args), method_object.expected_return_types)
def __dk_test_keyword_parameters(tester, method_object, hash_parameter)
method_object.keyword_parameters.each do |method_parameter|
next unless hash_parameter.key?(method_parameter.key_name)
tester.test_param(
hash_parameter[method_parameter.key_name],
method_parameter.expected_types
)
end
end
end
end

# @param method_parameter [DuckTesting::YARD::MethodParameter]
def handle_method_parameter(method_parameter)
return unless method_parameter.documented?
@buffer << " tester.test_param(#{method_parameter.name}, [\n"
method_parameter.parameter_tag.types.each do |type|
handle_type(type)
# @param method_object [DuckTesting::YARD::MethodObject]
def handle_method_object(method_object)
@building_module.module_eval do
define_method method_object.name do |*parameters|
tester = DuckTesting::Tester.new(self, method_object.name)
if method_object.keyword_parameters.any? && parameters.last.is_a?(Hash)
__dk_test_normal_parameters(tester, method_object, parameters[0...-1])
__dk_test_keyword_parameters(tester, method_object, parameters.last)
else
__dk_test_normal_parameters(tester, method_object, parameters)
end
tester.test_return(super(*parameters), method_object.expected_return_types)
end
end
@buffer << " ])\n"
end
end
end
Expand Down
19 changes: 1 addition & 18 deletions lib/duck_testing/yard/method_object.rb
Expand Up @@ -51,24 +51,7 @@ def return_tag

# @return [Array<DuckTesting::Type::Base>]
def expected_return_types
return [] unless return_tag
return_tag.types.map do |type|
if type == "Boolean"
[
DuckTesting::Type::Constant.new(true),
DuckTesting::Type::Constant.new(false),
]
elsif DuckTesting::Type::Constant::CONSTANTS.include?(type)
DuckTesting::Type::Constant.new(type)
elsif type == "void"
nil
elsif type.start_with?("Array")
# TODO: Support specifing types of array elements.
DuckTesting::Type::ClassInstance.new(Array)
else
DuckTesting::Type::ClassInstance.new(Object.const_get(type))
end
end.flatten.compact
return_tag ? DuckTesting::YARD.expected_types(return_tag.types) : []
end

# @return [Boolean]
Expand Down
18 changes: 1 addition & 17 deletions lib/duck_testing/yard/method_parameter.rb
Expand Up @@ -42,23 +42,7 @@ def key_name

# @return [Array<DuckTesting::Type::Base>]
def expected_types
parameter_tag.types.map do |type|
if type == "Boolean"
[
DuckTesting::Type::Constant.new(true),
DuckTesting::Type::Constant.new(false),
]
elsif DuckTesting::Type::Constant::CONSTANTS.include?(type)
DuckTesting::Type::Constant.new(type)
elsif type == "void"
nil
elsif type.start_with?("Array")
# TODO: Support specifing types of array elements.
DuckTesting::Type::ClassInstance.new(Array)
else
DuckTesting::Type::ClassInstance.new(Object.const_get(type))
end
end.flatten.compact
parameter_tag ? DuckTesting::YARD.expected_types(parameter_tag.types) : []
end
end
end
Expand Down
1 change: 0 additions & 1 deletion sample/spec/sample_spec.rb
Expand Up @@ -31,4 +31,3 @@
end
end
end

3 changes: 3 additions & 0 deletions spec/.rubocop.yml
Expand Up @@ -3,3 +3,6 @@ inherit_from:

Metrics/MethodLength:
Enabled: false

Style/SingleLineMethods:
Enabled: false
48 changes: 24 additions & 24 deletions spec/duck_testing/yard/builder_spec.rb
@@ -1,18 +1,18 @@
describe DuckTesting::YARD::Builder do
describe '#build' do
describe "#build" do
subject { builder.build(scope) }
let(:builder) { described_class.new(class_object) }
let(:class_object) { DuckTesting::YARD::Parser.parse_string(content).first }
let(:params) { [] }

context 'when scope parameter is :instance' do
context "when scope parameter is :instance" do
before { klass.prepend(subject) }
let(:contents) { "Hello, World" }
let(:instance) { klass.new }
let(:run) { instance.bar(*params) }
let(:scope) { :instance }

context 'and return tag comment is given' do
context "and return tag comment is given" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -22,23 +22,23 @@ class Foo
EOF
end

context 'and corresponding method returns valid type object' do
context "and corresponding method returns valid type object" do
let(:klass) do
Class.new { def bar; "String" end }
end
it { expect { run }.not_to raise_error }
end

context 'and corresponding method returns invalid type object' do
context "and corresponding method returns invalid type object" do
let(:klass) do
Class.new { def bar; :Symbol end }
end
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end
end

context 'and param tag comment is given' do
context 'and there is a parameter without default value' do
context "and param tag comment is given" do
context "and there is a parameter without default value" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -50,18 +50,18 @@ class Foo
let(:klass) do
Class.new { def bar(_name) end }
end
context 'and valid type object is given as the parameter' do
context "and valid type object is given as the parameter" do
let(:params) { ["String"] }
it { expect { run }.not_to raise_error }
end

context 'and invalid type object is given as the parameter' do
context "and invalid type object is given as the parameter" do
let(:params) { [:String] }
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end
end

context 'and there is a parameter with default value' do
context "and there is a parameter with default value" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -74,22 +74,22 @@ class Foo
Class.new { def bar(_name = nil) end }
end

context 'and the parameter is omitted' do
context "and the parameter is omitted" do
it { expect { run }.not_to raise_error }
end

context 'and valid type object is given as the parameter' do
context "and valid type object is given as the parameter" do
let(:params) { ["String"] }
it { expect { run }.not_to raise_error }
end

context 'and invalid type object is given as the parameter' do
context "and invalid type object is given as the parameter" do
let(:params) { [:String] }
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end
end

context 'and there is a keyword parameter' do
context "and there is a keyword parameter" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -102,18 +102,18 @@ def bar(key: nil) end
Class.new { def bar(key: nil) end }
end

context 'and valid type object is given as the parameter' do
context "and valid type object is given as the parameter" do
let(:params) { [key: "String"] }
it { expect { run }.not_to raise_error }
end

context 'and invalid type object is given as the parameter' do
context "and invalid type object is given as the parameter" do
let(:params) { [key: :Symbol] }
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end
end

context 'and there are both an normal paramter and a keyword parameter' do
context "and there are both an normal paramter and a keyword parameter" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -127,30 +127,30 @@ def bar(name, key: nil) end
Class.new { def bar(_name, key: nil) end }
end

context 'and valid type objects are given as those parameters' do
context "and valid type objects are given as those parameters" do
let(:params) { ["String", key: "String"] }
it { expect { run }.not_to raise_error }
end

context 'and invalid type object is given as the normal parameter' do
context "and invalid type object is given as the normal parameter" do
let(:params) { [:Symbol, key: "String"] }
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end

context 'and invalid type object is given as the keyword parameter' do
context "and invalid type object is given as the keyword parameter" do
let(:params) { ["String", key: :Symbol] }
it { expect { run }.to raise_error(DuckTesting::ContractViolationError) }
end
end
end
end

context 'when scope parameter is :class' do
context "when scope parameter is :class" do
before { klass.singleton_class.prepend(subject) }
let(:run) { klass.bar(*params) }
let(:scope) { :class }

context 'and return tag comment is given' do
context "and return tag comment is given" do
let(:content) do
<<-EOF
class Foo
Expand All @@ -160,14 +160,14 @@ class Foo
EOF
end

context 'and corresponding method returns valid type object' do
context "and corresponding method returns valid type object" do
let(:klass) do
Class.new { def self.bar; "String" end }
end
it { expect { run }.not_to raise_error }
end

context 'and corresponding method returns invalid type object' do
context "and corresponding method returns invalid type object" do
let(:klass) do
Class.new { def self.bar; :Symbol end }
end
Expand Down

0 comments on commit 5c3605a

Please sign in to comment.