diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index d5c110124c..6564b1301e 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -13,6 +13,12 @@
"commands": [
"husky"
]
+ },
+ "fsharp-analyzers": {
+ "version": "0.21.0",
+ "commands": [
+ "fsharp-analyzers"
+ ]
}
}
}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9f8dbf071e..285dabb62d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -218,3 +218,6 @@ __pycache__/
# Compilation tests
tests/**/*.actual
+
+# Analyzers
+*.sarif
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 33364963ee..6eac0dec54 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -24,5 +24,13 @@
+
+ all
+ build
+
+
+ all
+ analyzers
+
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
new file mode 100644
index 0000000000..1cc288a1b3
--- /dev/null
+++ b/src/Directory.Build.targets
@@ -0,0 +1,11 @@
+
+
+ --analyzers-path "$(PkgG-Research_FSharp_Analyzers)/analyzers/dotnet/fs"
+ $(FSharpAnalyzersOtherFlags) --analyzers-path "$(PkgIonide_Analyzers)/analyzers/dotnet/fs"
+ $([System.IO.Path]::GetDirectoryName($(DirectoryBuildTargetsPath)))
+ $(CodeRoot)/reports/
+ $(FSharpAnalyzersOtherFlags) --code-root "$(CodeRoot)"
+ $(FSharpAnalyzersOtherFlags) --report "$(SarifOutput)$(MSBuildProjectName)-$(TargetFramework).sarif"
+ $(FSharpAnalyzersOtherFlags) --exclude-analyzer PartialAppAnalyzer
+
+
diff --git a/src/Fable.AST/Common.fs b/src/Fable.AST/Common.fs
index e5f271f8fe..e9730edcf6 100644
--- a/src/Fable.AST/Common.fs
+++ b/src/Fable.AST/Common.fs
@@ -1,5 +1,7 @@
namespace Fable.AST
+open System
+
/// Each Position object consists of a line number (1-indexed) and a column number (0-indexed):
type Position =
{
@@ -24,7 +26,7 @@ type SourceLocation =
member this.DisplayName =
this.identifierName
|> Option.bind (fun name ->
- match name.IndexOf(";file:") with
+ match name.IndexOf(";file:", StringComparison.Ordinal) with
| -1 -> Some name
| 0 -> None
| i -> name.Substring(0, i) |> Some
@@ -33,7 +35,7 @@ type SourceLocation =
member this.File =
this.identifierName
|> Option.bind (fun name ->
- match name.IndexOf(";file:") with
+ match name.IndexOf(";file:", StringComparison.Ordinal) with
| -1 -> None
| i -> name.Substring(i + ";file:".Length) |> Some
)
diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md
index a829bd8c4c..9ef3dc893f 100644
--- a/src/Fable.Cli/CHANGELOG.md
+++ b/src/Fable.Cli/CHANGELOG.md
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+### Added
+
+#### All
+
+* Overall performance improvements
+ * [PR 3620](https://github.com/fable-compiler/Fable/pull/3620) Removed double-dictionary lookups (by @Thorium)
+ * [PR 3624](https://github.com/fable-compiler/Fable/pull/3624) Add G-Research analyzers and fix reported issues (by @nojaf)
+
### Fixed
#### Python
diff --git a/src/Fable.Cli/Entry.fs b/src/Fable.Cli/Entry.fs
index 93f113a6f8..d9394f949a 100644
--- a/src/Fable.Cli/Entry.fs
+++ b/src/Fable.Cli/Entry.fs
@@ -9,17 +9,17 @@ type CliArgs(args: string list) =
let args =
// Assume last arg has true value in case it's a flag
match List.tryLast args with
- | Some key when key.StartsWith("-") -> args @ [ "true" ]
+ | Some key when key.StartsWith('-') -> args @ [ "true" ]
| _ -> args
(Map.empty, List.windowed 2 args)
||> List.fold (fun map pair ->
match pair with
- | [ key; value ] when key.StartsWith("-") ->
+ | [ key; value ] when key.StartsWith('-') ->
let key = key.ToLower()
let value =
- if value.StartsWith("-") then
+ if value.StartsWith('-') then
"true"
else
value
@@ -279,11 +279,15 @@ type Runner =
|> Seq.toList
files
- |> List.filter (fun file -> file.EndsWith(".fsproj"))
+ |> List.filter (fun file ->
+ file.EndsWith(".fsproj", StringComparison.Ordinal)
+ )
|> function
| [] ->
files
- |> List.filter (fun file -> file.EndsWith(".fsx"))
+ |> List.filter (fun file ->
+ file.EndsWith(".fsx", StringComparison.Ordinal)
+ )
| candidates -> candidates
|> function
| [] ->
@@ -388,7 +392,7 @@ type Runner =
let fileExt =
args.Value("-e", "--extension")
|> Option.map (fun e ->
- if e.StartsWith(".") then
+ if e.StartsWith('.') then
e
else
"." + e
@@ -537,7 +541,7 @@ let clean (args: CliArgs) language rootDir =
"No files have been deleted. If Fable output is in another directory, pass it as argument."
)
else
- Log.always ("Clean completed! Files deleted: " + string fileCount)
+ Log.always ("Clean completed! Files deleted: " + string fileCount)
let getStatus =
function
@@ -563,7 +567,9 @@ let main argv =
let! argv, runProc =
argv
|> List.ofArray
- |> List.splitWhile (fun a -> not (a.StartsWith("--run")))
+ |> List.splitWhile (fun a ->
+ not (a.StartsWith("--run", StringComparison.Ordinal))
+ )
|> function
| argv, flag :: runArgs ->
match flag, runArgs with
@@ -584,7 +590,7 @@ let main argv =
| ("help" | "--help" | "-h") :: _ -> [ "--help" ], []
| "--version" :: _ -> [ "--version" ], []
| argv ->
- argv |> List.splitWhile (fun x -> x.StartsWith("-") |> not)
+ argv |> List.splitWhile (fun x -> x.StartsWith('-') |> not)
let! args = parseCliArgs args
let! language = argLanguage args
diff --git a/src/Fable.Cli/Globbing.fs b/src/Fable.Cli/Globbing.fs
index c881613f4f..12ba2152d6 100644
--- a/src/Fable.Cli/Globbing.fs
+++ b/src/Fable.Cli/Globbing.fs
@@ -1,5 +1,6 @@
namespace Fable.Cli
+open System
open System.Collections.Generic
open System.IO
@@ -141,7 +142,7 @@ module Globbing =
let globRoot =
// If we dropped "/" from the beginning of the path in the 'Split' call, put it back!
- if normPattern.StartsWith("/") then
+ if normPattern.StartsWith('/') then
"/" + globRoot
else
globRoot
@@ -163,9 +164,9 @@ module Globbing =
// names (as one folder name could be a substring of the other)
let start =
baseDir.TrimEnd([| Path.DirectorySeparatorChar |])
- + string Path.DirectorySeparatorChar
+ + string Path.DirectorySeparatorChar
// See https://github.com/fsharp/FAKE/issues/1925
- if input.StartsWith start then
+ if input.StartsWith(start, StringComparison.Ordinal) then
input.Substring start.Length
else
input
@@ -183,7 +184,10 @@ module Globbing =
let baseItems =
let start, rest =
- if input.StartsWith "\\\\" && splits.Length >= 4 then
+ if
+ input.StartsWith("\\\\", StringComparison.Ordinal)
+ && splits.Length >= 4
+ then
let serverName = splits.[2]
let share = splits.[3]
@@ -198,12 +202,12 @@ module Globbing =
elif
splits.Length >= 2
&& Path.IsPathRooted input
- && input.StartsWith "/"
+ && input.StartsWith '/'
then
[ Directory("/") ], splits |> Array.toSeq
else
if Path.IsPathRooted input then
- if input.StartsWith "\\" then
+ if input.StartsWith '\\' then
failwithf
"Please remove the leading '\\' or '/' and replace them with \
'.\\' or './' if you want to use a relative path. Leading \
@@ -415,13 +419,13 @@ module Globbing =
let included =
this.Includes
- |> Seq.exists (fun fileInclude ->
+ |> List.exists (fun fileInclude ->
Glob.isMatch (fullDir fileInclude) fullPath
)
let excluded =
this.Excludes
- |> Seq.exists (fun fileExclude ->
+ |> List.exists (fun fileExclude ->
Glob.isMatch (fullDir fileExclude) fullPath
)
@@ -468,7 +472,10 @@ module Globbing =
|> Seq.filter (fun d ->
directoryIncludes
|> Seq.exists (fun p ->
- d.StartsWith(p + string Path.DirectorySeparatorChar)
+ d.StartsWith(
+ p + string Path.DirectorySeparatorChar,
+ StringComparison.Ordinal
+ )
&& p <> d
)
|> not
diff --git a/src/Fable.Cli/Main.fs b/src/Fable.Cli/Main.fs
index 2281094915..20c7ba90ba 100644
--- a/src/Fable.Cli/Main.fs
+++ b/src/Fable.Cli/Main.fs
@@ -31,7 +31,8 @@ module private Util =
}
let isImplementationFile (fileName: string) =
- fileName.EndsWith(".fs") || fileName.EndsWith(".fsx")
+ fileName.EndsWith(".fs", StringComparison.Ordinal)
+ || fileName.EndsWith(".fsx", StringComparison.Ordinal)
let caseInsensitiveSet (items: string seq) : ISet =
let s = HashSet(items)
@@ -312,7 +313,7 @@ module FileWatcherUtil =
// See https://github.com/fable-compiler/Fable/pull/2725#issuecomment-1015123642
|> List.filter (fun file ->
not (
- file.EndsWith(".fsproj.fsx")
+ file.EndsWith(".fsproj.fsx", StringComparison.Ordinal)
// It looks like latest F# compiler puts generated files for resolution of packages
// in scripts in $HOME/.packagemanagement. See #3222
|| file.Contains(".packagemanagement")
@@ -334,7 +335,8 @@ module FileWatcherUtil =
if
restDirs
|> List.forall (fun d ->
- (withTrailingSep d).StartsWith dir'
+ (withTrailingSep d)
+ .StartsWith(dir', StringComparison.Ordinal)
)
then
dir
@@ -800,8 +802,14 @@ and FableCompiler
let filesToCompile =
state.FilesToCompile
|> Array.filter (fun file ->
- file.EndsWith(".fs")
- || file.EndsWith(".fsx")
+ file.EndsWith(
+ ".fs",
+ StringComparison.Ordinal
+ )
+ || file.EndsWith(
+ ".fsx",
+ StringComparison.Ordinal
+ )
)
(state, filesToCompile)
@@ -1084,7 +1092,8 @@ let private areCompiledFilesUpToDate (state: State) (filesToCompile: string[]) =
let upToDate =
filesToCompile
|> Array.filter (fun file ->
- file.EndsWith(".fs") || file.EndsWith(".fsx")
+ file.EndsWith(".fs", StringComparison.Ordinal)
+ || file.EndsWith(".fsx", StringComparison.Ordinal)
)
|> Array.forall (fun source ->
let outPath = getOutPath state.CliArgs pathResolver source
@@ -1208,7 +1217,10 @@ let private compilationCycle (state: State) (changes: ISet) =
| Some(projCracked, fableCompiler) ->
// For performance reasons, don't crack .fsx scripts for every change
let fsprojChanged =
- changes |> Seq.exists (fun c -> c.EndsWith(".fsproj"))
+ changes
+ |> Seq.exists (fun c ->
+ c.EndsWith(".fsproj", StringComparison.Ordinal)
+ )
if fsprojChanged then
let oldProjCracked = projCracked
diff --git a/src/Fable.Cli/Pipeline.fs b/src/Fable.Cli/Pipeline.fs
index d428c37433..bf2e7355da 100644
--- a/src/Fable.Cli/Pipeline.fs
+++ b/src/Fable.Cli/Pipeline.fs
@@ -102,7 +102,7 @@ module Js =
let fileExt =
let fileExt = cliArgs.CompilerOptions.FileExtension
- if fileExt.EndsWith(".ts") then
+ if fileExt.EndsWith(".ts", StringComparison.Ordinal) then
Path.ChangeExtension(fileExt, ".js")
else
fileExt
@@ -172,7 +172,7 @@ module Js =
cliArgs.OutDir
path
- if path.EndsWith(".fs") then
+ if path.EndsWith(".fs", StringComparison.Ordinal) then
let isInFableModules =
Path.Combine(targetDir, path) |> Naming.isInFableModules
@@ -488,7 +488,7 @@ module Php =
cliArgs.OutDir
path
- if path.EndsWith(".fs") then
+ if path.EndsWith(".fs", StringComparison.Ordinal) then
Path.ChangeExtension(path, fileExt)
else
path
@@ -546,7 +546,7 @@ module Dart =
cliArgs.OutDir
path
- if path.EndsWith(".fs") then
+ if path.EndsWith(".fs", StringComparison.Ordinal) then
Path.ChangeExtension(path, fileExt)
else
path
@@ -607,7 +607,7 @@ module Rust =
cliArgs.OutDir
path
- if path.EndsWith(".fs") then
+ if path.EndsWith(".fs", StringComparison.Ordinal) then
Path.ChangeExtension(path, fileExt)
else
path
diff --git a/src/Fable.Cli/ProjectCracker.fs b/src/Fable.Cli/ProjectCracker.fs
index b5d72072a2..637998b72b 100644
--- a/src/Fable.Cli/ProjectCracker.fs
+++ b/src/Fable.Cli/ProjectCracker.fs
@@ -185,9 +185,9 @@ type CrackerResponse =
}
let isSystemPackage (pkgName: string) =
- pkgName.StartsWith("System.")
- || pkgName.StartsWith("Microsoft.")
- || pkgName.StartsWith("runtime.")
+ pkgName.StartsWith("System.", StringComparison.Ordinal)
+ || pkgName.StartsWith("Microsoft.", StringComparison.Ordinal)
+ || pkgName.StartsWith("runtime.", StringComparison.Ordinal)
|| pkgName = "NETStandard.Library"
|| pkgName = "FSharp.Core"
|| pkgName = "Fable.Core"
@@ -295,7 +295,9 @@ let tryGetFablePackage (opts: CrackerOptions) (dllPath: string) =
let fsprojPath =
match Map.tryFind pkgId opts.Replace with
| Some replaced ->
- if replaced.EndsWith(".fsproj") then
+ if
+ replaced.EndsWith(".fsproj", StringComparison.Ordinal)
+ then
replaced
else
tryFileWithPattern replaced "*.fsproj"
@@ -468,18 +470,24 @@ let private extractUsefulOptionsAndSources
(line: string)
(accSources: string list, accOptions: string list)
=
- if line.StartsWith("-") then
+ if line.StartsWith('-') then
// "--warnaserror" // Disable for now to prevent unexpected errors, see #2288
- if line.StartsWith("--langversion:") && isMainProj then
+ if
+ line.StartsWith("--langversion:", StringComparison.Ordinal)
+ && isMainProj
+ then
let v = line.Substring("--langversion:".Length).ToLowerInvariant()
if v = "preview" then
accSources, line :: accOptions
else
accSources, accOptions
- elif line.StartsWith("--nowarn") || line.StartsWith("--warnon") then
+ elif
+ line.StartsWith("--nowarn", StringComparison.Ordinal)
+ || line.StartsWith("--warnon", StringComparison.Ordinal)
+ then
accSources, line :: accOptions
- elif line.StartsWith("--define:") then
+ elif line.StartsWith("--define:", StringComparison.Ordinal) then
// When parsing the project as .csproj there will be multiple defines in the same line,
// but the F# compiler seems to accept only one per line
let defines =
@@ -533,7 +541,7 @@ let getCrackedMainFsproj
let sourceFiles, otherOpts =
(projOpts, ([], []))
||> Array.foldBack (fun line (src, otherOpts) ->
- if line.StartsWith("-r:") then
+ if line.StartsWith("-r:", StringComparison.Ordinal) then
let line = Path.normalizePath (line[3..])
let dllName = getDllName line
dllRefs.Add(dllName, line)
@@ -663,7 +671,12 @@ let getProjectOptionsFromProjectFile =
r.CompilerArguments
|> Array.map (fun line ->
if reg.IsMatch(line) then
- if line.StartsWith("/reference") then
+ if
+ line.StartsWith(
+ "/reference",
+ StringComparison.Ordinal
+ )
+ then
"-r" + line.Substring(10)
else
"--" + line.Substring(1)
@@ -708,9 +721,12 @@ let getProjectOptionsFromProjectFile =
let projOpts =
compilerArgs
- |> Array.skipWhile (fun line -> not (line.StartsWith("-")))
+ |> Array.skipWhile (fun line -> not (line.StartsWith('-')))
|> Array.map (fun f ->
- if f.EndsWith(".fs") || f.EndsWith(".fsi") then
+ if
+ f.EndsWith(".fs", StringComparison.Ordinal)
+ || f.EndsWith(".fsi", StringComparison.Ordinal)
+ then
if Path.IsPathRooted f then
f
else
@@ -810,7 +826,7 @@ let retryGetCrackedProjects opts =
// Replace the .fsproj extension with .fableproj for files in fable_modules
// We do this to avoid conflicts with other F# tooling that scan for .fsproj files
let changeFsprojToFableproj (path: string) =
- if path.EndsWith(".fsproj") then
+ if path.EndsWith(".fsproj", StringComparison.Ordinal) then
IO.Path.ChangeExtension(path, Naming.fableProjExt)
else
path
@@ -857,7 +873,7 @@ let getFableLibraryPath (opts: CrackerOptions) =
| Python, Some Py.Naming.sitePackages ->
"fable-library-py", "fable-library"
| _, Some path ->
- if path.StartsWith("./") then
+ if path.StartsWith("./", StringComparison.Ordinal) then
"", Path.normalizeFullPath path
elif IO.Path.IsPathRooted(path) then
"", Path.normalizePath path
@@ -968,7 +984,7 @@ let loadPrecompiledInfo (opts: CrackerOptions) otherOptions sourceFiles =
// (e.g. fable_modules/Fable.Promise.2.1.0/Promise.fs) so we assume they're the same wherever they are
// TODO: Check if this holds true also for Python which may not include the version number in the path
let normalizePath (path: string) =
- let i = path.IndexOf(Naming.fableModules)
+ let i = path.IndexOf(Naming.fableModules, StringComparison.Ordinal)
if i >= 0 then
path[i..]
@@ -1237,7 +1253,7 @@ let getFullProjectOpts (opts: CrackerOptions) =
if
ignoredRefs.Contains(name)
- || (name.StartsWith("System.")
+ || (name.StartsWith("System.", StringComparison.Ordinal)
&& not (coreRefs.Contains(name)))
then
None
diff --git a/src/Fable.Cli/Util.fs b/src/Fable.Cli/Util.fs
index f60c3634c9..8ef93d9b6a 100644
--- a/src/Fable.Cli/Util.fs
+++ b/src/Fable.Cli/Util.fs
@@ -624,7 +624,8 @@ module Imports =
path.Replace("../", "").Replace("./", "").Replace(":", "")
let isRelativePath (path: string) =
- path.StartsWith("./") || path.StartsWith("../")
+ path.StartsWith("./", StringComparison.Ordinal)
+ || path.StartsWith("../", StringComparison.Ordinal)
let isAbsolutePath (path: string) =
path.StartsWith('/') || path.IndexOf(':') = 1
@@ -735,7 +736,7 @@ module Imports =
importPath
if isAbsolutePath importPath then
- if importPath.EndsWith(".fs") then
+ if importPath.EndsWith(".fs", StringComparison.Ordinal) then
getTargetRelativePath
pathResolver
importPath
diff --git a/src/Fable.PublishUtils/PublishUtils.fs b/src/Fable.PublishUtils/PublishUtils.fs
index 721e93cadd..ff3d83fd8f 100644
--- a/src/Fable.PublishUtils/PublishUtils.fs
+++ b/src/Fable.PublishUtils/PublishUtils.fs
@@ -403,7 +403,7 @@ module Publish =
let VERSION_HEADER = "#+ " + VERSION
let splitPrerelease (version: string) =
- let i = version.IndexOf("-")
+ let i = version.IndexOf('-')
if i > 0 then
version.Substring(0, i), Some(version.Substring(i + 1))
@@ -519,8 +519,8 @@ module Publish =
let private findFileWithExt (dir: string) (ext: string) =
IO.Directory.GetFiles(dir)
- |> Seq.tryPick (fun path ->
- if path.EndsWith(ext) then
+ |> Array.tryPick (fun path ->
+ if path.EndsWith(ext, StringComparison.Ordinal) then
Some(dir > path)
else
None
@@ -723,7 +723,7 @@ let getDotNetSDKVersionFromGlobalJson () : string =
let getNpmVersion (projDir: string) =
let pkgJsonPath =
- if projDir.EndsWith("package.json") then
+ if projDir.EndsWith("package.json", StringComparison.Ordinal) then
projDir
else
projDir > "package.json"
diff --git a/src/Fable.Transforms/BabelPrinter.fs b/src/Fable.Transforms/BabelPrinter.fs
index 1e0ac59924..ab3f900d26 100644
--- a/src/Fable.Transforms/BabelPrinter.fs
+++ b/src/Fable.Transforms/BabelPrinter.fs
@@ -1027,7 +1027,7 @@ module PrinterExtensions =
let i = int m.Groups[1].Value
for j = i to args.Length - 1 do
- rep.Add("$" + string j)
+ rep.Add("$" + string j)
String.concat ", " rep
)
diff --git a/src/Fable.Transforms/Dart/DartPrinter.fs b/src/Fable.Transforms/Dart/DartPrinter.fs
index 41cf7b74dc..6c7b0a9499 100644
--- a/src/Fable.Transforms/Dart/DartPrinter.fs
+++ b/src/Fable.Transforms/Dart/DartPrinter.fs
@@ -105,7 +105,7 @@ module PrinterExtensions =
let i = int m.Groups[1].Value
for j = i to args.Length - 1 do
- rep.Add("$" + string j)
+ rep.Add("$" + string j)
String.concat ", " rep
)
diff --git a/src/Fable.Transforms/Dart/Replacements.fs b/src/Fable.Transforms/Dart/Replacements.fs
index 97a89e7c5e..66f3bfe4a8 100644
--- a/src/Fable.Transforms/Dart/Replacements.fs
+++ b/src/Fable.Transforms/Dart/Replacements.fs
@@ -2,6 +2,7 @@ module Fable.Transforms.Dart.Replacements
#nowarn "1182"
+open System
open System.Text.RegularExpressions
open Fable
open Fable.AST
@@ -96,7 +97,7 @@ let toChar (arg: Expr) =
let charToString =
function
- | Value(CharConstant v, r) -> Value(StringConstant(string v), r)
+ | Value(CharConstant v, r) -> Value(StringConstant(string v), r)
| e -> Helper.GlobalCall("String", String, [ e ], memb = "fromCharCode")
let toString com (ctx: Context) r (args: Expr list) =
@@ -953,7 +954,7 @@ let tryReplacedEntityRef (com: Compiler) entFullName =
let entFullName = entFullName[entFullName.LastIndexOf(".") + 1 ..]
let entFullName =
- match entFullName.IndexOf("`") with
+ match entFullName.IndexOf("`", StringComparison.Ordinal) with
| -1 -> entFullName
| i -> entFullName[0 .. i - 1]
@@ -2370,7 +2371,10 @@ let formattableString
|}
)
- printJsTaggedTemplate str holes (fun i -> "$" + string (i + offset))
+ printJsTaggedTemplate
+ str
+ holes
+ (fun i -> "$" + string (i + offset))
emitExpr r t args (callMacro + jsTaggedTemplate) |> Some
| "get_Format", Some x, _ ->
@@ -2695,7 +2699,12 @@ let tuples
match i.CompiledName, thisArg with
| (".ctor" | "Create"), _ ->
- let isStruct = i.DeclaringEntityFullName.StartsWith("System.ValueTuple")
+ let isStruct =
+ i.DeclaringEntityFullName.StartsWith(
+ "System.ValueTuple",
+ StringComparison.Ordinal
+ )
+
Value(NewTuple(args, isStruct), r) |> Some
| "get_Item1", Some x -> Get(x, TupleIndex 0, t, r) |> Some
| "get_Item2", Some x -> Get(x, TupleIndex 1, t, r) |> Some
@@ -3636,7 +3645,7 @@ let bigints
?loc = r
)
|> Some
- | None, meth when meth.StartsWith("get_") ->
+ | None, meth when meth.StartsWith("get_", StringComparison.Ordinal) ->
Helper.LibValue(com, "BigInt", meth, t) |> Some
| callee, meth ->
let args =
@@ -5682,7 +5691,7 @@ let guids
=
let parseGuid (literalGuid: string) =
try
- System.Guid.Parse(literalGuid) |> string |> makeStrConst
+ System.Guid.Parse(literalGuid) |> string |> makeStrConst
with e ->
e.Message |> addErrorAndReturnNull com ctx.InlinePath r
|> Some
@@ -6439,7 +6448,9 @@ let tryCall
| "Microsoft.FSharp.Reflection.FSharpReflectionExtensions" ->
// In netcore F# Reflection methods become extensions
// with names like `FSharpType.GetExceptionFields.Static`
- let isFSharpType = info.CompiledName.StartsWith("FSharpType")
+ let isFSharpType =
+ info.CompiledName.StartsWith("FSharpType", StringComparison.Ordinal)
+
let methName = info.CompiledName |> Naming.extensionMethodName
if isFSharpType then
@@ -6505,7 +6516,8 @@ let tryBaseConstructor
| Types.exception_ -> Some(makeImportLib com Any "Exception" "Types", args)
| Types.attribute -> Some(makeImportLib com Any "Attribute" "Types", args)
| fullName when
- fullName.StartsWith("Fable.Core.") && fullName.EndsWith("Attribute")
+ fullName.StartsWith("Fable.Core.", StringComparison.Ordinal)
+ && fullName.EndsWith("Attribute", StringComparison.Ordinal)
->
Some(makeImportLib com Any "Attribute" "Types", args)
| Types.dictionary ->
diff --git a/src/Fable.Transforms/FSharp2Fable.Util.fs b/src/Fable.Transforms/FSharp2Fable.Util.fs
index 0793837c5f..4260e12af7 100644
--- a/src/Fable.Transforms/FSharp2Fable.Util.fs
+++ b/src/Fable.Transforms/FSharp2Fable.Util.fs
@@ -111,7 +111,7 @@ type FsField(fi: FSharpField) =
| Some ent ->
match countConflictingCases 0 ent name with
| 0 -> name
- | n -> name + "_" + (string n)
+ | n -> name + "_" + (string n)
[]
type CompiledValue =
@@ -126,7 +126,7 @@ type FsUnionCase(uci: FSharpUnionCase) =
uci.Attributes
|> Helpers.tryFindAttrib Atts.compiledName
|> Option.map (fun (att: FSharpAttribute) ->
- att.ConstructorArguments[0] |> snd |> string
+ att.ConstructorArguments[0] |> snd |> string
)
static member FullName(uci: FSharpUnionCase) =
@@ -353,7 +353,7 @@ type FsEnt(maybeAbbrevEnt: FSharpEntity) =
if ent.IsArrayType then
let rank =
match ent.ArrayRank with
- | rank when rank > 1 -> "`" + string rank
+ | rank when rank > 1 -> "`" + string rank
| _ -> ""
Some("System.Array" + rank)
@@ -648,7 +648,7 @@ module Helpers =
(Fable.SourcePath sourcePath | Fable.PrecompiledLib(sourcePath, _)) ->
let rootMod = com.GetRootModule(sourcePath)
- if fullName.StartsWith(rootMod) then
+ if fullName.StartsWith(rootMod, StringComparison.Ordinal) then
fullName.Substring(rootMod.Length).TrimStart('.')
else
fullName
@@ -946,7 +946,9 @@ module Helpers =
let parentHasSignatureFile () =
v.DeclaringEntity
|> Option.bind (fun p -> p.SignatureLocation)
- |> Option.map (fun m -> m.FileName.EndsWith(".fsi"))
+ |> Option.map (fun m ->
+ m.FileName.EndsWith(".fsi", StringComparison.Ordinal)
+ )
|> Option.defaultValue false
v.IsModuleValueOrMember
@@ -1468,7 +1470,7 @@ module Patterns =
Some(memb, None, "toString", membArgTypes, membArgs)
// work-around for optimized hash operator (Operators.hash)
| Call(Some expr, memb, _, [], [ Call(None, comp, [], [], []) ]) when
- memb.FullName.EndsWith(".GetHashCode")
+ memb.FullName.EndsWith(".GetHashCode", StringComparison.Ordinal)
&& comp.FullName = "Microsoft.FSharp.Core.LanguagePrimitives.GenericEqualityERComparer"
->
Some(memb, Some comp, "GenericHash", [ expr.Type ], [ expr ])
@@ -1478,7 +1480,7 @@ module Patterns =
_,
[],
[ Coerce(t2, e2); Call(None, comp, [], [], []) ]) when
- memb.FullName.EndsWith(".Equals")
+ memb.FullName.EndsWith(".Equals", StringComparison.Ordinal)
&& t2.HasTypeDefinition
&& t2.TypeDefinition.CompiledName = "obj"
&& comp.FullName = "Microsoft.FSharp.Core.LanguagePrimitives.GenericEqualityComparer"
@@ -2367,7 +2369,13 @@ module Util =
|> Some
match attributes with
- | _ when entRef.FullName.StartsWith("Fable.Core.JS.") -> globalRef None
+ | _ when
+ entRef.FullName.StartsWith(
+ "Fable.Core.JS.",
+ StringComparison.Ordinal
+ )
+ ->
+ globalRef None
| GlobalAtt customName -> globalRef customName
| ImportAtt(selector, path) ->
let selector =
@@ -2464,15 +2472,23 @@ module Util =
let private isReplacementCandidatePrivate isFromDll (entFullName: string) =
if
- entFullName.StartsWith("System.")
- || entFullName.StartsWith("Microsoft.FSharp.")
+ entFullName.StartsWith("System.", StringComparison.Ordinal)
+ || entFullName.StartsWith(
+ "Microsoft.FSharp.",
+ StringComparison.Ordinal
+ )
then
isFromDll ()
// When compiling Fable itself, Fable.Core entities will be part of the code base, but still need to be replaced
else
- entFullName.StartsWith("Fable.Core.")
- && (not (entFullName.StartsWith("Fable.Core.JS."))
- || entFullName.EndsWith("Attribute"))
+ entFullName.StartsWith("Fable.Core.", StringComparison.Ordinal)
+ && (not (
+ entFullName.StartsWith(
+ "Fable.Core.JS.",
+ StringComparison.Ordinal
+ )
+ )
+ || entFullName.EndsWith("Attribute", StringComparison.Ordinal))
let isReplacementCandidate (ent: Fable.EntityRef) =
let isFromDll () = isFromDllNotPrecompiled ent
@@ -2691,7 +2707,9 @@ module Util =
match ent.TryFullName with
// By default mangle interfaces in System namespace as they are not meant to interact with JS
// except those that are used in fable-library Typescript files
- | Some fullName when fullName.StartsWith("System.") ->
+ | Some fullName when
+ fullName.StartsWith("System.", StringComparison.Ordinal)
+ ->
match fullName with
| Types.object
| Types.idisposable
@@ -2825,7 +2843,12 @@ module Util =
(thisArg: Fable.Expr option)
=
let msg =
- if info.DeclaringEntityFullName.StartsWith("Fable.Core.") then
+ if
+ info.DeclaringEntityFullName.StartsWith(
+ "Fable.Core.",
+ StringComparison.Ordinal
+ )
+ then
$"{info.DeclaringEntityFullName}.{info.CompiledName} is not supported, try updating fable tool"
else
com.WarnOnlyOnce(
diff --git a/src/Fable.Transforms/FSharp2Fable.fs b/src/Fable.Transforms/FSharp2Fable.fs
index a0810cd49f..6f9faa9b13 100644
--- a/src/Fable.Transforms/FSharp2Fable.fs
+++ b/src/Fable.Transforms/FSharp2Fable.fs
@@ -1,5 +1,6 @@
module rec Fable.Transforms.FSharp2Fable.Compiler
+open System
open System.Collections.Generic
open FSharp.Compiler.Symbols
@@ -278,7 +279,7 @@ let private transformTraitCall
)
sourceTypes
- |> Seq.tryPick (fun t ->
+ |> List.tryPick (fun t ->
let typeOpt = Replacements.Api.tryType com t
match typeOpt with
@@ -299,7 +300,7 @@ let private transformTraitCall
let fieldName = Naming.removeGetSetPrefix traitName
entity.FSharpFields
- |> Seq.tryPick (fun fi ->
+ |> List.tryPick (fun fi ->
if fi.Name = fieldName then
let kind =
Fable.FieldInfo.Create(
@@ -442,12 +443,12 @@ let private getImplementedSignatureInfo
)
|> Option.defaultWith (fun () ->
let isGetter =
- sign.Name.StartsWith("get_")
+ sign.Name.StartsWith("get_", StringComparison.Ordinal)
&& countNonCurriedParamsForSignature sign = 0
let isSetter =
not isGetter
- && sign.Name.StartsWith("set_")
+ && sign.Name.StartsWith("set_", StringComparison.Ordinal)
&& countNonCurriedParamsForSignature sign = 1
let name =
diff --git a/src/Fable.Transforms/Fable2Babel.fs b/src/Fable.Transforms/Fable2Babel.fs
index 66030a48ce..6a3cdb8495 100644
--- a/src/Fable.Transforms/Fable2Babel.fs
+++ b/src/Fable.Transforms/Fable2Babel.fs
@@ -1,5 +1,6 @@
module rec Fable.Transforms.Fable2Babel
+open System
open Fable
open Fable.AST
open Fable.AST.Babel
@@ -1386,7 +1387,7 @@ module Util =
match line.Trim() with
| "" -> true
| Naming.Regex IMPORT_REGEX (_ :: selector :: path :: _) ->
- if selector.StartsWith("{") then
+ if selector.StartsWith("{", StringComparison.Ordinal) then
for selector in
selector.TrimStart('{').TrimEnd('}').Split(',') do
com.GetImportExpr(
@@ -1401,7 +1402,9 @@ module Util =
true
else
let selector =
- if selector.StartsWith("*") then
+ if
+ selector.StartsWith("*", StringComparison.Ordinal)
+ then
selector
else
$"default as {selector}"
@@ -1555,7 +1558,7 @@ module Util =
=
match memberName with
| "ToString" -> Expression.identifier ("toString"), false
- | n when n.StartsWith("Symbol.") ->
+ | n when n.StartsWith("Symbol.", StringComparison.Ordinal) ->
Expression.memberExpression (
Expression.identifier ("Symbol"),
Expression.identifier (n[7..]),
@@ -2185,7 +2188,8 @@ module Util =
Expression.nullLiteral (?loc = r)
| Fable.UnitConstant -> undefined r None
| Fable.BoolConstant x -> Expression.booleanLiteral (x, ?loc = r)
- | Fable.CharConstant x -> Expression.stringLiteral (string x, ?loc = r)
+ | Fable.CharConstant x ->
+ Expression.stringLiteral (string x, ?loc = r)
| Fable.StringConstant x -> Expression.stringLiteral (x, ?loc = r)
| Fable.StringTemplate(tag, parts, values) ->
let tag = tag |> Option.map (fun e -> com.TransformAsExpr(ctx, e))
@@ -2200,17 +2204,17 @@ module Util =
JS.Replacements.makeDecimal com r value.Type x
|> transformAsExpr com ctx
| BigInt, (:? bigint as x) ->
- Expression.bigintLiteral (string x, ?loc = r)
+ Expression.bigintLiteral (string x, ?loc = r)
| Int64, (:? int64 as x) ->
- Expression.bigintLiteral (string x, ?loc = r)
+ Expression.bigintLiteral (string x, ?loc = r)
| UInt64, (:? uint64 as x) ->
- Expression.bigintLiteral (string x, ?loc = r)
+ Expression.bigintLiteral (string x, ?loc = r)
// | Int128, (:? System.Int128 as x) -> Expression.bigintLiteral(string x, ?loc=r)
// | UInt128, (:? System.UInt128 as x) -> Expression.bigintLiteral(string x, ?loc=r)
| NativeInt, (:? nativeint as x) ->
- Expression.bigintLiteral (string x, ?loc = r)
+ Expression.bigintLiteral (string x, ?loc = r)
| UNativeInt, (:? unativeint as x) ->
- Expression.bigintLiteral (string x, ?loc = r)
+ Expression.bigintLiteral (string x, ?loc = r)
| Int8, (:? int8 as x) ->
Expression.numericLiteral (float x, ?loc = r)
| UInt8, (:? uint8 as x) ->
@@ -4556,7 +4560,7 @@ module Util =
let genArgs =
Array.init
(ent.GenericParameters.Length)
- (fun i -> "gen" + string i |> makeIdent)
+ (fun i -> "gen" + string i |> makeIdent)
let generics = genArgs |> Array.map identAsExpr
let body = transformReflectionInfo com ctx None ent generics
diff --git a/src/Fable.Transforms/Global/Compiler.fs b/src/Fable.Transforms/Global/Compiler.fs
index 1ae73a0cc0..f8b161cd71 100644
--- a/src/Fable.Transforms/Global/Compiler.fs
+++ b/src/Fable.Transforms/Global/Compiler.fs
@@ -1,5 +1,7 @@
namespace Fable
+open System
+
module Literals =
[]
let VERSION = "4.5.0"
@@ -222,7 +224,12 @@ module CompilerExt =
file
let relPath =
- if relPath.StartsWith("./") then
+ if
+ relPath.StartsWith(
+ "./",
+ StringComparison.Ordinal
+ )
+ then
relPath[2..]
else
relPath
diff --git a/src/Fable.Transforms/Global/Naming.fs b/src/Fable.Transforms/Global/Naming.fs
index e3a724eda2..94dcf04969 100644
--- a/src/Fable.Transforms/Global/Naming.fs
+++ b/src/Fable.Transforms/Global/Naming.fs
@@ -9,13 +9,13 @@ module Naming =
open System.Text.RegularExpressions
let (|StartsWith|_|) (pattern: string) (txt: string) =
- if txt.StartsWith(pattern) then
+ if txt.StartsWith(pattern, StringComparison.Ordinal) then
txt.Substring(pattern.Length) |> Some
else
None
let (|EndsWith|_|) (pattern: string) (txt: string) =
- if txt.EndsWith(pattern) then
+ if txt.EndsWith(pattern, StringComparison.Ordinal) then
txt.Substring(0, txt.Length - pattern.Length) |> Some
else
None
@@ -91,7 +91,7 @@ module Naming =
let c = ident.[i]
if isIdentChar i c then
- string c
+ string c
else
replace c
)
@@ -109,30 +109,33 @@ module Naming =
Regex.Replace(input, pattern, value)
let replacePrefix (prefix: string) (value: string) (input: string) =
- if input.StartsWith(prefix) then
+ if input.StartsWith(prefix, StringComparison.Ordinal) then
value + (input.Substring(prefix.Length))
else
input
let replaceSuffix (suffix: string) (value: string) (input: string) =
- if input.EndsWith(suffix) then
+ if input.EndsWith(suffix, StringComparison.Ordinal) then
(input.Substring(0, input.Length - suffix.Length)) + value
else
input
let removeGetSetPrefix (s: string) =
- if s.StartsWith("get_") || s.StartsWith("set_") then
+ if
+ s.StartsWith("get_", StringComparison.Ordinal)
+ || s.StartsWith("set_", StringComparison.Ordinal)
+ then
s.Substring(4)
else
s
let extensionMethodName (s: string) =
- let i1 = s.IndexOf(".")
+ let i1 = s.IndexOf(".", StringComparison.Ordinal)
if i1 < 0 then
s
else
- let i2 = s.IndexOf(".", i1 + 1)
+ let i2 = s.IndexOf(".", i1 + 1, StringComparison.Ordinal)
if i2 < 0 then
s
@@ -358,7 +361,7 @@ module Naming =
let rec check originalName n =
let name =
if n > 0 then
- originalName + "_" + (string n)
+ originalName + "_" + (string n)
else
originalName
diff --git a/src/Fable.Transforms/Global/Prelude.fs b/src/Fable.Transforms/Global/Prelude.fs
index e25455260e..6520697026 100644
--- a/src/Fable.Transforms/Global/Prelude.fs
+++ b/src/Fable.Transforms/Global/Prelude.fs
@@ -9,7 +9,10 @@ module Extensions =
type String with
member str.StartsWithAny([] patterns: string[]) =
- patterns |> Array.exists (fun p -> str.StartsWith(p))
+ patterns
+ |> Array.exists (fun p ->
+ str.StartsWith(p, StringComparison.Ordinal)
+ )
module Dictionary =
open System.Collections.Generic
@@ -359,7 +362,7 @@ module Path =
/// If path belongs to a signature file (.fsi), replace the extension with .fs
let ensureFsExtension (path: string) =
- if path.EndsWith(".fsi") then
+ if path.EndsWith(".fsi", StringComparison.Ordinal) then
path.Substring(0, path.Length - 1)
else
path
diff --git a/src/Fable.Transforms/OverloadSuffix.fs b/src/Fable.Transforms/OverloadSuffix.fs
index d9a4f04368..bf3f084114 100644
--- a/src/Fable.Transforms/OverloadSuffix.fs
+++ b/src/Fable.Transforms/OverloadSuffix.fs
@@ -184,7 +184,7 @@ let getHash
// and implementation files, use the position instead
let genParams =
entityGenericParams
- |> List.mapi (fun i p -> p, string i)
+ |> List.mapi (fun i p -> p, string i)
|> dict
getHashPrivate paramTypes genParams
diff --git a/src/Fable.Transforms/Php/Fable2Php.fs b/src/Fable.Transforms/Php/Fable2Php.fs
index a6ffc03366..25ff48dfe3 100644
--- a/src/Fable.Transforms/Php/Fable2Php.fs
+++ b/src/Fable.Transforms/Php/Fable2Php.fs
@@ -1,5 +1,6 @@
module Fable.Transforms.Fable2Php
+open System
open FSharp.Compiler.Symbols
open Fable
open Fable.AST
@@ -1552,7 +1553,9 @@ let rec convertExpr (com: IPhpCompiler) (expr: Fable.Expr) =
PhpGlobal(name)
| _ ->
com.AddRequire(info.Path)
- let sepPos = info.Selector.IndexOf("__")
+
+ let sepPos =
+ info.Selector.IndexOf("__", StringComparison.Ordinal)
if sepPos >= 0 then
PhpIdent(
@@ -1829,7 +1832,7 @@ and convertValue (com: IPhpCompiler) (value: Fable.ValueKind) range =
| Fable.StringConstant(s) -> PhpConst(PhpConstString s)
| Fable.BoolConstant(b) -> PhpConst(PhpConstBool b)
| Fable.UnitConstant -> PhpConst(PhpConstNull)
- | Fable.CharConstant(c) -> PhpConst(PhpConstString(string c))
+ | Fable.CharConstant(c) -> PhpConst(PhpConstString(string c))
| Fable.Null _ -> PhpConst(PhpConstNull)
| Fable.NewList(Some(head, tail), _) ->
libCall
@@ -2472,7 +2475,7 @@ type PhpCompiler(com: Fable.Compiler) =
member this.MakeUniqueVar(name) =
id <- id + 1
- "_" + name + "__" + string id
+ "_" + name + "__" + string id
member this.NewScope() =
let oldScope = scope
@@ -2524,7 +2527,7 @@ type PhpCompiler(com: Fable.Compiler) =
basePath
(fullPhpPath (fixExt file))
- if p.StartsWith "./" then
+ if p.StartsWith("./", StringComparison.Ordinal) then
p.Substring 2
else
p
diff --git a/src/Fable.Transforms/Php/PhpPrinter.fs b/src/Fable.Transforms/Php/PhpPrinter.fs
index 3c2e617a20..05e2fc4c2a 100644
--- a/src/Fable.Transforms/Php/PhpPrinter.fs
+++ b/src/Fable.Transforms/Php/PhpPrinter.fs
@@ -202,7 +202,7 @@ module Output =
)
| PhpConst cst ->
match cst with
- | PhpConstNumber n -> write ctx (string n)
+ | PhpConstNumber n -> write ctx (string n)
| PhpConstString s -> writeStr ctx s
| PhpConstBool true -> write ctx "true"
| PhpConstBool false -> write ctx "false"
@@ -390,7 +390,7 @@ module Output =
write ctx s
write ctx "' => "
| PhpArrayInt n ->
- write ctx (string n)
+ write ctx (string n)
write ctx " => "
| PhpArrayNoIndex -> ()
@@ -423,7 +423,7 @@ module Output =
match case with
| IntCase i ->
writei casesCtx "case "
- write casesCtx (string i)
+ write casesCtx (string i)
| StringCase s ->
writei casesCtx "case '"
write casesCtx s
@@ -442,7 +442,7 @@ module Output =
match level with
| Some l ->
write ctx " "
- write ctx (string level)
+ write ctx (string level)
| None -> ()
writeln ctx ";"
@@ -708,7 +708,7 @@ module Output =
}
for i, d in file.Decls do
- writeln ctx ("#" + string i)
+ writeln ctx ("#" + string i)
writeDecl ctx d
writeln ctx ""
diff --git a/src/Fable.Transforms/Python/Fable2Python.fs b/src/Fable.Transforms/Python/Fable2Python.fs
index 6c55abdaee..952ea0676c 100644
--- a/src/Fable.Transforms/Python/Fable2Python.fs
+++ b/src/Fable.Transforms/Python/Fable2Python.fs
@@ -942,7 +942,9 @@ module Annotation =
match t with
| Fable.Measure _
| Fable.Any -> stdlibModuleTypeHint com ctx "typing" "Any" []
- | Fable.GenericParam(name = name) when name.StartsWith("$$") ->
+ | Fable.GenericParam(name = name) when
+ name.StartsWith("$$", StringComparison.Ordinal)
+ ->
stdlibModuleTypeHint com ctx "typing" "Any" []
| Fable.GenericParam(name = name) ->
match repeatedGenerics with
@@ -1526,8 +1528,9 @@ module Util =
| "get" -> Expression.identifier "__getitem__"
| "has" -> Expression.identifier "__contains__"
| "delete" -> Expression.identifier "__delitem__"
- | n when n.EndsWith "get_Count" -> Expression.identifier "__len__" // TODO: find a better way
- | n when n.StartsWith("Symbol.iterator") ->
+ | n when n.EndsWith("get_Count", StringComparison.Ordinal) ->
+ Expression.identifier "__len__" // TODO: find a better way
+ | n when n.StartsWith("Symbol.iterator", StringComparison.Ordinal) ->
let name = Identifier "__iter__"
Expression.name name
| n ->
@@ -2223,7 +2226,7 @@ module Util =
| Fable.UnitConstant -> undefined r, []
| Fable.BoolConstant x -> Expression.boolConstant (x, ?loc = r), []
| Fable.CharConstant x ->
- Expression.stringConstant (string x, ?loc = r), []
+ Expression.stringConstant (string x, ?loc = r), []
| Fable.StringConstant x -> Expression.stringConstant (x, ?loc = r), []
| Fable.StringTemplate(_, parts, values) ->
match parts with
@@ -2809,7 +2812,7 @@ module Util =
let exprs, _, stmts' = transformCallArgs com ctx info
- if macro.StartsWith("functools") then
+ if macro.StartsWith("functools", StringComparison.Ordinal) then
com.GetImportExpr(ctx, "functools") |> ignore
let args = exprs |> List.append thisArg
@@ -4505,7 +4508,7 @@ module Util =
Id = Identifier name
}
}) when
- name.StartsWith("_")
+ name.StartsWith("_", StringComparison.Ordinal)
->
Expression.subscript (
value,
@@ -4980,7 +4983,7 @@ module Util =
let genArgs =
Array.init
ent.GenericParameters.Length
- (fun i -> "gen" + string i |> makeIdent)
+ (fun i -> "gen" + string i |> makeIdent)
let args =
genArgs
@@ -5719,9 +5722,12 @@ module Util =
| _ -> ""
match name with
- | name when name.StartsWith("__") -> "A" + name
- | name when name.StartsWith("fable") -> "C" + name
- | name when name.StartsWith(".") -> "D" + name
+ | name when name.StartsWith("__", StringComparison.Ordinal) ->
+ "A" + name
+ | name when name.StartsWith("fable", StringComparison.Ordinal) ->
+ "C" + name
+ | name when name.StartsWith(".", StringComparison.Ordinal) ->
+ "D" + name
| _ -> "B" + name
)
diff --git a/src/Fable.Transforms/Python/Prelude.fs b/src/Fable.Transforms/Python/Prelude.fs
index 723c73fadb..c01b8cc957 100644
--- a/src/Fable.Transforms/Python/Prelude.fs
+++ b/src/Fable.Transforms/Python/Prelude.fs
@@ -169,7 +169,7 @@ module Naming =
let rec check originalName n =
let name =
if n > 0 then
- originalName + "_" + (string n)
+ originalName + "_" + (string n)
else
originalName
@@ -200,7 +200,7 @@ module Naming =
let c = ident.[i]
if isIdentChar i c then
- string c
+ string c
elif
c = '$'
|| c = '_'
@@ -250,7 +250,7 @@ module Naming =
let sanitizeIdent conflicts (name: string) part =
let name =
- if name.EndsWith("@") then
+ if name.EndsWith("@", StringComparison.Ordinal) then
$"_{name.Substring(0, name.Length - 1)}"
else
name
diff --git a/src/Fable.Transforms/Python/PythonPrinter.fs b/src/Fable.Transforms/Python/PythonPrinter.fs
index 09dae126a7..30bd1fdb7a 100644
--- a/src/Fable.Transforms/Python/PythonPrinter.fs
+++ b/src/Fable.Transforms/Python/PythonPrinter.fs
@@ -370,7 +370,7 @@ module PrinterExtensions =
let i = int m.Groups[1].Value
for j = i to node.Args.Length - 1 do
- rep.Add("$" + string j)
+ rep.Add("$" + string j)
String.concat ", " rep
)
@@ -598,7 +598,7 @@ module PrinterExtensions =
printer.Print(Naming.escapeString (fun _ -> false) value)
printer.Print("\"")
| Constant(value = FloatLiteral value) ->
- let value = string value
+ let value = string value
printer.Print(value)
// Make sure it's a valid Python float (not int)
@@ -615,8 +615,9 @@ module PrinterExtensions =
else
"False"
)
- | Constant(value = IntLiteral value) -> printer.Print(string value)
- | Constant(value = value) -> printer.Print(string value)
+ | Constant(value = IntLiteral value) ->
+ printer.Print(string value)
+ | Constant(value = value) -> printer.Print(string value)
| IfExp ex -> printer.Print(ex)
| Call ex -> printer.Print(ex)
diff --git a/src/Fable.Transforms/Python/Replacements.fs b/src/Fable.Transforms/Python/Replacements.fs
index 225d43bbc0..d403384386 100644
--- a/src/Fable.Transforms/Python/Replacements.fs
+++ b/src/Fable.Transforms/Python/Replacements.fs
@@ -3,6 +3,7 @@ module Fable.Transforms.Py.Replacements
#nowarn "1182"
+open System
open Fable
open Fable.AST
open Fable.AST.Fable
@@ -3188,7 +3189,11 @@ let tuples
match i.CompiledName, thisArg with
| (".ctor" | "Create"), _ ->
- let isStruct = i.DeclaringEntityFullName.StartsWith("System.ValueTuple")
+ let isStruct =
+ i.DeclaringEntityFullName.StartsWith(
+ "System.ValueTuple",
+ StringComparison.Ordinal
+ )
Value(NewTuple(args, isStruct), r) |> Some
| "get_Item1", Some x -> Get(x, TupleIndex 0, t, r) |> Some
@@ -4129,7 +4134,7 @@ let bigints
?loc = r
)
|> Some
- | None, meth when meth.StartsWith("get_") ->
+ | None, meth when meth.StartsWith("get_", StringComparison.Ordinal) ->
Helper.LibValue(com, "big_int", meth, t) |> Some
| callee, meth ->
let args =
@@ -6943,7 +6948,9 @@ let tryCall
| "Microsoft.FSharp.Reflection.FSharpReflectionExtensions" ->
// In netcore F# Reflection methods become extensions
// with names like `FSharpType.GetExceptionFields.Static`
- let isFSharpType = info.CompiledName.StartsWith("FSharpType")
+ let isFSharpType =
+ info.CompiledName.StartsWith("FSharpType", StringComparison.Ordinal)
+
let methName = info.CompiledName |> Naming.extensionMethodName
if isFSharpType then
diff --git a/src/Fable.Transforms/Replacements.Util.fs b/src/Fable.Transforms/Replacements.Util.fs
index bdf885b438..7cf8f295c1 100644
--- a/src/Fable.Transforms/Replacements.Util.fs
+++ b/src/Fable.Transforms/Replacements.Util.fs
@@ -2,6 +2,7 @@ module Fable.Transforms.Replacements.Util
#nowarn "1182"
+open System
open System.Text.RegularExpressions
open Fable
@@ -296,7 +297,7 @@ let str txt = Value(StringConstant txt, None)
let genArg (com: ICompiler) (ctx: Context) r i (genArgs: Type list) =
List.tryItem i genArgs
|> Option.defaultWith (fun () ->
- "Couldn't find generic argument in position " + (string i)
+ "Couldn't find generic argument in position " + (string i)
|> addError com ctx.InlinePath r
Any
@@ -436,7 +437,7 @@ let changeRangeToCallSite
let splitFullName (fullname: string) =
let fullname =
- match fullname.IndexOf("[") with
+ match fullname.IndexOf("[", StringComparison.Ordinal) with
| -1 -> fullname
| i -> fullname[.. i - 1]
@@ -446,7 +447,7 @@ let splitFullName (fullname: string) =
let getTypeNameFromFullName (fullname: string) =
let fullname =
- match fullname.IndexOf("[") with
+ match fullname.IndexOf("[", StringComparison.Ordinal) with
| -1 -> fullname
| i -> fullname[.. i - 1]
diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs
index 88e070f8cc..cd28bc2c91 100644
--- a/src/Fable.Transforms/Replacements.fs
+++ b/src/Fable.Transforms/Replacements.fs
@@ -2,6 +2,7 @@ module Fable.Transforms.JS.Replacements
#nowarn "1182"
+open System
open System.Text.RegularExpressions
open Fable
open Fable.AST
@@ -1435,12 +1436,14 @@ let fableCoreLib
=
let fixDynamicImportPath =
function
- | Value(StringConstant path, r) when path.EndsWith(".fs") ->
+ | Value(StringConstant path, r) when
+ path.EndsWith(".fs", StringComparison.Ordinal)
+ ->
// In imports *.ts extensions have to be converted to *.js extensions instead
let fileExt = com.Options.FileExtension
let fileExt =
- if fileExt.EndsWith(".ts") then
+ if fileExt.EndsWith(".ts", StringComparison.Ordinal) then
Path.ChangeExtension(fileExt, ".js")
else
fileExt
@@ -2546,7 +2549,19 @@ let strings
| [ ExprType Char ]
| [ ExprType String ]
| [ ExprType Char; ExprType(Number(Int32, NumberInfo.Empty)) ]
- | [ ExprType String; ExprType(Number(Int32, NumberInfo.Empty)) ] ->
+ | [ ExprType String; ExprType(Number(Int32, NumberInfo.Empty)) ]
+ | [ ExprType String; StringComparisonEnumValue ]
+ | [ ExprType String
+ ExprType(Number(Int32, NumberInfo.Empty))
+ StringComparisonEnumValue ] ->
+ let args =
+ args
+ |> List.filter (
+ function
+ | StringComparisonEnumValue -> false
+ | _ -> true
+ )
+
Helper.InstanceCall(
c,
Naming.lowerFirst i.CompiledName,
@@ -3261,7 +3276,12 @@ let tuples
match i.CompiledName, thisArg with
| (".ctor" | "Create"), _ ->
- let isStruct = i.DeclaringEntityFullName.StartsWith("System.ValueTuple")
+ let isStruct =
+ i.DeclaringEntityFullName.StartsWith(
+ "System.ValueTuple",
+ StringComparison.Ordinal
+ )
+
Value(NewTuple(args, isStruct), r) |> Some
| "get_Item1", Some x -> Get(x, TupleIndex 0, t, r) |> Some
| "get_Item2", Some x -> Get(x, TupleIndex 1, t, r) |> Some
@@ -6283,7 +6303,7 @@ let guids
=
let parseGuid (literalGuid: string) =
try
- System.Guid.Parse(literalGuid) |> string |> makeStrConst
+ System.Guid.Parse(literalGuid) |> string |> makeStrConst
with e ->
e.Message |> addErrorAndReturnNull com ctx.InlinePath r
|> Some
@@ -7042,7 +7062,9 @@ let tryCall
| "Microsoft.FSharp.Reflection.FSharpReflectionExtensions" ->
// In netcore F# Reflection methods become extensions
// with names like `FSharpType.GetExceptionFields.Static`
- let isFSharpType = info.CompiledName.StartsWith("FSharpType")
+ let isFSharpType =
+ info.CompiledName.StartsWith("FSharpType", StringComparison.Ordinal)
+
let methName = info.CompiledName |> Naming.extensionMethodName
if isFSharpType then
@@ -7108,7 +7130,8 @@ let tryBaseConstructor
| Types.exception_ -> Some(makeImportLib com Any "Exception" "Types", args)
| Types.attribute -> Some(makeImportLib com Any "Attribute" "Types", args)
| fullName when
- fullName.StartsWith("Fable.Core.") && fullName.EndsWith("Attribute")
+ fullName.StartsWith("Fable.Core.", StringComparison.Ordinal)
+ && fullName.EndsWith("Attribute", StringComparison.Ordinal)
->
Some(makeImportLib com Any "Attribute" "Types", args)
| Types.dictionary ->
diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs
index 57585ae2bf..a74ee2c1bc 100644
--- a/src/Fable.Transforms/Rust/Fable2Rust.fs
+++ b/src/Fable.Transforms/Rust/Fable2Rust.fs
@@ -1,5 +1,6 @@
module rec Fable.Transforms.Rust.Fable2Rust
+open System
open Fable
open Fable.AST
open Fable.Transforms
@@ -393,11 +394,11 @@ module TypeInfo =
let hasMutableFields (com: IRustCompiler) (ent: Fable.Entity) =
if ent.IsFSharpUnion then
ent.UnionCases
- |> Seq.exists (fun uci ->
+ |> List.exists (fun uci ->
uci.UnionCaseFields |> List.exists (fun fi -> fi.IsMutable)
)
else
- ent.FSharpFields |> Seq.exists (fun fi -> fi.IsMutable)
+ ent.FSharpFields |> List.exists (fun fi -> fi.IsMutable)
let isEntityOfType
(com: IRustCompiler)
@@ -839,7 +840,7 @@ module TypeInfo =
| [ Fable.Unit ] -> []
| _ -> argTypes
- let argCount = string (List.length argTypes)
+ let argCount = string (List.length argTypes)
let genArgs = argTypes @ [ returnType ]
transformImportType com ctx genArgs "Native" ("Func" + argCount)
@@ -989,7 +990,12 @@ module TypeInfo =
let (|HasEmitAttribute|_|) (ent: Fable.Entity) =
ent.Attributes
|> Seq.tryPick (fun att ->
- if att.Entity.FullName.StartsWith(Atts.emit) then
+ if
+ att.Entity.FullName.StartsWith(
+ Atts.emit,
+ StringComparison.Ordinal
+ )
+ then
match att.ConstructorArgs with
| [ :? string as macro ] -> Some macro
| _ -> None
@@ -1006,7 +1012,12 @@ module TypeInfo =
let (|HasReferenceTypeAttribute|_|) (ent: Fable.Entity) =
ent.Attributes
|> Seq.tryPick (fun att ->
- if att.Entity.FullName.StartsWith(Atts.referenceType) then
+ if
+ att.Entity.FullName.StartsWith(
+ Atts.referenceType,
+ StringComparison.Ordinal
+ )
+ then
match att.ConstructorArgs with
| [ :? int as ptrType ] ->
match ptrType with
@@ -1058,7 +1069,7 @@ module TypeInfo =
transformGenericType com ctx genArgs (rawIdent "Result")
let transformChoiceType com ctx genArgs : Rust.Ty =
- let argCount = string (List.length genArgs)
+ let argCount = string (List.length genArgs)
transformImportType com ctx genArgs "Choice" ("Choice`" + argCount)
let transformRefCellType com ctx genArg : Rust.Ty =
@@ -1368,7 +1379,7 @@ module Util =
let isUnitArg (ident: Fable.Ident) =
ident.IsCompilerGenerated
&& ident.Type = Fable.Unit
- && (ident.DisplayName.StartsWith("unitVar")
+ && (ident.DisplayName.StartsWith("unitVar", StringComparison.Ordinal)
|| ident.DisplayName.Contains("@"))
let discardUnitArg (genArgs: Fable.Type list) (args: Fable.Ident list) =
@@ -1753,7 +1764,7 @@ module Util =
| [ Fable.Unit ] -> []
| _ -> argTypes
- let argCount = string (List.length argTypes)
+ let argCount = string (List.length argTypes)
let funcWrap = getLibraryImportName com ctx "Native" ("Func" + argCount)
let expr = transformIdent com ctx None ident
@@ -2007,35 +2018,35 @@ module Util =
None
| NativeInt, (:? nativeint as x) ->
- let expr = mkIsizeLitExpr (abs x |> string)
+ let expr = mkIsizeLitExpr (abs x |> string)
if x < 0n then
expr |> mkNegExpr
else
expr
| Int8, (:? int8 as x) ->
- let expr = mkInt8LitExpr (abs x |> string)
+ let expr = mkInt8LitExpr (abs x |> string)
if x < 0y then
expr |> mkNegExpr
else
expr
| Int16, (:? int16 as x) ->
- let expr = mkInt16LitExpr (abs x |> string)
+ let expr = mkInt16LitExpr (abs x |> string)
if x < 0s then
expr |> mkNegExpr
else
expr
| Int32, (:? int32 as x) ->
- let expr = mkInt32LitExpr (abs x |> string)
+ let expr = mkInt32LitExpr (abs x |> string)
if x < 0 then
expr |> mkNegExpr
else
expr
| Int64, (:? int64 as x) ->
- let expr = mkInt64LitExpr (abs x |> string)
+ let expr = mkInt64LitExpr (abs x |> string)
if x < 0 then
expr |> mkNegExpr
@@ -2044,36 +2055,37 @@ module Util =
| Int128, x -> // (:? System.Int128 as x) ->
// let expr = mkInt128LitExpr (System.Int128.Abs(x) |> string)
// if x < 0 then expr |> mkNegExpr else expr
- let s = string x
+ let s = string x
let expr = mkInt128LitExpr (s.TrimStart('-'))
- if s.StartsWith("-") then
+ if s.StartsWith("-", StringComparison.Ordinal) then
expr |> mkNegExpr
else
expr
- | UNativeInt, (:? unativeint as x) -> mkUsizeLitExpr (x |> string)
- | UInt8, (:? uint8 as x) -> mkUInt8LitExpr (x |> string)
- | UInt16, (:? uint16 as x) -> mkUInt16LitExpr (x |> string)
- | UInt32, (:? uint32 as x) -> mkUInt32LitExpr (x |> string)
- | UInt64, (:? uint64 as x) -> mkUInt64LitExpr (x |> string)
+ | UNativeInt, (:? unativeint as x) ->
+ mkUsizeLitExpr (x |> string)
+ | UInt8, (:? uint8 as x) -> mkUInt8LitExpr (x |> string)
+ | UInt16, (:? uint16 as x) -> mkUInt16LitExpr (x |> string)
+ | UInt32, (:? uint32 as x) -> mkUInt32LitExpr (x |> string)
+ | UInt64, (:? uint64 as x) -> mkUInt64LitExpr (x |> string)
| UInt128, x -> // (:? System.UInt128 as x) ->
- mkUInt128LitExpr (x |> string)
+ mkUInt128LitExpr (x |> string)
| Float16, (:? float32 as x) ->
- let expr = mkFloat32LitExpr (abs x |> string)
+ let expr = mkFloat32LitExpr (abs x |> string)
if x < 0.0f then
expr |> mkNegExpr
else
expr
| Float32, (:? float32 as x) ->
- let expr = mkFloat32LitExpr (abs x |> string)
+ let expr = mkFloat32LitExpr (abs x |> string)
if x < 0.0f then
expr |> mkNegExpr
else
expr
| Float64, (:? float as x) ->
- let expr = mkFloat64LitExpr (abs x |> string)
+ let expr = mkFloat64LitExpr (abs x |> string)
if x < 0.0 then
expr |> mkNegExpr
@@ -2085,7 +2097,7 @@ module Util =
$"Expected literal of type %A{kind} but got {x.GetType().FullName}"
|> addError com [] r
- mkFloat64LitExpr (string 0.)
+ mkFloat64LitExpr (string 0.)
let makeStaticString com ctx (value: Rust.Expr) =
makeLibCall com ctx None "String" "string" [ value ]
@@ -2245,7 +2257,12 @@ module Util =
| "FSharp.Core.FSharpResult`2.Ok" -> rawIdent "Ok" |> Some
| "FSharp.Core.FSharpResult`2.Error" -> rawIdent "Err" |> Some
| _ ->
- if fullName.StartsWith("FSharp.Core.FSharpChoice`") then
+ if
+ fullName.StartsWith(
+ "FSharp.Core.FSharpChoice`",
+ StringComparison.Ordinal
+ )
+ then
fullName
|> Fable.Naming.replacePrefix "FSharp.Core.FSharp" ""
|> Some
@@ -2674,7 +2691,7 @@ module Util =
let info = emitInfo.CallInfo
let macro = emitInfo.Macro
// if it ends with '!', it's a Rust macro
- if macro.EndsWith("!") then
+ if macro.EndsWith("!", StringComparison.Ordinal) then
transformMacro com ctx range emitInfo
else // otherwise it's an Emit
let thisArg =
@@ -4392,7 +4409,7 @@ module Util =
ctx.ScopedSymbols |> Helpers.Map.except closedOverCloneableIdents
let ctx = { ctx with ScopedSymbols = scopedSymbols } //; HasMultipleUses = true }
- let argCount = args |> List.length |> string
+ let argCount = args |> List.length |> string
let fnBody = transformFunctionBody com ctx args body
let fnBody =
@@ -4665,11 +4682,16 @@ module Util =
| [ :? string as name; :? string as value ] ->
[ mkEqAttr name value ]
| [ :? string as name; :? (obj[]) as items ] ->
- [ mkAttr name (items |> Array.map string) ]
+ [ mkAttr name (items |> Array.map string) ]
| _ -> []
// translate test methods attributes
// TODO: support more test frameworks
- elif a.Entity.FullName.EndsWith(".FactAttribute") then
+ elif
+ a.Entity.FullName.EndsWith(
+ ".FactAttribute",
+ StringComparison.Ordinal
+ )
+ then
[ mkAttr "test" [] ]
else
[]
@@ -4686,7 +4708,7 @@ module Util =
| [ :? string as name; :? string as value ] ->
[ mkInnerEqAttr name value ]
| [ :? string as name; :? (obj[]) as items ] ->
- [ mkInnerAttr name (items |> Array.map string) ]
+ [ mkInnerAttr name (items |> Array.map string) ]
| _ -> []
else
[]
@@ -5827,13 +5849,14 @@ module Util =
let isFableLibraryPath (com: IRustCompiler) (path: string) =
not (isFableLibrary com)
- && (path.StartsWith(com.LibraryDir) || path = "fable_library_rust")
+ && (path.StartsWith(com.LibraryDir, StringComparison.Ordinal)
+ || path = "fable_library_rust")
let getImportModulePath (com: IRustCompiler) (path: string) =
let isAbsolutePath =
- path.StartsWith("/")
- || path.StartsWith("\\")
- || path.IndexOf(":") = 1
+ path.StartsWith("/", StringComparison.Ordinal)
+ || path.StartsWith("\\", StringComparison.Ordinal)
+ || path.IndexOf(":", StringComparison.Ordinal) = 1
let modulePath =
if isAbsolutePath || (isFableLibraryPath com path) then
@@ -5900,7 +5923,7 @@ module Util =
|> getUniqueNameInRootScope ctx
let fixFileExtension (com: IRustCompiler) (path: string) =
- if path.EndsWith(".fs") then
+ if path.EndsWith(".fs", StringComparison.Ordinal) then
let fileExt = com.Options.FileExtension
Path.ChangeExtension(path, fileExt)
else
@@ -5930,7 +5953,7 @@ module Compiler =
"`importMember` must be assigned to a variable"
|> addError com [] r
- let isMacro = selector.EndsWith("!")
+ let isMacro = selector.EndsWith("!", StringComparison.Ordinal)
let selector = selector |> Fable.Naming.replaceSuffix "!" ""
let path = fixFileExtension self path
diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs
index 134e008d39..1ecd2e240c 100644
--- a/src/Fable.Transforms/Rust/Replacements.fs
+++ b/src/Fable.Transforms/Rust/Replacements.fs
@@ -3,6 +3,7 @@ module Fable.Transforms.Rust.Replacements
#nowarn "1182"
+open System
open System.Text.RegularExpressions
open Fable
open Fable.AST
@@ -3116,7 +3117,12 @@ let tuples
match i.CompiledName, thisArg with
| (".ctor" | "Create"), _ ->
- let isStruct = i.DeclaringEntityFullName.StartsWith("System.ValueTuple")
+ let isStruct =
+ i.DeclaringEntityFullName.StartsWith(
+ "System.ValueTuple",
+ StringComparison.Ordinal
+ )
+
Value(NewTuple(args, isStruct), r) |> Some
| "get_Item1", Some x -> Get(x, TupleIndex 0, t, r) |> Some
| "get_Item2", Some x -> Get(x, TupleIndex 1, t, r) |> Some
@@ -4087,7 +4093,7 @@ let bigints
?loc = r
)
|> Some
- | meth, None, _ when meth.StartsWith("get_") ->
+ | meth, None, _ when meth.StartsWith("get_", StringComparison.Ordinal) ->
let meth = meth |> Naming.removeGetSetPrefix |> Naming.lowerFirst
Helper.LibCall(com, "BigInt", meth, t, []) |> Some
| meth, None, _ ->
@@ -6569,7 +6575,9 @@ let tryCall
| "Microsoft.FSharp.Reflection.FSharpReflectionExtensions" ->
// In netcore F# Reflection methods become extensions
// with names like `FSharpType.GetExceptionFields.Static`
- let isFSharpType = info.CompiledName.StartsWith("FSharpType")
+ let isFSharpType =
+ info.CompiledName.StartsWith("FSharpType", StringComparison.Ordinal)
+
let methName = info.CompiledName |> Naming.extensionMethodName
if isFSharpType then
diff --git a/src/Fable.Transforms/Transforms.Util.fs b/src/Fable.Transforms/Transforms.Util.fs
index bbcb8114ed..4cbde5d27e 100644
--- a/src/Fable.Transforms/Transforms.Util.fs
+++ b/src/Fable.Transforms/Transforms.Util.fs
@@ -1,5 +1,7 @@
namespace Fable.Transforms
+open System
+
[]
module Atts =
[]
@@ -663,7 +665,7 @@ module Log =
let attachRange (range: SourceLocation option) msg =
match range with
- | Some range -> msg + " " + (string range)
+ | Some range -> msg + " " + (string range)
| None -> msg
let attachRangeAndFile
@@ -672,7 +674,8 @@ module Log =
msg
=
match range with
- | Some range -> msg + " " + (string range) + " (" + fileName + ")"
+ | Some range ->
+ msg + " " + (string range) + " (" + fileName + ")"
| None -> msg + " (" + fileName + ")"
@@ -851,6 +854,15 @@ module AST =
| MaybeCasted(Value(Null _, _)) -> Some()
| _ -> None
+ let (|StringComparisonEnumValue|_|) e =
+ match e with
+ | Expr.Value(
+ kind = NumberConstant(
+ info = NumberInfo.IsEnum({
+ FullName = "System.StringComparison"
+ }))) -> Some()
+ | _ -> 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)
@@ -1141,7 +1153,11 @@ module AST =
match com.Options.Language with
| Rust ->
if
- moduleName = "System" || moduleName.StartsWith("System.")
+ moduleName = "System"
+ || moduleName.StartsWith(
+ "System.",
+ StringComparison.Ordinal
+ )
then
moduleName + "::" + memberName
else
diff --git a/src/fable-library-dart/Seq.fs b/src/fable-library-dart/Seq.fs
index f585ddcc16..a1be4f23df 100644
--- a/src/fable-library-dart/Seq.fs
+++ b/src/fable-library-dart/Seq.fs
@@ -37,7 +37,7 @@ module Enumerator =
if i > 0 then
str <- str + "; "
- str <- str + (string e.Current)
+ str <- str + (string<'T> e.Current)
i <- i + 1
if i = maxCount then
diff --git a/src/fable-library/Seq.fs b/src/fable-library/Seq.fs
index 62d4126216..abe177b489 100644
--- a/src/fable-library/Seq.fs
+++ b/src/fable-library/Seq.fs
@@ -56,7 +56,7 @@ module Enumerator =
if i > 0 then
str <- str + "; "
- str <- str + (string e.Current)
+ str <- str + (string<'T> e.Current)
i <- i + 1
if i = maxCount then
diff --git a/src/fable-library/System.Text.fs b/src/fable-library/System.Text.fs
index 5c21436631..f47b8c7e1e 100644
--- a/src/fable-library/System.Text.fs
+++ b/src/fable-library/System.Text.fs
@@ -22,23 +22,23 @@ type StringBuilder(value: string, capacity: int) =
x
member x.Append(c: char) =
- buf.Add(string c)
+ buf.Add(string c)
x
member x.Append(o: int) =
- buf.Add(string o)
+ buf.Add(string o)
x
member x.Append(o: float) =
- buf.Add(string o)
+ buf.Add(string o)
x
member x.Append(o: bool) =
- buf.Add(string o)
+ buf.Add(string o)
x
member x.Append(o: obj) =
- buf.Add(string o)
+ buf.Add(string o)
x
member x.Append(cs: char[]) =
diff --git a/src/quicktest-dart/QuickTest.fs b/src/quicktest-dart/QuickTest.fs
index e71add1a83..8ca2a7234d 100644
--- a/src/quicktest-dart/QuickTest.fs
+++ b/src/quicktest-dart/QuickTest.fs
@@ -27,7 +27,7 @@ let throwsAnyError (f: unit -> 'a) : unit =
f () |> ignore
true
with e ->
- print $"Got expected error: %s{string e}"
+ print $"Got expected error: %s{string e}"
false
if success then
diff --git a/src/quicktest/QuickTest.fs b/src/quicktest/QuickTest.fs
index 64f5b9c1a8..3db32de935 100644
--- a/src/quicktest/QuickTest.fs
+++ b/src/quicktest/QuickTest.fs
@@ -42,7 +42,9 @@ let testCase (msg: string) f : unit =
printfn "%s" ex.Message
if
- ex.Message <> null && ex.Message.StartsWith("[ASSERT ERROR]") |> not
+ ex.Message <> null
+ && ex.Message.StartsWith("[ASSERT ERROR]", StringComparison.Ordinal)
+ |> not
then
printfn "%s" (ex.StackTrace ??= "")
@@ -60,7 +62,11 @@ let testCaseAsync msg f =
if
ex.Message <> null
- && ex.Message.StartsWith("[ASSERT ERROR]") |> not
+ && ex.Message.StartsWith(
+ "[ASSERT ERROR]",
+ StringComparison.Ordinal
+ )
+ |> not
then
printfn "%s" (ex.StackTrace ??= "")
}
diff --git a/tests/Js/Main/StringTests.fs b/tests/Js/Main/StringTests.fs
index 92ce6496f6..a7c7eb271c 100644
--- a/tests/Js/Main/StringTests.fs
+++ b/tests/Js/Main/StringTests.fs
@@ -719,6 +719,14 @@ let tests =
"abcdbc".IndexOf('b', 3)
|> equal 4
+ testCase "String.IndexOf with StringComparison" <| fun () ->
+ "abcdbc".IndexOf("b", StringComparison.Ordinal)
+ |> equal 1
+
+ testCase "String.IndexOf with index and StringComparison" <| fun () ->
+ "abcdbc".IndexOf("b", 3, StringComparison.Ordinal)
+ |> equal 4
+
testCase "String.LastIndexOf char works" <| fun () ->
"abcdbc".LastIndexOf('b') * 100 + "abcd".LastIndexOf('e')
|> equal 399
@@ -727,6 +735,14 @@ let tests =
"abcdbcebc".LastIndexOf('b', 3)
|> equal 1
+ testCase "String.LastIndexOf with StringComparison" <| fun () ->
+ "abcdbc".LastIndexOf("b", StringComparison.Ordinal)
+ |> equal 4
+
+ testCase "String.LastIndexOf with index and StringComparison" <| fun () ->
+ "abcdbc".LastIndexOf("b", 3, StringComparison.Ordinal)
+ |> equal 1
+
testCase "String.IndexOf works" <| fun () ->
"abcd".IndexOf("bc") * 100 + "abcd".IndexOf("bd")
|> equal 99