diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs index 8da6ceb2927..e3de75d0d1b 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs @@ -10,8 +10,8 @@ module Program = let addMSBuildv14BackupResolution () = let onResolveEvent = new ResolveEventHandler(fun sender evArgs -> let requestedAssembly = AssemblyName(evArgs.Name) - if requestedAssembly.Name.StartsWith("Microsoft.Build") && - not (requestedAssembly.Name.EndsWith(".resources")) && + if requestedAssembly.Name.StartsWith("Microsoft.Build", StringComparison.Ordinal) && + not (requestedAssembly.Name.EndsWith(".resources", StringComparison.Ordinal)) && not (requestedAssembly.Version.ToString().Contains("12.0.0.0")) then // If the version of MSBuild that we're using wasn't present on the machine, then diff --git a/src/absil/il.fs b/src/absil/il.fs index 726ac147674..180a170f209 100644 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -356,8 +356,7 @@ type AssemblyRefData = let AssemblyRefUniqueStampGenerator = new UniqueStampGenerator() let isMscorlib data = - if System.String.Compare(data.assemRefName, "mscorlib") = 0 then true - else false + data.assemRefName = "mscorlib" [] type ILAssemblyRef(data) = diff --git a/src/absil/illib.fs b/src/absil/illib.fs index dab61033a3f..b2fd979a55e 100644 --- a/src/absil/illib.fs +++ b/src/absil/illib.fs @@ -445,6 +445,13 @@ module ValueOption = let inline ofOption x = match x with Some x -> ValueSome x | None -> ValueNone let inline bind f x = match x with ValueSome x -> f x | ValueNone -> ValueNone +type String with + member inline x.StartsWithOrdinal(value) = + x.StartsWith(value, StringComparison.Ordinal) + + member inline x.EndsWithOrdinal(value) = + x.EndsWith(value, StringComparison.Ordinal) + module String = let indexNotFound() = raise (new KeyNotFoundException("An index for the character was not found in the string")) @@ -524,7 +531,7 @@ module String = let (|StartsWith|_|) pattern value = if String.IsNullOrWhiteSpace value then None - elif value.StartsWith pattern then + elif value.StartsWithOrdinal(pattern) then Some() else None @@ -542,7 +549,7 @@ module String = while not (isNull !line) do yield !line line := reader.ReadLine() - if str.EndsWith("\n") then + if str.EndsWithOrdinal("\n") then // last trailing space not returned // http://stackoverflow.com/questions/19365404/stringreader-omits-trailing-linebreak yield String.Empty diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index 191282fe5bc..95194aea5ad 100644 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -1296,7 +1296,7 @@ let rec emitInstr cenv (modB : ModuleBuilder) emEnv (ilG:ILGenerator) instr = ignore src () #else - if cenv.generatePdb && not (src.Document.File.EndsWith("stdin", StringComparison.Ordinal)) then + if cenv.generatePdb && not (src.Document.File.EndsWithOrdinal("stdin")) then let guid x = match x with None -> Guid.Empty | Some g -> Guid(g:byte[]) in let symDoc = modB.DefineDocumentAndLog(src.Document.File, guid src.Document.Language, guid src.Document.Vendor, guid src.Document.DocumentType) ilG.MarkSequencePointAndLog(symDoc, src.Line, src.Column, src.EndLine, src.EndColumn) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 69d3d5aab2e..42528dd3881 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -695,7 +695,7 @@ let OutputPhasedErrorR (os:StringBuilder) (err:PhasedDiagnostic) = | ContextInfo.TupleInRecordFields -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore os.Append(System.Environment.NewLine + FSComp.SR.commaInsteadOfSemicolonInRecord()) |> ignore - | _ when t2 = "bool" && t1.EndsWith " ref" -> + | _ when t2 = "bool" && t1.EndsWithOrdinal(" ref") -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore os.Append(System.Environment.NewLine + FSComp.SR.derefInsteadOfNot()) |> ignore | _ -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore @@ -1604,7 +1604,7 @@ let SanitizeFileName fileName implicitIncludeDir = let currentDir = implicitIncludeDir // if the file name is not rooted in the current directory, return the full path - if not(fullPath.StartsWith(currentDir)) then + if not(fullPath.StartsWithOrdinal(currentDir)) then fullPath // if the file name is rooted in the current directory, return the relative path else @@ -1796,7 +1796,7 @@ type private TypeInThisAssembly = class end let GetDefaultSystemValueTupleReference () = try let asm = typeof>.Assembly - if asm.FullName.StartsWith "System.ValueTuple" then + if asm.FullName.StartsWithOrdinal("System.ValueTuple") then Some asm.Location else let location = Path.GetDirectoryName(typeof.Assembly.Location) @@ -2025,7 +2025,7 @@ let GetWarningNumber(m, s:string) = // therefore if we have warning id that starts with a numeric digit we convert it to Some (int32) // anything else is ignored None if Char.IsDigit(s.[0]) then Some (int32 s) - elif s.StartsWith("FS", StringComparison.Ordinal) = true then raise (new ArgumentException()) + elif s.StartsWithOrdinal("FS") = true then raise (new ArgumentException()) else None with err -> warning(Error(FSComp.SR.buildInvalidWarningNumber(s), m)) @@ -3748,28 +3748,29 @@ type TcAssemblyResolutions(tcConfig: TcConfig, results: AssemblyResolution list, //-------------------------------------------------------------------------- let IsSignatureDataResource (r: ILResource) = - r.Name.StartsWith FSharpSignatureDataResourceName || - r.Name.StartsWith FSharpSignatureDataResourceName2 + r.Name.StartsWithOrdinal(FSharpSignatureDataResourceName) || + r.Name.StartsWithOrdinal(FSharpSignatureDataResourceName2) let IsOptimizationDataResource (r: ILResource) = - r.Name.StartsWith FSharpOptimizationDataResourceName || - r.Name.StartsWith FSharpOptimizationDataResourceName2 + r.Name.StartsWithOrdinal(FSharpOptimizationDataResourceName)|| + r.Name.StartsWithOrdinal(FSharpOptimizationDataResourceName2) let GetSignatureDataResourceName (r: ILResource) = - if r.Name.StartsWith FSharpSignatureDataResourceName then + if r.Name.StartsWithOrdinal(FSharpSignatureDataResourceName) then String.dropPrefix r.Name FSharpSignatureDataResourceName - elif r.Name.StartsWith FSharpSignatureDataResourceName2 then + elif r.Name.StartsWithOrdinal(FSharpSignatureDataResourceName2) then String.dropPrefix r.Name FSharpSignatureDataResourceName2 else failwith "GetSignatureDataResourceName" let GetOptimizationDataResourceName (r: ILResource) = - if r.Name.StartsWith FSharpOptimizationDataResourceName then + if r.Name.StartsWithOrdinal(FSharpOptimizationDataResourceName) then String.dropPrefix r.Name FSharpOptimizationDataResourceName - elif r.Name.StartsWith FSharpOptimizationDataResourceName2 then + elif r.Name.StartsWithOrdinal(FSharpOptimizationDataResourceName2) then String.dropPrefix r.Name FSharpOptimizationDataResourceName2 else failwith "GetOptimizationDataResourceName" -let IsReflectedDefinitionsResource (r: ILResource) = r.Name.StartsWith QuotationPickler.SerializedReflectedDefinitionsResourceNameBase +let IsReflectedDefinitionsResource (r: ILResource) = + r.Name.StartsWithOrdinal(QuotationPickler.SerializedReflectedDefinitionsResourceNameBase) let MakeILResource rname bytes = { Name = rname diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 5969e38fc89..d660eb712d4 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -188,7 +188,7 @@ module ResponseFile = let parseLine (l: string) = match l with | s when String.IsNullOrWhiteSpace(s) -> None - | s when l.StartsWith("#") -> Some (ResponseFileLine.Comment (s.TrimStart('#'))) + | s when l.StartsWithOrdinal("#") -> Some (ResponseFileLine.Comment (s.TrimStart('#'))) | s -> Some (ResponseFileLine.CompilerOptionSpec (s.Trim())) try @@ -224,7 +224,7 @@ let ParseCompilerOptions (collectOtherArgument : string -> unit, blocks: Compile if opt.Length = 2 || isSlashOpt opt then opt <- opt.[1 ..] // else, it should be a non-abbreviated option starting with "--" - elif opt.Length > 3 && opt.StartsWith("--") then + elif opt.Length > 3 && opt.StartsWithOrdinal("--") then opt <- opt.[2 ..] else opt <- "" @@ -247,19 +247,19 @@ let ParseCompilerOptions (collectOtherArgument : string -> unit, blocks: Compile let getSwitchOpt (opt : string) = // if opt is a switch, strip the '+' or '-' - if opt <> "--" && opt.Length > 1 && (opt.EndsWith("+",StringComparison.Ordinal) || opt.EndsWith("-",StringComparison.Ordinal)) then + if opt <> "--" && opt.Length > 1 && (opt.EndsWithOrdinal("+") || opt.EndsWithOrdinal("-")) then opt.[0 .. opt.Length - 2] else opt let getSwitch (s: string) = let s = (s.Split([|':'|])).[0] - if s <> "--" && s.EndsWith("-",StringComparison.Ordinal) then OptionSwitch.Off else OptionSwitch.On + if s <> "--" && s.EndsWithOrdinal("-") then OptionSwitch.Off else OptionSwitch.On let rec processArg args = match args with | [] -> () - | ((rsp: string) :: t) when rsp.StartsWith("@") -> + | ((rsp: string) :: t) when rsp.StartsWithOrdinal("@") -> let responseFileOptions = let fullpath = try @@ -555,7 +555,7 @@ let inputFileFlagsFsc tcConfigB = inputFileFlagsBoth tcConfigB //--------------------------------- let errorsAndWarningsFlags (tcConfigB: TcConfigBuilder) = - let trimFS (s:string) = if s.StartsWith("FS", StringComparison.Ordinal) = true then s.Substring(2) else s + let trimFS (s:string) = if s.StartsWithOrdinal("FS") = true then s.Substring(2) else s let trimFStoInt (s:string) = try Some (int32 (trimFS s)) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 24fc159e41d..2a228711ca9 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1241,8 +1241,8 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) ignoreUnresolvedOverload p // First look for a solution by a record property let recdPropSearch = - let isGetProp = nm.StartsWith "get_" - let isSetProp = nm.StartsWith "set_" + let isGetProp = nm.StartsWithOrdinal("get_") + let isSetProp = nm.StartsWithOrdinal("set_") if argtys.IsEmpty && isGetProp || isSetProp then let propName = nm.[4..] let props = diff --git a/src/fsharp/ErrorResolutionHints.fs b/src/fsharp/ErrorResolutionHints.fs index 64ef837c85f..e674adb6f46 100644 --- a/src/fsharp/ErrorResolutionHints.fs +++ b/src/fsharp/ErrorResolutionHints.fs @@ -4,6 +4,7 @@ module internal Microsoft.FSharp.Compiler.ErrorResolutionHints open Internal.Utilities +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library let maxSuggestions = 5 let minThresholdForSuggestions = 0.7 @@ -28,17 +29,18 @@ let FilterPredictions (idText:string) (suggestionF:ErrorLogger.Suggestions) = let allSuggestions = suggestionF() let demangle (nm:string) = - if nm.StartsWith "( " && nm.EndsWith " )" then + if nm.StartsWithOrdinal("( ") && nm.EndsWithOrdinal(" )") then let cleanName = nm.[2..nm.Length - 3] cleanName else nm /// Returns `true` if given string is an operator display name, e.g. ( |>> ) let IsOperatorName (name: string) = - if not (name.StartsWith "( " && name.EndsWith " )") then false else - let name = name.[2..name.Length - 3] - let res = name |> Seq.forall (fun c -> c <> ' ') - res + if not (name.StartsWithOrdinal("( ") && name.EndsWithOrdinal(" )")) then + false + else + let name = name.[2..name.Length - 3] + name |> Seq.forall (fun c -> c <> ' ') if allSuggestions.Contains idText then [] else // some other parsing error occurred allSuggestions @@ -47,11 +49,11 @@ let FilterPredictions (idText:string) (suggestionF:ErrorLogger.Suggestions) = // value as well as to formally squelch the associated compiler // error/warning (FS1182), we remove such names from the suggestions, // both to prevent accidental usages as well as to encourage good taste - if IsOperatorName suggestion || suggestion.StartsWith "_" then None else + if IsOperatorName suggestion || suggestion.StartsWithOrdinal("_") then None else let suggestion:string = demangle suggestion let suggestedText = suggestion.ToUpperInvariant() let similarity = EditDistance.JaroWinklerDistance uppercaseText suggestedText - if similarity >= highConfidenceThreshold || suggestion.EndsWith ("." + idText) then + if similarity >= highConfidenceThreshold || suggestion.EndsWithOrdinal("." + idText) then Some(similarity, suggestion) elif similarity < minThresholdForSuggestions && suggestedText.Length > minStringLengthForThreshold then None diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 4318c062035..23c4af9526f 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5281,9 +5281,9 @@ and GenMethodForBinding let mdef = if // operator names - mdef.Name.StartsWith("op_",System.StringComparison.Ordinal) || + mdef.Name.StartsWithOrdinal("op_") || // active pattern names - mdef.Name.StartsWith("|",System.StringComparison.Ordinal) || + mdef.Name.StartsWithOrdinal("|") || // event add/remove method v.val_flags.IsGeneratedEventVal then mdef.WithSpecialName diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 91a8fc710d2..085936494ab 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -1300,7 +1300,8 @@ let MethInfoChecks g amap isInstance tyargsOpt objArgs ad m (minfo:MethInfo) = if not (IsTypeAndMethInfoAccessible amap m adOriginal ad minfo) then error (Error (FSComp.SR.tcMethodNotAccessible(minfo.LogicalName), m)) - if isAnyTupleTy g minfo.ApparentEnclosingType && not minfo.IsExtensionMember && (minfo.LogicalName.StartsWith "get_Item" || minfo.LogicalName.StartsWith "get_Rest") then + if isAnyTupleTy g minfo.ApparentEnclosingType && not minfo.IsExtensionMember && + (minfo.LogicalName.StartsWithOrdinal("get_Item") || minfo.LogicalName.StartsWithOrdinal("get_Rest")) then warning (Error (FSComp.SR.tcTupleMemberNotNormallyUsed(), m)) CheckMethInfoAttributes g m tyargsOpt minfo |> CommitOperationResult diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 9fb16843ff5..726ef0f1f1a 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -2890,7 +2890,7 @@ let rec ResolveTypeLongIdentPrim sink (ncenv:NameResolver) occurence first fully | ItemOccurence.UseInAttribute -> [yield e.Value.DisplayName yield e.Value.DemangledModuleOrNamespaceName - if e.Value.DisplayName.EndsWith "Attribute" then + if e.Value.DisplayName.EndsWithOrdinal("Attribute") then yield e.Value.DisplayName.Replace("Attribute","")] | _ -> [e.Value.DisplayName; e.Value.DemangledModuleOrNamespaceName]) |> HashSet @@ -3598,7 +3598,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso if methsWithStaticParams.IsEmpty then minfos else minfos |> List.filter (fun minfo -> let nm = minfo.LogicalName - not (nm.Contains "," && methsWithStaticParams |> List.exists (fun m -> nm.StartsWith(m)))) + not (nm.Contains "," && methsWithStaticParams |> List.exists (fun m -> nm.StartsWithOrdinal(m)))) #endif minfos @@ -4227,7 +4227,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty ( if methsWithStaticParams.IsEmpty then minfos else minfos |> List.filter (fun minfo -> let nm = minfo.LogicalName - not (nm.Contains "," && methsWithStaticParams |> List.exists (fun m -> nm.StartsWith(m)))) + not (nm.Contains "," && methsWithStaticParams |> List.exists (fun m -> nm.StartsWithOrdinal(m)))) #endif minfos diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 0d15d512da2..f0964312245 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -71,7 +71,7 @@ module internal PrintUtilities = tcref.DisplayName // has no static params else tcref.DisplayName+"<...>" // shorten - if isAttribute && name.EndsWith "Attribute" then + if isAttribute && name.EndsWithOrdinal("Attribute") then String.dropSuffix name "Attribute" else name @@ -655,7 +655,7 @@ module private PrintTypes = | ILAttrib ilMethRef -> let trimmedName = let name = ilMethRef.DeclaringTypeRef.Name - if name.EndsWith "Attribute" then + if name.EndsWithOrdinal("Attribute") then String.dropSuffix name "Attribute" else name diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index f59d94502f9..db5205e896d 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -4,6 +4,7 @@ /// is complete. module internal Microsoft.FSharp.Compiler.PostTypeCheckSemanticChecks +open System open System.Collections.Generic open Microsoft.FSharp.Compiler @@ -153,7 +154,7 @@ let BindVal cenv env (v:Val) = cenv.reportErrors && not v.HasBeenReferenced && not v.IsCompiledAsTopLevel && - not (v.DisplayName.StartsWith("_", System.StringComparison.Ordinal)) && + not (v.DisplayName.StartsWithOrdinal("_")) && not v.IsCompilerGenerated then match v.BaseOrThisInfo with @@ -1478,14 +1479,14 @@ let CheckModuleBinding cenv env (TBind(v,e,_) as bind) = // Default augmentation contains the nasty 'Case' etc. let prefix = "New" - if nm.StartsWith prefix then + if nm.StartsWithOrdinal(prefix) then match tcref.GetUnionCaseByName(nm.[prefix.Length ..]) with | Some(uc) -> error(NameClash(nm,kind,v.DisplayName,v.Range, FSComp.SR.chkUnionCaseCompiledForm(),uc.DisplayName,uc.Range)) | None -> () // Default augmentation contains the nasty 'Is' etc. let prefix = "Is" - if nm.StartsWith prefix && hasDefaultAugmentation then + if nm.StartsWithOrdinal(prefix) && hasDefaultAugmentation then match tcref.GetUnionCaseByName(nm.[prefix.Length ..]) with | Some(uc) -> error(NameClash(nm,kind,v.DisplayName,v.Range, FSComp.SR.chkUnionCaseDefaultAugmentation(),uc.DisplayName,uc.Range)) | None -> () diff --git a/src/fsharp/PrettyNaming.fs b/src/fsharp/PrettyNaming.fs index bb784e0e007..fe0bb577451 100755 --- a/src/fsharp/PrettyNaming.fs +++ b/src/fsharp/PrettyNaming.fs @@ -136,13 +136,15 @@ module public Microsoft.FSharp.Compiler.PrettyNaming /// Returns `true` if given string is an operator display name, e.g. ( |>> ) let IsOperatorName (name: string) = - let name = if name.StartsWith "( " && name.EndsWith " )" then name.[2..name.Length - 3] else name + let name = + if name.StartsWithOrdinal("( ") && name.EndsWithOrdinal(" )") then + name.[2 .. name.Length - 3] + else name // there is single operator containing a space - range operator with step: `.. ..` - let res = name = ".. .." || name |> Seq.forall (fun c -> c <> ' ' && opCharSet.Contains c) - res + name = ".. .." || name |> Seq.forall (fun c -> c <> ' ' && opCharSet.Contains c) let IsMangledOpName (n:string) = - n.StartsWith (opNamePrefix, StringComparison.Ordinal) + n.StartsWithOrdinal(opNamePrefix) /// Compiles a custom operator into a mangled operator name. /// For example, "!%" becomes "op_DereferencePercent". @@ -427,7 +429,7 @@ module public Microsoft.FSharp.Compiler.PrettyNaming // This function recognises these "infix operator" names. let s = DecompileOpName s let skipIgnoredChars = s.TrimStart(ignoredChars) - let afterSkipStartsWith prefix = skipIgnoredChars.StartsWith(prefix,StringComparison.Ordinal) + let afterSkipStartsWith prefix = skipIgnoredChars.StartsWithOrdinal(prefix) let afterSkipStarts prefixes = Array.exists afterSkipStartsWith prefixes // The following conditions follow the declExpr infix clauses. // The test corresponds to the lexer definition for the token. @@ -468,7 +470,7 @@ module public Microsoft.FSharp.Compiler.PrettyNaming if IsCompilerGeneratedName nm then nm else nm+compilerGeneratedMarker let GetBasicNameOfPossibleCompilerGeneratedName (name:string) = - match name.IndexOf compilerGeneratedMarker with + match name.IndexOf(compilerGeneratedMarker, StringComparison.Ordinal) with | -1 | 0 -> name | n -> name.[0..n-1] @@ -518,13 +520,13 @@ module public Microsoft.FSharp.Compiler.PrettyNaming let TryChopPropertyName (s: string) = // extract the logical name from any mangled name produced by MakeMemberDataAndMangledNameForMemberVal if s.Length <= 4 then None else - if s.StartsWith("get_", StringComparison.Ordinal) || - s.StartsWith("set_", StringComparison.Ordinal) + if s.StartsWithOrdinal("get_") || + s.StartsWithOrdinal("set_") then Some (s.Substring(4, s.Length - 4)) else let s = chopStringTo s '.' - if s.StartsWith("get_", StringComparison.Ordinal) || - s.StartsWith("set_", StringComparison.Ordinal) + if s.StartsWithOrdinal("get_") || + s.StartsWithOrdinal("set_") then Some (s.Substring(4, s.Length - 4)) else None @@ -537,7 +539,7 @@ module public Microsoft.FSharp.Compiler.PrettyNaming | Some res -> res let SplitNamesForILPath (s : string) : string list = - if s.StartsWith("``",StringComparison.Ordinal) && s.EndsWith("``",StringComparison.Ordinal) && s.Length > 4 then [s.Substring(2, s.Length-4)] // identifier is enclosed in `` .. ``, so it is only a single element (this is very approximate) + if s.StartsWithOrdinal("``") && s.EndsWithOrdinal("``") && s.Length > 4 then [s.Substring(2, s.Length-4)] // identifier is enclosed in `` .. ``, so it is only a single element (this is very approximate) else s.Split [| '.' ; '`' |] |> Array.toList // '.' chops members / namespaces / modules; '`' chops generic parameters for .NET types /// Return a string array delimited by the given separator. diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 312d12322ff..9c7bc53e333 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -161,7 +161,7 @@ let (|ObjectInitializationCheck|_|) g expr = [| TTarget([], Expr.App(Expr.Val(failInitRef, _, _), _, _, _, _), _); _ |], _, resultTy ) when IsCompilerGeneratedName name && - name.StartsWith "init" && + name.StartsWithOrdinal("init") && selfRef.BaseOrThisInfo = MemberThisVal && valRefEq g failInitRef (ValRefForIntrinsic g.fail_init_info) && isUnitTy g resultTy -> Some() @@ -562,8 +562,8 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let methArgTypesR = List.map (ConvILType cenv env m) ilMethRef.ArgTypes let methRetTypeR = ConvILType cenv env m ilMethRef.ReturnType let methName = ilMethRef.Name - let isPropGet = isProp && methName.StartsWith("get_",System.StringComparison.Ordinal) - let isPropSet = isProp && methName.StartsWith("set_",System.StringComparison.Ordinal) + let isPropGet = isProp && methName.StartsWithOrdinal("get_") + let isPropSet = isProp && methName.StartsWithOrdinal("set_") let tyargs = (enclTypeArgs@methTypeArgs) ConvObjectModelCall cenv env m (isPropGet,isPropSet,isNewObj,parentTyconR,methArgTypesR,methRetTypeR,methName,tyargs,methTypeArgs.Length,callArgs) diff --git a/src/fsharp/SimulatedMSBuildReferenceResolver.fs b/src/fsharp/SimulatedMSBuildReferenceResolver.fs index 4fac34e6184..e74f2d49ced 100644 --- a/src/fsharp/SimulatedMSBuildReferenceResolver.fs +++ b/src/fsharp/SimulatedMSBuildReferenceResolver.fs @@ -103,7 +103,7 @@ let internal SimulatedMSBuildResolver = #if !FX_RESHAPED_MSBUILD // For this one we need to get the version search exactly right, without doing a load try - if not found && r.StartsWith("FSharp.Core, Version=") && Environment.OSVersion.Platform = PlatformID.Win32NT then + if not found && r.StartsWithOrdinal("FSharp.Core, Version=") && Environment.OSVersion.Platform = PlatformID.Win32NT then let n = AssemblyName(r) let fscoreDir0 = let PF = diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 1c46acf2a39..b068a063f35 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -623,7 +623,7 @@ let TryStripPrefixPath (g:TcGlobals) (enclosingNamespacePath: Ident list) = | p::rest when g.isInteractive && not (isNil rest) && - p.idText.StartsWith(FsiDynamicModulePrefix, System.StringComparison.Ordinal) && + p.idText.StartsWithOrdinal(FsiDynamicModulePrefix) && p.idText.[FsiDynamicModulePrefix.Length..] |> String.forall System.Char.IsDigit -> Some(p, rest) | _ -> None @@ -762,7 +762,7 @@ let ReportImplicitlyIgnoredBoolExpression denv m ty expr = UnitTypeExpectedWithEquality (denv, ty, m) else UnitTypeExpectedWithEquality (denv, ty, m) - | Expr.Op(TOp.ILCall(_, _, _, _, _, _, _, methodRef, _, _, _), _, Expr.Val(vf, _, _) :: _, _) :: _ when methodRef.Name.StartsWith "get_"-> + | Expr.Op(TOp.ILCall(_, _, _, _, _, _, _, methodRef, _, _, _), _, Expr.Val(vf, _, _) :: _, _) :: _ when methodRef.Name.StartsWithOrdinal("get_") -> UnitTypeExpectedWithPossiblePropertySetter (denv, ty, vf.DisplayName, PrettyNaming.ChopPropertyName(methodRef.Name), m) | Expr.Val(vf, _, _) :: _ -> UnitTypeExpectedWithPossibleAssignment (denv, ty, vf.IsMutable, vf.DisplayName, m) @@ -5125,7 +5125,7 @@ and TcPatBindingName cenv env id ty isMemberThis vis1 topValData (inlineFlag, de // isLeftMost indicates we are processing the left-most path through a disjunctive or pattern. // For those binding locations, CallNameResolutionSink is called in MakeAndPublishValue, like all other bindings // For non-left-most paths, we register the name resolutions here - if not isLeftMost && not vspec.IsCompilerGenerated && not (vspec.LogicalName.StartsWith "_") then + if not isLeftMost && not vspec.IsCompilerGenerated && not (vspec.LogicalName.StartsWithOrdinal("_")) then let item = Item.Value(mkLocalValRef vspec) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Binding, env.DisplayEnv, env.eAccessRights) @@ -9678,7 +9678,7 @@ and TcMethodApplication match unrefinedItem with | Item.MethodGroup(_, overridenMeths, _) -> overridenMeths |> List.map (fun minfo -> minfo, None) | Item.Property(_, pinfos) -> - if result.Method.LogicalName.StartsWith ("set_") then + if result.Method.LogicalName.StartsWithOrdinal("set_") then SettersOfPropInfos pinfos else GettersOfPropInfos pinfos @@ -12219,7 +12219,7 @@ let TcOpenDecl tcSink (g:TcGlobals) amap m scopem env (longId : Ident list) = let p = match p with | [] -> [] - | (h, _):: t -> if h.StartsWith(FsiDynamicModulePrefix, System.StringComparison.Ordinal) then t else p + | (h, _):: t -> if h.StartsWithOrdinal(FsiDynamicModulePrefix) then t else p // See https://fslang.uservoice.com/forums/245727-f-language/suggestions/6107641-make-microsoft-prefix-optional-when-using-core-f let isFSharpCoreSpecialCase = @@ -12487,7 +12487,7 @@ module IncrClassChecking = nm, takenFieldNames.Add(nm) let reportIfUnused() = - if not v.HasBeenReferenced && not v.IsCompiledAsTopLevel && not (v.DisplayName.StartsWith "_") && not v.IsCompilerGenerated then + if not v.HasBeenReferenced && not v.IsCompiledAsTopLevel && not (v.DisplayName.StartsWithOrdinal("_")) && not v.IsCompilerGenerated then warning (Error(FSComp.SR.chkUnusedValue(v.DisplayName), v.Range)) let repr = @@ -15994,7 +15994,7 @@ module TcDeclarations = | None -> //false // There is a special case we allow when compiling FSharp.Core.dll which permits interface implementations across namespace fragments - (cenv.g.compilingFslib && tcref.LogicalName.StartsWith("Tuple`")) + (cenv.g.compilingFslib && tcref.LogicalName.StartsWithOrdinal("Tuple`")) let nReqTypars = reqTypars.Length diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index b3c50cfbbb6..1f0941eea4a 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -100,7 +100,7 @@ type XmlDoc = | (lineA::rest) as lines -> let lineAT = lineA.TrimStart([|' '|]) if lineAT = "" then processLines rest - else if lineAT.StartsWith "<" then lines + else if lineAT.StartsWithOrdinal("<") then lines else [""] @ (lines |> List.map (fun line -> Microsoft.FSharp.Core.XmlAdapters.escape(line))) @ [""] diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index e8fd010a648..eb926991dc1 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2343,7 +2343,7 @@ type internal FsiInteractionProcessor let nItems = NameResolution.ResolvePartialLongIdent ncenv nenv (ConstraintSolver.IsApplicableMethApprox istate.tcGlobals amap rangeStdin) rangeStdin ad lid false let names = nItems |> List.map (fun d -> d.DisplayName) - let names = names |> List.filter (fun name -> name.StartsWith(stem,StringComparison.Ordinal)) + let names = names |> List.filter (fun name -> name.StartsWithOrdinal(stem)) names member __.ParseAndCheckInteraction (ctok, legacyReferenceResolver, checker, istate, text:string) = diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index 00c261755b1..ae69731494f 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -355,7 +355,10 @@ module Keywords = /// Quote identifier with double backticks if needed, remove unnecessary double backticks quotation. let NormalizeIdentifierBackticks (s : string) : string = - let s = if s.StartsWith "``" && s.EndsWith "``" then s.[2..s.Length - 3] else s + let s = + if s.StartsWithOrdinal("``") && s.EndsWithOrdinal("``") then + s.[2..s.Length - 3] + else s QuoteIdentifierIfNeeded s /// Keywords paired with their descriptions. Used in completion and quick info. diff --git a/src/fsharp/range.fs b/src/fsharp/range.fs index 81f7d121e0d..8649b700867 100755 --- a/src/fsharp/range.fs +++ b/src/fsharp/range.fs @@ -3,6 +3,7 @@ /// Anything to do with special names of identifiers and other lexical rules module Microsoft.FSharp.Compiler.Range +open System open System.IO open System.Collections.Generic open Microsoft.FSharp.Core.Printf @@ -177,7 +178,7 @@ type range(code:int64) = |> Seq.skip (r.StartLine - 1) |> Seq.take (r.EndLine - r.StartLine + 1) |> String.concat "\n" - |> fun s -> s.Substring(startCol + 1, s.LastIndexOf("\n") + 1 - startCol + endCol) + |> fun s -> s.Substring(startCol + 1, s.LastIndexOf("\n", StringComparison.Ordinal) + 1 - startCol + endCol) with e -> e.ToString() #endif diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index b1533ea8896..7065d72a6f0 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1745,7 +1745,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let tcConfigB, sourceFilesNew = let getSwitchValue switchstring = - match commandLineArgs |> Seq.tryFindIndex(fun s -> s.StartsWith(switchstring)) with + match commandLineArgs |> Seq.tryFindIndex(fun s -> s.StartsWithOrdinal(switchstring)) with | Some idx -> Some(commandLineArgs.[idx].Substring(switchstring.Length)) | _ -> None diff --git a/src/fsharp/service/QuickParse.fs b/src/fsharp/service/QuickParse.fs index 1530759307b..9e851fef05f 100644 --- a/src/fsharp/service/QuickParse.fs +++ b/src/fsharp/service/QuickParse.fs @@ -3,6 +3,7 @@ namespace Microsoft.FSharp.Compiler open System +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.SourceCodeServices /// Qualified long name. @@ -46,7 +47,8 @@ module QuickParse = // Adjusts the token tag for the given identifier // - if we're inside active pattern name (at the bar), correct the token TAG to be an identifier let CorrectIdentifierToken (tokenText: string) (tokenTag: int) = - if tokenText.EndsWith "|" then Microsoft.FSharp.Compiler.Parser.tagOfToken (Microsoft.FSharp.Compiler.Parser.token.IDENT tokenText) + if tokenText.EndsWithOrdinal("|") then + Microsoft.FSharp.Compiler.Parser.tagOfToken (Microsoft.FSharp.Compiler.Parser.token.IDENT tokenText) else tokenTag let rec isValidStrippedName (name:string) idx = @@ -61,9 +63,7 @@ module QuickParse = let private isValidActivePatternName (name: string) = // Strip the surrounding bars (e.g. from "|xyz|_|") to get "xyz" - match name.StartsWith("|", System.StringComparison.Ordinal), - name.EndsWith("|_|", System.StringComparison.Ordinal), - name.EndsWith("|", System.StringComparison.Ordinal) with + match name.StartsWithOrdinal("|"), name.EndsWithOrdinal("|_|"), name.EndsWithOrdinal("|") with | true, true, _ when name.Length > 4 -> isValidStrippedName (name.Substring(1, name.Length - 4)) 0 | true, _, true when name.Length > 2 -> isValidStrippedName (name.Substring(1, name.Length - 2)) 0 | _ -> false diff --git a/src/fsharp/service/ServiceAssemblyContent.fs b/src/fsharp/service/ServiceAssemblyContent.fs index b5278b439f2..a61f8f2b2f8 100644 --- a/src/fsharp/service/ServiceAssemblyContent.fs +++ b/src/fsharp/service/ServiceAssemblyContent.fs @@ -66,7 +66,7 @@ module Extensions = try x.MembersFunctionsAndValues with _ -> [||] :> _ let isOperator (name: string) = - name.StartsWith "( " && name.EndsWith " )" && name.Length > 4 + name.StartsWithOrdinal("( ") && name.EndsWithOrdinal(" )") && name.Length > 4 && name.Substring (2, name.Length - 4) |> String.forall (fun c -> c <> ' ' && not (Char.IsLetter c)) @@ -1007,7 +1007,8 @@ module ParsedInput = if ctx.Pos.Line > 1 then // it's an implicit module without any open declarations let line = getLineStr (ctx.Pos.Line - 2) - let isImpliciteTopLevelModule = not (line.StartsWith "module" && not (line.EndsWith "=")) + let isImpliciteTopLevelModule = + not (line.StartsWithOrdinal("module") && not (line.EndsWithOrdinal("="))) if isImpliciteTopLevelModule then 1 else ctx.Pos.Line else 1 | ScopeKind.Namespace -> @@ -1016,7 +1017,7 @@ module ParsedInput = [0..ctx.Pos.Line - 1] |> List.mapi (fun i line -> i, getLineStr line) |> List.tryPick (fun (i, lineStr) -> - if lineStr.StartsWith "namespace" then Some i + if lineStr.StartsWithOrdinal("namespace") then Some i else None) |> function // move to the next line below "namespace" and convert it to F# 1-based line number diff --git a/src/fsharp/service/ServiceDeclarationLists.fs b/src/fsharp/service/ServiceDeclarationLists.fs index 5abeacf0998..838d221ead9 100644 --- a/src/fsharp/service/ServiceDeclarationLists.fs +++ b/src/fsharp/service/ServiceDeclarationLists.fs @@ -11,7 +11,6 @@ open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics - open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Layout @@ -642,7 +641,7 @@ type FSharpDeclarationListInfo(declarations: FSharpDeclarationListItem[], isForT let glyph = GlyphOfItem(denv, item.Item) let name, nameInCode = - if displayName.StartsWith "( " && displayName.EndsWith " )" then + if displayName.StartsWithOrdinal("( ") && displayName.EndsWithOrdinal(" )") then let cleanName = displayName.[2..displayName.Length - 3] cleanName, if IsOperatorName displayName then cleanName else "``" + cleanName + "``" @@ -655,7 +654,7 @@ type FSharpDeclarationListInfo(declarations: FSharpDeclarationListItem[], isForT let isAttributeItem = lazy (SymbolHelpers.IsAttribute infoReader item.Item) let cutAttributeSuffix (name: string) = - if isAttributeApplicationContext && name <> "Attribute" && name.EndsWith "Attribute" && isAttributeItem.Value then + if isAttributeApplicationContext && name <> "Attribute" && name.EndsWithOrdinal("Attribute") && isAttributeItem.Value then name.[0..name.Length - "Attribute".Length - 1] else name diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index 6a2a1c06749..5d093079f92 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -289,8 +289,8 @@ module internal InterfaceStubGenerator = /// Convert a getter/setter to its canonical form let internal normalizePropertyName (v: FSharpMemberOrFunctionOrValue) = let displayName = v.DisplayName - if (v.IsPropertyGetterMethod && displayName.StartsWith("get_")) || - (v.IsPropertySetterMethod && displayName.StartsWith("set_")) then + if (v.IsPropertyGetterMethod && displayName.StartsWithOrdinal("get_")) || + (v.IsPropertySetterMethod && displayName.StartsWithOrdinal("set_")) then displayName.[4..] else displayName @@ -308,7 +308,7 @@ module internal InterfaceStubGenerator = | _ -> formatArgsUsage ctx verboseMode v argInfos if String.IsNullOrWhiteSpace(args) then "" - elif args.StartsWith("(") then args + elif args.StartsWithOrdinal("(") then args elif v.CurriedParameterGroups.Count > 1 && (not verboseMode) then " " + args else sprintf "(%s)" args , namesWithIndices @@ -321,7 +321,7 @@ module internal InterfaceStubGenerator = | _, _, ".ctor", _ -> "new" + parArgs // Properties (skipping arguments) | _, true, _, name when v.IsPropertyGetterMethod || v.IsPropertySetterMethod -> - if name.StartsWith("get_") || name.StartsWith("set_") then name.[4..] else name + if name.StartsWithOrdinal("get_") || name.StartsWithOrdinal("set_") then name.[4..] else name // Ordinary instance members | _, true, _, name -> name + parArgs // Ordinary functions or values @@ -509,10 +509,10 @@ module internal InterfaceStubGenerator = let internal (|MemberNameAndRange|_|) = function | Binding(_access, _bindingKind, _isInline, _isMutable, _attrs, _xmldoc, SynValData(Some mf, _, _), LongIdentPattern(name, range), _retTy, _expr, _bindingRange, _seqPoint) when mf.MemberKind = MemberKind.PropertyGet -> - if name.StartsWith("get_") then Some(name, range) else Some("get_" + name, range) + if name.StartsWithOrdinal("get_") then Some(name, range) else Some("get_" + name, range) | Binding(_access, _bindingKind, _isInline, _isMutable, _attrs, _xmldoc, SynValData(Some mf, _, _), LongIdentPattern(name, range), _retTy, _expr, _bindingRange, _seqPoint) when mf.MemberKind = MemberKind.PropertySet -> - if name.StartsWith("set_") then Some(name, range) else Some("set_" + name, range) + if name.StartsWithOrdinal("set_") then Some(name, range) else Some("set_" + name, range) | Binding(_access, _bindingKind, _isInline, _isMutable, _attrs, _xmldoc, _valData, LongIdentPattern(name, range), _retTy, _expr, _bindingRange, _seqPoint) -> Some(name, range) @@ -535,8 +535,8 @@ module internal InterfaceStubGenerator = let internal normalizeEventName (m: FSharpMemberOrFunctionOrValue) = let name = m.DisplayName - if name.StartsWith("add_") then name.[4..] - elif name.StartsWith("remove_") then name.[7..] + if name.StartsWithOrdinal("add_") then name.[4..] + elif name.StartsWithOrdinal("remove_") then name.[7..] else name /// Ideally this info should be returned in error symbols from FCS. diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index 64b83328d3b..343fc203170 100755 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -6,8 +6,10 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices +open System open System.Collections.Generic open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.Parser open Microsoft.FSharp.Compiler.Range @@ -511,7 +513,7 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, // Process: anywhite* # let processDirective (str:string) directiveLength delay cont = - let hashIdx = str.IndexOf("#") + let hashIdx = str.IndexOf("#", StringComparison.Ordinal) if (hashIdx <> 0) then delay(WHITESPACE cont, 0, hashIdx - 1) delay(HASH_IF(range0, "", cont), hashIdx, hashIdx + directiveLength) hashIdx + directiveLength + 1 @@ -623,34 +625,34 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, delayToken(greaters.[i] false, leftc + i, rightc - opstr.Length + i + 1) false, (greaters.[0] false, leftc, rightc - opstr.Length + 1) // break up any operators that start with '.' so that we can get auto-popup-completion for e.g. "x.+1" when typing the dot - | INFIX_STAR_STAR_OP opstr when opstr.StartsWith(".") -> + | INFIX_STAR_STAR_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_STAR_STAR_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | PLUS_MINUS_OP opstr when opstr.StartsWith(".") -> + | PLUS_MINUS_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(PLUS_MINUS_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | INFIX_COMPARE_OP opstr when opstr.StartsWith(".") -> + | INFIX_COMPARE_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_COMPARE_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | INFIX_AT_HAT_OP opstr when opstr.StartsWith(".") -> + | INFIX_AT_HAT_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_AT_HAT_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | INFIX_BAR_OP opstr when opstr.StartsWith(".") -> + | INFIX_BAR_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_BAR_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | PREFIX_OP opstr when opstr.StartsWith(".") -> + | PREFIX_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(PREFIX_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | INFIX_STAR_DIV_MOD_OP opstr when opstr.StartsWith(".") -> + | INFIX_STAR_DIV_MOD_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_STAR_DIV_MOD_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | INFIX_AMP_OP opstr when opstr.StartsWith(".") -> + | INFIX_AMP_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(INFIX_AMP_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | ADJACENT_PREFIX_OP opstr when opstr.StartsWith(".") -> + | ADJACENT_PREFIX_OP opstr when opstr.StartsWithOrdinal(".") -> delayToken(ADJACENT_PREFIX_OP(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) - | FUNKY_OPERATOR_NAME opstr when opstr.StartsWith(".") -> + | FUNKY_OPERATOR_NAME opstr when opstr.StartsWithOrdinal(".") -> delayToken(FUNKY_OPERATOR_NAME(opstr.Substring(1)), leftc+1, rightc) false, (DOT, leftc, leftc) | _ -> false, (token, leftc, rightc) diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index e2f1c8780d4..c86358c8f59 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -2,8 +2,9 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices -open Microsoft.FSharp.Compiler.Ast open System.Collections.Generic +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.Range @@ -624,8 +625,8 @@ module Structure = /// Determine if a line is a single line or xml docummentation comment let (|Comment|_|) (line: string) = - if line.StartsWith "///" then Some XmlDoc - elif line.StartsWith "//" then Some SingleLine + if line.StartsWithOrdinal("///") then Some XmlDoc + elif line.StartsWithOrdinal("//") then Some SingleLine else None let getCommentRanges (lines: string[]) = diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index 4c6bbe8f9cf..397e6f604bf 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -1358,7 +1358,7 @@ module UntypedParseImpl = else None) else // Paired [< and >] were not found, try to determine that we are after [< without closing >] - match lineStr.LastIndexOf "[<" with + match lineStr.LastIndexOf("[<", StringComparison.Ordinal) with | -1 -> None | openParenIndex when pos.Column >= openParenIndex + 2 -> let str = lineStr.[openParenIndex + 2..pos.Column - 1].TrimStart() diff --git a/src/fsharp/service/ServiceXmlDocParser.fs b/src/fsharp/service/ServiceXmlDocParser.fs index 187c84bdd0a..92535f0cecf 100644 --- a/src/fsharp/service/ServiceXmlDocParser.fs +++ b/src/fsharp/service/ServiceXmlDocParser.fs @@ -165,7 +165,7 @@ module XmlDocComment = Some (res, pos + (s.Length - res.Length)) let private str (prefix: string) (s: string, pos) = - match s.StartsWith prefix with + match s.StartsWithOrdinal(prefix) with | true -> let res = s.Substring prefix.Length Some (res, pos + (s.Length - res.Length)) diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index bec99f6a7e2..f6213ef2ff6 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -183,7 +183,7 @@ module FSharpExprConvert = rfref.RecdField.IsCompilerGenerated && rfref.RecdField.IsStatic && rfref.RecdField.IsMutable && - rfref.RecdField.Name.StartsWith "init" + rfref.RecdField.Name.StartsWithOrdinal("init") // Match "if [AI_clt](init@41, 6) then IntrinsicFunctions.FailStaticInit () else ()" let (|StaticInitializationCheck|_|) e = @@ -857,8 +857,8 @@ module FSharpExprConvert = and ConvILCall (cenv:SymbolEnv) env (isNewObj, valUseFlags, ilMethRef, enclTypeArgs, methTypeArgs, callArgs, m) = let isNewObj = (isNewObj || (match valUseFlags with CtorValUsedAsSuperInit | CtorValUsedAsSelfInit -> true | _ -> false)) let methName = ilMethRef.Name - let isPropGet = methName.StartsWith("get_", System.StringComparison.Ordinal) - let isPropSet = methName.StartsWith("set_", System.StringComparison.Ordinal) + let isPropGet = methName.StartsWithOrdinal("get_") + let isPropSet = methName.StartsWithOrdinal("set_") let isProp = isPropGet || isPropSet let tcref, subClass = @@ -916,8 +916,8 @@ module FSharpExprConvert = let vr = VRefLocal v makeFSCall isMember vr | [] -> - let isPropGet = vName.StartsWith("get_", System.StringComparison.Ordinal) - let isPropSet = vName.StartsWith("set_", System.StringComparison.Ordinal) + let isPropGet = vName.StartsWithOrdinal("get_") + let isPropSet = vName.StartsWithOrdinal("set_") if isPropGet || isPropSet then let name = PrettyNaming.ChopPropertyName vName let findByName = @@ -956,12 +956,12 @@ module FSharpExprConvert = if vName = "GetTag" || vName = "get_Tag" then let objR = ConvExpr cenv env callArgs.Head E.UnionCaseTag(objR, typR) - elif vName.StartsWith("New") then + elif vName.StartsWithOrdinal("New") then let name = vName.Substring(3) let mkR = ConvUnionCaseRef cenv (UCRef(tcref, name)) let argsR = ConvExprs cenv env callArgs E.NewUnionCase(typR, mkR, argsR) - elif vName.StartsWith("Is") then + elif vName.StartsWithOrdinal("Is") then let name = vName.Substring(2) let mkR = ConvUnionCaseRef cenv (UCRef(tcref, name)) let objR = ConvExpr cenv env callArgs.Head diff --git a/src/fsharp/symbols/SymbolPatterns.fs b/src/fsharp/symbols/SymbolPatterns.fs index 2ee14c2a4e9..74b9bcf60c6 100644 --- a/src/fsharp/symbols/SymbolPatterns.fs +++ b/src/fsharp/symbols/SymbolPatterns.fs @@ -5,8 +5,9 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices /// Patterns over FSharpSymbol and derivatives. [] module Symbol = - open System.Text.RegularExpressions open System + open System.Text.RegularExpressions + open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library let isAttribute<'T> (attribute: FSharpAttribute) = // CompiledName throws exception on DataContractAttribute generated by SQLProvider @@ -36,7 +37,7 @@ module Symbol = |> Option.isSome let isOperator (name: string) = - name.StartsWith "( " && name.EndsWith " )" && name.Length > 4 + name.StartsWithOrdinal("( ") && name.EndsWithOrdinal(" )") && name.Length > 4 && name.Substring (2, name.Length - 4) |> String.forall (fun c -> c <> ' ' && not (Char.IsLetter c)) diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index e0d9da91678..4ce77c11efe 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -1550,7 +1550,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = member __.IsEventAddMethod = if isUnresolved() then false else match d with - | M m when m.LogicalName.StartsWith("add_") -> + | M m when m.LogicalName.StartsWithOrdinal("add_") -> let eventName = m.LogicalName.[4..] let entityTy = generalizedTyconRef m.DeclaringTyconRef not (isNil (cenv.infoReader.GetImmediateIntrinsicEventsOfType (Some eventName, AccessibleFromSomeFSharpCode, range0, entityTy))) || @@ -1564,7 +1564,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = member __.IsEventRemoveMethod = if isUnresolved() then false else match d with - | M m when m.LogicalName.StartsWith("remove_") -> + | M m when m.LogicalName.StartsWithOrdinal("remove_") -> let eventName = m.LogicalName.[7..] let entityTy = generalizedTyconRef m.DeclaringTyconRef not (isNil (cenv.infoReader.GetImmediateIntrinsicEventsOfType (Some eventName, AccessibleFromSomeFSharpCode, range0, entityTy))) || @@ -1591,7 +1591,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = member __.IsPropertyGetterMethod = if isUnresolved() then false else match d with - | M m when m.LogicalName.StartsWith("get_") -> + | M m when m.LogicalName.StartsWithOrdinal("get_") -> let propName = PrettyNaming.ChopPropertyName(m.LogicalName) let declaringTy = generalizedTyconRef m.DeclaringTyconRef not (isNil (GetImmediateIntrinsicPropInfosOfType (Some propName, AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 declaringTy)) @@ -1602,7 +1602,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = if isUnresolved() then false else match d with // Look for a matching property with the right name. - | M m when m.LogicalName.StartsWith("set_") -> + | M m when m.LogicalName.StartsWithOrdinal("set_") -> let propName = PrettyNaming.ChopPropertyName(m.LogicalName) let declaringTy = generalizedTyconRef m.DeclaringTyconRef not (isNil (GetImmediateIntrinsicPropInfosOfType (Some propName, AccessibleFromSomeFSharpCode) cenv.g cenv.amap range0 declaringTy)) diff --git a/src/utils/filename.fs b/src/utils/filename.fs index 93a8c96994d..35d6d5a769a 100644 --- a/src/utils/filename.fs +++ b/src/utils/filename.fs @@ -14,7 +14,7 @@ let checkPathForIllegalChars = if chars.Contains c then raise(IllegalFileNameChar(path, c))) // Case sensitive (original behaviour preserved). -let checkSuffix (x:string) (y:string) = x.EndsWith(y,System.StringComparison.Ordinal) +let checkSuffix (x:string) (y:string) = x.EndsWithOrdinal(y) let hasExtensionWithValidate (validate:bool) (s:string) = if validate then (checkPathForIllegalChars s) |> ignore diff --git a/tests/service/Common.fs b/tests/service/Common.fs index f174908114a..d388a9ca783 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -1,5 +1,6 @@ module internal FSharp.Compiler.Service.Tests.Common +open System open System.IO open System.Collections.Generic open Microsoft.FSharp.Compiler @@ -36,7 +37,7 @@ let readRefs (folder : string) (projectFile: string) = match result with | Ok(Dotnet.ProjInfo.Inspect.GetResult.FscArgs x) -> x - |> List.filter (fun s -> s.StartsWith("-r:")) + |> List.filter (fun s -> s.StartsWith("-r:", StringComparison.Ordinal)) |> List.map (fun s -> s.Replace("-r:", "")) | _ -> [] #endif diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index f2e0819310f..3e2df86ca5e 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -183,7 +183,7 @@ module internal Utils = let printGenericParameter (p: FSharpGenericParameter) = let name = - if p.Name.StartsWith "?" then "_" + if p.Name.StartsWith("?", StringComparison.Ordinal) then "_" elif p.IsSolveAtCompileTime then "^" + p.Name else "'" + p.Name let constraints =