Merge: Apply optional params in strip_extension, basename and join
authorJean Privat <jean@pryen.org>
Mon, 20 Jul 2015 13:33:45 +0000 (09:33 -0400)
committerJean Privat <jean@pryen.org>
Mon, 20 Jul 2015 13:33:45 +0000 (09:33 -0400)
Using optional parameters, the methods `strip_extension`, `basename` and `join` have a default behavior that fit most usage.

* `Collection::join` appends all elements of the collection by default, the same as `join("")`. This is the old behavior of `Collection::to_s`.

* `String::strip_extension` removes the rightmost extension by default, the same as `s.strip_extension("." + s.file_extension)`.

* `String::basename` does not strip the extension by default.

I haven't updated any users of `strip_extension` because the default behavior requires more work. Thus changing the already existing calls to something else would slow down the programs by a very small margin.

Pull-Request: #1575
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>

25 files changed:
contrib/jwrapper/src/code_generator.nit
contrib/jwrapper/src/model.nit
contrib/neo_doxygen/src/model/linked_text.nit
contrib/nitiwiki/src/wiki_base.nit
contrib/pep8analysis/src/cfg/dot_printer.nit
examples/rosettacode/balanced_brackets.nit
examples/rosettacode/one_dimensional_cellular_automata.nit
lib/curl/curl.nit
lib/dom/xml_entities.nit
lib/linux/data_store.nit
lib/standard/file.nit
lib/standard/text/abstract_text.nit
src/c_tools.nit
src/compiler/abstract_compiler.nit
src/ffi/cpp.nit
src/ffi/extra_java_files.nit
src/ffi/java.nit
src/ffi/objc.nit
src/loader.nit
src/nitserial.nit
src/platform/android.nit
src/platform/ios.nit
src/platform/pnacl.nit
src/toolcontext.nit
tests/example_string.nit

index ee0942f..88a8f86 100644 (file)
@@ -84,10 +84,10 @@ class CodeGenerator
                if module_name != null then file_out.write "module {module_name}\n"
 
                file_out.write("\n")
-               file_out.write(imports.join(""))
+               file_out.write(imports.join)
                file_out.write("\n")
-               file_out.write(class_content.join(""))
-               file_out.write(wrappers.join(""))
+               file_out.write(class_content.join)
+               file_out.write(wrappers.join)
        end
 
        fun gen_licence: String
@@ -117,7 +117,7 @@ class CodeGenerator
                temp.add("extern class Native{jtype.id} in \"Java\" `\{ {jtype} `\}\n")
                temp.add("\tsuper JavaObject\n\n")
 
-               return temp.join("")
+               return temp.join
        end
 
        fun gen_unknown_class_header(jtype: JavaType): String
@@ -133,7 +133,7 @@ class CodeGenerator
                temp.add("extern class {nit_type} in \"Java\" `\{ {jtype.to_package_name} `\}\n")
                temp.add("\tsuper JavaObject\n\nend\n")
 
-               return temp.join("")
+               return temp.join
        end
 
        fun gen_attribute(jid: String, jtype: JavaType): String
@@ -219,7 +219,7 @@ class CodeGenerator
 
                var temp = new Array[String]
 
-               temp.add(comment + nit_signature.join(""))
+               temp.add(comment + nit_signature.join)
 
                # FIXME : This huge `if` block is only necessary to copy primitive arrays as long as there's no better way to do it
                if comment == "#" then
@@ -235,7 +235,7 @@ class CodeGenerator
                        temp.add(" in \"Java\" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n")
                end
 
-               return temp.join("")
+               return temp.join
        end
 end
 
index d38a7a1..422c051 100644 (file)
@@ -94,9 +94,9 @@ class JavaType
                var name
                if is_primitive_array then
                        # Primitive arrays have a special naming convention
-                       name = "Native" + extern_class_name.join("").capitalized + "Array"
+                       name = "Native" + extern_class_name.join.capitalized + "Array"
                else
-                       name = "Native" + extern_class_name.join("")
+                       name = "Native" + extern_class_name.join
                end
 
                var nit_type = new NitType(name)
