diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index f5fd44859..62ae10223 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [Python] Fix type annotations for protocols, ABCs, Atom, and Set module (by @dbrattli) * [Python] Fix type annotations for async functions, date operations, and None handling (by @dbrattli) * [Python] Fix type annotations for tuple indexing, generic defaults, and reflection (by @dbrattli) +* [All] Fix `StringBuilder.Chars` getter and setter (by @MangelMaxime) ### Removed diff --git a/src/Fable.Compiler/CHANGELOG.md b/src/Fable.Compiler/CHANGELOG.md index eaabd3e23..369c5bebe 100644 --- a/src/Fable.Compiler/CHANGELOG.md +++ b/src/Fable.Compiler/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [Python] Fix type annotations for protocols, ABCs, Atom, and Set module (by @dbrattli) * [Python] Fix type annotations for async functions, date operations, and None handling (by @dbrattli) * [Python] Fix type annotations for tuple indexing, generic defaults, and reflection (by @dbrattli) +* [All] Fix `StringBuilder.Chars` getter and setter (by @MangelMaxime) ## 5.0.0-alpha.21 - 2025-12-26 diff --git a/src/fable-library-dart/System.Text.fs b/src/fable-library-dart/System.Text.fs index 217e8ccf3..44c09f4b1 100644 --- a/src/fable-library-dart/System.Text.fs +++ b/src/fable-library-dart/System.Text.fs @@ -101,35 +101,35 @@ type StringBuilder(value: string, capacity: int) = with get (index: int) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 + let pos = index - len buf[i][pos] and set (index: int) (value: char) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 - buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] + let pos = index - len + buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] member x.Replace(oldValue: char, newValue: char) = - let oldValue = string oldValue - let newValue = string newValue + let oldValue = string oldValue + let newValue = string newValue for i = buf.Count - 1 downto 0 do buf[i] <- buf[i].Replace(oldValue, newValue) diff --git a/src/fable-library-py/fable_library/System.Text.fs b/src/fable-library-py/fable_library/System.Text.fs index 03d54fbd9..1fa48be00 100644 --- a/src/fable-library-py/fable_library/System.Text.fs +++ b/src/fable-library-py/fable_library/System.Text.fs @@ -15,11 +15,11 @@ type StringBuilder(value: string, capacity: int) = new() = StringBuilder("", 16) member x.Append(s: string | null) = - buf.Add(string s) + buf.Add(string s) x member x.Append(s: string | null, startIndex: int, count: int) = - buf.Add((string s).Substring(startIndex, count)) + buf.Add((string s).Substring(startIndex, count)) x member x.Append(c: char) = @@ -104,31 +104,31 @@ type StringBuilder(value: string, capacity: int) = with get (index: int) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 + let pos = index - len buf[i][pos] and set (index: int) (value: char) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 - buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] + let pos = index - len + buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] member x.Replace(oldValue: char, newValue: char) = for i = buf.Count - 1 downto 0 do diff --git a/src/fable-library-rust/src/System.Text.fs b/src/fable-library-rust/src/System.Text.fs index 48ce53061..0735dde38 100644 --- a/src/fable-library-rust/src/System.Text.fs +++ b/src/fable-library-rust/src/System.Text.fs @@ -17,24 +17,24 @@ type StringBuilder(value: string, capacity: int) = buf.Add(s) x - member x.Append(o: bool) = x.Append(string o) - member x.Append(c: char) = x.Append(string c) + member x.Append(o: bool) = x.Append(string o) + member x.Append(c: char) = x.Append(string c) member x.Append(c: char, repeatCount: int) = let s = String.replicate repeatCount (string c) buf.Add(s) x - member x.Append(o: int8) = x.Append(string o) - member x.Append(o: byte) = x.Append(string o) - member x.Append(o: int16) = x.Append(string o) - member x.Append(o: uint16) = x.Append(string o) - member x.Append(o: int32) = x.Append(string o) - member x.Append(o: uint32) = x.Append(string o) - member x.Append(o: int64) = x.Append(string o) - member x.Append(o: uint64) = x.Append(string o) - member x.Append(o: float32) = x.Append(string o) - member x.Append(o: float) = x.Append(string o) + member x.Append(o: int8) = x.Append(string o) + member x.Append(o: byte) = x.Append(string o) + member x.Append(o: int16) = x.Append(string o) + member x.Append(o: uint16) = x.Append(string o) + member x.Append(o: int32) = x.Append(string o) + member x.Append(o: uint32) = x.Append(string o) + member x.Append(o: int64) = x.Append(string o) + member x.Append(o: uint64) = x.Append(string o) + member x.Append(o: float32) = x.Append(string o) + member x.Append(o: float) = x.Append(string o) member x.Append(s: string, index: int, count: int) = x.Append(s.Substring(index, count)) @@ -57,31 +57,31 @@ type StringBuilder(value: string, capacity: int) = with get (index: int) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 + let pos = index - len buf[i][pos] and set (index: int) (value: char) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 - buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] + let pos = index - len + buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] member x.Length = let mutable len = 0 @@ -92,8 +92,8 @@ type StringBuilder(value: string, capacity: int) = len member x.Replace(oldValue: char, newValue: char) = - let oldValue = string oldValue - let newValue = string newValue + let oldValue = string oldValue + let newValue = string newValue for i = buf.Count - 1 downto 0 do buf[i] <- buf[i].Replace(oldValue, newValue) diff --git a/src/fable-library-ts/System.Text.fs b/src/fable-library-ts/System.Text.fs index c4423570f..fd1b6f47e 100644 --- a/src/fable-library-ts/System.Text.fs +++ b/src/fable-library-ts/System.Text.fs @@ -12,11 +12,11 @@ type StringBuilder(value: string, capacity: int) = new() = StringBuilder("", 16) member x.Append(s: string | null) = - buf.Add(string s) + buf.Add(string s) x member x.Append(s: string | null, startIndex: int, count: int) = - buf.Add((string s).Substring(startIndex, count)) + buf.Add((string s).Substring(startIndex, count)) x member x.Append(c: char) = @@ -101,31 +101,31 @@ type StringBuilder(value: string, capacity: int) = with get (index: int) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 + let pos = index - len buf[i][pos] and set (index: int) (value: char) = let mutable len = 0 - let mutable i = -1 + let mutable i = 0 - while i + 1 < buf.Count && len < index do - i <- i + 1 + while i < buf.Count && len + buf[i].Length <= index do len <- len + buf[i].Length + i <- i + 1 - if index < 0 || i < 0 || i >= buf.Count then + if index < 0 || i >= buf.Count then failwith "Index was outside the bounds of the array" else - let pos = len - index - 1 - buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] + let pos = index - len + buf[i] <- buf[i][0 .. (pos - 1)] + (string value) + buf[i][(pos + 1) ..] member x.Replace(oldValue: char, newValue: char) = for i = buf.Count - 1 downto 0 do diff --git a/tests/Dart/src/StringTests.fs b/tests/Dart/src/StringTests.fs index 901070874..62f24fa4b 100644 --- a/tests/Dart/src/StringTests.fs +++ b/tests/Dart/src/StringTests.fs @@ -145,13 +145,20 @@ let tests() = testCase "StringBuilder.Chars works" <| fun () -> let sb = System.Text.StringBuilder() .Append("abc") + .Append("def") + sb.Chars(0) |> equal 'a' sb.Chars(1) |> equal 'b' + sb.Chars(2) |> equal 'c' + sb.Chars(3) |> equal 'd' + sb.Chars(4) |> equal 'e' + sb.Chars(5) |> equal 'f' testCase "StringBuilder.Chars throws when index is out of bounds" <| fun () -> + let sb = System.Text.StringBuilder() + .Append("abc") throwsAnyError <| fun () -> - let sb = System.Text.StringBuilder() - .Append("abc") sb.Chars(-1) |> ignore + throwsAnyError <| fun () -> sb.Chars(3) |> ignore testCase "StringBuilder.Replace works" <| fun () -> @@ -173,6 +180,11 @@ let tests() = sb[1] <- 'x' sb.ToString() |> equal "axc" + throwsAnyError <| fun () -> + sb[-1] <- 'y' + throwsAnyError <| fun () -> + sb[3] <- 'z' + // Formatting // testCase "kprintf works" <| fun () -> diff --git a/tests/Js/Main/StringTests.fs b/tests/Js/Main/StringTests.fs index 17f6e76ae..659cd386b 100644 --- a/tests/Js/Main/StringTests.fs +++ b/tests/Js/Main/StringTests.fs @@ -123,13 +123,20 @@ let tests = testList "Strings" [ testCase "StringBuilder.Chars works" <| fun () -> let sb = System.Text.StringBuilder() .Append("abc") + .Append("def") + sb.Chars(0) |> equal 'a' sb.Chars(1) |> equal 'b' + sb.Chars(2) |> equal 'c' + sb.Chars(3) |> equal 'd' + sb.Chars(4) |> equal 'e' + sb.Chars(5) |> equal 'f' testCase "StringBuilder.Chars throws when index is out of bounds" <| fun () -> + let sb = System.Text.StringBuilder() + .Append("abc") throwsAnyError <| fun () -> - let sb = System.Text.StringBuilder() - .Append("abc") sb.Chars(-1) |> ignore + throwsAnyError <| fun () -> sb.Chars(3) |> ignore testCase "StringBuilder.Replace works" <| fun () -> @@ -150,6 +157,10 @@ let tests = testList "Strings" [ .Append("abc") sb[1] <- 'x' sb.ToString() |> equal "axc" + throwsAnyError <| fun () -> + sb[-1] <- 'y' + throwsAnyError <| fun () -> + sb[3] <- 'z' // Formatting diff --git a/tests/Php/TestString.fs b/tests/Php/TestString.fs index 55a37c8e0..7c51597b4 100644 --- a/tests/Php/TestString.fs +++ b/tests/Php/TestString.fs @@ -218,14 +218,21 @@ let ``StringBuilder.AppendFormat with provider works`` () = let ``StringBuilder.Chars works`` () = let sb = System.Text.StringBuilder() .Append("abc") + .Append("def") + sb.Chars(0) |> equal 'a' sb.Chars(1) |> equal 'b' + sb.Chars(2) |> equal 'c' + sb.Chars(3) |> equal 'd' + sb.Chars(4) |> equal 'e' + sb.Chars(5) |> equal 'f' [] let ``StringBuilder.Chars throws when index is out of bounds`` () = + let sb = System.Text.StringBuilder() + .Append("abc") throwsAnyError <| fun () -> - let sb = System.Text.StringBuilder() - .Append("abc") sb.Chars(-1) |> ignore + throwsAnyError <| fun () -> sb.Chars(3) |> ignore [] @@ -249,6 +256,10 @@ let ``StringBuilder index setter works`` () = .Append("abc") sb[1] <- 'x' sb.ToString() |> equal "axc" + throwsAnyError <| fun () -> + sb[-1] <- 'y' + throwsAnyError <| fun () -> + sb[3] <- 'z' [] let ``test Conversion char to int works`` () = diff --git a/tests/Python/TestString.fs b/tests/Python/TestString.fs index f3942daa2..e9f7dc4e3 100644 --- a/tests/Python/TestString.fs +++ b/tests/Python/TestString.fs @@ -277,14 +277,21 @@ let ``test StringBuilder.AppendFormat with provider works`` () = let ``test StringBuilder.Chars works`` () = let sb = System.Text.StringBuilder() .Append("abc") + .Append("def") + sb.Chars(0) |> equal 'a' sb.Chars(1) |> equal 'b' + sb.Chars(2) |> equal 'c' + sb.Chars(3) |> equal 'd' + sb.Chars(4) |> equal 'e' + sb.Chars(5) |> equal 'f' [] let ``test StringBuilder.Chars throws when index is out of bounds`` () = + let sb = System.Text.StringBuilder() + .Append("abc") throwsAnyError <| fun () -> - let sb = System.Text.StringBuilder() - .Append("abc") sb.Chars(-1) |> ignore + throwsAnyError <| fun () -> sb.Chars(3) |> ignore [] @@ -308,6 +315,10 @@ let ``test StringBuilder index setter works`` () = .Append("abc") sb[1] <- 'x' equal "axc" (sb.ToString()) + throwsAnyError <| fun () -> + sb[-1] <- 'y' + throwsAnyError <| fun () -> + sb[3] <- 'z' [] let ``test Conversion char to int works`` () = diff --git a/tests/Rust/tests/src/StringTests.fs b/tests/Rust/tests/src/StringTests.fs index cd3fb78c1..8d66db7a9 100644 --- a/tests/Rust/tests/src/StringTests.fs +++ b/tests/Rust/tests/src/StringTests.fs @@ -135,14 +135,22 @@ let ``StringBuilder.AppendFormat with provider works`` () = let ``StringBuilder.Chars works`` () = let sb = System.Text.StringBuilder() .Append("abc") + .Append("def") + sb.Chars(0) |> equal 'a' sb.Chars(1) |> equal 'b' + sb.Chars(2) |> equal 'c' + sb.Chars(3) |> equal 'd' + sb.Chars(4) |> equal 'e' + sb.Chars(5) |> equal 'f' + [] let ``StringBuilder.Chars throws when index is out of bounds`` () = + let sb = System.Text.StringBuilder() + .Append("abc") throwsAnyError <| fun () -> - let sb = System.Text.StringBuilder() - .Append("abc") sb.Chars(-1) |> ignore + throwsAnyError <| fun () -> sb.Chars(3) |> ignore [] @@ -166,6 +174,10 @@ let ``StringBuilder index setter works`` () = .Append("abc") sb[1] <- 'x' sb.ToString() |> equal "axc" + throwsAnyError <| fun () -> + sb[-1] <- 'y' + throwsAnyError <| fun () -> + sb[3] <- 'z' [] let ``kprintf works`` () =