Skip to content

Use ordinal string comparison in string manipulation methods #4912

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/absil/il.fs
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,7 @@ type AssemblyRefData =
let AssemblyRefUniqueStampGenerator = new UniqueStampGenerator<AssemblyRefData>()

let isMscorlib data =
if System.String.Compare(data.assemRefName, "mscorlib") = 0 then true
else false
data.assemRefName = "mscorlib"

[<Sealed>]
type ILAssemblyRef(data) =
Expand Down
11 changes: 9 additions & 2 deletions src/absil/illib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))

Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/absil/ilreflect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
27 changes: 14 additions & 13 deletions src/fsharp/CompileOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1796,7 +1796,7 @@ type private TypeInThisAssembly = class end
let GetDefaultSystemValueTupleReference () =
try
let asm = typeof<System.ValueTuple<int, int>>.Assembly
if asm.FullName.StartsWith "System.ValueTuple" then
if asm.FullName.StartsWithOrdinal("System.ValueTuple") then
Some asm.Location
else
let location = Path.GetDirectoryName(typeof<TypeInThisAssembly>.Assembly.Location)
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions src/fsharp/CompileOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <- ""
Expand All @@ -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
Expand Down Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/ConstraintSolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
16 changes: 9 additions & 7 deletions src/fsharp/ErrorResolutionHints.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/fsharp/MethodCalls.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/fsharp/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/NicePrint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions src/fsharp/PostInferenceChecks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// is complete.
module internal Microsoft.FSharp.Compiler.PostTypeCheckSemanticChecks

open System
open System.Collections.Generic

open Microsoft.FSharp.Compiler
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1478,14 +1479,14 @@ let CheckModuleBinding cenv env (TBind(v,e,_) as bind) =

// Default augmentation contains the nasty 'Case<UnionCase>' 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<UnionCase>' 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 -> ()
Expand Down
Loading