index bfdf6a5..83fa3b8 100644 (file)
@@ -112,7 +112,7 @@ abstract class LinkedText
                var text = self["text"]
 
                if text isa JsonArray then
-                       return text.join("")
+                       return text.join
                else
                        return "UNDEFINED"
                end
index 62dee9c..8257091 100644 (file)
@@ -151,7 +151,7 @@ class Nitiwiki
                path = path.simplify_path
                if entries.has_key(path) then return entries[path].as(WikiSection)
                var root = expand_path(config.root_dir, config.source_dir)
-               var name = path.basename("")
+               var name = path.basename
                var section = new WikiSection(self, name)
                entries[path] = section
                if path == root then return section
index 0bf39c0..116c91c 100644 (file)
@@ -23,7 +23,7 @@ redef class BasicBlock
        do
                var code_lines = new Array[String]
                for line in lines do code_lines.add(line.text)
-               var code = code_lines.join("")
+               var code = code_lines.join
 
                code = code.replace("\n","\\l").replace("\"","\\\"").replace("\\n","|n").replace("/","\\/").replace("\r","")
                # the last one is a hack
index a1ae476..acf50a0 100644 (file)
@@ -34,6 +34,6 @@ if args.not_empty then n = args.first.to_i
 for i in [0..10[ do
        var a = (['[', ']'] * n)
        a.shuffle
-       var b = a.join("")
+       var b = a.join
        if is_balanced(b) then print "{b} is well-balanced" else print "{b} is not well-balanced"
 end
index 77b2ed2..fd3ead4 100644 (file)
@@ -33,7 +33,7 @@ end
 
 var ary = "_###_##_#_#_#_#__#__".chars
 loop
-       print ary.join("")
+       print ary.join
        var nxt = evolve(ary)
        if ary == nxt then break
        ary = nxt
index b68623b..11c39bf 100644 (file)
@@ -165,7 +165,7 @@ class CurlHTTPRequest
                if not output_file_name == null then
                        opt_name = output_file_name
                else if not self.url.substring(self.url.length-1, self.url.length) == "/" then
-                       opt_name = self.url.basename("")
+                       opt_name = self.url.basename
                else
                        return answer_failure(0, "Unable to extract file name, please specify one")
                end
index ef080d4..9e6c8bc 100644 (file)
@@ -129,7 +129,7 @@ end
 class XMLDocument
        super XMLEntity
 
-       redef fun to_s do return children.join("")
+       redef fun to_s do return children.join
 end
 
 # PCDATA is any kind of non-xml formatted text
index 8291616..4d7ff2b 100644 (file)
@@ -45,7 +45,7 @@ private class LinuxStore
 
                # Find DB path
                var config_home = xdg_basedir.config_home.to_s
-               var config_dir = config_home.join_path(sys.program_name.basename(""))
+               var config_dir = config_home.join_path(sys.program_name.basename)
                if not config_dir.file_exists then config_dir.mkdir
                var db_path = config_dir.join_path(db_file)
 
index cc6711c..2a36c83 100644 (file)
@@ -366,7 +366,7 @@ class Path
        # var path = "/tmp/somefile".to_path
        # assert path.filename == "somefile"
        # ~~~
-       var filename: String = path.basename("") is lazy
+       var filename: String = path.basename is lazy
 
        # Does the file at `path` exists?
        fun exists: Bool do return stat != null
@@ -704,36 +704,51 @@ redef class String
        # Copy content of file at `self` to `dest`
        fun file_copy_to(dest: String) do to_path.copy(dest.to_path)
 
-       # Remove the trailing extension `ext`.
+       # Remove the trailing `extension`.
        #
-       # `ext` usually starts with a dot but could be anything.
+       # `extension` usually starts with a dot but could be anything.
        #
-       #     assert "file.txt".strip_extension(".txt")  == "file"
-       #     assert "file.txt".strip_extension("le.txt")  == "fi"
-       #     assert "file.txt".strip_extension("xt")  == "file.t"
+       #     assert "file.txt".strip_extension(".txt")   == "file"
+       #     assert "file.txt".strip_extension("le.txt") == "fi"
+       #     assert "file.txt".strip_extension("xt")     == "file.t"
        #
-       # if `ext` is not present, `self` is returned unmodified.
+       # If `extension == null`, the rightmost extension is stripped, including the last dot.
+       #
+       #     assert "file.txt".strip_extension           == "file"
+       #
+       # If `extension` is not present, `self` is returned unmodified.
        #
        #     assert "file.txt".strip_extension(".tar.gz")  == "file.txt"
-       fun strip_extension(ext: String): String
+       fun strip_extension(extension: nullable String): String
        do
-               if has_suffix(ext) then
-                       return substring(0, length - ext.length)
+               if extension == null then
+                       extension = file_extension
+                       if extension == null then
+                               return self
+                       else extension = ".{extension}"
+               end
+
+               if has_suffix(extension) then
+                       return substring(0, length - extension.length)
                end
                return self
        end
 
-       # Extract the basename of a path and remove the extension
+       # Extract the basename of a path and strip the `extension`
+       #
+       # The extension is stripped only if `extension != null`.
        #
-       #     assert "/path/to/a_file.ext".basename(".ext")         == "a_file"
-       #     assert "path/to/a_file.ext".basename(".ext")          == "a_file"
-       #     assert "path/to".basename(".ext")                     == "to"
-       #     assert "path/to/".basename(".ext")                    == "to"
+       #     assert "/path/to/a_file.ext".basename(".ext")     == "a_file"
+       #     assert "path/to/a_file.ext".basename(".ext")      == "a_file"
+       #     assert "path/to/a_file.ext".basename              == "a_file.ext"
+       #     assert "path/to".basename(".ext")                 == "to"
+       #     assert "path/to/".basename(".ext")                == "to"
+       #     assert "path/to".basename                         == "to"
        #     assert "path".basename("")                        == "path"
        #     assert "/path".basename("")                       == "path"
        #     assert "/".basename("")                           == "/"
        #     assert "".basename("")                            == ""
-       fun basename(ext: String): String
+       fun basename(extension: nullable String): String
        do
                var l = length - 1 # Index of the last char
                while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
@@ -743,7 +758,10 @@ redef class String
                if pos >= 0 then
                        n = substring(pos+1, l-pos)
                end
-               return n.strip_extension(ext)
+
+               if extension != null then
+                       return n.strip_extension(extension)
+               else return n
        end
 
        # Extract the dirname of a path
@@ -902,7 +920,7 @@ redef class String
        # In other cases, parts of the current directory may be exhibited:
        #
        #     var p = "../foo/bar".relpath("baz")
-       #     var c = getcwd.basename("")
+       #     var c = getcwd.basename
        #     assert p == "../../{c}/baz"
        #
        # For path resolution independent of the current directory (eg. for paths in URL),
index 93d613f..af45dab 100644 (file)
@@ -1598,11 +1598,14 @@ redef class Collection[E]
                return s.to_s
        end
 
-       # Concatenate and separate each elements with `sep`.
+       # Concatenate and separate each elements with `separator`.
        #
-       #     assert [1, 2, 3].join(":")         == "1:2:3"
-       #     assert [1..3].join(":")            == "1:2:3"
-       fun join(sep: Text): String
+       # Only concatenate if `separator == null`.
+       #
+       #     assert [1, 2, 3].join(":")    == "1:2:3"
+       #     assert [1..3].join(":")       == "1:2:3"
+       #     assert [1..3].join            == "123"
+       fun join(separator: nullable Text): String
        do
                if is_empty then return ""
 
@@ -1616,7 +1619,7 @@ redef class Collection[E]
                # Concat other items
                i.next
                while i.is_ok do
-                       s.append(sep)
+                       if separator != null then s.append(separator)
                        e = i.item
                        if e != null then s.append(e.to_s)
                        i.next
@@ -1626,15 +1629,15 @@ redef class Collection[E]
 end
 
 redef class Map[K,V]
-       # Concatenate couple of 'key value'.
-       # key and value are separated by `couple_sep`.
-       # each couple is separated each couple with `sep`.
+       # Concatenate couples of key value.
+       # Key and value are separated by `couple_sep`.
+       # Couples are separated by `sep`.
        #
-       #     var m = new ArrayMap[Int, String]
+       #     var m = new HashMap[Int, String]
        #     m[1] = "one"
        #     m[10] = "ten"
        #     assert m.join("; ", "=") == "1=one; 10=ten"
-       fun join(sep: String, couple_sep: String): String is abstract
+       fun join(sep, couple_sep: String): String is abstract
 end
 
 redef class Sys
index 50bbcd3..24bdf23 100644 (file)
@@ -142,7 +142,7 @@ class ExternCFile
        end
 
        redef fun makefile_rule_content do
-               var ff = filename.basename("")
+               var ff = filename.basename
                var o = makefile_rule_name
                var pkg = ""
                if not pkgconfigs.is_empty then
index 9601c1d..43686ae 100644 (file)
@@ -220,7 +220,7 @@ class MakefileToolchain
 
                # Copy original .[ch] files to compile_dir
                for src in compiler.files_to_copy do
-                       var basename = src.basename("")
+                       var basename = src.basename
                        var dst = "{compile_dir}/{basename}"
                        src.file_copy_to dst
                end
@@ -444,7 +444,7 @@ endif
                # Compile each required extern body into a specific .o
                for f in compiler.extern_bodies do
                        var o = f.makefile_rule_name
-                       var ff = f.filename.basename("")
+                       var ff = f.filename.basename
                        makefile.write("{o}: {ff}\n")
                        makefile.write("\t{f.makefile_rule_content}\n\n")
                        dep_rules.add(f.makefile_rule_name)
@@ -1598,12 +1598,12 @@ abstract class AbstractCompilerVisitor
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.declare_once("#include \"{tryfile.basename}\"")
                        self.compiler.files_to_copy.add(tryfile)
                end
                tryfile = file + "_nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.declare_once("#include \"{tryfile.basename}\"")
                        self.compiler.files_to_copy.add(tryfile)
                end
 
@@ -1614,7 +1614,7 @@ abstract class AbstractCompilerVisitor
                        tryfile = file + "_nit.c"
                        if not tryfile.file_exists then return
                end
-               var f = new ExternCFile(tryfile.basename(""), "")
+               var f = new ExternCFile(tryfile.basename, "")
                self.compiler.extern_bodies.add(f)
                self.compiler.files_to_copy.add(tryfile)
        end
index 7a5dec0..b96c600 100644 (file)
@@ -180,8 +180,8 @@ class ExternCppFile
 
        var mmodule: MModule
 
-       redef fun makefile_rule_name do return "{filename.basename("")}.o"
-       redef fun makefile_rule_content do return "$(CXX) $(CFLAGS) {mmodule.cppflags[""].join(" ")} -c {filename.basename("")} -o {filename.basename("")}.o"
+       redef fun makefile_rule_name do return "{filename.basename}.o"
+       redef fun makefile_rule_content do return "$(CXX) $(CFLAGS) {mmodule.cppflags[""].join(" ")} -c {filename.basename} -o {filename.basename}.o"
        redef fun compiles_to_o_file do return true
 end
 
index 71485cc..0e093a0 100644 (file)
@@ -97,7 +97,7 @@ redef class JavaLanguage
                var extra_java_files = mmodule.extra_java_files
                if extra_java_files != null then for file in extra_java_files do
                        var path = file.filename
-                       path.file_copy_to("{compdir}/{path.basename("")}")
+                       path.file_copy_to("{compdir}/{path.basename}")
                end
        end
 end
index c26fea2..da641a5 100644 (file)
@@ -362,7 +362,7 @@ class JavaFile
        super ExternFile
 
        redef fun makefile_rule_name do return "{filename.basename(".java")}.class"
-       redef fun makefile_rule_content do return "javac {filename.basename("")} -d ."
+       redef fun makefile_rule_content do return "javac {filename.basename} -d ."
        redef fun add_to_jar do return true
 end
 
@@ -606,7 +606,7 @@ redef class MMethod
                        else format.add "V"
                end
 
-               return format.join("")
+               return format.join
        end
 
        # Similar to `build_c_signature` but adapted to create the signature expected by JNI for C functions
index 4aafb91..7c293cf 100644 (file)
@@ -169,7 +169,7 @@ class ExternObjCFile
 
        redef fun makefile_rule_name do return "{filename.basename(".m")}_m.o"
        redef fun makefile_rule_content do
-               return "clang $(CFLAGS) -c {filename.basename("")} -o {makefile_rule_name}"
+               return "clang $(CFLAGS) -c {filename.basename} -o {makefile_rule_name}"
        end
        redef fun compiles_to_o_file do return true
 end
index 5d20c9c..4aaa72d 100644 (file)
@@ -431,7 +431,7 @@ redef class ModelBuilder
                        if pn == "src" then
                                # With a src directory, the group name is the name of the parent directory
                                dirpath2 = rdp.dirname
-                               pn = dirpath2.basename("")
+                               pn = dirpath2.basename
                        else
                                # Check a `src` subdirectory
                                dirpath = dirpath2 / "src"
index 83c4c6c..2a416ef 100644 (file)
@@ -152,7 +152,7 @@ for mmodule in mmodules do
        else if module_path.has_suffix(".nit") then
                module_name = module_path.basename(".nit")
        else
-               module_name = module_path.basename("")
+               module_name = module_path.basename
                module_path += ".nit"
        end
 
index 6627d3e..f001cd3 100644 (file)
@@ -109,7 +109,7 @@ class AndroidToolchain
 
                # Gather extra C files generated elsewhere than in super
                for f in compiler.extern_bodies do
-                       if f isa ExternCFile then cfiles.add(f.filename.basename(""))
+                       if f isa ExternCFile then cfiles.add(f.filename.basename)
                end
 
                # Is there an icon?
@@ -134,7 +134,7 @@ class AndroidToolchain
                        var extra_java_files = mmodule.extra_java_files
                        if extra_java_files != null then for file in extra_java_files do
                                var path = file.filename
-                               path.file_copy_to(dir/path.basename(""))
+                               path.file_copy_to(dir/path.basename)
                        end
                end
 
index 77564f1..9972ea6 100644 (file)
@@ -83,7 +83,7 @@ private class IOSToolchain
                ## Register all source files
                for file in cfiles do pbx.add_file new PbxFile(file)
                for file in compiler.extern_bodies do
-                       pbx.add_file new PbxFile(file.filename.basename(""))
+                       pbx.add_file new PbxFile(file.filename.basename)
                end
 
                ## TODO Register asset files
index 8136187..f994c45 100644 (file)
@@ -56,7 +56,7 @@ class PnaclToolchain
 
                # Gather extra C files generated elsewhere than in super
                for f in compiler.extern_bodies do
-                       if f isa ExternCFile then cfiles.add(f.filename.basename(""))
+                       if f isa ExternCFile then cfiles.add(f.filename.basename)
                end
 
                # Outname
index 4468d91..47366b3 100644 (file)
@@ -515,7 +515,7 @@ The Nit language documentation and the source code of its tools and libraries ma
                if opt_set_dummy_tool.value then
                        return "DUMMY_TOOL"
                end
-               return sys.program_name.basename("")
+               return sys.program_name.basename
        end
 
        # The identified root directory of the Nit project
index 106e498..1264a67 100644 (file)
@@ -49,4 +49,4 @@ printn("The value of a is: " + a.to_s + ".\n")
 # Fiveth way: Join arrays.
 # Pro: Sometime efficient on complex concatenation.
 # Con: Crazy.
-printn(["The value of a is: ", a.to_s, ".\n"].join(""))
+printn(["The value of a is: ", a.to_s, ".\n"].join)