diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b79ea7d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,20 @@ +name: ubuntu + +on: [push, pull_request] + +jobs: + build: + name: build (${{ matrix.ruby }} / ${{ matrix.os }}) + strategy: + matrix: + ruby: [ '3.0', 2.7, 2.6, head ] + os: [ ubuntu-latest, macos-latest, windows-latest ] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@master + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - name: Run test + run: rake test diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3b9d383 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright 2019-2020 Nobuyoshi Nakada, Yusuke Endoh + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index f3b56aa..4cc0282 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,26 @@ ruby2_keywords def oldstyle_keywords(options = {}) end ``` +You can do the same for a method defined by `Module#define_method`: + +```ruby +define_method :delegating_method do |*args, &block| + other_method(*args, &block) +end +ruby2_keywords :delegating_method +``` + ## Contributing -Bug reports and pull requests are welcome on GitHub at https://bugs.ruby-lang.org. +Bug reports and pull requests are welcome on [GitHub] or +[Ruby Issue Tracking System]. ## License -The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause). +The gem is available as open source under the terms of the +[Ruby License] or the [2-Clause BSD License]. + +[GitHub]: https://github.com/ruby/ruby2_keywords/ +[Ruby Issue Tracking System]: https://bugs.ruby-lang.org +[Ruby License]: https://www.ruby-lang.org/en/about/license.txt +[2-Clause BSD License]: https://opensource.org/licenses/BSD-2-Clause diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..8830e05 --- /dev/null +++ b/Rakefile @@ -0,0 +1,8 @@ +require "bundler/gem_tasks" +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.test_files = FileList["test/**/test_*.rb"] +end + +task :default => :test diff --git a/lib/ruby2_keywords.rb b/lib/ruby2_keywords.rb index 8c48333..97cd081 100644 --- a/lib/ruby2_keywords.rb +++ b/lib/ruby2_keywords.rb @@ -1,6 +1,10 @@ class Module - unless respond_to?(:ruby2_keywords, true) + unless private_method_defined?(:ruby2_keywords, true) private + # call-seq: + # ruby2_keywords(method_name, ...) + # + # Does nothing. def ruby2_keywords(name, *) # nil end @@ -9,6 +13,10 @@ def ruby2_keywords(name, *) main = TOPLEVEL_BINDING.receiver unless main.respond_to?(:ruby2_keywords, true) + # call-seq: + # ruby2_keywords(method_name, ...) + # + # Does nothing. def main.ruby2_keywords(name, *) # nil end @@ -16,8 +24,34 @@ def main.ruby2_keywords(name, *) class Proc unless method_defined?(:ruby2_keywords) + # call-seq: + # proc.ruby2_keywords -> proc + # + # Does nothing and just returns the receiver. def ruby2_keywords self end end end + +class << Hash + unless method_defined?(:ruby2_keywords_hash?) + # call-seq: + # Hash.ruby2_keywords_hash?(hash) -> false + # + # Returns false. + def ruby2_keywords_hash?(hash) + false + end + end + + unless method_defined?(:ruby2_keywords_hash) + # call-seq: + # Hash.ruby2_keywords_hash(hash) -> new_hash + # + # Duplicates a given hash and returns the new hash. + def ruby2_keywords_hash(hash) + hash.dup + end + end +end diff --git a/ruby2_keywords.gemspec b/ruby2_keywords.gemspec index 623c58c..5eac57b 100644 --- a/ruby2_keywords.gemspec +++ b/ruby2_keywords.gemspec @@ -1,16 +1,18 @@ -version = IO.popen(%W[git -C #{__dir__} describe --tags --match v[0-9]*], &:read)[/\Av?(\d+(?:\.\d+)*)/, 1] +version = "0.0.3" +abort "Version must not reach 1" if version[/\d+/].to_i >= 1 Gem::Specification.new do |s| s.name = "ruby2_keywords" s.version = version s.summary = "Shim library for Module#ruby2_keywords" s.homepage = "https://github.com/ruby/ruby2_keywords" - s.licenses = ["Ruby"] + s.licenses = ["Ruby", "BSD-2-Clause"] s.authors = ["Nobuyoshi Nakada"] s.require_paths = ["lib"] + s.rdoc_options = ["--main", "README.md"] s.files = [ + "LICENSE", "README.md", "lib/ruby2_keywords.rb", - "ruby2_keywords.gemspec", ] end diff --git a/test/test_keyword.rb b/test/test_keyword.rb new file mode 100644 index 0000000..5fcecb5 --- /dev/null +++ b/test/test_keyword.rb @@ -0,0 +1,41 @@ +require 'test/unit' +LOADING_RUBY2_KEYWORDS = (RUBY_VERSION.scan(/\d+/).map(&:to_i) <=> [2, 7]) < 0 +if LOADING_RUBY2_KEYWORDS + require 'ruby2_keywords' +end + +class TestKeywordArguments < Test::Unit::TestCase + def test_loaded_features + list = $LOADED_FEATURES.grep(%r[/ruby2_keywords\.rb\z]) + if LOADING_RUBY2_KEYWORDS + assert_not_empty(list) + assert_not_include($LOADED_FEATURES, "ruby2_keywords.rb") + else + assert_empty(list) + assert_include($LOADED_FEATURES, "ruby2_keywords.rb") + end + end + + def test_module_ruby2_keywords + assert_send([Module, :private_method_defined?, :ruby2_keywords]) + assert_operator(Module.instance_method(:ruby2_keywords).arity, :<, 0) + end + + def test_toplevel_ruby2_keywords + main = TOPLEVEL_BINDING.receiver + assert_send([main, :respond_to?, :ruby2_keywords, true]) + assert_operator(main.method(:ruby2_keywords).arity, :<, 0) + end + + def test_proc_ruby2_keywords + assert_respond_to(Proc.new {}, :ruby2_keywords) + end + + def test_hash_ruby2_keywords_hash? + assert_false(Hash.ruby2_keywords_hash?({})) + end + + def test_hash_ruby2_keywords_hash + assert_equal({}, Hash.ruby2_keywords_hash({}.freeze)) + end +end