-
Notifications
You must be signed in to change notification settings - Fork 158
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
Minor code clean-ups and performance improvements #906
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,8 +15,12 @@ open FSharp.Formatting.Markdown | |
|
||
module String = | ||
/// Matches when a string is a whitespace or null | ||
[<return: Struct>] | ||
let (|WhiteSpace|_|) (s) = | ||
if String.IsNullOrWhiteSpace(s) then Some() else None | ||
if String.IsNullOrWhiteSpace(s) then | ||
ValueSome() | ||
else | ||
ValueNone | ||
|
||
/// Returns a string trimmed from both start and end | ||
let (|TrimBoth|) (text: string) = text.Trim() | ||
|
@@ -117,15 +121,20 @@ module String = | |
|
||
module StringPosition = | ||
/// Matches when a string is a whitespace or null | ||
[<return: Struct>] | ||
let (|WhiteSpace|_|) (s, _n: MarkdownRange) = | ||
if String.IsNullOrWhiteSpace(s) then Some() else None | ||
if String.IsNullOrWhiteSpace(s) then | ||
ValueSome() | ||
else | ||
ValueNone | ||
|
||
/// Matches when a string does starts with non-whitespace | ||
[<return: Struct>] | ||
let (|Unindented|_|) (s: string, _n: MarkdownRange) = | ||
if not (String.IsNullOrWhiteSpace(s)) && s.TrimStart() = s then | ||
Some() | ||
ValueSome() | ||
else | ||
None | ||
ValueNone | ||
|
||
/// Returns a string trimmed from both start and end | ||
let (|TrimBoth|) (text: string, n: MarkdownRange) = | ||
|
@@ -174,11 +183,12 @@ module StringPosition = | |
StartColumn = n.StartColumn + text.Length - trimmed.Length }) | ||
|
||
/// Matches when a string starts with any of the specified sub-strings | ||
[<return: Struct>] | ||
let (|StartsWithAny|_|) (starts: string seq) (text: string, _n: MarkdownRange) = | ||
if starts |> Seq.exists (fun s -> text.StartsWith(s, StringComparison.Ordinal)) then | ||
Some() | ||
ValueSome() | ||
else | ||
None | ||
ValueNone | ||
|
||
/// Matches when a string starts with the specified sub-string | ||
let (|StartsWith|_|) (start: string) (text: string, n: MarkdownRange) = | ||
|
@@ -297,15 +307,16 @@ module StringPosition = | |
|
||
/// Matches when a string consists of some number of | ||
/// complete repetitions of a specified sub-string. | ||
[<return: Struct>] | ||
let (|EqualsRepeated|_|) (repeated, _n: MarkdownRange) = | ||
function | ||
| StartsWithRepeated repeated (_n, (v, _)) when (String.IsNullOrWhiteSpace v) -> Some() | ||
| _ -> None | ||
| StartsWithRepeated repeated (_n, (v, _)) when (String.IsNullOrWhiteSpace v) -> ValueSome() | ||
| _ -> ValueNone | ||
|
||
module List = | ||
/// Matches a list if it starts with a sub-list that is delimited | ||
/// using the specified delimiters. Returns a wrapped list and the rest. | ||
let inline (|DelimitedWith|_|) startl endl input = | ||
let inline internal (|DelimitedWith|_|) startl endl input = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just want to limit the scope to this solution: As you know inline makes compiler slower. So if you have hundreds of public inline functions in your solution and someone refers your project via Nuget package, they are going to pay the price with their compilation too, because those inline-functions come available for them too, even when they probably are not aware of them and probably will never need them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is my reasoning only, and I might be wrong: But in case of inline functions, they use statically resolved type parameters. So if you have a referenced 10s other nuget packages and all have 10s of inline functions, then... all of those might be potentials for your auto-complete. You probably don't want call those, so it's just noise that could be avoided if they'd be internal functions. |
||
if List.startsWith startl input then | ||
match List.partitionUntilEquals endl (List.skip startl.Length input) with | ||
| Some(pre, post) -> Some(pre, List.skip endl.Length post, startl.Length, endl.Length) | ||
|
@@ -314,14 +325,14 @@ module List = | |
None | ||
|
||
/// Matches a list if it starts with a sub-list. Returns the list. | ||
let inline (|StartsWith|_|) startl input = | ||
let inline internal (|StartsWith|_|) startl input = | ||
if List.startsWith startl input then Some input else None | ||
|
||
/// Matches a list if it starts with a sub-list that is delimited | ||
/// using the specified delimiter. Returns a wrapped list and the rest. | ||
let inline (|Delimited|_|) str = (|DelimitedWith|_|) str str | ||
let inline internal (|Delimited|_|) str = (|DelimitedWith|_|) str str | ||
|
||
let inline (|DelimitedNTimes|_|) str input = | ||
let inline internal (|DelimitedNTimes|_|) str input = | ||
let strs, _items = List.partitionWhile (fun i -> i = str) input | ||
|
||
match strs with | ||
|
@@ -403,9 +414,8 @@ module Lines = | |
let (|TrimParagraphLines|) lines = | ||
lines | ||
// first remove all whitespace on the beginning of the line | ||
|> List.map (fun (StringPosition.TrimStart s) -> s) | ||
// Now remove all additional spaces at the end, but keep two spaces if existent | ||
|> List.map (fun (s, n) -> | ||
// then remove all additional spaces at the end, but keep two spaces if existent | ||
|> List.map (fun (StringPosition.TrimStart(s, n)) -> | ||
let endsWithTwoSpaces = s.EndsWith(" ", StringComparison.Ordinal) | ||
|
||
let trimmed = s.TrimEnd([| ' ' |]) + if endsWithTwoSpaces then " " else "" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -246,10 +246,9 @@ module internal CompilerServiceExtensions = | |
dllFiles | ||
|> List.map (fun file -> | ||
file, | ||
(if referenceDict.ContainsKey file then | ||
Some referenceDict.[file] | ||
else | ||
None)) | ||
(match referenceDict.TryGetValue file with | ||
| true, refFile -> Some refFile | ||
| false, _ -> None)) | ||
|
||
let getProjectReferencesSimple frameworkVersion (dllFiles: string list) = | ||
getProjectReferences frameworkVersion None None dllFiles |> resolve dllFiles | ||
|
@@ -464,26 +463,29 @@ module internal ArgParser = | |
else | ||
None | ||
|
||
[<return: Struct>] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nojaf here is an example where there is a Struct boolean. As boolean is a tiny field, there is no point of wrapping it to inside a separate class, like the original code did. Wrapping just makes the processing of comparisons etc slower. |
||
let (|FsiBoolArg|_|) argName s = | ||
match s with | ||
| StartsWith argName rest -> | ||
if String.IsNullOrWhiteSpace rest then | ||
Some true | ||
ValueSome true | ||
else | ||
match rest with | ||
| "+" -> Some true | ||
| "-" -> Some false | ||
| _ -> None | ||
| _ -> None | ||
| "+" -> ValueSome true | ||
| "-" -> ValueSome false | ||
| _ -> ValueNone | ||
| _ -> ValueNone | ||
|
||
open ArgParser | ||
|
||
[<Struct>] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The heuristic would be here to add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, Enums and similar are struct per default, so if you do this: type MyE =
| A = 1
| B = 2 it's fine as is. But if you do this:
...it's not a struct. So basically it'll generate a class of MyE containing a class of A and class of B and an instance of either. |
||
type internal DebugMode = | ||
| Full | ||
| PdbOnly | ||
| Portable | ||
| NoDebug | ||
|
||
[<Struct>] | ||
type internal OptimizationType = | ||
| NoJitOptimize | ||
| NoJitTracking | ||
|
@@ -761,7 +763,7 @@ type internal FsiOptions = | |
| [] -> Seq.empty | ||
| opts -> | ||
opts | ||
|> Seq.map (fun (enable, types) -> | ||
|> Seq.collect (fun (enable, types) -> | ||
seq { | ||
yield sprintf "--optimize%s" (getMinusPlus enable) | ||
|
||
|
@@ -778,7 +780,6 @@ type internal FsiOptions = | |
| NoTailCalls -> "notailcalls") | ||
|> String.concat "," | ||
}) | ||
|> Seq.concat | ||
|
||
yield! getSimpleBoolArg "--quiet" x.Quiet | ||
yield! getSimpleBoolArg "--quotations-debug" x.QuotationsDebug | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any idea under which conditions you would start using this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Struct constructs came with FSharp.Core 6.0.1 so that's the minimum version.
Works with other return types too.