fsharp icon indicating copy to clipboard operation
fsharp copied to clipboard

Fix preferreduilang switch leaking into fsi.CommandLineArgs

Open Copilot opened this issue 2 months ago • 0 comments

Description

The --preferreduilang and /preferreduilang switches were appearing in fsi.CommandLineArgs when positioned after the script file, breaking script argument contracts and causing MSBuild-invoked FSI sessions to leak implementation details.

Changes

Core Implementation (src/Compiler/Interactive/fsi.fs)

  • Modified script argument handler to filter and consume preferreduilang switches regardless of position
  • Extracts culture value, sets tcConfigB.preferredUiLang and Thread.CurrentThread.CurrentUICulture
  • Validates argument format and handles invalid cultures gracefully with specific exception catching

Tests (tests/FSharp.Compiler.ComponentTests/Scripting/PreferredUiLangTests.fs)

  • Added 6 regression tests covering switch positions (before/after script), both forms (--//), culture application, and error handling

Example

// Before: switch leaked into CommandLineArgs
// dotnet fsi script.fsx --preferreduilang:es-ES arg1
// fsi.CommandLineArgs = ["script.fsx"; "--preferreduilang:es-ES"; "arg1"]

// After: switch consumed, culture set
// dotnet fsi script.fsx --preferreduilang:es-ES arg1
// fsi.CommandLineArgs = ["script.fsx"; "arg1"]
// Thread.CurrentThread.CurrentUICulture.Name = "es-ES"

Checklist

  • [x] Test cases added
  • [ ] Performance benchmarks added in case of performance changes
  • [x] Release notes entry updated
Original prompt

Implement proper handling of the preferreduilang switch in FSI and add regression tests.

Scope:

  1. Consume and apply --preferreduilang//preferreduilang in FSI option parsing so it does not surface in fsi.CommandLineArgs, and set localization accordingly.

    • Add a recognized option in src/Compiler/Interactive/fsi.fs (option table near OptionGeneral("script.fsx arg1 arg2 ...")).
    • Support both /preferreduilang:<culture> and --preferreduilang:<culture>.
    • On parse: set tcConfigB.lcid and Thread.CurrentThread.CurrentUICulture (and possibly CurrentCulture) to the parsed culture; if parsing fails, warn and ignore.
    • Ensure this happens before ReportUserCommandLineArgs so the switch is consumed and not forwarded to scripts.
  2. Add tests for argument separation and localization.

    • CLI regression tests (new folder tests/fsharp/core/interactive-args/ or extend existing tests/fsharpqa/Source/InteractiveSession/Misc/CommandLineArgs01*.fs): a) dotnet fsi --preferreduilang:en-US --exec script.fsx afsi.CommandLineArgs = ["script.fsx"; "a"] (switch consumed). b) dotnet fsi script.fsx --preferreduilang:en-US afsi.CommandLineArgs = ["script.fsx"; "a"] (even after script). c) Localization: dotnet fsi --preferreduilang:es-ES --exec script.fsx where the script triggers a warning/error; assert the culture is set (CurrentUICulture.Name starts with es-ES) and the message is localized or falls back if resources are missing. Consider a second locale (e.g., fr-FR).
  3. MSBuild-path regression test.

    • Add a sample project under tests/projects/FSI/PreferreduilangRepro/ that runs a script printing fsi.CommandLineArgs and CurrentUICulture.Name.
    • Invoke via dotnet msbuild (or existing VS integration harness) so the ToolTask-injected /preferreduilang is present.
    • Assert the switch is not in CommandLineArgs and the culture is applied.
  4. Notes/guardrails:

    • Do not leak preferreduilang into explicitArgs/CommandLineArgs regardless of position relative to the script token.
    • If culture parsing fails, warn but do not treat it as a script arg.
    • Keep behavior consistent between CLI and MSBuild paths.

References:

  • Option parsing & script arg handling: src/Compiler/Interactive/fsi.fs (option table around ~1053–1108; final ReportUserCommandLineArgs around ~1208–1222).
  • Public contract for fsi.CommandLineArgs: src/Compiler/Interactive/fsi.fsi (~397–412).
  • MSBuild host that may inject /preferreduilang: src/FSharp.Build/Fsi.fs (ToolTask; captured args around ~421–424).

This pull request was created as a result of the following prompt from Copilot chat.

Implement proper handling of the preferreduilang switch in FSI and add regression tests.

Scope:

  1. Consume and apply --preferreduilang//preferreduilang in FSI option parsing so it does not surface in fsi.CommandLineArgs, and set localization accordingly.

    • Add a recognized option in src/Compiler/Interactive/fsi.fs (option table near OptionGeneral("script.fsx arg1 arg2 ...")).
    • Support both /preferreduilang:<culture> and --preferreduilang:<culture>.
    • On parse: set tcConfigB.lcid and Thread.CurrentThread.CurrentUICulture (and possibly CurrentCulture) to the parsed culture; if parsing fails, warn and ignore.
    • Ensure this happens before ReportUserCommandLineArgs so the switch is consumed and not forwarded to scripts.
  2. Add tests for argument separation and localization.

    • CLI regression tests (new folder tests/fsharp/core/interactive-args/ or extend existing tests/fsharpqa/Source/InteractiveSession/Misc/CommandLineArgs01*.fs): a) dotnet fsi --preferreduilang:en-US --exec script.fsx afsi.CommandLineArgs = ["script.fsx"; "a"] (switch consumed). b) dotnet fsi script.fsx --preferreduilang:en-US afsi.CommandLineArgs = ["script.fsx"; "a"] (even after script). c) Localization: dotnet fsi --preferreduilang:es-ES --exec script.fsx where the script triggers a warning/error; assert the culture is set (CurrentUICulture.Name starts with es-ES) and the message is localized or falls back if resources are missing. Consider a second locale (e.g., fr-FR).
  3. MSBuild-path regression test.

    • Add a sample project under tests/projects/FSI/PreferreduilangRepro/ that runs a script printing fsi.CommandLineArgs and CurrentUICulture.Name.
    • Invoke via dotnet msbuild (or existing VS integration harness) so the ToolTask-injected /preferreduilang is present.
    • Assert the switch is not in CommandLineArgs and the culture is applied.
  4. Notes/guardrails:

    • Do not leak preferreduilang into explicitArgs/CommandLineArgs regardless of position relative to the script token.
    • If culture parsing fails, warn but do not treat it as a script arg.
    • Keep behavior consistent between CLI and MSBuild paths.

References:

  • Option parsing & script arg handling: src/Compiler/Interactive/fsi.fs (option table around ~1053–1108; final ReportUserCommandLineArgs around ~1208–1222).
  • Public contract for fsi.CommandLineArgs: src/Compiler/Interactive/fsi.fsi (~397–412).
  • MSBuild host that may inject /preferreduilang: src/FSharp.Build/Fsi.fs (ToolTask; captured args around ~421–424).

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot avatar Dec 11 '25 17:12 Copilot