From e7504e60517f3a4484794e4b0fa3d4b0b0641ae5 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Sat, 16 Jan 2021 00:14:28 +0900 Subject: [PATCH 1/3] Add signature of FileUtils - https://ruby-doc.org/stdlib-2.7.2/libdoc/fileutils/rdoc/FileUtils.html - https://github.com/ruby/fileutils --- stdlib/fileutils/0/fileutils.rbs | 569 +++++++++++++++++++++++++++++++ test/stdlib/FileUtils_test.rb | 522 ++++++++++++++++++++++++++++ 2 files changed, 1091 insertions(+) create mode 100644 stdlib/fileutils/0/fileutils.rbs create mode 100644 test/stdlib/FileUtils_test.rb diff --git a/stdlib/fileutils/0/fileutils.rbs b/stdlib/fileutils/0/fileutils.rbs new file mode 100644 index 000000000..44e63d3c6 --- /dev/null +++ b/stdlib/fileutils/0/fileutils.rbs @@ -0,0 +1,569 @@ +# # fileutils.rb +# +# Copyright (c) 2000-2007 Minero Aoki +# +# This program is free software. You can distribute/modify this program under +# the same terms of ruby. +# +# ## module FileUtils +# +# Namespace for several file utility methods for copying, moving, removing, etc. +# +# ### Module Functions +# +# require 'fileutils' +# +# FileUtils.cd(dir, **options) +# FileUtils.cd(dir, **options) {|dir| block } +# FileUtils.pwd() +# FileUtils.mkdir(dir, **options) +# FileUtils.mkdir(list, **options) +# FileUtils.mkdir_p(dir, **options) +# FileUtils.mkdir_p(list, **options) +# FileUtils.rmdir(dir, **options) +# FileUtils.rmdir(list, **options) +# FileUtils.ln(target, link, **options) +# FileUtils.ln(targets, dir, **options) +# FileUtils.ln_s(target, link, **options) +# FileUtils.ln_s(targets, dir, **options) +# FileUtils.ln_sf(target, link, **options) +# FileUtils.cp(src, dest, **options) +# FileUtils.cp(list, dir, **options) +# FileUtils.cp_r(src, dest, **options) +# FileUtils.cp_r(list, dir, **options) +# FileUtils.mv(src, dest, **options) +# FileUtils.mv(list, dir, **options) +# FileUtils.rm(list, **options) +# FileUtils.rm_r(list, **options) +# FileUtils.rm_rf(list, **options) +# FileUtils.install(src, dest, **options) +# FileUtils.chmod(mode, list, **options) +# FileUtils.chmod_R(mode, list, **options) +# FileUtils.chown(user, group, list, **options) +# FileUtils.chown_R(user, group, list, **options) +# FileUtils.touch(list, **options) +# +# Possible `options` are: +# +# `:force` +# : forced operation (rewrite files if exist, remove directories if not empty, +# etc.); +# `:verbose` +# : print command to be run, in bash syntax, before performing it; +# `:preserve` +# : preserve object's group, user and modification time on copying; +# `:noop` +# : no changes are made (usable in combination with `:verbose` which will +# print the command to run) +# +# +# Each method documents the options that it honours. See also ::commands, +# ::options and ::options_of methods to introspect which command have which +# options. +# +# All methods that have the concept of a "source" file or directory can take +# either one file or a list of files in that argument. See the method +# documentation for examples. +# +# There are some `low level' methods, which do not accept keyword arguments: +# +# FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) +# FileUtils.copy_file(src, dest, preserve = false, dereference = true) +# FileUtils.copy_stream(srcstream, deststream) +# FileUtils.remove_entry(path, force = false) +# FileUtils.remove_entry_secure(path, force = false) +# FileUtils.remove_file(path, force = false) +# FileUtils.compare_file(path_a, path_b) +# FileUtils.compare_stream(stream_a, stream_b) +# FileUtils.uptodate?(file, cmp_list) +# +# ## module FileUtils::Verbose +# +# This module has all methods of FileUtils module, but it outputs messages +# before acting. This equates to passing the `:verbose` flag to methods in +# FileUtils. +# +# ## module FileUtils::NoWrite +# +# This module has all methods of FileUtils module, but never changes +# files/directories. This equates to passing the `:noop` flag to methods in +# FileUtils. +# +# ## module FileUtils::DryRun +# +# This module has all methods of FileUtils module, but never changes +# files/directories. This equates to passing the `:noop` and `:verbose` flags +# to methods in FileUtils. +module FileUtils + VERSION: String + + type mode = Integer | String + + type pathlist = String | Array[String] + + # Changes the current directory to the directory `dir`. + # + # If this method is called with block, resumes to the previous working directory + # after the block execution has finished. + # + # FileUtils.cd('/') # change directory + # + # FileUtils.cd('/', verbose: true) # change directory and report it + # + # FileUtils.cd('/') do # change directory + # # ... # do something + # end # return to original directory + # + def self.cd: (String dir, ?verbose: boolish) -> void + | [X] (String dir, ?verbose: boolish) { (String) -> X } -> X + + alias self.chdir self.cd + + # Changes permission bits on the named files (in `list`) to the bit pattern + # represented by `mode`. + # + # `mode` is the symbolic and absolute mode can be used. + # + # Absolute mode is + # FileUtils.chmod 0755, 'somecommand' + # FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb) + # FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true + # + # Symbolic mode is + # FileUtils.chmod "u=wrx,go=rx", 'somecommand' + # FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb) + # FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true + # + # "a" + # : is user, group, other mask. + # "u" + # : is user's mask. + # "g" + # : is group's mask. + # "o" + # : is other's mask. + # "w" + # : is write permission. + # "r" + # : is read permission. + # "x" + # : is execute permission. + # "X" + # : is execute permission for directories only, must be used in conjunction + # with "+" + # "s" + # : is uid, gid. + # "t" + # : is sticky bit. + # "+" + # : is added to a class given the specified mode. + # "-" + # : Is removed from a given class given mode. + # "=" + # : Is the exact nature of the class will be given a specified mode. + # + def self.chmod: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish) -> void + + # Changes permission bits on the named files (in `list`) to the bit pattern + # represented by `mode`. + # + # FileUtils.chmod_R 0700, "/tmp/app.#{$$}" + # FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}" + # + def self.chmod_R: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void + + # Changes owner and group on the named files (in `list`) to the user `user` and + # the group `group`. `user` and `group` may be an ID (Integer/String) or a name + # (String). If `user` or `group` is nil, this method does not change the + # attribute. + # + # FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby' + # FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true + # + def self.chown: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish) -> void + + # Changes owner and group on the named files (in `list`) to the user `user` and + # the group `group` recursively. `user` and `group` may be an ID + # (Integer/String) or a name (String). If `user` or `group` is nil, this method + # does not change the attribute. + # + # FileUtils.chown_R 'www', 'www', '/var/www/htdocs' + # FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true + # + def self.chown_R: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void + + # Returns an Array of methods names which have the option `opt`. + # + # p FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"] + # + def self.collect_method: (Symbol opt) -> Array[String] + + # Returns an Array of names of high-level methods that accept any keyword + # arguments. + # + # p FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...] + # + def self.commands: () -> Array[String] + + # Returns true if the contents of a file `a` and a file `b` are identical. + # + # FileUtils.compare_file('somefile', 'somefile') #=> true + # FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false + # + def self.compare_file: (String a, String b) -> bool + + alias self.cmp self.compare_file + + alias self.identical? self.compare_file + + # Returns true if the contents of a stream `a` and `b` are identical. + # + def self.compare_stream: (IO a, IO b) -> bool + + # Copies a file system entry `src` to `dest`. If `src` is a directory, this + # method copies its contents recursively. This method preserves file types, c.f. + # symlink, directory... (FIFO, device files and etc. are not supported yet) + # + # Both of `src` and `dest` must be a path name. `src` must exist, `dest` must + # not exist. + # + # If `preserve` is true, this method preserves owner, group, and modified time. + # Permissions are copied regardless `preserve`. + # + # If `dereference_root` is true, this method dereference tree root. + # + # If `remove_destination` is true, this method removes each destination file + # before copy. + # + def self.copy_entry: (String src, String dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void + + # Copies file contents of `src` to `dest`. Both of `src` and `dest` must be a + # path name. + # + def self.copy_file: (String src, String dest, ?boolish preserve, ?boolish dereference) -> void + + # Copies stream `src` to `dest`. `src` must respond to #read(n) and `dest` must + # respond to #write(str). + # + def self.copy_stream: (_Reader src, _Writer dest) -> void + + # Copies a file content `src` to `dest`. If `dest` is a directory, copies `src` + # to `dest/src`. + # + # If `src` is a list of files, then `dest` must be a directory. + # + # FileUtils.cp 'eval.c', 'eval.c.org' + # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6' + # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true + # FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink + # + def self.cp: (pathlist src, String dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + + alias self.copy self.cp + + # Hard link `src` to `dest`. If `src` is a directory, this method links all its + # contents recursively. If `dest` is a directory, links `src` to `dest/src`. + # + # `src` can be a list of files. + # + # If `dereference_root` is true, this method dereference tree root. + # + # If `remove_destination` is true, this method removes each destination file + # before copy. + # + # FileUtils.rm_r site_ruby + '/mylib', force: true + # FileUtils.cp_lr 'lib/', site_ruby + '/mylib' + # + # # Examples of linking several files to target directory. + # FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail' + # FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true + # + # # If you want to link all contents of a directory instead of the + # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y, + # # use the following code. + # FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't. + # + def self.cp_lr: (pathlist src, String dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + + # Copies `src` to `dest`. If `src` is a directory, this method copies all its + # contents recursively. If `dest` is a directory, copies `src` to `dest/src`. + # + # `src` can be a list of files. + # + # If `dereference_root` is true, this method dereference tree root. + # + # If `remove_destination` is true, this method removes each destination file + # before copy. + # + # # Installing Ruby library "mylib" under the site_ruby + # FileUtils.rm_r site_ruby + '/mylib', force: true + # FileUtils.cp_r 'lib/', site_ruby + '/mylib' + # + # # Examples of copying several files to target directory. + # FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail' + # FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true + # + # # If you want to copy all contents of a directory instead of the + # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y, + # # use following code. + # FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src, + # # but this doesn't. + # + def self.cp_r: (pathlist src, String dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + + # Returns true if the method `mid` have an option `opt`. + # + # p FileUtils.have_option?(:cp, :noop) #=> true + # p FileUtils.have_option?(:rm, :force) #=> true + # p FileUtils.have_option?(:rm, :preserve) #=> false + # + def self.have_option?: (Symbol mid, Symbol opt) -> bool + + # If `src` is not same as `dest`, copies it and changes the permission mode to + # `mode`. If `dest` is a directory, destination is `dest`/`src`. This method + # removes destination before copy. + # + # FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true + # FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true + # + def self.install: (String src, String dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + + # Hard links a file system entry `src` to `dest`. If `src` is a directory, this + # method links its contents recursively. + # + # Both of `src` and `dest` must be a path name. `src` must exist, `dest` must + # not exist. + # + # If `dereference_root` is true, this method dereferences the tree root. + # + # If `remove_destination` is true, this method removes each destination file + # before copy. + # + def self.link_entry: (String src, String dest, ?boolish dereference_root, ?boolish remove_destination) -> void + + # In the first form, creates a hard link `link` which points to `target`. If + # `link` already exists, raises Errno::EEXIST. But if the `force` option is set, + # overwrites `link`. + # + # FileUtils.ln 'gcc', 'cc', verbose: true + # FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs' + # + # In the second form, creates a link `dir/target` pointing to `target`. In the + # third form, creates several hard links in the directory `dir`, pointing to + # each item in `targets`. If `dir` is not a directory, raises Errno::ENOTDIR. + # + # FileUtils.cd '/sbin' + # FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked. + # + def self.ln: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + + alias self.link self.ln + + # In the first form, creates a symbolic link `link` which points to `target`. If + # `link` already exists, raises Errno::EEXIST. But if the `force` option is set, + # overwrites `link`. + # + # FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby' + # FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true + # + # In the second form, creates a link `dir/target` pointing to `target`. In the + # third form, creates several symbolic links in the directory `dir`, pointing to + # each item in `targets`. If `dir` is not a directory, raises Errno::ENOTDIR. + # + # FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin' + # + def self.ln_s: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + + alias self.symlink self.ln_s + + # Same as + # + # FileUtils.ln_s(*args, force: true) + # + def self.ln_sf: (pathlist src, String dest, ?noop: boolish, ?verbose: boolish) -> void + + # Creates one or more directories. + # + # FileUtils.mkdir 'test' + # FileUtils.mkdir %w(tmp data) + # FileUtils.mkdir 'notexist', noop: true # Does not really create. + # FileUtils.mkdir 'tmp', mode: 0700 + # + def self.mkdir: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void + + # Creates a directory and all its parent directories. For example, + # + # FileUtils.mkdir_p '/usr/local/lib/ruby' + # + # causes to make following directories, if they do not exist. + # + # * /usr + # * /usr/local + # * /usr/local/lib + # * /usr/local/lib/ruby + # + # + # You can pass several directories at a time in a list. + # + def self.mkdir_p: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void + + alias self.makedirs self.mkdir_p + + alias self.mkpath self.mkdir_p + + # Moves file(s) `src` to `dest`. If `file` and `dest` exist on the different + # disk partition, the file is copied then the original file is removed. + # + # FileUtils.mv 'badname.rb', 'goodname.rb' + # FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true # no error + # + # FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/' + # FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true + # + def self.mv: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + + alias self.move self.mv + + # Returns an Array of option names. + # + # p FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"] + # + def self.options: () -> Array[String] + + # Returns an Array of option names of the method `mid`. + # + # p FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"] + # + def self.options_of: (Symbol mid) -> Array[String] + + # Returns the name of the current directory. + # + def self.pwd: () -> String + + alias self.getwd self.pwd + + # Removes a directory `dir` and its contents recursively. This method ignores + # StandardError if `force` is true. + # + def self.remove_dir: (String path, ?boolish force) -> void + + # This method removes a file system entry `path`. `path` might be a regular + # file, a directory, or something. If `path` is a directory, remove it + # recursively. + # + # See also remove_entry_secure. + # + def self.remove_entry: (String path, ?boolish force) -> void + + # This method removes a file system entry `path`. `path` shall be a regular + # file, a directory, or something. If `path` is a directory, remove it + # recursively. This method is required to avoid TOCTTOU + # (time-of-check-to-time-of-use) local security vulnerability of rm_r. #rm_r + # causes security hole when: + # + # * Parent directory is world writable (including /tmp). + # * Removing directory tree includes world writable directory. + # * The system has symbolic link. + # + # + # To avoid this security hole, this method applies special preprocess. If `path` + # is a directory, this method chown(2) and chmod(2) all removing directories. + # This requires the current process is the owner of the removing whole directory + # tree, or is the super user (root). + # + # WARNING: You must ensure that **ALL** parent directories cannot be moved by + # other untrusted users. For example, parent directories should not be owned by + # untrusted users, and should not be world writable except when the sticky bit + # set. + # + # WARNING: Only the owner of the removing directory tree, or Unix super user + # (root) should invoke this method. Otherwise this method does not work. + # + # For details of this security vulnerability, see Perl's case: + # + # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448 + # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452 + # + # + # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. + # + def self.remove_entry_secure: (String path, ?boolish force) -> void + + # Removes a file `path`. This method ignores StandardError if `force` is true. + # + def self.remove_file: (String path, ?void force) -> void + + # Remove file(s) specified in `list`. This method cannot remove directories. + # All StandardErrors are ignored when the :force option is set. + # + # FileUtils.rm %w( junk.txt dust.txt ) + # FileUtils.rm Dir.glob('*.so') + # FileUtils.rm 'NotExistFile', force: true # never raises exception + # + def self.rm: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + + alias self.remove self.rm + + # Equivalent to + # + # FileUtils.rm(list, force: true) + # + def self.rm_f: (pathlist list, ?noop: boolish, ?verbose: boolish) -> void + + alias self.safe_unlink self.rm_f + + # remove files `list[0]` `list[1]`... If `list[n]` is a directory, removes its + # all contents recursively. This method ignores StandardError when :force option + # is set. + # + # FileUtils.rm_r Dir.glob('/tmp/*') + # FileUtils.rm_r 'some_dir', force: true + # + # WARNING: This method causes local vulnerability if one of parent directories + # or removing directory tree are world writable (including /tmp, whose + # permission is 1777), and the current process has strong privilege such as Unix + # super user (root), and the system has symbolic link. For secure removing, + # read the documentation of remove_entry_secure carefully, and set :secure + # option to true. Default is `secure: false`. + # + # NOTE: This method calls remove_entry_secure if :secure option is set. See also + # remove_entry_secure. + # + def self.rm_r: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + + # Equivalent to + # + # FileUtils.rm_r(list, force: true) + # + # WARNING: This method causes local vulnerability. Read the documentation of + # rm_r first. + # + def self.rm_rf: (pathlist list, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + + # Removes one or more directories. + # + # FileUtils.rmdir 'somedir' + # FileUtils.rmdir %w(somedir anydir otherdir) + # # Does not really remove directory; outputs message. + # FileUtils.rmdir 'somedir', verbose: true, noop: true + # + def self.rmdir: (pathlist list, ?parents: boolish, ?noop: boolish, ?verbose: boolish) -> void + + alias self.rmtree self.rm_rf + + # Updates modification time (mtime) and access time (atime) of file(s) in + # `list`. Files are created if they don't exist. + # + # FileUtils.touch 'timestamp' + # FileUtils.touch Dir.glob('*.c'); system 'make' + # + def self.touch: (pathlist list, ?noop: boolish, ?verbose: boolish, ?mtime: (Time | Numeric)?, ?nocreate: boolish) -> void + + # Returns true if `new` is newer than all `old_list`. Non-existent files are + # older than any file. + # + # FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \ + # system 'make hello.o' + # + def self.uptodate?: (String new, Array[String] old_list) -> bool +end diff --git a/test/stdlib/FileUtils_test.rb b/test/stdlib/FileUtils_test.rb new file mode 100644 index 000000000..df7db4de2 --- /dev/null +++ b/test/stdlib/FileUtils_test.rb @@ -0,0 +1,522 @@ +require_relative "test_helper" +require "fileutils" + +class FileUtilsSingletonTest < Test::Unit::TestCase + include TypeAssertions + + library "fileutils" + testing "singleton(::FileUtils)" + + def test_cd + assert_send_type "(String) -> void", + FileUtils, :cd, __dir__ + assert_send_type "(String, verbose: bool) -> void", + FileUtils, :cd, __dir__, verbose: false + assert_send_type "(String) { (String) -> Integer } -> Integer", + FileUtils, :cd, __dir__ do |dir| 1 end + assert_send_type "(String, verbose: nil) { (String) -> Integer } -> Integer", + FileUtils, :cd, __dir__, verbose: nil do |dir| 1 end + end + + def test_chdir + assert_send_type "(String) -> void", + FileUtils, :chdir, __dir__ + assert_send_type "(String) { (String) -> Integer } -> Integer", + FileUtils, :chdir, __dir__ do |dir| 1 end + end + + def test_chmod + in_tmpdir do |dir| + assert_send_type "(Integer, String) -> void", + FileUtils, :chmod, 0755, dir + assert_send_type "(String, Array[String]) -> void", + FileUtils, :chmod, "u=wrx", [dir] + assert_send_type "(Integer, Array[String], noop: bool, verbose: bool) -> void", + FileUtils, :chmod, 0755, [dir], noop: false, verbose: false + end + end + + def test_chmod_R + in_tmpdir do |dir| + assert_send_type "(Integer, String) -> void", + FileUtils, :chmod_R, 0755, dir + assert_send_type "(String, Array[String]) -> void", + FileUtils, :chmod_R, "u=wrx", [dir] + assert_send_type "(Integer, Array[String], noop: bool, verbose: bool, force: nil) -> void", + FileUtils, :chmod_R, 0755, [dir], noop: true, verbose: false, force: nil + end + end + + def test_chown + in_tmpdir do |dir| + assert_send_type "(nil, nil, String) -> void", + FileUtils, :chown, nil, nil, dir + assert_send_type "(nil, nil, Array[String]) -> void", + FileUtils, :chown, nil, nil, [dir] + assert_send_type "(String, String, Array[String], noop: bool, verbose: nil) -> void", + FileUtils, :chown, "user", "group", [dir], noop: true, verbose: nil + end + end + + def test_chown_R + in_tmpdir do |dir| + assert_send_type "(nil, nil, String) -> void", + FileUtils, :chown_R, nil, nil, dir + assert_send_type "(nil, nil, Array[String]) -> void", + FileUtils, :chown_R, nil, nil, [dir] + assert_send_type "(String, String, Array[String], noop: bool, verbose: nil, force: bool) -> void", + FileUtils, :chown_R, "user", "group", [dir], noop: true, verbose: nil, force: false + end + end + + def test_collect_method + assert_send_type "(Symbol) -> Array[String]", + FileUtils, :collect_method, :preserve + end + + def test_commands + assert_send_type "() -> Array[String]", + FileUtils, :commands + end + + def test_compare_file + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + FileUtils, :compare_file, "foo", "foo" + end + end + + def test_cmp + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + FileUtils, :cmp, "foo", "foo" + end + end + + def test_identical? + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + FileUtils, :identical?, "foo", "foo" + end + end + + def test_compare_stream + in_tmpdir do + File.write "foo", "" + File.open("foo") do |io| + assert_send_type "(IO, IO) -> bool", + FileUtils, :compare_stream, io, io + end + end + end + + def test_copy_entry + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + FileUtils, :copy_entry, "src", "dest" + assert_send_type "(String, String, bool, nil, bool) -> void", + FileUtils, :copy_entry, "src", "dest", true, nil, false + end + end + + def test_copy_file + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + FileUtils, :copy_file, "src", "dest" + assert_send_type "(String, String, bool, nil) -> void", + FileUtils, :copy_file, "src", "dest", false, nil + end + end + + def test_copy_stream + in_tmpdir do + File.write "src", "" + File.open("src") do |src| + File.open("dest", "a") do |dest| + assert_send_type "(IO, IO) -> void", + FileUtils, :copy_stream, src, dest + end + end + end + end + + def test_cp + in_tmpdir do + File.write "src", "" + Dir.mkdir "dest_dir" + + assert_send_type "(String, String) -> void", + FileUtils, :cp, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :cp, ["src"], "dest_dir" + assert_send_type "(String, String, preserve: bool, noop: nil, verbose: bool) -> void", + FileUtils, :cp, "src", "dest", preserve: true, noop: nil, verbose: false + end + end + + def test_copy + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String, preserve: bool, noop: nil, verbose: bool) -> void", + FileUtils, :copy, "src", "dest", preserve: true, noop: nil, verbose: false + end + end + + def test_cp_lr + in_tmpdir do + Dir.mkdir "src" + + assert_send_type "(String, String) -> void", + FileUtils, :cp_lr, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :cp_lr, ["src"], "dest" + assert_send_type "(String, String, noop: bool, verbose: false, dereference_root: nil, remove_destination: nil) -> void", + FileUtils, :cp_lr, "src", "dest", noop: true, verbose: false, dereference_root: nil, remove_destination: nil + end + end + + def test_cp_r + in_tmpdir do + Dir.mkdir "src" + + assert_send_type "(String, String) -> void", + FileUtils, :cp_r, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :cp_r, ["src"], "dest" + assert_send_type "(String, String, preserve: nil, noop: bool, verbose: bool, dereference_root: bool, remove_destination: nil) -> void", + FileUtils, :cp_r, "src", "dest", preserve: nil, noop: false, verbose: false, dereference_root: false, remove_destination: nil + end + end + + def test_have_option? + assert_send_type "(Symbol, Symbol) -> bool", + FileUtils, :have_option?, :cp, :noop + end + + def test_install + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + FileUtils, :install, "src", "dest" + assert_send_type "(String, String, mode: Integer) -> void", + FileUtils, :install, "src", "dest", mode: 0755 + assert_send_type "(String, String, mode: String, owner: String, group: nil, preserve: bool, noop: bool, verbose: nil) -> void", + FileUtils, :install, "src", "dest", mode: "u=wrx", owner: "user", group: nil, preserve: false, noop: true, verbose: nil + end + end + + def test_link_entry + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + FileUtils, :link_entry, "src", "dest" + assert_send_type "(String, String, bool, bool) -> void", + FileUtils, :link_entry, "src", "dest", false, true + end + end + + def test_ln + in_tmpdir do |dir| + File.write "src", "" + File.write "src2", "" + Dir.mkdir "dest" + + assert_send_type "(String, String) -> void", + FileUtils, :ln, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :ln, ["src2"], "dest" + assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :ln, "src", "dest", force: true, noop: nil, verbose: false + end + end + + def test_link + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :link, "src", "dest", force: true, noop: nil, verbose: false + end + end + + def test_ln_s + in_tmpdir do + File.write "src", "" + Dir.mkdir "dest_dir" + + assert_send_type "(String, String) -> void", + FileUtils, :ln_s, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :ln_s, ["src"], "dest_dir" + assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :ln_s, "src", "dest", force: true, noop: nil, verbose: false + end + end + + def test_symlink + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :symlink, "src", "dest", force: true, noop: nil, verbose: false + end + end + + def test_ln_sf + in_tmpdir do + File.write "src", "" + Dir.mkdir "dest_dir" + + assert_send_type "(String, String) -> void", + FileUtils, :ln_sf, "src", "dest" + assert_send_type "(Array[String], String, noop: bool, verbose: bool) -> void", + FileUtils, :ln_sf, ["src"], "dest_dir", noop: true, verbose: false + end + end + + def test_mkdir + in_tmpdir do + assert_send_type "(String) -> void", + FileUtils, :mkdir, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :mkdir, ["bar"] + assert_send_type "(String, mode: Integer, noop: bool, verbose: nil) -> void", + FileUtils, :mkdir, "foo", mode: 0755, noop: true, verbose: nil + end + end + + def test_mkdir_p + in_tmpdir do + assert_send_type "(String) -> void", + FileUtils, :mkdir_p, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :mkdir_p, ["foo"] + assert_send_type "(String, mode: Integer, noop: bool, verbose: bool) -> void", + FileUtils, :mkdir_p, "foo", mode: 0755, noop: false, verbose: false + end + end + + def test_makedirs + in_tmpdir do + assert_send_type "(String, mode: Integer, noop: bool, verbose: bool) -> void", + FileUtils, :makedirs, "foo", mode: 0755, noop: false, verbose: false + end + end + + def test_mkpath + in_tmpdir do + assert_send_type "(String, mode: Integer, noop: bool, verbose: bool) -> void", + FileUtils, :mkpath, "foo", mode: 0755, noop: false, verbose: false + end + end + + def test_mv + in_tmpdir do + File.write "src", "" + File.write "src2", "" + Dir.mkdir "dest_dir" + + assert_send_type "(String, String) -> void", + FileUtils, :mv, "src", "dest" + assert_send_type "(Array[String], String) -> void", + FileUtils, :mv, ["src2"], "dest_dir" + assert_send_type "(String, String, force: bool, noop: bool, verbose: nil, secure: bool) -> void", + FileUtils, :mv, "src", "dest", force: true, noop: true, verbose: nil, secure: true + end + end + + def test_move + in_tmpdir do + assert_send_type "(String, String, force: bool, noop: bool, verbose: nil, secure: bool) -> void", + FileUtils, :move, "src", "dest", force: true, noop: true, verbose: nil, secure: true + end + end + + def test_options + assert_send_type "() -> Array[String]", + FileUtils, :options + end + + def test_options_of + assert_send_type "(Symbol) -> Array[String]", + FileUtils, :options_of, :rm + end + + def test_pwd + assert_send_type "() -> String", + FileUtils, :pwd + end + + def test_getwd + assert_send_type "() -> String", + FileUtils, :getwd + end + + def test_remove_dir + in_tmpdir do + Dir.mkdir "foo" + + assert_send_type "(String) -> void", + FileUtils, :remove_dir, "foo" + assert_send_type "(String, bool) -> void", + FileUtils, :remove_dir, "foo", true + end + end + + def test_remove_entry + in_tmpdir do + Dir.mkdir "foo" + + assert_send_type "(String) -> void", + FileUtils, :remove_entry, "foo" + assert_send_type "(String, bool) -> void", + FileUtils, :remove_entry, "foo", true + end + end + + def test_remove_entry_secure + in_tmpdir do + Dir.mkdir "foo" + + assert_send_type "(String) -> void", + FileUtils, :remove_entry_secure, "foo" + assert_send_type "(String, bool) -> void", + FileUtils, :remove_entry_secure, "foo", true + end + end + + def test_remove_file + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String) -> void", + FileUtils, :remove_file, "foo" + assert_send_type "(String, bool) -> void", + FileUtils, :remove_file, "foo", true + end + end + + def test_rm + in_tmpdir do + File.write "foo", "" + File.write "bar", "" + + assert_send_type "(String) -> void", + FileUtils, :rm, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :rm, ["bar"] + assert_send_type "(String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :rm, "foo", force: true, noop: nil, verbose: false + end + end + + def test_remove + in_tmpdir do + assert_send_type "(String, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :remove, "foo", force: true, noop: nil, verbose: false + end + end + + def test_rm_f + in_tmpdir do + assert_send_type "(String) -> void", + FileUtils, :rm_f, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :rm_f, ["foo"] + assert_send_type "(String, noop: bool, verbose: nil) -> void", + FileUtils, :rm_f, "foo", noop: false, verbose: nil + end + end + + def test_safe_unlink + in_tmpdir do + assert_send_type "(String, noop: bool, verbose: nil) -> void", + FileUtils, :safe_unlink, "foo", noop: false, verbose: nil + end + end + + def test_rm_r + in_tmpdir do + Dir.mkdir "foo" + Dir.mkdir "bar" + + assert_send_type "(String) -> void", + FileUtils, :rm_r, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :rm_r, ["bar"] + assert_send_type "(String, force: bool, noop: bool, verbose: nil, secure: bool) -> void", + FileUtils, :rm_r, "foo", force: true, noop: false, verbose: nil, secure: true + end + end + + def test_rm_rf + in_tmpdir do + assert_send_type "(String) -> void", + FileUtils, :rm_rf, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :rm_rf, ["foo"] + assert_send_type "(String, noop: nil, verbose: nil, secure: bool) -> void", + FileUtils, :rm_rf, "foo", noop: nil, verbose: nil, secure: true + end + end + + def test_rmtree + in_tmpdir do + assert_send_type "(String, noop: nil, verbose: nil, secure: bool) -> void", + FileUtils, :rmtree, "foo", noop: nil, verbose: nil, secure: true + end + end + + def test_rmdir + in_tmpdir do + Dir.mkdir "foo" + Dir.mkdir "bar" + + assert_send_type "(String) -> void", + FileUtils, :rmdir, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :rmdir, ["bar"] + assert_send_type "(String, parents: bool, noop: bool, verbose: nil) -> void", + FileUtils, :rmdir, "foo", parents: false, noop: true, verbose: nil + end + end + + def test_touch + in_tmpdir do + assert_send_type "(String) -> void", + FileUtils, :touch, "foo" + assert_send_type "(Array[String]) -> void", + FileUtils, :touch, ["foo", "bar"] + assert_send_type "(String, mtime: Time) -> void", + FileUtils, :touch, "foo", mtime: Time.now + assert_send_type "(String, noop: bool, verbose: bool, mtime: Integer, nocreate: nil) -> void", + FileUtils, :touch, "foo", noop: true, verbose: false, mtime: 1000, nocreate: nil + end + end + + def test_uptodate? + assert_send_type "(String, Array[String]) -> bool", + FileUtils, :uptodate?, "foo", ["bar"] + end + + private + + def in_tmpdir(&block) + Dir.mktmpdir do |dir| + Dir.chdir(dir, &block) + end + end +end From 929ecc8a6268d2028e4277db4aedb325faed1ba4 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Mon, 18 Jan 2021 00:06:20 +0900 Subject: [PATCH 2/3] Introduce `path` type alias --- stdlib/fileutils/0/fileutils.rbs | 49 +++--- test/stdlib/FileUtils_test.rb | 273 +++++++++++++++++++------------ 2 files changed, 196 insertions(+), 126 deletions(-) diff --git a/stdlib/fileutils/0/fileutils.rbs b/stdlib/fileutils/0/fileutils.rbs index 44e63d3c6..a1ac64d63 100644 --- a/stdlib/fileutils/0/fileutils.rbs +++ b/stdlib/fileutils/0/fileutils.rbs @@ -94,12 +94,15 @@ # This module has all methods of FileUtils module, but never changes # files/directories. This equates to passing the `:noop` and `:verbose` flags # to methods in FileUtils. +# module FileUtils VERSION: String type mode = Integer | String - type pathlist = String | Array[String] + type path = string | _ToPath + + type pathlist = path | Array[path] # Changes the current directory to the directory `dir`. # @@ -114,8 +117,8 @@ module FileUtils # # ... # do something # end # return to original directory # - def self.cd: (String dir, ?verbose: boolish) -> void - | [X] (String dir, ?verbose: boolish) { (String) -> X } -> X + def self.cd: (path dir, ?verbose: boolish) -> void + | [X] (path dir, ?verbose: boolish) { (String) -> X } -> X alias self.chdir self.cd @@ -210,7 +213,7 @@ module FileUtils # FileUtils.compare_file('somefile', 'somefile') #=> true # FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false # - def self.compare_file: (String a, String b) -> bool + def self.compare_file: (path a, path b) -> bool alias self.cmp self.compare_file @@ -235,12 +238,12 @@ module FileUtils # If `remove_destination` is true, this method removes each destination file # before copy. # - def self.copy_entry: (String src, String dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void + def self.copy_entry: (path src, path dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void # Copies file contents of `src` to `dest`. Both of `src` and `dest` must be a # path name. # - def self.copy_file: (String src, String dest, ?boolish preserve, ?boolish dereference) -> void + def self.copy_file: (path src, path dest, ?boolish preserve, ?boolish dereference) -> void # Copies stream `src` to `dest`. `src` must respond to #read(n) and `dest` must # respond to #write(str). @@ -257,7 +260,7 @@ module FileUtils # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true # FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink # - def self.cp: (pathlist src, String dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self.cp: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.copy self.cp @@ -283,7 +286,7 @@ module FileUtils # # use the following code. # FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't. # - def self.cp_lr: (pathlist src, String dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + def self.cp_lr: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void # Copies `src` to `dest`. If `src` is a directory, this method copies all its # contents recursively. If `dest` is a directory, copies `src` to `dest/src`. @@ -309,7 +312,7 @@ module FileUtils # FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src, # # but this doesn't. # - def self.cp_r: (pathlist src, String dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + def self.cp_r: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void # Returns true if the method `mid` have an option `opt`. # @@ -326,7 +329,7 @@ module FileUtils # FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true # FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true # - def self.install: (String src, String dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self.install: (path src, path dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void # Hard links a file system entry `src` to `dest`. If `src` is a directory, this # method links its contents recursively. @@ -339,7 +342,7 @@ module FileUtils # If `remove_destination` is true, this method removes each destination file # before copy. # - def self.link_entry: (String src, String dest, ?boolish dereference_root, ?boolish remove_destination) -> void + def self.link_entry: (path src, path dest, ?boolish dereference_root, ?boolish remove_destination) -> void # In the first form, creates a hard link `link` which points to `target`. If # `link` already exists, raises Errno::EEXIST. But if the `force` option is set, @@ -355,7 +358,7 @@ module FileUtils # FileUtils.cd '/sbin' # FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked. # - def self.ln: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self.ln: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.link self.ln @@ -372,7 +375,7 @@ module FileUtils # # FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin' # - def self.ln_s: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self.ln_s: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.symlink self.ln_s @@ -380,7 +383,7 @@ module FileUtils # # FileUtils.ln_s(*args, force: true) # - def self.ln_sf: (pathlist src, String dest, ?noop: boolish, ?verbose: boolish) -> void + def self.ln_sf: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish) -> void # Creates one or more directories. # @@ -389,7 +392,7 @@ module FileUtils # FileUtils.mkdir 'notexist', noop: true # Does not really create. # FileUtils.mkdir 'tmp', mode: 0700 # - def self.mkdir: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void + def self.mkdir: (pathlist list, ?mode: Integer?, ?noop: boolish, ?verbose: boolish) -> void # Creates a directory and all its parent directories. For example, # @@ -420,7 +423,7 @@ module FileUtils # FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/' # FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true # - def self.mv: (pathlist src, String dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + def self.mv: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void alias self.move self.mv @@ -445,7 +448,7 @@ module FileUtils # Removes a directory `dir` and its contents recursively. This method ignores # StandardError if `force` is true. # - def self.remove_dir: (String path, ?boolish force) -> void + def self.remove_dir: (path path, ?boolish force) -> void # This method removes a file system entry `path`. `path` might be a regular # file, a directory, or something. If `path` is a directory, remove it @@ -453,7 +456,7 @@ module FileUtils # # See also remove_entry_secure. # - def self.remove_entry: (String path, ?boolish force) -> void + def self.remove_entry: (path path, ?boolish force) -> void # This method removes a file system entry `path`. `path` shall be a regular # file, a directory, or something. If `path` is a directory, remove it @@ -487,11 +490,11 @@ module FileUtils # # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. # - def self.remove_entry_secure: (String path, ?boolish force) -> void + def self.remove_entry_secure: (path path, ?boolish force) -> void # Removes a file `path`. This method ignores StandardError if `force` is true. # - def self.remove_file: (String path, ?void force) -> void + def self.remove_file: (path path, ?void force) -> void # Remove file(s) specified in `list`. This method cannot remove directories. # All StandardErrors are ignored when the :force option is set. @@ -540,6 +543,8 @@ module FileUtils # def self.rm_rf: (pathlist list, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + alias self.rmtree self.rm_rf + # Removes one or more directories. # # FileUtils.rmdir 'somedir' @@ -549,8 +554,6 @@ module FileUtils # def self.rmdir: (pathlist list, ?parents: boolish, ?noop: boolish, ?verbose: boolish) -> void - alias self.rmtree self.rm_rf - # Updates modification time (mtime) and access time (atime) of file(s) in # `list`. Files are created if they don't exist. # @@ -565,5 +568,5 @@ module FileUtils # FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \ # system 'make hello.o' # - def self.uptodate?: (String new, Array[String] old_list) -> bool + def self.uptodate?: (path new, pathlist old_list) -> bool end diff --git a/test/stdlib/FileUtils_test.rb b/test/stdlib/FileUtils_test.rb index df7db4de2..fc7362b70 100644 --- a/test/stdlib/FileUtils_test.rb +++ b/test/stdlib/FileUtils_test.rb @@ -10,12 +10,16 @@ class FileUtilsSingletonTest < Test::Unit::TestCase def test_cd assert_send_type "(String) -> void", FileUtils, :cd, __dir__ - assert_send_type "(String, verbose: bool) -> void", - FileUtils, :cd, __dir__, verbose: false + assert_send_type "(ToStr) -> void", + FileUtils, :cd, ToStr.new(__dir__) + assert_send_type "(ToPath, verbose: bool) -> void", + FileUtils, :cd, ToPath.new(__dir__), verbose: false assert_send_type "(String) { (String) -> Integer } -> Integer", FileUtils, :cd, __dir__ do |dir| 1 end - assert_send_type "(String, verbose: nil) { (String) -> Integer } -> Integer", - FileUtils, :cd, __dir__, verbose: nil do |dir| 1 end + assert_send_type "(ToStr) { (String) -> Integer } -> Integer", + FileUtils, :cd, ToStr.new(__dir__) do |dir| 1 end + assert_send_type "(ToPath, verbose: nil) { (String) -> Integer } -> Integer", + FileUtils, :cd, ToPath.new(__dir__), verbose: nil do |dir| 1 end end def test_chdir @@ -29,8 +33,12 @@ def test_chmod in_tmpdir do |dir| assert_send_type "(Integer, String) -> void", FileUtils, :chmod, 0755, dir - assert_send_type "(String, Array[String]) -> void", - FileUtils, :chmod, "u=wrx", [dir] + assert_send_type "(Integer, ToStr) -> void", + FileUtils, :chmod, 0755, ToStr.new(dir) + assert_send_type "(Integer, ToPath) -> void", + FileUtils, :chmod, 0755, ToPath.new(dir) + assert_send_type "(String, Array[String | ToStr | ToPath]) -> void", + FileUtils, :chmod, "u=wrx", [dir, ToStr.new(dir), ToPath.new(dir)] assert_send_type "(Integer, Array[String], noop: bool, verbose: bool) -> void", FileUtils, :chmod, 0755, [dir], noop: false, verbose: false end @@ -40,8 +48,12 @@ def test_chmod_R in_tmpdir do |dir| assert_send_type "(Integer, String) -> void", FileUtils, :chmod_R, 0755, dir - assert_send_type "(String, Array[String]) -> void", - FileUtils, :chmod_R, "u=wrx", [dir] + assert_send_type "(Integer, ToStr) -> void", + FileUtils, :chmod_R, 0755, ToStr.new(dir) + assert_send_type "(Integer, ToPath) -> void", + FileUtils, :chmod_R, 0755, ToPath.new(dir) + assert_send_type "(String, Array[String | ToStr | ToPath]) -> void", + FileUtils, :chmod_R, "u=wrx", [dir, ToStr.new(dir), ToPath.new(dir)] assert_send_type "(Integer, Array[String], noop: bool, verbose: bool, force: nil) -> void", FileUtils, :chmod_R, 0755, [dir], noop: true, verbose: false, force: nil end @@ -51,8 +63,12 @@ def test_chown in_tmpdir do |dir| assert_send_type "(nil, nil, String) -> void", FileUtils, :chown, nil, nil, dir - assert_send_type "(nil, nil, Array[String]) -> void", - FileUtils, :chown, nil, nil, [dir] + assert_send_type "(nil, nil, ToStr) -> void", + FileUtils, :chown, nil, nil, ToStr.new(dir) + assert_send_type "(nil, nil, ToPath) -> void", + FileUtils, :chown, nil, nil, ToPath.new(dir) + assert_send_type "(nil, nil, Array[String | ToStr | ToPath]) -> void", + FileUtils, :chown, nil, nil, [dir, ToStr.new(dir), ToPath.new(dir)] assert_send_type "(String, String, Array[String], noop: bool, verbose: nil) -> void", FileUtils, :chown, "user", "group", [dir], noop: true, verbose: nil end @@ -62,8 +78,12 @@ def test_chown_R in_tmpdir do |dir| assert_send_type "(nil, nil, String) -> void", FileUtils, :chown_R, nil, nil, dir - assert_send_type "(nil, nil, Array[String]) -> void", - FileUtils, :chown_R, nil, nil, [dir] + assert_send_type "(nil, nil, ToStr) -> void", + FileUtils, :chown_R, nil, nil, ToStr.new(dir) + assert_send_type "(nil, nil, ToPath) -> void", + FileUtils, :chown_R, nil, nil, ToPath.new(dir) + assert_send_type "(nil, nil, Array[String | ToStr | ToPath]) -> void", + FileUtils, :chown_R, nil, nil, [dir, ToStr.new(dir), ToPath.new(dir)] assert_send_type "(String, String, Array[String], noop: bool, verbose: nil, force: bool) -> void", FileUtils, :chown_R, "user", "group", [dir], noop: true, verbose: nil, force: false end @@ -85,6 +105,10 @@ def test_compare_file assert_send_type "(String, String) -> bool", FileUtils, :compare_file, "foo", "foo" + assert_send_type "(ToStr, ToStr) -> bool", + FileUtils, :compare_file, ToStr.new("foo"), ToStr.new("foo") + assert_send_type "(ToPath, ToPath) -> bool", + FileUtils, :compare_file, ToPath.new("foo"), ToPath.new("foo") end end @@ -122,8 +146,10 @@ def test_copy_entry assert_send_type "(String, String) -> void", FileUtils, :copy_entry, "src", "dest" - assert_send_type "(String, String, bool, nil, bool) -> void", - FileUtils, :copy_entry, "src", "dest", true, nil, false + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :copy_entry, ToStr.new("src"), ToStr.new("dest") + assert_send_type "(ToPath, ToPath, bool, nil, bool) -> void", + FileUtils, :copy_entry, ToPath.new("src"), ToPath.new("dest"), true, nil, false end end @@ -133,8 +159,10 @@ def test_copy_file assert_send_type "(String, String) -> void", FileUtils, :copy_file, "src", "dest" - assert_send_type "(String, String, bool, nil) -> void", - FileUtils, :copy_file, "src", "dest", false, nil + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :copy_file, ToStr.new("src"), ToStr.new("dest") + assert_send_type "(ToPath, ToPath, bool, nil) -> void", + FileUtils, :copy_file, ToPath.new("src"), ToPath.new("dest"), false, nil end end @@ -157,10 +185,12 @@ def test_cp assert_send_type "(String, String) -> void", FileUtils, :cp, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :cp, ["src"], "dest_dir" - assert_send_type "(String, String, preserve: bool, noop: nil, verbose: bool) -> void", - FileUtils, :cp, "src", "dest", preserve: true, noop: nil, verbose: false + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :cp, ToStr.new("src"), ToStr.new("dest") + assert_send_type "(Array[String | ToStr | ToPath], String) -> void", + FileUtils, :cp, ["src", ToStr.new("src"), ToPath.new("src")], "dest_dir" + assert_send_type "(ToPath, ToPath, preserve: bool, noop: nil, verbose: bool) -> void", + FileUtils, :cp, ToPath.new("src"), ToPath.new("dest"), preserve: true, noop: nil, verbose: false end end @@ -179,10 +209,12 @@ def test_cp_lr assert_send_type "(String, String) -> void", FileUtils, :cp_lr, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :cp_lr, ["src"], "dest" - assert_send_type "(String, String, noop: bool, verbose: false, dereference_root: nil, remove_destination: nil) -> void", - FileUtils, :cp_lr, "src", "dest", noop: true, verbose: false, dereference_root: nil, remove_destination: nil + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :cp_lr, ToStr.new("src"), ToStr.new("dest") + assert_send_type "(Array[String | ToStr | ToPath], String) -> void", + FileUtils, :cp_lr, ["src", ToStr.new("src"), ToPath.new("src")], "dest" + assert_send_type "(ToPath, ToPath, noop: bool, verbose: false, dereference_root: nil, remove_destination: nil) -> void", + FileUtils, :cp_lr, ToPath.new("src"), ToPath.new("dest"), noop: true, verbose: false, dereference_root: nil, remove_destination: nil end end @@ -192,10 +224,12 @@ def test_cp_r assert_send_type "(String, String) -> void", FileUtils, :cp_r, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :cp_r, ["src"], "dest" - assert_send_type "(String, String, preserve: nil, noop: bool, verbose: bool, dereference_root: bool, remove_destination: nil) -> void", - FileUtils, :cp_r, "src", "dest", preserve: nil, noop: false, verbose: false, dereference_root: false, remove_destination: nil + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :cp_r, ToStr.new("src"), ToStr.new("dest") + assert_send_type "(Array[String | ToStr | ToPath], String) -> void", + FileUtils, :cp_r, ["src", ToStr.new("src"), ToPath.new("src")], "dest" + assert_send_type "(ToPath, ToPath, preserve: nil, noop: bool, verbose: bool, dereference_root: bool, remove_destination: nil) -> void", + FileUtils, :cp_r, ToPath.new("src"), ToPath.new("dest"), preserve: nil, noop: false, verbose: false, dereference_root: false, remove_destination: nil end end @@ -210,8 +244,10 @@ def test_install assert_send_type "(String, String) -> void", FileUtils, :install, "src", "dest" - assert_send_type "(String, String, mode: Integer) -> void", - FileUtils, :install, "src", "dest", mode: 0755 + assert_send_type "(ToStr, ToStr, mode: nil) -> void", + FileUtils, :install, ToStr.new("src"), ToStr.new("dest"), mode: nil + assert_send_type "(ToPath, ToPath, mode: Integer) -> void", + FileUtils, :install, ToPath.new("src"), ToPath.new("dest"), mode: 0755 assert_send_type "(String, String, mode: String, owner: String, group: nil, preserve: bool, noop: bool, verbose: nil) -> void", FileUtils, :install, "src", "dest", mode: "u=wrx", owner: "user", group: nil, preserve: false, noop: true, verbose: nil end @@ -223,32 +259,33 @@ def test_link_entry assert_send_type "(String, String) -> void", FileUtils, :link_entry, "src", "dest" - assert_send_type "(String, String, bool, bool) -> void", - FileUtils, :link_entry, "src", "dest", false, true + assert_send_type "(ToStr, ToStr) -> void", + FileUtils, :link_entry, ToStr.new("src"), ToStr.new("dest2") + assert_send_type "(ToPath, ToPath, bool, bool) -> void", + FileUtils, :link_entry, ToPath.new("src"), ToPath.new("dest"), false, true end end def test_ln in_tmpdir do |dir| File.write "src", "" - File.write "src2", "" Dir.mkdir "dest" assert_send_type "(String, String) -> void", FileUtils, :ln, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :ln, ["src2"], "dest" - assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", - FileUtils, :ln, "src", "dest", force: true, noop: nil, verbose: false + assert_send_type "(ToStr, ToStr, noop: bool) -> void", + FileUtils, :ln, ToStr.new("src"), ToStr.new("dest"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], String, noop: bool) -> void", + FileUtils, :ln, ["src", ToStr.new("src"), ToPath.new("src")], "dest", noop: true + assert_send_type "(ToPath, ToPath, force: bool, noop: nil, verbose: bool) -> void", + FileUtils, :ln, ToPath.new("src"), ToPath.new("dest"), force: true, noop: nil, verbose: false end end def test_link in_tmpdir do - File.write "src", "" - - assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", - FileUtils, :link, "src", "dest", force: true, noop: nil, verbose: false + assert_send_type "(String, String, force: nil, noop: bool, verbose: bool) -> void", + FileUtils, :link, "src", "dest", force: nil, noop: true, verbose: false end end @@ -259,19 +296,19 @@ def test_ln_s assert_send_type "(String, String) -> void", FileUtils, :ln_s, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :ln_s, ["src"], "dest_dir" - assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", - FileUtils, :ln_s, "src", "dest", force: true, noop: nil, verbose: false + assert_send_type "(ToStr, ToStr, noop: bool) -> void", + FileUtils, :ln_s, ToStr.new("src"), ToStr.new("dest"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], String, noop: bool) -> void", + FileUtils, :ln_s, ["src", ToStr.new("src"), ToPath.new("src")], "dest_dir", noop: true + assert_send_type "(ToPath, ToPath, force: nil, noop: bool, verbose: bool) -> void", + FileUtils, :ln_s, ToPath.new("src"), ToPath.new("dest"), force: nil, noop: true, verbose: false end end def test_symlink in_tmpdir do - File.write "src", "" - - assert_send_type "(String, String, force: bool, noop: nil, verbose: bool) -> void", - FileUtils, :symlink, "src", "dest", force: true, noop: nil, verbose: false + assert_send_type "(String, String, force: nil, noop: bool, verbose: bool) -> void", + FileUtils, :symlink, "src", "dest", force: nil, noop: true, verbose: false end end @@ -282,8 +319,12 @@ def test_ln_sf assert_send_type "(String, String) -> void", FileUtils, :ln_sf, "src", "dest" - assert_send_type "(Array[String], String, noop: bool, verbose: bool) -> void", - FileUtils, :ln_sf, ["src"], "dest_dir", noop: true, verbose: false + assert_send_type "(ToStr, ToStr, noop: bool) -> void", + FileUtils, :ln_sf, ToStr.new("src"), ToStr.new("dest"), noop: true + assert_send_type "(ToPath, ToPath, noop: bool) -> void", + FileUtils, :ln_sf, ToPath.new("src"), ToPath.new("dest"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], String, noop: bool, verbose: bool) -> void", + FileUtils, :ln_sf, ["src", ToStr.new("src"), ToStr.new("src")], "dest_dir", noop: true, verbose: false end end @@ -291,10 +332,12 @@ def test_mkdir in_tmpdir do assert_send_type "(String) -> void", FileUtils, :mkdir, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :mkdir, ["bar"] - assert_send_type "(String, mode: Integer, noop: bool, verbose: nil) -> void", - FileUtils, :mkdir, "foo", mode: 0755, noop: true, verbose: nil + assert_send_type "(ToStr) -> void", + FileUtils, :mkdir, ToStr.new("bar") + assert_send_type "(Array[String | ToStr | ToPath], mode: nil) -> void", + FileUtils, :mkdir, ["bar1", ToStr.new("bar2"), ToPath.new("bar3")], mode: nil + assert_send_type "(ToPath, mode: Integer, noop: bool, verbose: nil) -> void", + FileUtils, :mkdir, ToPath.new("foo"), mode: 0755, noop: true, verbose: nil end end @@ -302,10 +345,12 @@ def test_mkdir_p in_tmpdir do assert_send_type "(String) -> void", FileUtils, :mkdir_p, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :mkdir_p, ["foo"] - assert_send_type "(String, mode: Integer, noop: bool, verbose: bool) -> void", - FileUtils, :mkdir_p, "foo", mode: 0755, noop: false, verbose: false + assert_send_type "(ToStr) -> void", + FileUtils, :mkdir_p, ToStr.new("foo") + assert_send_type "(Array[String | ToStr | ToPath], mode: nil) -> void", + FileUtils, :mkdir_p, ["foo", ToStr.new("foo"), ToPath.new("foo")], mode: nil + assert_send_type "(ToPath, mode: Integer, noop: bool, verbose: bool) -> void", + FileUtils, :mkdir_p, ToPath.new("foo"), mode: 0755, noop: false, verbose: false end end @@ -326,15 +371,16 @@ def test_mkpath def test_mv in_tmpdir do File.write "src", "" - File.write "src2", "" Dir.mkdir "dest_dir" assert_send_type "(String, String) -> void", FileUtils, :mv, "src", "dest" - assert_send_type "(Array[String], String) -> void", - FileUtils, :mv, ["src2"], "dest_dir" - assert_send_type "(String, String, force: bool, noop: bool, verbose: nil, secure: bool) -> void", - FileUtils, :mv, "src", "dest", force: true, noop: true, verbose: nil, secure: true + assert_send_type "(ToStr, ToStr, noop: bool) -> void", + FileUtils, :mv, ToStr.new("src"), ToStr.new("dest"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], String, noop: bool) -> void", + FileUtils, :mv, ["src", ToStr.new("src"), ToPath.new("src")], "dest_dir", noop: true + assert_send_type "(ToPath, ToPath, force: bool, noop: bool, verbose: nil, secure: bool) -> void", + FileUtils, :mv, ToPath.new("src"), ToPath.new("dest"), force: true, noop: true, verbose: nil, secure: true end end @@ -371,8 +417,10 @@ def test_remove_dir assert_send_type "(String) -> void", FileUtils, :remove_dir, "foo" - assert_send_type "(String, bool) -> void", - FileUtils, :remove_dir, "foo", true + assert_send_type "(ToStr, bool) -> void", + FileUtils, :remove_dir, ToStr.new("foo"), true + assert_send_type "(ToPath, bool) -> void", + FileUtils, :remove_dir, ToPath.new("foo"), true end end @@ -382,8 +430,10 @@ def test_remove_entry assert_send_type "(String) -> void", FileUtils, :remove_entry, "foo" - assert_send_type "(String, bool) -> void", - FileUtils, :remove_entry, "foo", true + assert_send_type "(ToStr, bool) -> void", + FileUtils, :remove_entry, ToStr.new("foo"), true + assert_send_type "(ToPath, bool) -> void", + FileUtils, :remove_entry, ToPath.new("foo"), true end end @@ -393,8 +443,10 @@ def test_remove_entry_secure assert_send_type "(String) -> void", FileUtils, :remove_entry_secure, "foo" - assert_send_type "(String, bool) -> void", - FileUtils, :remove_entry_secure, "foo", true + assert_send_type "(ToStr, bool) -> void", + FileUtils, :remove_entry_secure, ToStr.new("foo"), true + assert_send_type "(ToPath, bool) -> void", + FileUtils, :remove_entry_secure, ToPath.new("foo"), true end end @@ -404,22 +456,25 @@ def test_remove_file assert_send_type "(String) -> void", FileUtils, :remove_file, "foo" - assert_send_type "(String, bool) -> void", - FileUtils, :remove_file, "foo", true + assert_send_type "(ToStr, bool) -> void", + FileUtils, :remove_file, ToStr.new("foo"), true + assert_send_type "(ToPath, bool) -> void", + FileUtils, :remove_file, ToPath.new("foo"), true end end def test_rm in_tmpdir do File.write "foo", "" - File.write "bar", "" assert_send_type "(String) -> void", FileUtils, :rm, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :rm, ["bar"] - assert_send_type "(String, force: bool, noop: nil, verbose: bool) -> void", - FileUtils, :rm, "foo", force: true, noop: nil, verbose: false + assert_send_type "(ToStr, noop: bool) -> void", + FileUtils, :rm, ToStr.new("foo"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], noop: bool) -> void", + FileUtils, :rm, ["foo", ToStr.new("foo"), ToPath.new("foo")], noop: true + assert_send_type "(ToPath, force: nil, noop: bool, verbose: bool) -> void", + FileUtils, :rm, ToPath.new("foo"), force: nil, noop: true, verbose: false end end @@ -434,10 +489,12 @@ def test_rm_f in_tmpdir do assert_send_type "(String) -> void", FileUtils, :rm_f, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :rm_f, ["foo"] - assert_send_type "(String, noop: bool, verbose: nil) -> void", - FileUtils, :rm_f, "foo", noop: false, verbose: nil + assert_send_type "(ToStr) -> void", + FileUtils, :rm_f, ToStr.new("foo") + assert_send_type "(Array[String | ToStr | ToPath]) -> void", + FileUtils, :rm_f, ["foo", ToStr.new("foo"), ToPath.new("foo")] + assert_send_type "(ToPath, noop: bool, verbose: nil) -> void", + FileUtils, :rm_f, ToPath.new("foo"), noop: false, verbose: nil end end @@ -451,14 +508,15 @@ def test_safe_unlink def test_rm_r in_tmpdir do Dir.mkdir "foo" - Dir.mkdir "bar" assert_send_type "(String) -> void", FileUtils, :rm_r, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :rm_r, ["bar"] - assert_send_type "(String, force: bool, noop: bool, verbose: nil, secure: bool) -> void", - FileUtils, :rm_r, "foo", force: true, noop: false, verbose: nil, secure: true + assert_send_type "(ToStr, noop: bool) -> void", + FileUtils, :rm_r, ToStr.new("foo"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], noop: bool) -> void", + FileUtils, :rm_r, ["foo", ToStr.new("foo"), ToPath.new("foo")], noop: true + assert_send_type "(ToPath, force: bool, noop: bool, verbose: nil, secure: bool) -> void", + FileUtils, :rm_r, ToPath.new("foo"), force: true, noop: true, verbose: nil, secure: true end end @@ -466,10 +524,12 @@ def test_rm_rf in_tmpdir do assert_send_type "(String) -> void", FileUtils, :rm_rf, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :rm_rf, ["foo"] - assert_send_type "(String, noop: nil, verbose: nil, secure: bool) -> void", - FileUtils, :rm_rf, "foo", noop: nil, verbose: nil, secure: true + assert_send_type "(ToStr) -> void", + FileUtils, :rm_rf, ToStr.new("foo") + assert_send_type "(Array[String | ToStr | ToPath]) -> void", + FileUtils, :rm_rf, ["foo", ToStr.new("foo"), ToPath.new("foo")] + assert_send_type "(ToPath, noop: nil, verbose: nil, secure: bool) -> void", + FileUtils, :rm_rf, ToPath.new("foo"), noop: nil, verbose: nil, secure: true end end @@ -483,14 +543,15 @@ def test_rmtree def test_rmdir in_tmpdir do Dir.mkdir "foo" - Dir.mkdir "bar" assert_send_type "(String) -> void", FileUtils, :rmdir, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :rmdir, ["bar"] - assert_send_type "(String, parents: bool, noop: bool, verbose: nil) -> void", - FileUtils, :rmdir, "foo", parents: false, noop: true, verbose: nil + assert_send_type "(ToStr, noop: bool) -> void", + FileUtils, :rmdir, ToStr.new("foo"), noop: true + assert_send_type "(Array[String | ToStr | ToPath], noop: bool) -> void", + FileUtils, :rmdir, ["foo", ToStr.new("foo"), ToPath.new("foo")], noop: true + assert_send_type "(ToPath, parents: bool, noop: bool, verbose: nil) -> void", + FileUtils, :rmdir, ToPath.new("foo"), parents: false, noop: true, verbose: nil end end @@ -498,18 +559,24 @@ def test_touch in_tmpdir do assert_send_type "(String) -> void", FileUtils, :touch, "foo" - assert_send_type "(Array[String]) -> void", - FileUtils, :touch, ["foo", "bar"] - assert_send_type "(String, mtime: Time) -> void", - FileUtils, :touch, "foo", mtime: Time.now - assert_send_type "(String, noop: bool, verbose: bool, mtime: Integer, nocreate: nil) -> void", - FileUtils, :touch, "foo", noop: true, verbose: false, mtime: 1000, nocreate: nil + assert_send_type "(Array[String | ToStr | ToPath]) -> void", + FileUtils, :touch, ["foo", ToStr.new("foo"), ToPath.new("foo")] + assert_send_type "(ToStr, mtime: Time) -> void", + FileUtils, :touch, ToStr.new("foo"), mtime: Time.now + assert_send_type "(ToPath, noop: bool, verbose: bool, mtime: Integer, nocreate: nil) -> void", + FileUtils, :touch, ToPath.new("foo"), noop: true, verbose: false, mtime: 1000, nocreate: nil end end def test_uptodate? - assert_send_type "(String, Array[String]) -> bool", - FileUtils, :uptodate?, "foo", ["bar"] + assert_send_type "(String, String) -> bool", + FileUtils, :uptodate?, "foo", "bar" + assert_send_type "(String, Array[String | ToStr | ToPath]) -> bool", + FileUtils, :uptodate?, "foo", ["bar", ToStr.new("bar"), ToPath.new("bar")] + assert_send_type "(ToStr, ToStr) -> bool", + FileUtils, :uptodate?, ToStr.new("foo"), ToStr.new("bar") + assert_send_type "(ToPath, ToPath) -> bool", + FileUtils, :uptodate?, ToPath.new("foo"), ToPath.new("bar") end private From ca1d180d1b0a9b283e3d3e9d66961b84424884e4 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Mon, 18 Jan 2021 10:33:15 +0900 Subject: [PATCH 3/3] Support `module_function` (using `self?`) --- stdlib/fileutils/0/fileutils.rbs | 81 ++++--- test/stdlib/FileUtils_test.rb | 365 ++++++++++++++++++++++++++++++- 2 files changed, 403 insertions(+), 43 deletions(-) diff --git a/stdlib/fileutils/0/fileutils.rbs b/stdlib/fileutils/0/fileutils.rbs index a1ac64d63..25291ee3b 100644 --- a/stdlib/fileutils/0/fileutils.rbs +++ b/stdlib/fileutils/0/fileutils.rbs @@ -117,10 +117,11 @@ module FileUtils # # ... # do something # end # return to original directory # - def self.cd: (path dir, ?verbose: boolish) -> void - | [X] (path dir, ?verbose: boolish) { (String) -> X } -> X + def self?.cd: (path dir, ?verbose: boolish) -> void + | [X] (path dir, ?verbose: boolish) { (String) -> X } -> X alias self.chdir self.cd + alias chdir cd # Changes permission bits on the named files (in `list`) to the bit pattern # represented by `mode`. @@ -165,7 +166,7 @@ module FileUtils # "=" # : Is the exact nature of the class will be given a specified mode. # - def self.chmod: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish) -> void + def self?.chmod: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish) -> void # Changes permission bits on the named files (in `list`) to the bit pattern # represented by `mode`. @@ -173,7 +174,7 @@ module FileUtils # FileUtils.chmod_R 0700, "/tmp/app.#{$$}" # FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}" # - def self.chmod_R: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void + def self?.chmod_R: (mode mode, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void # Changes owner and group on the named files (in `list`) to the user `user` and # the group `group`. `user` and `group` may be an ID (Integer/String) or a name @@ -183,7 +184,7 @@ module FileUtils # FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby' # FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true # - def self.chown: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish) -> void + def self?.chown: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish) -> void # Changes owner and group on the named files (in `list`) to the user `user` and # the group `group` recursively. `user` and `group` may be an ID @@ -193,7 +194,7 @@ module FileUtils # FileUtils.chown_R 'www', 'www', '/var/www/htdocs' # FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true # - def self.chown_R: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void + def self?.chown_R: (String? user, String? group, pathlist list, ?noop: boolish, ?verbose: boolish, ?force: boolish) -> void # Returns an Array of methods names which have the option `opt`. # @@ -213,15 +214,17 @@ module FileUtils # FileUtils.compare_file('somefile', 'somefile') #=> true # FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false # - def self.compare_file: (path a, path b) -> bool + def self?.compare_file: (path a, path b) -> bool alias self.cmp self.compare_file + alias cmp compare_file alias self.identical? self.compare_file + alias identical? compare_file # Returns true if the contents of a stream `a` and `b` are identical. # - def self.compare_stream: (IO a, IO b) -> bool + def self?.compare_stream: (IO a, IO b) -> bool # Copies a file system entry `src` to `dest`. If `src` is a directory, this # method copies its contents recursively. This method preserves file types, c.f. @@ -238,17 +241,17 @@ module FileUtils # If `remove_destination` is true, this method removes each destination file # before copy. # - def self.copy_entry: (path src, path dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void + def self?.copy_entry: (path src, path dest, ?boolish preserve, ?boolish dereference_root, ?boolish remove_destination) -> void # Copies file contents of `src` to `dest`. Both of `src` and `dest` must be a # path name. # - def self.copy_file: (path src, path dest, ?boolish preserve, ?boolish dereference) -> void + def self?.copy_file: (path src, path dest, ?boolish preserve, ?boolish dereference) -> void # Copies stream `src` to `dest`. `src` must respond to #read(n) and `dest` must # respond to #write(str). # - def self.copy_stream: (_Reader src, _Writer dest) -> void + def self?.copy_stream: (_Reader src, _Writer dest) -> void # Copies a file content `src` to `dest`. If `dest` is a directory, copies `src` # to `dest/src`. @@ -260,9 +263,10 @@ module FileUtils # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true # FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink # - def self.cp: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.cp: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.copy self.cp + alias copy cp # Hard link `src` to `dest`. If `src` is a directory, this method links all its # contents recursively. If `dest` is a directory, links `src` to `dest/src`. @@ -286,7 +290,7 @@ module FileUtils # # use the following code. # FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't. # - def self.cp_lr: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + def self?.cp_lr: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void # Copies `src` to `dest`. If `src` is a directory, this method copies all its # contents recursively. If `dest` is a directory, copies `src` to `dest/src`. @@ -312,7 +316,7 @@ module FileUtils # FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src, # # but this doesn't. # - def self.cp_r: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void + def self?.cp_r: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish, ?dereference_root: boolish, ?remove_destination: boolish) -> void # Returns true if the method `mid` have an option `opt`. # @@ -329,7 +333,7 @@ module FileUtils # FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true # FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true # - def self.install: (path src, path dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.install: (path src, path dest, ?mode: mode?, ?owner: String?, ?group: String?, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void # Hard links a file system entry `src` to `dest`. If `src` is a directory, this # method links its contents recursively. @@ -342,7 +346,7 @@ module FileUtils # If `remove_destination` is true, this method removes each destination file # before copy. # - def self.link_entry: (path src, path dest, ?boolish dereference_root, ?boolish remove_destination) -> void + def self?.link_entry: (path src, path dest, ?boolish dereference_root, ?boolish remove_destination) -> void # In the first form, creates a hard link `link` which points to `target`. If # `link` already exists, raises Errno::EEXIST. But if the `force` option is set, @@ -358,9 +362,10 @@ module FileUtils # FileUtils.cd '/sbin' # FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked. # - def self.ln: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.ln: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.link self.ln + alias link ln # In the first form, creates a symbolic link `link` which points to `target`. If # `link` already exists, raises Errno::EEXIST. But if the `force` option is set, @@ -375,15 +380,16 @@ module FileUtils # # FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin' # - def self.ln_s: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.ln_s: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.symlink self.ln_s + alias symlink ln_s # Same as # # FileUtils.ln_s(*args, force: true) # - def self.ln_sf: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish) -> void + def self?.ln_sf: (pathlist src, path dest, ?noop: boolish, ?verbose: boolish) -> void # Creates one or more directories. # @@ -392,7 +398,7 @@ module FileUtils # FileUtils.mkdir 'notexist', noop: true # Does not really create. # FileUtils.mkdir 'tmp', mode: 0700 # - def self.mkdir: (pathlist list, ?mode: Integer?, ?noop: boolish, ?verbose: boolish) -> void + def self?.mkdir: (pathlist list, ?mode: Integer?, ?noop: boolish, ?verbose: boolish) -> void # Creates a directory and all its parent directories. For example, # @@ -408,11 +414,13 @@ module FileUtils # # You can pass several directories at a time in a list. # - def self.mkdir_p: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void + def self?.mkdir_p: (pathlist list, ?mode: mode?, ?noop: boolish, ?verbose: boolish) -> void alias self.makedirs self.mkdir_p + alias makedirs mkdir_p alias self.mkpath self.mkdir_p + alias mkpath mkdir_p # Moves file(s) `src` to `dest`. If `file` and `dest` exist on the different # disk partition, the file is copied then the original file is removed. @@ -423,9 +431,10 @@ module FileUtils # FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/' # FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true # - def self.mv: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + def self?.mv: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void alias self.move self.mv + alias move mv # Returns an Array of option names. # @@ -441,14 +450,15 @@ module FileUtils # Returns the name of the current directory. # - def self.pwd: () -> String + def self?.pwd: () -> String alias self.getwd self.pwd + alias getwd pwd # Removes a directory `dir` and its contents recursively. This method ignores # StandardError if `force` is true. # - def self.remove_dir: (path path, ?boolish force) -> void + def self?.remove_dir: (path path, ?boolish force) -> void # This method removes a file system entry `path`. `path` might be a regular # file, a directory, or something. If `path` is a directory, remove it @@ -456,7 +466,7 @@ module FileUtils # # See also remove_entry_secure. # - def self.remove_entry: (path path, ?boolish force) -> void + def self?.remove_entry: (path path, ?boolish force) -> void # This method removes a file system entry `path`. `path` shall be a regular # file, a directory, or something. If `path` is a directory, remove it @@ -490,11 +500,11 @@ module FileUtils # # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. # - def self.remove_entry_secure: (path path, ?boolish force) -> void + def self?.remove_entry_secure: (path path, ?boolish force) -> void # Removes a file `path`. This method ignores StandardError if `force` is true. # - def self.remove_file: (path path, ?void force) -> void + def self?.remove_file: (path path, ?void force) -> void # Remove file(s) specified in `list`. This method cannot remove directories. # All StandardErrors are ignored when the :force option is set. @@ -503,17 +513,19 @@ module FileUtils # FileUtils.rm Dir.glob('*.so') # FileUtils.rm 'NotExistFile', force: true # never raises exception # - def self.rm: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.rm: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void alias self.remove self.rm + alias remove rm # Equivalent to # # FileUtils.rm(list, force: true) # - def self.rm_f: (pathlist list, ?noop: boolish, ?verbose: boolish) -> void + def self?.rm_f: (pathlist list, ?noop: boolish, ?verbose: boolish) -> void alias self.safe_unlink self.rm_f + alias safe_unlink rm_f # remove files `list[0]` `list[1]`... If `list[n]` is a directory, removes its # all contents recursively. This method ignores StandardError when :force option @@ -532,7 +544,7 @@ module FileUtils # NOTE: This method calls remove_entry_secure if :secure option is set. See also # remove_entry_secure. # - def self.rm_r: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + def self?.rm_r: (pathlist list, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void # Equivalent to # @@ -541,9 +553,10 @@ module FileUtils # WARNING: This method causes local vulnerability. Read the documentation of # rm_r first. # - def self.rm_rf: (pathlist list, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void + def self?.rm_rf: (pathlist list, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void alias self.rmtree self.rm_rf + alias rmtree rm_rf # Removes one or more directories. # @@ -552,7 +565,7 @@ module FileUtils # # Does not really remove directory; outputs message. # FileUtils.rmdir 'somedir', verbose: true, noop: true # - def self.rmdir: (pathlist list, ?parents: boolish, ?noop: boolish, ?verbose: boolish) -> void + def self?.rmdir: (pathlist list, ?parents: boolish, ?noop: boolish, ?verbose: boolish) -> void # Updates modification time (mtime) and access time (atime) of file(s) in # `list`. Files are created if they don't exist. @@ -560,7 +573,7 @@ module FileUtils # FileUtils.touch 'timestamp' # FileUtils.touch Dir.glob('*.c'); system 'make' # - def self.touch: (pathlist list, ?noop: boolish, ?verbose: boolish, ?mtime: (Time | Numeric)?, ?nocreate: boolish) -> void + def self?.touch: (pathlist list, ?noop: boolish, ?verbose: boolish, ?mtime: (Time | Numeric)?, ?nocreate: boolish) -> void # Returns true if `new` is newer than all `old_list`. Non-existent files are # older than any file. @@ -568,5 +581,5 @@ module FileUtils # FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \ # system 'make hello.o' # - def self.uptodate?: (path new, pathlist old_list) -> bool + def self?.uptodate?: (path new, pathlist old_list) -> bool end diff --git a/test/stdlib/FileUtils_test.rb b/test/stdlib/FileUtils_test.rb index fc7362b70..a2157fa05 100644 --- a/test/stdlib/FileUtils_test.rb +++ b/test/stdlib/FileUtils_test.rb @@ -1,8 +1,19 @@ require_relative "test_helper" require "fileutils" +module TmpdirHelper + private + + def in_tmpdir(&block) + Dir.mktmpdir do |dir| + Dir.chdir(dir, &block) + end + end +end + class FileUtilsSingletonTest < Test::Unit::TestCase include TypeAssertions + include TmpdirHelper library "fileutils" testing "singleton(::FileUtils)" @@ -170,7 +181,7 @@ def test_copy_stream in_tmpdir do File.write "src", "" File.open("src") do |src| - File.open("dest", "a") do |dest| + File.open("dest", "w") do |dest| assert_send_type "(IO, IO) -> void", FileUtils, :copy_stream, src, dest end @@ -196,10 +207,8 @@ def test_cp def test_copy in_tmpdir do - File.write "src", "" - - assert_send_type "(String, String, preserve: bool, noop: nil, verbose: bool) -> void", - FileUtils, :copy, "src", "dest", preserve: true, noop: nil, verbose: false + assert_send_type "(String, String, preserve: bool, noop: bool, verbose: nil) -> void", + FileUtils, :copy, "src", "dest", preserve: true, noop: true, verbose: nil end end @@ -578,12 +587,350 @@ def test_uptodate? assert_send_type "(ToPath, ToPath) -> bool", FileUtils, :uptodate?, ToPath.new("foo"), ToPath.new("bar") end +end - private +class FileUtilsInstanceTest < Test::Unit::TestCase + include TypeAssertions + include TmpdirHelper - def in_tmpdir(&block) - Dir.mktmpdir do |dir| - Dir.chdir(dir, &block) + library "fileutils" + testing "::FileUtils" + + class Foo + include FileUtils + end + + def test_cd + assert_send_type "(String) -> void", + Foo.new, :cd, __dir__ + end + + def test_chdir + assert_send_type "(String) -> void", + Foo.new, :chdir, __dir__ + end + + def test_chmod + in_tmpdir do |dir| + assert_send_type "(Integer, String) -> void", + Foo.new, :chmod, 0755, dir + end + end + + def test_chmod_R + in_tmpdir do |dir| + assert_send_type "(Integer, String) -> void", + Foo.new, :chmod_R, 0755, dir + end + end + + def test_chown + in_tmpdir do |dir| + assert_send_type "(nil, nil, String) -> void", + Foo.new, :chown, nil, nil, dir + end + end + + def test_chown_R + in_tmpdir do |dir| + assert_send_type "(nil, nil, String) -> void", + Foo.new, :chown_R, nil, nil, dir + end + end + + def test_compare_file + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + Foo.new, :compare_file, "foo", "foo" + end + end + + def test_cmp + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + Foo.new, :cmp, "foo", "foo" + end + end + + def test_identical? + in_tmpdir do + File.write "foo", "" + + assert_send_type "(String, String) -> bool", + Foo.new, :identical?, "foo", "foo" + end + end + + def test_compare_stream + in_tmpdir do + File.write "foo", "" + File.open("foo") do |io| + assert_send_type "(IO, IO) -> bool", + Foo.new, :compare_stream, io, io + end + end + end + + def test_copy_entry + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + Foo.new, :copy_entry, "src", "dest" + end + end + + def test_copy_file + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + Foo.new, :copy_file, "src", "dest" + end + end + + def test_copy_stream + in_tmpdir do + File.write "src", "" + File.open("src") do |src| + File.open("dest", "w") do |dest| + assert_send_type "(IO, IO) -> void", + Foo.new, :copy_stream, src, dest + end + end + end + end + + def test_cp + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :cp, "src", "dest", noop: true + end + end + + def test_copy + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :copy, "src", "dest", noop: true + end + end + + def test_cp_lr + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :cp_lr, "src", "dest", noop: true + end + end + + def test_cp_r + in_tmpdir do + Dir.mkdir "src" + + assert_send_type "(String, String) -> void", + Foo.new, :cp_r, "src", "dest" + end + end + + def test_install + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :install, "src", "dest", noop: true + end + end + + def test_link_entry + in_tmpdir do + File.write "src", "" + + assert_send_type "(String, String) -> void", + Foo.new, :link_entry, "src", "dest" + end + end + + def test_ln + in_tmpdir do |dir| + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :ln, "src", "dest", noop: true + end + end + + def test_link + in_tmpdir do |dir| + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :link, "src", "dest", noop: true + end + end + + def test_ln_s + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :ln_s, "src", "dest", noop: true + end + end + + def test_symlink + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :symlink, "src", "dest", noop: true + end + end + + def test_ln_sf + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :ln_sf, "src", "dest", noop: true end end + + def test_mkdir + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :mkdir, "foo", noop: true + end + end + + def test_mkdir_p + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :mkdir_p, "foo", noop: true + end + end + + def test_makedirs + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :makedirs, "foo", noop: true + end + end + + def test_mkpath + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :mkpath, "foo", noop: true + end + end + + def test_mv + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :mv, "src", "dest", noop: true + end + end + + def test_move + in_tmpdir do + assert_send_type "(String, String, noop: bool) -> void", + Foo.new, :move, "src", "dest", noop: true + end + end + + def test_pwd + assert_send_type "() -> String", + Foo.new, :pwd + end + + def test_getwd + assert_send_type "() -> String", + Foo.new, :getwd + end + + def test_remove_dir + in_tmpdir do + assert_send_type "(String, bool) -> void", + Foo.new, :remove_dir, "foo", true + end + end + + def test_remove_entry + in_tmpdir do + assert_send_type "(String, bool) -> void", + Foo.new, :remove_entry, "foo", true + end + end + + def test_remove_entry_secure + in_tmpdir do + assert_send_type "(String, bool) -> void", + Foo.new, :remove_entry_secure, "foo", true + end + end + + def test_remove_file + in_tmpdir do + assert_send_type "(String, bool) -> void", + Foo.new, :remove_file, "foo", true + end + end + + def test_rm + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :rm, "foo", noop: true + end + end + + def test_remove + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :remove, "foo", noop: true + end + end + + def test_rm_f + in_tmpdir do + assert_send_type "(String) -> void", + Foo.new, :rm_f, "foo" + end + end + + def test_safe_unlink + in_tmpdir do + assert_send_type "(String) -> void", + Foo.new, :safe_unlink, "foo" + end + end + + def test_rm_r + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :rm_r, "foo", noop: true + end + end + + def test_rm_rf + in_tmpdir do + assert_send_type "(String) -> void", + Foo.new, :rm_rf, "foo" + end + end + + def test_rmtree + in_tmpdir do + assert_send_type "(String) -> void", + Foo.new, :rmtree, "foo" + end + end + + def test_rmdir + in_tmpdir do + assert_send_type "(String, noop: bool) -> void", + Foo.new, :rmdir, "foo", noop: true + end + end + + def test_touch + in_tmpdir do + assert_send_type "(String) -> void", + Foo.new, :touch, "foo" + end + end + + def test_uptodate? + assert_send_type "(String, String) -> bool", + Foo.new, :uptodate?, "foo", "bar" + end end