diff --git a/src/char.cr b/src/char.cr index 1c7666b961f6..5ce20fd15822 100644 --- a/src/char.cr +++ b/src/char.cr @@ -61,7 +61,7 @@ struct Char # 'b' - 'a' # => 1 # 'c' - 'a' # => 2 # ``` - def -(other : Char) + def -(other : Char) : Int32 ord - other.ord end @@ -70,7 +70,7 @@ struct Char # ``` # 'f' + "oo" # => "foo" # ``` - def +(str : String) + def +(str : String) : String bytesize = str.bytesize + self.bytesize String.new(bytesize) do |buffer| count = 0 @@ -142,7 +142,7 @@ struct Char # Returns `true` if this char is an ASCII character # (codepoint is in (0..127)) - def ascii? + def ascii? : Bool ord < 128 end @@ -155,7 +155,7 @@ struct Char # 'z'.ascii_number? # => false # 'z'.ascii_number?(36) # => true # ``` - def ascii_number?(base : Int = 10) + def ascii_number?(base : Int = 10) : Bool !!to_i?(base) end @@ -165,7 +165,7 @@ struct Char # '1'.number? # => true # 'a'.number? # => false # ``` - def number? + def number? : Bool ascii? ? ascii_number? : Unicode.number?(self) end @@ -177,7 +177,7 @@ struct Char # 'G'.ascii_lowercase? # => false # '.'.ascii_lowercase? # => false # ``` - def ascii_lowercase? + def ascii_lowercase? : Bool 'a' <= self <= 'z' end @@ -189,7 +189,7 @@ struct Char # 'G'.lowercase? # => false # '.'.lowercase? # => false # ``` - def lowercase? + def lowercase? : Bool ascii? ? ascii_lowercase? : Unicode.lowercase?(self) end @@ -201,7 +201,7 @@ struct Char # 'c'.ascii_uppercase? # => false # '.'.ascii_uppercase? # => false # ``` - def ascii_uppercase? + def ascii_uppercase? : Bool 'A' <= self <= 'Z' end @@ -213,7 +213,7 @@ struct Char # 'c'.uppercase? # => false # '.'.uppercase? # => false # ``` - def uppercase? + def uppercase? : Bool ascii? ? ascii_uppercase? : Unicode.uppercase?(self) end @@ -224,7 +224,7 @@ struct Char # 'á'.ascii_letter? # => false # '8'.ascii_letter? # => false # ``` - def ascii_letter? + def ascii_letter? : Bool ascii_lowercase? || ascii_uppercase? end @@ -235,7 +235,7 @@ struct Char # 'á'.letter? # => true # '8'.letter? # => false # ``` - def letter? + def letter? : Bool ascii? ? ascii_letter? : Unicode.letter?(self) end @@ -246,7 +246,7 @@ struct Char # '8'.ascii_alphanumeric? # => true # '.'.ascii_alphanumeric? # => false # ``` - def ascii_alphanumeric? + def ascii_alphanumeric? : Bool ascii_letter? || ascii_number? end @@ -257,7 +257,7 @@ struct Char # '8'.alphanumeric? # => true # '.'.alphanumeric? # => false # ``` - def alphanumeric? + def alphanumeric? : Bool letter? || number? end @@ -268,7 +268,7 @@ struct Char # '\t'.ascii_whitespace? # => true # 'b'.ascii_whitespace? # => false # ``` - def ascii_whitespace? + def ascii_whitespace? : Bool self == ' ' || 9 <= ord <= 13 end @@ -279,7 +279,7 @@ struct Char # '\t'.whitespace? # => true # 'b'.whitespace? # => false # ``` - def whitespace? + def whitespace? : Bool ascii? ? ascii_whitespace? : Unicode.whitespace?(self) end @@ -291,7 +291,7 @@ struct Char # 'F'.hex? # => true # 'g'.hex? # => false # ``` - def hex? + def hex? : Bool ascii_number? 16 end @@ -322,7 +322,7 @@ struct Char # '\\'.in_set? "\\A" # => false # '\\'.in_set? "X-\\w" # => true # ``` - def in_set?(*sets : String) + def in_set?(*sets : String) : Bool if sets.size > 1 return sets.all? { |set| in_set?(set) } end @@ -388,7 +388,7 @@ struct Char # 'x'.downcase # => 'x' # '.'.downcase # => '.' # ``` - def downcase(options = Unicode::CaseOptions::None) + def downcase(options = Unicode::CaseOptions::None) : Char Unicode.downcase(self, options) end @@ -415,7 +415,7 @@ struct Char # 'X'.upcase # => 'X' # '.'.upcase # => '.' # ``` - def upcase(options = Unicode::CaseOptions::None) + def upcase(options = Unicode::CaseOptions::None) : Char Unicode.upcase(self, options) end @@ -446,7 +446,7 @@ struct Char # ``` # # This method allows creating a `Range` of chars. - def succ + def succ : Char (ord + 1).chr end @@ -456,7 +456,7 @@ struct Char # 'b'.pred # => 'a' # 'ぃ'.pred # => 'あ' # ``` - def pred + def pred : Char (ord - 1).chr end @@ -471,17 +471,17 @@ struct Char # char.control? # => true # end # ``` - def ascii_control? + def ascii_control? : Bool ord < 0x20 || (0x7F <= ord <= 0x9F) end # Returns `true` if this char is a control character according to unicode. - def control? + def control? : Bool ascii? ? ascii_control? : Unicode.control?(self) end # Returns `true` if this is char is a mark character according to unicode. - def mark? + def mark? : Bool Unicode.mark?(self) end @@ -521,7 +521,7 @@ struct Char # 'あ'.dump # => "'\\u{3042}'" # '\u0012'.dump # => "'\\u{12}'" # ``` - def dump + def dump : String dump_or_inspect do |io| if ascii_control? || ord >= 0x80 io << "\\u{" @@ -637,7 +637,7 @@ struct Char # '8'.to_f # => 8.0 # 'c'.to_f # raises ArgumentError # ``` - def to_f + def to_f : Float64 to_f64 end @@ -649,27 +649,27 @@ struct Char # '8'.to_f? # => 8.0 # 'c'.to_f? # => nil # ``` - def to_f? + def to_f? : Float64? to_f64? end # See also: `to_f`. - def to_f32 + def to_f32 : Float32 to_i.to_f32 end # See also: `to_f?`. - def to_f32? + def to_f32? : Float32? to_i?.try &.to_f32 end # Same as `to_f`. - def to_f64 + def to_f64 : Float64 to_i.to_f64 end # Same as `to_f?`. - def to_f64? + def to_f64? : Float64? to_i?.try &.to_f64 end @@ -732,7 +732,7 @@ struct Char # 'a'.bytesize # => 1 # '好'.bytesize # => 3 # ``` - def bytesize + def bytesize : Int32 # See http://en.wikipedia.org/wiki/UTF-8#Sample_code c = ord @@ -759,7 +759,7 @@ struct Char # 'a'.bytes # => [97] # 'あ'.bytes # => [227, 129, 130] # ``` - def bytes + def bytes : Array(UInt8) bytes = [] of UInt8 each_byte do |byte| bytes << byte diff --git a/src/char/reader.cr b/src/char/reader.cr index a9dbfb3bd54c..00a848632742 100644 --- a/src/char/reader.cr +++ b/src/char/reader.cr @@ -82,7 +82,7 @@ struct Char # reader.has_next? # => true # reader.peek_next_char # => '\0' # ``` - def has_next? + def has_next? : Bool !@end end @@ -94,7 +94,7 @@ struct Char # reader = Char::Reader.new("ab") # reader.next_char # => 'b' # ``` - def next_char + def next_char : Char @pos += @current_char_width if @pos > @string.bytesize raise IndexError.new @@ -113,7 +113,7 @@ struct Char # reader.peek_next_char # => 'b' # reader.current_char # => 'a' # ``` - def peek_next_char + def peek_next_char : Char next_pos = @pos + @current_char_width if next_pos > @string.bytesize @@ -127,7 +127,7 @@ struct Char # Returns `true` if there are characters before # the current one. - def has_previous? + def has_previous? : Bool @pos > 0 end diff --git a/src/int.cr b/src/int.cr index 3e3781370fae..a34f1499b167 100644 --- a/src/int.cr +++ b/src/int.cr @@ -67,7 +67,7 @@ struct Int # ``` # 97.chr # => 'a' # ``` - def chr + def chr : Char unless 0 <= self <= Char::MAX_CODEPOINT raise ArgumentError.new("#{self} out of char range") end diff --git a/src/levenshtein.cr b/src/levenshtein.cr index 6137cbe49690..deefe6b7d933 100644 --- a/src/levenshtein.cr +++ b/src/levenshtein.cr @@ -82,7 +82,7 @@ module Levenshtein end end - def best_match + def best_match : String? @best_entry.try &.value end @@ -92,7 +92,7 @@ module Levenshtein sn.best_match end - def self.find(name, all_names, tolerance = nil) + def self.find(name, all_names, tolerance = nil) : String? find(name, tolerance) do |similar| all_names.each do |a_name| similar.test(a_name) diff --git a/src/regex.cr b/src/regex.cr index d02742adb961..cc4d13e5e852 100644 --- a/src/regex.cr +++ b/src/regex.cr @@ -267,7 +267,7 @@ class Regex # Regex.error?("(foo|bar)") # => nil # Regex.error?("(foo|bar") # => "missing ) at 8" # ``` - def self.error?(source) + def self.error?(source) : String? re = LibPCRE.compile(source, (Options::UTF_8 | Options::NO_UTF8_CHECK | Options::DUPNAMES), out errptr, out erroffset, nil) if re nil @@ -368,7 +368,7 @@ class Regex # re.match("Skiing") # => Regex::MatchData("Skiing") # re.match("sledding") # => Regex::MatchData("sledding") # ``` - def +(other) + def +(other) : Regex Regex.union(self, other) end @@ -421,7 +421,7 @@ class Regex # /at/ =~ "input data" # => 7 # /ax/ =~ "input data" # => nil # ``` - def =~(other : String) + def =~(other : String) : Int32? match = self.match(other) $~ = match match.try &.begin(0) diff --git a/src/regex/match_data.cr b/src/regex/match_data.cr index 0bd6a089facf..33db7b44b5e9 100644 --- a/src/regex/match_data.cr +++ b/src/regex/match_data.cr @@ -50,7 +50,7 @@ class Regex # "Crystal".match(/r(ys)/).not_nil!.size # => 2 # "Crystal".match(/r(ys)(?ta)/).not_nil!.size # => 3 # ``` - def size + def size : Int32 group_size + 1 end @@ -92,7 +92,7 @@ class Regex # "Crystal".match(/r(ys)/).not_nil!.byte_begin(1) # => 2 # "クリスタル".match(/リ(ス)/).not_nil!.byte_begin(0) # => 3 # ``` - def byte_begin(n = 0) + def byte_begin(n = 0) : Int32 check_index_out_of_bounds n n += size if n < 0 @ovector[n * 2] @@ -108,7 +108,7 @@ class Regex # "Crystal".match(/r(ys)/).not_nil!.byte_end(1) # => 4 # "クリスタル".match(/リ(ス)/).not_nil!.byte_end(0) # => 9 # ``` - def byte_end(n = 0) + def byte_end(n = 0) : Int32 check_index_out_of_bounds n n += size if n < 0 @ovector[n * 2 + 1] @@ -124,7 +124,7 @@ class Regex # "Crystal".match(/r(ys)/).not_nil![1]? # => "ys" # "Crystal".match(/r(ys)/).not_nil![2]? # => nil # ``` - def []?(n : Int) + def []?(n : Int) : String? return unless valid_group?(n) n += size if n < 0 @@ -141,7 +141,7 @@ class Regex # "Crystal".match(/r(ys)/).not_nil![1] # => "ys" # "Crystal".match(/r(ys)/).not_nil![2] # raises IndexError # ``` - def [](n : Int) + def [](n : Int) : String check_index_out_of_bounds n n += size if n < 0 @@ -164,7 +164,7 @@ class Regex # ``` # "Crystal".match(/(?Cr).*(?al)/).not_nil!["ok"]? # => "al" # ``` - def []?(group_name : String) + def []?(group_name : String) : String? max_start = -1 match = nil named_capture_number(group_name) do |n| @@ -191,7 +191,7 @@ class Regex # ``` # "Crystal".match(/(?Cr).*(?al)/).not_nil!["ok"] # => "al" # ``` - def [](group_name : String) + def [](group_name : String) : String match = self[group_name]? unless match named_capture_number(group_name) do @@ -203,23 +203,23 @@ class Regex end # Returns all matches that are within the given range. - def [](range : Range) + def [](range : Range) : Array(String) self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] end # Like `#[](Range)`, but returns `nil` if the range's start is out of range. - def []?(range : Range) + def []?(range : Range) : Array(String)? self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]? end # Returns count or less (if there aren't enough) matches starting at the # given start index. - def [](start : Int, count : Int) + def [](start : Int, count : Int) : Array(String) self[start, count]? || raise IndexError.new end # Like `#[](Int, Int)` but returns `nil` if the *start* index is out of range. - def []?(start : Int, count : Int) + def []?(start : Int, count : Int) : Array(String)? raise ArgumentError.new "Negative count: #{count}" if count < 0 return Array(String).new if start == size @@ -253,7 +253,7 @@ class Regex # ``` # "Crystal".match(/yst/).not_nil!.pre_match # => "Cr" # ``` - def pre_match + def pre_match : String @string.byte_slice(0, byte_begin(0)) end @@ -263,7 +263,7 @@ class Regex # ``` # "Crystal".match(/yst/).not_nil!.post_match # => "al" # ``` - def post_match + def post_match : String @string.byte_slice(byte_end(0)) end @@ -280,7 +280,7 @@ class Regex # match = "Crystal".match(/(Cr)(stal)?/).not_nil! # match.captures # => ["Cr", nil] # ``` - def captures + def captures : Array(String?) name_table = @regex.name_table caps = [] of String? @@ -302,7 +302,7 @@ class Regex # match = "Crystal".match(/(?Cr)(?stal)?/).not_nil! # match.named_captures # => {"name1" => "Cr", "name2" => nil} # ``` - def named_captures + def named_captures : Hash(String, String?) name_table = @regex.name_table caps = {} of String => String? @@ -326,7 +326,7 @@ class Regex # match = "Crystal".match(/(Cr)(?stal)?/).not_nil! # match.to_a # => ["Cr", "Cr", nil] # ``` - def to_a + def to_a : Array(String?) (0...size).map { |i| self[i]? } end @@ -341,7 +341,7 @@ class Regex # match = "Crystal".match(/(Cr)(?stal)?/).not_nil! # match.to_h # => {0 => "Cr", 1 => "Cr", "name1" => nil} # ``` - def to_h + def to_h : Hash(Int32 | String, String?) name_table = @regex.name_table hash = {} of (String | Int32) => String? diff --git a/src/string.cr b/src/string.cr index 2d31c0dbfaad..2750bb036e00 100644 --- a/src/string.cr +++ b/src/string.cr @@ -285,7 +285,7 @@ class String # "hello".bytesize # => 5 # "你好".bytesize # => 6 # ``` - def bytesize + def bytesize : Int32 @bytesize end @@ -657,7 +657,7 @@ class String end # :ditto: - def to_f64(whitespace : Bool = true, strict : Bool = true) + def to_f64(whitespace : Bool = true, strict : Bool = true) : Float64 to_f64?(whitespace: whitespace, strict: strict) || raise ArgumentError.new("Invalid Float64: #{self}") end @@ -682,7 +682,7 @@ class String end # :ditto: - def to_f64?(whitespace : Bool = true, strict : Bool = true) + def to_f64?(whitespace : Bool = true, strict : Bool = true) : Float64? to_f_impl(whitespace: whitespace, strict: strict) do v = LibC.strtod self, out endptr {v, endptr} @@ -763,7 +763,7 @@ class String # "hello"[-2] # => 'l' # "hello"[5] # raises IndexError # ``` - def [](index : Int) + def [](index : Int) : Char char_at(index) { raise IndexError.new } end @@ -815,7 +815,7 @@ class String # s[-2..-4] # => "" # s[-2..1] # => "" # s[3..-4] # => "" - # ``` + # ``` : String def [](range : Range) : String self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] end @@ -865,7 +865,7 @@ class String end end - def []?(index : Int) + def []?(index : Int) : Char? char_at(index) { nil } end @@ -873,11 +873,11 @@ class String includes?(str) ? str : nil end - def []?(regex : Regex) + def []?(regex : Regex) : String? self[regex, 0]? end - def []?(regex : Regex, group) + def []?(regex : Regex, group) : String? match = match(regex) match[group]? if match end @@ -886,11 +886,11 @@ class String self[str]?.not_nil! end - def [](regex : Regex) + def [](regex : Regex) : String self[regex]?.not_nil! end - def [](regex : Regex, group) + def [](regex : Regex, group) : String self[regex, group]?.not_nil! end @@ -957,7 +957,7 @@ class String # ``` # # Raises `IndexError` if any index is outside the bounds of this string. - def delete_at(range : Range) + def delete_at(range : Range) : String delete_at(*Indexable.range_to_index_and_count(range, size) || raise IndexError.new) end @@ -1435,7 +1435,7 @@ class String # "string".chomp # => "string" # "x".chomp.chomp # => "x" # ``` - def chomp + def chomp : String return self if empty? case to_unsafe[bytesize - 1] @@ -1459,7 +1459,7 @@ class String # "hello".chomp('o') # => "hell" # "hello".chomp('a') # => "hello" # ``` - def chomp(suffix : Char) + def chomp(suffix : Char) : String if suffix == '\n' chomp elsif ends_with?(suffix) @@ -1476,7 +1476,7 @@ class String # "hello".chomp("llo") # => "he" # "hello".chomp("ol") # => "hello" # ``` - def chomp(suffix : String) + def chomp(suffix : String) : String if suffix.bytesize == 1 chomp(suffix.to_unsafe[0].unsafe_chr) elsif ends_with?(suffix) @@ -1696,7 +1696,7 @@ class String # "abcd".insert(5, 'X') # raises IndexError # "abcd".insert(-6, 'X') # raises IndexError # ``` - def insert(index : Int, other : Char) + def insert(index : Int, other : Char) : String index = index.to_i index += size + 1 if index < 0 @@ -1727,7 +1727,7 @@ class String # "abcd".insert(5, "FOO") # raises IndexError # "abcd".insert(-6, "FOO") # raises IndexError # ``` - def insert(index : Int, other : String) + def insert(index : Int, other : String) : String index = index.to_i index += size + 1 if index < 0 @@ -1757,7 +1757,7 @@ class String # " hello ".strip # => "hello" # "\tgoodbye\r\n".strip # => "goodbye" # ``` - def strip + def strip : String excess_left = calc_excess_left if excess_left == bytesize return "" @@ -1772,7 +1772,7 @@ class String # ``` # "aaabcdaaa".strip('a') # => "bcd" # ``` - def strip(char : Char) + def strip(char : Char) : String return self if empty? excess_left = calc_excess_left(char) @@ -1791,7 +1791,7 @@ class String # ``` # "abcdefcba".strip("abc") # => "def" # ``` - def strip(chars : String) + def strip(chars : String) : String return self if empty? case chars.size @@ -1834,7 +1834,7 @@ class String # " hello ".rstrip # => " hello" # "\tgoodbye\r\n".rstrip # => "\tgoodbye" # ``` - def rstrip + def rstrip : String remove_excess_right(calc_excess_right) end @@ -1843,7 +1843,7 @@ class String # ``` # "aaabcdaaa".rstrip('a') # => "aaabcd" # ``` - def rstrip(char : Char) + def rstrip(char : Char) : String return self if empty? remove_excess_right(calc_excess_right(char)) @@ -1856,7 +1856,7 @@ class String # ``` # "abcdefcba".rstrip("abc") # => "abcdef" # ``` - def rstrip(chars : String) + def rstrip(chars : String) : String return self if empty? case chars.size @@ -1888,7 +1888,7 @@ class String # " hello ".lstrip # => "hello " # "\tgoodbye\r\n".lstrip # => "goodbye\r\n" # ``` - def lstrip + def lstrip : String remove_excess_left(calc_excess_left) end @@ -1897,7 +1897,7 @@ class String # ``` # "aaabcdaaa".lstrip('a') # => "bcdaaa" # ``` - def lstrip(char : Char) + def lstrip(char : Char) : String return self if empty? remove_excess_left(calc_excess_left(char)) @@ -1910,7 +1910,7 @@ class String # ``` # "bcadefcba".lstrip("abc") # => "defcba" # ``` - def lstrip(chars : String) + def lstrip(chars : String) : String return self if empty? case chars.size @@ -2048,7 +2048,7 @@ class String # "aabbcc".tr("abc", "x") # => "xxxxxx" # "aabbcc".tr("a", "xyz") # => "xxbbcc" # ``` - def tr(from : String, to : String) + def tr(from : String, to : String) : String return delete(from) if to.empty? if from.bytesize == 1 @@ -2118,7 +2118,7 @@ class String # "hello".sub('l', "lo") # => "helolo" # "hello world".sub('o', 'a') # => "hella world" # ``` - def sub(char : Char, replacement) + def sub(char : Char, replacement) : String if includes?(char) String.build(bytesize) do |buffer| reader = Char::Reader.new(self) @@ -2190,7 +2190,7 @@ class String # # Raises `IndexError` if a named group referenced in *replacement* is not present # in *pattern*. - def sub(pattern : Regex, replacement, backreferences = true) + def sub(pattern : Regex, replacement, backreferences = true) : String if backreferences && replacement.is_a?(String) && replacement.has_back_references? sub_append(pattern) { |_, match, buffer| scan_backreferences(replacement, match, buffer) } else @@ -2206,7 +2206,7 @@ class String # "hello".sub(/(he|l|o)/, {"he": "ha", "l": "la"}) # => "hallo" # "hello".sub(/(he|l|o)/, {"l": "la"}) # => "hello" # ``` - def sub(pattern : Regex, hash : Hash(String, _) | NamedTuple) + def sub(pattern : Regex, hash : Hash(String, _) | NamedTuple) : String sub(pattern) do |match| if hash.has_key?(match) hash[match] @@ -2222,7 +2222,7 @@ class String # ``` # "hello yellow".sub("ll", "dd") # => "heddo yellow" # ``` - def sub(string : String, replacement) + def sub(string : String, replacement) : String sub(string) { replacement } end @@ -2249,7 +2249,7 @@ class String # ``` # "hello".sub({'a' => 'b', 'l' => 'd'}) # => "hedlo" # ``` - def sub(hash : Hash(Char, _)) + def sub(hash : Hash(Char, _)) : String return self if empty? String.build(bytesize) do |buffer| @@ -2292,7 +2292,7 @@ class String # ``` # "hello".sub(1, 'a') # => "hallo" # ``` - def sub(index : Int, replacement : Char) + def sub(index : Int, replacement : Char) : String sub_index(index.to_i, replacement) do |buffer| replacement.each_byte do |byte| buffer.value = byte @@ -2308,7 +2308,7 @@ class String # ``` # "hello".sub(1, "eee") # => "heeello" # ``` - def sub(index : Int, replacement : String) + def sub(index : Int, replacement : String) : String sub_index(index.to_i, replacement) do |buffer| buffer.copy_from(replacement.to_unsafe, replacement.bytesize) buffer += replacement.bytesize @@ -2342,7 +2342,7 @@ class String # ``` # "hello".sub(1..2, 'a') # => "halo" # ``` - def sub(range : Range, replacement : Char) + def sub(range : Range, replacement : Char) : String sub_range(range, replacement) do |buffer, from_index, to_index| replacement.each_byte do |byte| buffer.value = byte @@ -2358,7 +2358,7 @@ class String # ``` # "hello".sub(1..2, "eee") # => "heeelo" # ``` - def sub(range : Range, replacement : String) + def sub(range : Range, replacement : String) : String sub_range(range, replacement) do |buffer| buffer.copy_from(replacement.to_unsafe, replacement.bytesize) buffer += replacement.bytesize @@ -2468,7 +2468,7 @@ class String # "hello".gsub('l', "lo") # => "heloloo" # "hello world".gsub('o', 'a') # => "hella warld" # ``` - def gsub(char : Char, replacement) + def gsub(char : Char, replacement) : String if replacement.is_a?(String) && replacement.bytesize == 1 return gsub(char, replacement.unsafe_byte_at(0).unsafe_chr) end @@ -2548,7 +2548,7 @@ class String # # Raises `IndexError` if a named group referenced in *replacement* is not present # in *pattern*. - def gsub(pattern : Regex, replacement, backreferences = true) + def gsub(pattern : Regex, replacement, backreferences = true) : String if backreferences && replacement.is_a?(String) && replacement.has_back_references? gsub_append(pattern) { |_, match, buffer| scan_backreferences(replacement, match, buffer) } else @@ -2566,7 +2566,7 @@ class String # # but "o" is not and so is not included # "hello".gsub(/(he|l|o)/, {"he": "ha", "l": "la"}) # => "halala" # ``` - def gsub(pattern : Regex, hash : Hash(String, _) | NamedTuple) + def gsub(pattern : Regex, hash : Hash(String, _) | NamedTuple) : String gsub(pattern) do |match| hash[match]? end @@ -2578,7 +2578,7 @@ class String # ``` # "hello yellow".gsub("ll", "dd") # => "heddo yeddow" # ``` - def gsub(string : String, replacement) + def gsub(string : String, replacement) : String if string.bytesize == 1 gsub(string.unsafe_byte_at(0).unsafe_chr, replacement) else @@ -2627,7 +2627,7 @@ class String # ``` # "hello".gsub({'e' => 'a', 'l' => 'd'}) # => "haddo" # ``` - def gsub(hash : Hash(Char, _)) + def gsub(hash : Hash(Char, _)) : String gsub do |char| hash[char]? || char end @@ -2639,7 +2639,7 @@ class String # ``` # "hello".gsub({e: 'a', l: 'd'}) # => "haddo" # ``` - def gsub(tuple : NamedTuple) + def gsub(tuple : NamedTuple) : String gsub do |char| tuple[char.to_s]? || char end @@ -2697,14 +2697,14 @@ class String # ``` # "aabbcc".count('a') # => 2 # ``` - def count(other : Char) + def count(other : Char) : Int32 count { |char| char == other } end # Sets should be a list of strings following the rules # described at `Char#in_set?`. Returns the number of characters # in this string that match the given set. - def count(*sets) + def count(*sets) : Int32 count { |char| char.in_set?(*sets) } end @@ -2728,7 +2728,7 @@ class String # ``` # "aabbcc".delete('b') # => "aacc" # ``` - def delete(char : Char) + def delete(char : Char) : String delete { |my_char| my_char == char } end @@ -2739,7 +2739,7 @@ class String # ``` # "aabbccdd".delete("a-c") # => "dd" # ``` - def delete(*sets) + def delete(*sets) : String delete { |char| char.in_set?(*sets) } end @@ -2767,7 +2767,7 @@ class String # ``` # "a bbb".squeeze(' ') # => "a bbb" # ``` - def squeeze(char : Char) + def squeeze(char : Char) : String squeeze { |my_char| char == my_char } end @@ -2782,7 +2782,7 @@ class String # "aaabbbcccddd".squeeze("b-d") # => "aaabcd" # "a bbb".squeeze # => "a b" # ``` - def squeeze(*sets : String) + def squeeze(*sets : String) : String squeeze { |char| char.in_set?(*sets) } end @@ -2792,12 +2792,12 @@ class String # ``` # "a bbb".squeeze # => "a b" # ``` - def squeeze + def squeeze : String squeeze { true } end # Returns `true` if this is the empty string, `""`. - def empty? + def empty? : Bool bytesize == 0 end @@ -2808,7 +2808,7 @@ class String # " ".blank? # => true # " a ".blank? # => false # ``` - def blank? + def blank? : Bool each_char do |char| return false unless char.whitespace? end @@ -2947,7 +2947,7 @@ class String # # "Haystack" =~ 45 # => nil # ``` - def =~(regex : Regex) + def =~(regex : Regex) : Int32? match = regex.match(self) $~ = match match.try &.begin(0) @@ -2964,7 +2964,7 @@ class String # "abc" + "def" # => "abcdef" # "abc" + 'd' # => "abcd" # ``` - def +(other : self) + def +(other : self) : String return self if other.empty? return other if self.empty? @@ -2982,7 +2982,7 @@ class String end # :ditto: - def +(char : Char) + def +(char : Char) : String bytes, count = String.char_bytes_and_bytesize(char) size = bytesize + count String.new(size) do |buffer| @@ -3003,7 +3003,7 @@ class String # "Developers! " * 4 # # => "Developers! Developers! Developers! Developers! " # ``` - def *(times : Int) + def *(times : Int) : String raise ArgumentError.new "Negative argument" if times < 0 if times == 0 || bytesize == 0 @@ -3056,7 +3056,7 @@ class String # "Hello, World".index(/[ ]+/) # => 6 # "Hello, World".index(/\d+/) # => nil # ``` - def index(search : Char, offset = 0) + def index(search : Char, offset = 0) : Int32? # If it's ASCII we can delegate to slice if search.ascii? && single_byte_optimizable? return to_slice.index(search.ord.to_u8, offset) @@ -3075,7 +3075,7 @@ class String end # :ditto: - def index(search : String, offset = 0) + def index(search : String, offset = 0) : Int32? offset += size if offset < 0 return if offset < 0 @@ -3134,7 +3134,7 @@ class String end # :ditto: - def index(search : Regex, offset = 0) + def index(search : Regex, offset = 0) : Int32? offset += size if offset < 0 return nil unless 0 <= offset <= size @@ -3151,7 +3151,7 @@ class String # "Hello, World".rindex("o", 5) # => 4 # "Hello, World".rindex("W", 2) # => nil # ``` - def rindex(search : Char, offset = size - 1) + def rindex(search : Char, offset = size - 1) : Int32? # If it's ASCII we can delegate to slice if search.ascii? && single_byte_optimizable? return to_slice.rindex(search.ord.to_u8, offset) @@ -3181,7 +3181,7 @@ class String end # :ditto: - def rindex(search : String, offset = size - search.size) + def rindex(search : String, offset = size - search.size) : Int32? offset += size if offset < 0 return if offset < 0 @@ -3234,7 +3234,7 @@ class String end # :ditto: - def rindex(search : Regex, offset = size) + def rindex(search : Regex, offset = size) : Int32? offset += size if offset < 0 return nil unless 0 <= offset <= size @@ -3456,7 +3456,7 @@ class String # # It is valid to pass `#bytesize` to *index*, and in this case the answer # will be the size of this string. - def byte_index_to_char_index(index) + def byte_index_to_char_index(index) : Int32? if single_byte_optimizable? return 0 <= index <= bytesize ? index : nil end @@ -3474,7 +3474,7 @@ class String # "Team".includes?('i') # => false # "Dysfunctional".includes?("fun") # => true # ``` - def includes?(search : Char | String) + def includes?(search : Char | String) : Bool !!index(search) end @@ -3493,7 +3493,7 @@ class String # old_pond.split # => ["Old", "pond", "a", "frog", "leaps", "in", "water's", "sound"] # old_pond.split(3) # => ["Old", "pond", "a frog leaps in\n water's sound\n"] # ``` - def split(limit : Int32? = nil) + def split(limit : Int32? = nil) : Array(String) ary = Array(String).new split(limit) do |string| ary << string @@ -3890,7 +3890,7 @@ class String end end - def lines(chomp = true) + def lines(chomp = true) : Array(String) lines = [] of String each_line(chomp: chomp) do |line| lines << line @@ -4077,7 +4077,7 @@ class String # "Argentina".reverse # => "anitnegrA" # "racecar".reverse # => "racecar" # ``` - def reverse + def reverse : String return self if bytesize <= 1 if single_byte_optimizable? @@ -4110,7 +4110,7 @@ class String # "Purple".ljust(8, '-') # => "Purple--" # "Aubergine".ljust(8) # => "Aubergine" # ``` - def ljust(len : Int, char : Char = ' ') + def ljust(len : Int, char : Char = ' ') : String just len, char, -1 end @@ -4134,7 +4134,7 @@ class String # "Purple".rjust(8, '-') # => "--Purple" # "Aubergine".rjust(8) # => "Aubergine" # ``` - def rjust(len : Int, char : Char = ' ') + def rjust(len : Int, char : Char = ' ') : String just len, char, 1 end @@ -4159,7 +4159,7 @@ class String # "Purple".center(9, '-') # => "-Purple--" # "Aubergine".center(8) # => "Aubergine" # ``` - def center(len : Int, char : Char = ' ') + def center(len : Int, char : Char = ' ') : String just len, char, 0 end @@ -4249,7 +4249,7 @@ class String # "ZZZ9999".succ # => "AAAA0000" # "***".succ # => "**+" # ``` - def succ + def succ : String return self if empty? chars = self.chars @@ -4345,7 +4345,7 @@ class String # Searches the string for instances of *pattern*, # returning an `Array` of `Regex::MatchData` for each match. - def scan(pattern : Regex) + def scan(pattern : Regex) : Array(Regex::MatchData) matches = [] of Regex::MatchData scan(pattern) do |match| matches << match @@ -4367,7 +4367,7 @@ class String # Searches the string for instances of *pattern*, # returning an array of the matched string for each match. - def scan(pattern : String) + def scan(pattern : String) : Array(String) matches = [] of String scan(pattern) do |match| matches << match @@ -4432,7 +4432,7 @@ class String # ``` # "ab☃".chars # => ['a', 'b', '☃'] # ``` - def chars + def chars : Array(Char) chars = Array(Char).new(@length > 0 ? @length : bytesize) each_char do |char| chars << char @@ -4478,7 +4478,7 @@ class String # ``` # # See also: `Char#ord`. - def codepoints + def codepoints : Array(Int32) codepoints = Array(Int32).new(@length > 0 ? @length : bytesize) each_codepoint do |codepoint| codepoints << codepoint @@ -4522,7 +4522,7 @@ class String # "hello".bytes # => [104, 101, 108, 108, 111] # "你好".bytes # => [228, 189, 160, 229, 165, 189] # ``` - def bytes + def bytes : Array(UInt8) Array.new(bytesize) { |i| to_unsafe[i] } end @@ -4802,7 +4802,7 @@ class String # "sum: %{one} + %{two} = %{three}" % {one: 1, two: 2, three: 1 + 2} # => "sum: 1 + 2 = 3" # "I have %s apples" % {apples: 4} # => "I have 4 apples" # ``` - def %(other) + def %(other) : String sprintf self, other end @@ -4817,7 +4817,7 @@ class String # "hello".size # => 5 # "你好".size # => 2 # ``` - def size + def size : Int32 if @length > 0 || @bytesize == 0 return @length end @@ -4832,7 +4832,7 @@ class String # "hello".ascii_only? # => true # "你好".ascii_only? # => false # ``` - def ascii_only? + def ascii_only? : Bool if @bytesize == size each_byte do |byte| return false unless byte < 0x80 @@ -4844,13 +4844,13 @@ class String end # :nodoc: - def single_byte_optimizable? + def single_byte_optimizable? : Bool @bytesize == size end # Returns `true` if this String is encoded correctly # according to the UTF-8 encoding. - def valid_encoding? + def valid_encoding? : Bool reader = Char::Reader.new(self) while reader.has_next? return false if reader.error @@ -4948,7 +4948,7 @@ class String end # :nodoc: - def size_known? + def size_known? : Bool @bytesize == 0 || @length > 0 end @@ -5034,7 +5034,7 @@ class String # Raises an `ArgumentError` if `self` has null bytes. Returns `self` otherwise. # # This method should sometimes be called before passing a `String` to a C function. - def check_no_null_byte(name = nil) + def check_no_null_byte(name = nil) : String if byte_index(0) name = "`#{name}` " if name raise ArgumentError.new("String #{name}contains null byte") @@ -5126,7 +5126,7 @@ class String # In this case the implementation just returns the same string. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(value : String) + def self.interpolation(value : String) : String value end @@ -5142,7 +5142,7 @@ class String # In this case the implementation just returns the result of calling `value.to_s`. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(value) + def self.interpolation(value) : String value.to_s end @@ -5158,7 +5158,7 @@ class String # In this case the implementation just does `value + char`. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(value : String, char : Char) + def self.interpolation(value : String, char : Char) : String value + char end @@ -5174,7 +5174,7 @@ class String # In this case the implementation just does `char + value`. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(char : Char, value : String) + def self.interpolation(char : Char, value : String) : String char + value end @@ -5192,7 +5192,7 @@ class String # it's a bit more performant than interpolating non-string values. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(*values : String) + def self.interpolation(*values : String) : String bytesize = values.sum(&.bytesize) size = if values.all?(&.size_known?) values.sum(&.size) @@ -5221,7 +5221,7 @@ class String # In this case the implementation will call `String.build` with the given values. # # NOTE: there should never be a need to call this method instead of using string interpolation. - def self.interpolation(*values : *T) forall T + def self.interpolation(*values : *T) : String forall T capacity = 0 {% for i in 0...T.size %} value{{i}} = values[{{i}}] diff --git a/src/string/builder.cr b/src/string/builder.cr index 788829b393a9..f1ef6bd53d92 100644 --- a/src/string/builder.cr +++ b/src/string/builder.cr @@ -64,17 +64,17 @@ class String::Builder < IO nil end - def buffer + def buffer : Pointer(UInt8) @buffer + String::HEADER_SIZE end - def empty? + def empty? : Bool @bytesize == 0 end # Chomps the last byte from the string buffer. # If the byte is `'\n'` and there's a `'\r'` before it, it is also removed. - def chomp!(byte : UInt8) + def chomp!(byte : UInt8) : self if bytesize > 0 && buffer[bytesize - 1] == byte back(1) @@ -87,7 +87,7 @@ class String::Builder < IO # Moves the write pointer, and the resulting string bytesize, # by the given *amount*. - def back(amount : Int) + def back(amount : Int) : Int32 unless 0 <= amount <= @bytesize raise ArgumentError.new "Invalid back amount" end diff --git a/src/string/formatter.cr b/src/string/formatter.cr index 8d33ddaa2a9e..69874d87183c 100644 --- a/src/string/formatter.cr +++ b/src/string/formatter.cr @@ -386,15 +386,15 @@ struct String::Formatter(A) @precision_size = 0 end - def left_padding? + def left_padding? : Bool @minus ? @width < 0 : @width > 0 end - def right_padding? + def right_padding? : Bool @minus ? @width > 0 : @width < 0 end - def padding_char + def padding_char : Char @zero ? '0' : ' ' end end diff --git a/src/string_pool.cr b/src/string_pool.cr index e02a707e59f0..16785d6272de 100644 --- a/src/string_pool.cr +++ b/src/string_pool.cr @@ -60,7 +60,7 @@ class StringPool # pool.get("crystal") # pool.empty? # => false # ``` - def empty? + def empty? : Bool @size == 0 end @@ -79,7 +79,7 @@ class StringPool # pool.get(slice) # pool.empty? # => false # ``` - def get(slice : Bytes) + def get(slice : Bytes) : String get slice.to_unsafe, slice.size end @@ -95,7 +95,7 @@ class StringPool # pool.get("hey".to_unsafe, 3) # pool.size # => 1 # ``` - def get(str : UInt8*, len) + def get(str : UInt8*, len) : String hash = hash(str, len) get(hash, str, len) end @@ -150,7 +150,7 @@ class StringPool # pool.get(io) # pool.empty? # => false # ``` - def get(str : IO::Memory) + def get(str : IO::Memory) : String get(str.buffer, str.bytesize) end @@ -168,7 +168,7 @@ class StringPool # pool.get(string) # pool.empty? # => false # ``` - def get(str : String) + def get(str : String) : String get(str.to_unsafe, str.bytesize) end diff --git a/src/string_scanner.cr b/src/string_scanner.cr index 5e9c42338ee7..b79725a9c354 100644 --- a/src/string_scanner.cr +++ b/src/string_scanner.cr @@ -72,7 +72,7 @@ class StringScanner end # Returns the current position of the scan offset. - def offset + def offset : Int32 @str.byte_index_to_char_index(@byte_offset).not_nil! end @@ -89,7 +89,7 @@ class StringScanner # s.scan(/\s\w+/) # => " string" # s.scan(/.*/) # => "" # ``` - def scan(pattern) + def scan(pattern) : String? match(pattern, advance: true, options: Regex::Options::ANCHORED) end @@ -105,7 +105,7 @@ class StringScanner # s.scan_until(/tr/) # => nil # s.scan_until(/g/) # => "ing" # ``` - def scan_until(pattern) + def scan_until(pattern) : String? match(pattern, advance: true, options: Regex::Options::None) end @@ -132,7 +132,7 @@ class StringScanner # # This method is the same as `#scan`, but without returning the matched # string. - def skip(pattern) + def skip(pattern) : Int32? match = scan(pattern) match.size if match end @@ -148,7 +148,7 @@ class StringScanner # # This method is the same as `#scan_until`, but without returning the matched # string. - def skip_until(pattern) + def skip_until(pattern) : Int32? match = scan_until(pattern) match.size if match end @@ -164,7 +164,7 @@ class StringScanner # s.check(/\w+/) # => "is" # s.check(/\w+/) # => "is" # ``` - def check(pattern) + def check(pattern) : String? match(pattern, advance: false, options: Regex::Options::ANCHORED) end @@ -178,7 +178,7 @@ class StringScanner # s.check_until(/tr/) # => "test str" # s.check_until(/g/) # => "test string" # ``` - def check_until(pattern) + def check_until(pattern) : String? match(pattern, advance: false, options: Regex::Options::None) end @@ -200,7 +200,7 @@ class StringScanner # s["month"] # => "Dec" # s["day"] # => "12" # ``` - def [](n) + def [](n) : String @last_match.not_nil![n] end @@ -226,7 +226,7 @@ class StringScanner # s.scan(/more/) # => nil # s[0]? # => nil # ``` - def []?(n) + def []?(n) : String? @last_match.try(&.[n]?) end @@ -240,7 +240,7 @@ class StringScanner # s.scan(/(\w+\s?){4}/) # => "this is a string" # s.eos? # => true # ``` - def eos? + def eos? : Bool @byte_offset >= @str.bytesize end @@ -257,13 +257,13 @@ class StringScanner end # Returns the string being scanned. - def string + def string : String @str end # Extracts a string corresponding to string[offset,*len*], without advancing # the scan offset. - def peek(len) + def peek(len) : String @str[offset, len] end @@ -276,7 +276,7 @@ class StringScanner # s.scan(/(\w+\s?){2}/) # => "this is " # s.rest # => "a string" # ``` - def rest + def rest : String @str.byte_slice(@byte_offset, @str.bytesize - @byte_offset) end diff --git a/src/symbol.cr b/src/symbol.cr index 4e5d5959bf84..34d2bf159358 100644 --- a/src/symbol.cr +++ b/src/symbol.cr @@ -76,7 +76,7 @@ struct Symbol # :nodoc: # Determines if a string needs to be quoted to be used for an external # parameter name or a named argument's key. - def self.needs_quotes_for_named_argument?(string) + def self.needs_quotes_for_named_argument?(string) : Bool case string when "", "_" true diff --git a/src/unicode/unicode.cr b/src/unicode/unicode.cr index aac38e0c4cf8..deb4377b0d2d 100644 --- a/src/unicode/unicode.cr +++ b/src/unicode/unicode.cr @@ -21,7 +21,7 @@ module Unicode end # :nodoc: - def self.upcase(char : Char, options : CaseOptions) + def self.upcase(char : Char, options : CaseOptions) : Char result = check_upcase_ascii(char, options) return result if result @@ -88,7 +88,7 @@ module Unicode end # :nodoc: - def self.downcase(char : Char, options : CaseOptions) + def self.downcase(char : Char, options : CaseOptions) : Char result = check_downcase_ascii(char, options) return result if result @@ -175,37 +175,37 @@ module Unicode end # :nodoc: - def self.lowercase?(char : Char) + def self.lowercase?(char : Char) : Bool in_category?(char.ord, category_Ll) end # :nodoc: - def self.uppercase?(char : Char) + def self.uppercase?(char : Char) : Bool in_category?(char.ord, category_Lu) end # :nodoc: - def self.letter?(char : Char) + def self.letter?(char : Char) : Bool in_any_category?(char.ord, category_Lu, category_Ll, category_Lt) end # :nodoc: - def self.number?(char : Char) + def self.number?(char : Char) : Bool in_any_category?(char.ord, category_Nd, category_Nl, category_No) end # :nodoc: - def self.control?(char : Char) + def self.control?(char : Char) : Bool in_any_category?(char.ord, category_Cs, category_Co, category_Cn, category_Cf, category_Cc) end # :nodoc: - def self.whitespace?(char : Char) + def self.whitespace?(char : Char) : Bool in_any_category?(char.ord, category_Zs, category_Zl, category_Zp) end # :nodoc: - def self.mark?(char : Char) + def self.mark?(char : Char) : Bool in_any_category?(char.ord, category_Mn, category_Me, category_Mc) end @@ -236,7 +236,7 @@ module Unicode end end - private def self.in_any_category?(needle, *haystacks) + private def self.in_any_category?(needle, *haystacks) : Bool haystacks.any? { |haystack| in_category?(needle, haystack) } end end