Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JS] Support string.normalize() #3928

Merged
merged 2 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [Rust] Added String.Replace(char, char) and test (by @ncave)
* [Rust] Support type extensions for external types (by @ncave)
* [Rust] Support more System.Array methods and tests (by @ncave)
* [JS] Add `System.String.Normalize` support (by @DashieTM)

## 4.22.0 - 2024-10-02

Expand Down
28 changes: 28 additions & 0 deletions src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,34 @@ let strings (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr opt
Helper.LibCall(com, "String", "concat", t, args, hasSpread = true, ?loc = r)
|> Some
| "CompareOrdinal", None, _ -> Helper.LibCall(com, "String", "compareOrdinal", t, args, ?loc = r) |> Some
| "Normalize", Some str, _ ->
match args with
| [] ->
Helper.InstanceCall(
str,
Naming.lowerFirst i.CompiledName,
t,
[ makeStrConst "NFC" ],
i.SignatureArgTypes,
genArgs = i.GenericArgs,
?loc = r
)
|> Some
| [ NormalizationFormEnumValue normalizationForm ] ->
Helper.InstanceCall(
str,
Naming.lowerFirst i.CompiledName,
t,
[ makeStrConst normalizationForm ],
i.SignatureArgTypes,
genArgs = i.GenericArgs,
?loc = r
)
|> Some
| _ ->
"Normalization expects an optional System.Text.NormalizationForm"
|> addErrorAndReturnNull com ctx.InlinePath r
|> Some
| Patterns.SetContains implementedStringFunctions, thisArg, args ->
Helper.LibCall(
com,
Expand Down
13 changes: 13 additions & 0 deletions src/Fable.Transforms/Transforms.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,19 @@ module AST =
Some()
| _ -> None

let (|NormalizationFormEnumValue|_|) e =
match e with
| Expr.Value(
kind = NumberConstant(NumberValue.Int32 value,
NumberInfo.IsEnum({ FullName = "System.Text.NormalizationForm" }))) ->
match value with
| 1 -> Some "NFC"
| 2 -> Some "NFD"
| 5 -> Some "NFKC"
| 6 -> Some "NFKD"
| _ -> None
| _ -> None

// TODO: Improve this, see https://github.com/fable-compiler/Fable/issues/1659#issuecomment-445071965
// This is mainly used for inlining so a computation or a reference to a mutable value are understood
// as a side effects too (because we don't want to duplicate or change the order of execution)
Expand Down
13 changes: 11 additions & 2 deletions tests/Js/Main/StringTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -831,12 +831,12 @@ let tests = testList "Strings" [
for arg in args do
"abcd".EndsWith(fst arg)
|> equal (snd arg)

testCase "String.EndsWith with OrdinalIgnoreCase works" <| fun () ->
let args = [("ab", false); ("CD", true); ("cd", true); ("bc", false); ("xabcd", false); ("abcd", true)]
for arg in args do
"ABCD".EndsWith(fst arg, StringComparison.OrdinalIgnoreCase)
|> equal (snd arg)
|> equal (snd arg)

testCase "String.Trim works" <| fun () ->
" abc ".Trim()
Expand Down Expand Up @@ -966,6 +966,15 @@ let tests = testList "Strings" [
String.Concat(seq { yield "a"; yield "b"; yield "c" })
|> equal "abc"

testCase "System.String.Normalize works" <| fun () ->
let name1 = "\u0041\u006d\u00e9\u006c\u0069\u0065";
let name2 = "\u0041\u006d\u0065\u0301\u006c\u0069\u0065";
notEqual name1 name2

let normalized1 = name1.Normalize System.Text.NormalizationForm.FormC
let normalized2 = name2.Normalize System.Text.NormalizationForm.FormC
equal normalized1 normalized2

testCase "System.String.Join with long array works" <| fun () ->
let n = 1_000_000
let a = Array.init n (fun _i -> "a")
Expand Down
Loading