From 3777cd4d8f9b4fb397df6c6069476dd8a7365ae4 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 19 Feb 2020 14:52:35 -0800 Subject: [PATCH 01/14] Update Build.ps1 (#8579) * Update Build.ps1 * Update MsbuildOverallVersion to 16.4 * fix versions --- eng/Build.ps1 | 2 +- eng/Versions.props | 5 +++-- .../tests/GetTypesVS.UnitTests/GetTypesVS.UnitTests.fsproj | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 4d503dbeda..a3c7ed968f 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -216,7 +216,7 @@ function UpdatePath() { TestAndAddToPath $subdir # add windows SDK dir for ildasm.exe - foreach ($child in Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.?.? Tools") { + foreach ($child in Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.* Tools") { $subdir = $child } TestAndAddToPath $subdir diff --git a/eng/Versions.props b/eng/Versions.props index 3c78780d9f..d702a560e4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -74,7 +74,7 @@ 4.3.0 4.3.0 4.3.0 - 4.5.2 + 4.5.3 4.3.0 4.3.0 4.3.0 @@ -88,6 +88,7 @@ 4.3.0 4.3.0 4.3.0 + 4.11.0 4.3.0 4.3.0 4.3.0 @@ -102,7 +103,7 @@ 2.0.17 $(RoslynVersion) - 16.0.461 + 16.4 $(MicrosoftBuildOverallPackagesVersion) $(MicrosoftBuildOverallPackagesVersion) $(MicrosoftBuildOverallPackagesVersion) diff --git a/vsintegration/tests/GetTypesVS.UnitTests/GetTypesVS.UnitTests.fsproj b/vsintegration/tests/GetTypesVS.UnitTests/GetTypesVS.UnitTests.fsproj index 8c70a8c5e0..9cc5005a54 100644 --- a/vsintegration/tests/GetTypesVS.UnitTests/GetTypesVS.UnitTests.fsproj +++ b/vsintegration/tests/GetTypesVS.UnitTests/GetTypesVS.UnitTests.fsproj @@ -25,6 +25,8 @@ + + From 9a87342ecb943c0ca09bee0923910a62da1db689 Mon Sep 17 00:00:00 2001 From: Hadrian Tang Date: Fri, 21 Feb 2020 00:57:22 +0800 Subject: [PATCH 02/14] Add lowercase L and octal for ints to set of valid numeric literals in FS1156 message (#8584) * Add lowercase L to set of valid numeric literals in FS1156 message * Add octal --- src/fsharp/FSComp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 2f26477c61..b854d70b17 100755 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1021,7 +1021,7 @@ lexUnexpectedChar,"Unexpected character '%s'" 1153,lexInvalidFloat,"Invalid floating point number" 1154,lexOusideDecimal,"This number is outside the allowable range for decimal literals" 1155,lexOusideThirtyTwoBitFloat,"This number is outside the allowable range for 32-bit floats" -1156,lexInvalidNumericLiteral,"This is not a valid numeric literal. Valid numeric literals include 1, 0x1, 0b0001 (int), 1u (uint32), 1L (int64), 1UL (uint64), 1s (int16), 1y (sbyte), 1uy (byte), 1.0 (float), 1.0f (float32), 1.0m (decimal), 1I (BigInteger)." +1156,lexInvalidNumericLiteral,"This is not a valid numeric literal. Valid numeric literals include 1, 0x1, 0o1, 0b1, 1l (int), 1u (uint32), 1L (int64), 1UL (uint64), 1s (int16), 1y (sbyte), 1uy (byte), 1.0 (float), 1.0f (float32), 1.0m (decimal), 1I (BigInteger)." 1157,lexInvalidByteLiteral,"This is not a valid byte literal" 1158,lexInvalidCharLiteral,"This is not a valid character literal" 1159,lexThisUnicodeOnlyInStringLiterals,"This Unicode encoding is only valid in string literals" From f19f6bde7f3224c4a38fff8604c0c27bfc5c4e30 Mon Sep 17 00:00:00 2001 From: Leandro Fernandes Date: Fri, 21 Feb 2020 13:16:07 -0300 Subject: [PATCH 03/14] Create Language-Version-History.md (#8540) * Create Create Language-Version-History.md c# has one file like this here: https://github.com/dotnet/csharplang/blob/master/Language-Version-History.md so looks fine f# should have too. I am learning F# and missed it from this official repository * replace quotes for language markdown * adjusts on 4.7 section * adds references for version 1 and 1.1 * adds object expressions * Rename Create Language-Version-History.md to Language-Version-History.md * start line with upper case * removes Tailcall attribute, it is not implemented * removed 4.7 preview features --- Language-Version-History.md | 107 ++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Language-Version-History.md diff --git a/Language-Version-History.md b/Language-Version-History.md new file mode 100644 index 0000000000..d4d075a9d8 --- /dev/null +++ b/Language-Version-History.md @@ -0,0 +1,107 @@ +Features Added in F# Language Versions +==================== + +# [F# 1.0](https://docs.microsoft.com/en-us/archive/blogs/dsyme/welcome-to-dons-f-blog) + +- Discriminated unions +- Records +- Tuples +- Pattern matching +- Type abbreviations +- Structs +- Signature files +- Imperative programming +- Modules (no functors) +- Nested modules +- .NET Interoperability + +# [F# 1.1](https://docs.microsoft.com/en-us/archive/blogs/dsyme/a-taste-of-whats-new-in-f-1-1) + +- Interactive environment +- Object programming +- Encapsulation Extensions + +# [F# 2.0](https://fsharp.org/specs/language-spec/2.0/FSharpSpec-2.0-April-2012.pdf) + +- Active patterns +- Units of measure +- Object expressions +- Sequence expressions +- Asynchronous programming +- Agent programming +- Extension members +- Named arguments +- Optional arguments +- Array slicing +- Quotations +- Native interoperability +- Computation expressions + +# [F# 3.0](https://fsharp.org/specs/language-spec/3.0/FSharpSpec-3.0-final.pdf) + +- Type providers +- LINQ query expressions +- CLIMutable attribute +- Triple-quoted strings +- Auto-properties +- Provided units-of-measure + +# [F# 3.1](https://fsharp.org/specs/language-spec/3.1/FSharpSpec-3.1-final.pdf) + +- Named union type fields +- Extensions to array slicing +- Type inference enhancements + +# [F# 4.0](https://fsharp.org/specs/language-spec/4.0/FSharpSpec-4.0-final.pdf) + +- `printf` on unitized values +- Extension property initializers +- Non-null provided types +- Primary constructors as functions +- Static parameters for provided methods +- `printf` interpolation +- Extended `#if` grammar +- Multiple interface instantiations +- Optional type args +- Params dictionaries + +# [F# 4.1](https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf) + +- Struct tuples which inter-operate with C# tuples +- Struct annotations for Records +- Struct annotations for Single-case Discriminated Unions +- Underscores in numeric literals +- Caller info argument attributes +- Result type and some basic Result functions +- Mutually referential types and modules within the same file +- Implicit `Module` syntax on modules with shared name as type +- Byref returns, supporting consuming C# `ref`-returning methods +- Error message improvements +- Support for `fixed` + +# [F# 4.5](https://docs.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-45) + +- Versioning alignment of binary, package, and language +- Support for `Span<'T>` and related types +- Ability to produce `byref` returns +- The `voidptr` type +- The `inref<'T>` and `outref<'T>` types to represent readonly and write-only `byref`s +- `IsByRefLike` structs +- `IsReadOnly` structs +- Extension method support for `byref<'T>`/`inref<'T>`/`outref<'T>` +- `match!` keyword in computation expressions +- Relaxed upcast with `yield` in F# sequence/list/array expressions +- Relaxed indentation with list and array expressions +- Enumeration cases emitted as public + +# [F# 4.6](https://docs.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-46) + +- Anonymous records +- `ValueOption` module functions + +# [F# 4.7](https://docs.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-47) + +- Compiler support for `LangVersion` +- Implicit `yield`s +- No more required double underscore (wildcard identifier) +- Indentation relaxations for parameters passed to constructors and static methods From e6212207710b99b7e483ea8c67234211f948ab06 Mon Sep 17 00:00:00 2001 From: Leandro Fernandes Date: Fri, 21 Feb 2020 16:10:09 -0300 Subject: [PATCH 04/14] update object expression was target on F#1.1 while in dons blog it is on 1.0 (#8613) --- Language-Version-History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Language-Version-History.md b/Language-Version-History.md index d4d075a9d8..72da5b5b33 100644 --- a/Language-Version-History.md +++ b/Language-Version-History.md @@ -8,6 +8,7 @@ Features Added in F# Language Versions - Tuples - Pattern matching - Type abbreviations +- Object expressions - Structs - Signature files - Imperative programming @@ -25,7 +26,6 @@ Features Added in F# Language Versions - Active patterns - Units of measure -- Object expressions - Sequence expressions - Asynchronous programming - Agent programming From 1c41665789a23fbfa92ea6782aa23dbf80444db3 Mon Sep 17 00:00:00 2001 From: BooksBaum <15612932+Booksbaum@users.noreply.github.com> Date: Sun, 23 Feb 2020 18:06:25 +0100 Subject: [PATCH 05/14] Respect env variable NUGET_PACKAGES in FSharpQA (#8622) --- eng/Build.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 0445711695..51a71f9db2 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -363,16 +363,17 @@ try { if ($testFSharpQA -and -not $noVisualStudio) { Push-Location "$RepoRoot\tests\fsharpqa\source" + $nugetPackages = Get-PackagesDir $resultsRoot = "$ArtifactsDir\TestResults\$configuration" $resultsLog = "test-net40-fsharpqa-results.log" $errorLog = "test-net40-fsharpqa-errors.log" $failLog = "test-net40-fsharpqa-errors" - $perlPackageRoot = "$env:USERPROFILE\.nuget\packages\StrawberryPerl\5.28.0.1"; + $perlPackageRoot = "$nugetPackages\StrawberryPerl\5.28.0.1"; $perlExe = "$perlPackageRoot\bin\perl.exe" Create-Directory $resultsRoot UpdatePath $env:HOSTED_COMPILER = 1 - $env:CSC_PIPE = "$env:USERPROFILE\.nuget\packages\Microsoft.Net.Compilers\2.7.0\tools\csc.exe" + $env:CSC_PIPE = "$nugetPackages\Microsoft.Net.Compilers\2.7.0\tools\csc.exe" $env:FSCOREDLLPATH = "$ArtifactsDir\bin\fsc\$configuration\net472\FSharp.Core.dll" $env:LINK_EXE = "$RepoRoot\tests\fsharpqa\testenv\bin\link\link.exe" $env:OSARCH = $env:PROCESSOR_ARCHITECTURE From c958341a37d91bb85bc443aacc78c0dc23b8cb17 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 24 Feb 2020 10:23:19 -0800 Subject: [PATCH 06/14] Fixed taking native address of an immutable local value (#8618) --- src/fsharp/TastOps.fs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 761acf38b8..3dd76a5074 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -6078,6 +6078,16 @@ let mkDerefAddrExpr mAddrGet expr mExpr exprTy = /// have intended effect (i.e. is a readonly pointer and/or a defensive copy). let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut expr addrExprVal m = if mustTakeAddress then + let isNativePtr = + match addrExprVal with + | Some vf -> valRefEq g vf g.addrof2_vref + | _ -> false + + // If we are taking the native address using "&&" to get a nativeptr, disallow if it's readonly. + let checkTakeNativeAddress readonly = + if isNativePtr && readonly then + error(Error(FSComp.SR.tastValueMustBeMutable(), m)) + match expr with // LVALUE of "*x" where "x" is byref is just the byref itself | Expr.Op (TOp.LValueOp (LByrefGet, vref), _, [], m) when MustTakeAddressOfByrefGet g vref || CanTakeAddressOfByrefGet g vref mut -> @@ -6090,6 +6100,7 @@ let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress | Expr.Val (vref, _, m) when MustTakeAddressOfVal g vref || CanTakeAddressOfImmutableVal g m vref mut -> let readonly = not (MustTakeAddressOfVal g vref) let writeonly = false + checkTakeNativeAddress readonly None, mkValAddr m readonly vref, readonly, writeonly // LVALUE of "e.f" where "f" is an instance F# field or record field. @@ -6134,15 +6145,11 @@ let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress // LVALUE of "e.[n]" where e is an array of structs | Expr.App (Expr.Val (vf, _, _), _, [elemTy], [aexpr;nexpr], _) when (valRefEq g vf g.array_get_vref) -> - + let readonly = false // array address is never forced to be readonly let writeonly = false let shape = ILArrayShape.SingleDimensional let ilInstrReadOnlyAnnotation = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress - let isNativePtr = - match addrExprVal with - | Some vf -> valRefEq g vf g.addrof2_vref - | _ -> false None, mkArrayElemAddress g (readonly, ilInstrReadOnlyAnnotation, isNativePtr, shape, elemTy, [aexpr; nexpr], m), readonly, writeonly // LVALUE of "e.[n1, n2]", "e.[n1, n2, n3]", "e.[n1, n2, n3, n4]" where e is an array of structs @@ -6153,11 +6160,6 @@ let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress let writeonly = false let shape = ILArrayShape.FromRank args.Length let ilInstrReadOnlyAnnotation = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress - let isNativePtr = - match addrExprVal with - | Some vf -> valRefEq g vf g.addrof2_vref - | _ -> false - None, mkArrayElemAddress g (readonly, ilInstrReadOnlyAnnotation, isNativePtr, shape, elemTy, (aexpr :: args), m), readonly, writeonly // LVALUE: "&meth(args)" where meth has a byref or inref return. Includes "&span.[idx]". From 78316583427c325007a56b819eff82cb8f40c0f7 Mon Sep 17 00:00:00 2001 From: BooksBaum <15612932+Booksbaum@users.noreply.github.com> Date: Mon, 24 Feb 2020 22:24:51 +0100 Subject: [PATCH 07/14] Respect env variable NUGET_PACKAGES in additonal locations (#8624) * Respect NUGET_PACKAGES in FSharpQA test script * Respect NUGET_PACKAGES in FSharp Test Suite (Cambridge) * Respect NUGET_PACKAGES in Span tests * Respect NUGET_PACKAGES in typechecking tests * Remove unused nuget packages path --- clean.sh | 1 + tests/scripts/codingConventions.fsx | 149 ---------------------------- tests/scripts/update-baselines.fsx | 83 ---------------- 3 files changed, 1 insertion(+), 232 deletions(-) delete mode 100644 tests/scripts/codingConventions.fsx delete mode 100644 tests/scripts/update-baselines.fsx diff --git a/clean.sh b/clean.sh index 5fa6ffd30a..ad94376d9f 100755 --- a/clean.sh +++ b/clean.sh @@ -24,6 +24,7 @@ DEAD_DIRS=( "tests/fsharp/tests.fs" "tests/fsharp/typecheck" "tests/fsharpqa" + "tests/scripts" "VisualFSharp.sln" "vsintegration" ) diff --git a/tests/scripts/codingConventions.fsx b/tests/scripts/codingConventions.fsx deleted file mode 100644 index 02e0dc541a..0000000000 --- a/tests/scripts/codingConventions.fsx +++ /dev/null @@ -1,149 +0,0 @@ -// Print some stats about some very very basic code formatting conventions - -open System.IO - -let lines = - [| for dir in [ "src/fsharp"; "src/fsharp/FSharp.Core"; "src/fsharp/symbols"; "src/fsharp/service"; "src/absil" ]do - for file in Directory.EnumerateFiles(__SOURCE_DIRECTORY__ + "/../../" + dir, "*.fs") do - // TcGlobals.fs gets an exception - let lines = File.ReadAllLines file - for (line, lineText) in Array.indexed lines do - - // We hardwire some exceptions - if not (Path.GetFileName(file) = "service.fs") && // churning - not (lineText.Contains("SuppressMessage")) && // old fxcop annotation - not (Path.GetFileName(file) = "TcGlobals.fs") && - not (Path.GetFileName(file) = "tast.fs" && line > 2100 && line < 2400) then - - yield file, (line+1, lineText) |] - - -printfn "------ LINE LENGTH ANALYSIS ----------" -let totalLines = lines.Length -let buckets = lines |> Array.groupBy (fun (_file, (_line, lineText)) -> lineText.Length / 10) |> Array.sortByDescending (fun (key, vs) -> key) - -for (key, sz) in buckets do - printfn "bucket %d-%d - %%%2.1f" (key*10) (key*10+9) (double sz.Length / double totalLines * 100.0) - -printfn "top bucket: " - -for (file, (line, text)) in snd buckets.[0] do - printfn "%s %d %s..." file line text.[0..50] - -let numLong = lines |> Array.filter (fun (_, (line, lineText)) -> lineText.Length > 120) |> Array.length -let numHuge = lines |> Array.filter (fun (_, (line, lineText)) -> lineText.Length > 160) |> Array.length -let numHumungous = lines |> Array.filter (fun (_, (line, lineText)) -> lineText.Length > 200) |> Array.length - -printfn "%d long lines = %2.2f%%" numLong (double numLong / double totalLines) -printfn "%d huge lines = %2.2f%%" numHuge (double numHuge / double totalLines) -printfn "%d humungous lines = %2.2f%%" numHumungous (double numHumungous / double totalLines) - -printfn "------ SPACE AFTER COMMA ANALYSIS ----------" - -let commas = - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.sumBy (fun (_, (_, line)) -> - line |> Seq.pairwise |> Seq.filter (fun (c1, c2) -> c1 = ',' && c2 <> ' ') |> Seq.length)) - |> Array.sortByDescending snd - -printfn "Top files that have commas without spaces: %A" (Array.truncate 10 commas) - - -printfn "------DANGLINE SEMICOLONS----------" - -let semis = - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> line.Trim().EndsWith(";")) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have semicolon at end of line: %A" (Array.truncate 10 semis) - - -printfn "------NO SPACE AFTER COLON----------" - -open System.Text.RegularExpressions - -let noSpaceAfterColons = - let re = Regex(":[a-zA-Z]") - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> re.IsMatch(line)) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have no space after colon:\n%A" (Array.truncate 10 noSpaceAfterColons) - -printfn "------ SPACE BEFORE COLON----------" - - -let spaceBeforeColon = - let re = Regex("[^\\)] : [a-zA-Z]") - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> re.IsMatch(line)) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have extra space before colon:\n%A" (Array.truncate 10 spaceBeforeColon) - -printfn "------ Internal spacing----------" - - -let internalSpacing = - let re = Regex("[^ ] [^ ]") - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> re.IsMatch(line)) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have internal spacing in lines:\n%A" (Array.truncate 10 internalSpacing) - -printfn "------ cenv.g ----------" - -let cenv_dot_g = - let re = Regex("cenv\.g") - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> re.IsMatch(line)) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have endless cenv.g:\n%A" (Array.truncate 10 cenv_dot_g) - -printfn "------ parenthesized atomic expressions (id) ----------" - -let parens_id = - let re = Regex("\([a-zA-Z0-9]+\)") - lines - |> Array.groupBy fst - |> Array.map (fun (file, lines) -> - file, - lines - |> Array.filter (fun (_, (_, line)) -> re.IsMatch(line)) - |> Array.length) - |> Array.sortByDescending snd - -printfn "Top files that have parenthesized atomic expressionsg:\n%A" (Array.truncate 10 parens_id) - diff --git a/tests/scripts/update-baselines.fsx b/tests/scripts/update-baselines.fsx deleted file mode 100644 index 06e9c13ef8..0000000000 --- a/tests/scripts/update-baselines.fsx +++ /dev/null @@ -1,83 +0,0 @@ -open System -open System.IO - -// this script is usefull for tests using a .bsl file (baseline) containing expected compiler output -// which is matched against .vserr or .err file aside once the test has run -// the script replaces all the .bsl/.bslpp with either .err or .vserr - -let diff path1 path2 = - let result = System.Text.StringBuilder() - let append s = result.AppendLine s |> ignore - - if not <| File.Exists(path1) then failwithf "Invalid path %s" path1 - if not <| File.Exists(path2) then failwithf "Invalid path %s" path2 - - let lines1 = File.ReadAllLines(path1) - let lines2 = File.ReadAllLines(path2) - - let minLines = min lines1.Length lines2.Length - - for i = 0 to (minLines - 1) do - - let normalizePath line = line - let line1 = normalizePath lines1.[i] - let line2 = normalizePath lines2.[i] - - if not (line1.Contains "// MVID") && - not (line1.Contains "// Image base:") && - not (line1.Contains ".line") && - not (line1.Contains " .ver ") && - not (line1.Contains "// Offset:") then - if line1 <> line2 then - append <| sprintf "diff between [%s] and [%s]" path1 path2 - append <| sprintf "line %d" (i+1) - append <| sprintf " - %s" line1 - append <| sprintf " + %s" line2 - - if lines1.Length <> lines2.Length then - append <| sprintf "diff between [%s] and [%s]" path1 path2 - append <| sprintf "diff at line %d" minLines - lines1.[minLines .. (lines1.Length - 1)] |> Array.iter (append << sprintf "- %s") - lines2.[minLines .. (lines2.Length - 1)] |> Array.iter (append << sprintf "+ %s") - - result.ToString() - -let fsdiff actualFile expectedFile = - let errorText = System.IO.File.ReadAllText actualFile - - let result = diff expectedFile actualFile - if result <> "" then - printfn "%s" result - - result - -let directories = - [ - "fsharp/typecheck/sigs" - "fsharp/typecheck/overloads" - "fsharpqa/Source" - ] - |> List.map (fun d -> Path.Combine(__SOURCE_DIRECTORY__, ".." , d) |> DirectoryInfo) - -let extensionPatterns = ["*.bsl"; "*.vsbsl"; "*.il.bsl"] -for d in directories do - for p in extensionPatterns do - for bslFile in d.GetFiles (p, SearchOption.AllDirectories) do - let baseLineFileName = bslFile.FullName - if not (baseLineFileName.EndsWith("bslpp")) then - let errFileName = - if baseLineFileName.EndsWith "vsbsl" then Path.ChangeExtension(baseLineFileName, "vserr") - elif baseLineFileName.EndsWith "il.bsl" then baseLineFileName.Replace("il.bsl", "il") - else Path.ChangeExtension(baseLineFileName, "err") - let baseLineFile = FileInfo(baseLineFileName) - let errFile = FileInfo(errFileName) - //let baseLineFilePreProcess = FileInfo(Path.ChangeExtension(errFile.FullName, "bslpp")) - - if baseLineFile.Exists && errFile.Exists then - - //printfn "consider %s and %s" baseLineFile.FullName errFileName - if fsdiff errFileName baseLineFileName <> "" then - - printfn "%s not matching, replacing with %s" baseLineFileName errFileName - if not (fsi.CommandLineArgs |> Array.contains "-n") then - errFile.CopyTo(baseLineFileName, true) |> ignore From cb4495d9db2b7e9187df4dccb895f23a088a0867 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 25 Feb 2020 13:14:16 +0000 Subject: [PATCH 08/14] Update dependencies from https://github.com/dotnet/arcade build 20200224.2 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.20124.2 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3d0782ecae..66cc21e803 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 15f00efd583eab4372b2e9ca25bd80ace5b119ad + 0b8ce7c1c078eefb4cbc4d7e67ffc02f1f73382d diff --git a/global.json b/global.json index 6a33a4ecc1..024090cb36 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.20113.5", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.20124.2", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 836f8aba1f19f6994c335d97bd2d11f221396b8c Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 28 Feb 2020 03:26:42 +0300 Subject: [PATCH 09/14] Fix wild self id pat range (#8635) --- src/fsharp/pars.fsy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 66ee0bd792..278ad39154 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -1942,8 +1942,8 @@ atomicPatternLongIdent: | pathOp { (None,$1) } | access UNDERSCORE DOT pathOp { if not (parseState.LexBuffer.SupportsFeature LanguageFeature.SingleUnderscorePattern) then - raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedSymbolDot()) - let (LongIdentWithDots(lid,dotms)) = $4 in (Some($1),LongIdentWithDots(ident("_",rhs parseState 1)::lid, rhs parseState 2::dotms)) + raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedSymbolDot()) + let (LongIdentWithDots(lid,dotms)) = $4 in (Some($1),LongIdentWithDots(ident("_",rhs parseState 2)::lid, rhs parseState 3::dotms)) } | access pathOp { (Some($1), $2) } From 5b9748add16fd78b69a69f5e5c610f68f6246a63 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 3 Mar 2020 00:08:49 +0300 Subject: [PATCH 10/14] Fix more declaration ranges (#7774) * Fix field declaration ranges * Fix type fields ranges * Add test * Fix more ranges * Update baselines --- src/fsharp/pars.fsy | 68 +++++++++++++++------------- tests/service/StructureTests.fs | 80 ++++++++++++++++++++++++++++++--- 2 files changed, 110 insertions(+), 38 deletions(-) diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 278ad39154..59a07765b3 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -676,7 +676,7 @@ fileModuleSpec: | opt_attributes opt_declVisibility moduleIntro moduleSpfnsPossiblyEmptyBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) let m2 = rhs parseState 3 - let m = (rhs2 parseState 3 4) + let m = (rhs2 parseState 1 4) let isRec,path2,xml,vis = $3 (fun (isRec2,path,_) -> if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(),m2)) @@ -745,7 +745,7 @@ moduleSpfn: if not (isNil $1) then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()) match vis with | Some vis -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreVisibilityOnModuleAbbreviationAlwaysPrivate(vis.ToString())) - | _ -> SynModuleSigDecl.ModuleAbbrev(List.head path,$5,rhs2 parseState 3 5) } + | _ -> SynModuleSigDecl.ModuleAbbrev(List.head path,$5,rhs2 parseState 1 5) } | opt_attributes opt_declVisibility moduleIntro colonOrEquals moduleSpecBlock { let isRec, path, xml, vis = $3 @@ -753,7 +753,7 @@ moduleSpfn: if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) let info = ComponentInfo($1,[],[],path,xml,false,vis,rhs parseState 3) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - SynModuleSigDecl.NestedModule(info, isRec, $5, rhs2 parseState 3 5) } + SynModuleSigDecl.NestedModule(info, isRec, $5, rhs2 parseState 1 5) } | opt_attributes opt_declVisibility tyconSpfns { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) @@ -778,7 +778,7 @@ valSpfn: { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) let attr1,attr2,isInline,isMutable,vis2,id,doc,explicitValTyparDecls,(ty,arity),konst = ($1),($4),($5),($6),($7),($8),grabXmlDoc(parseState,3),($9),($11),($12) if not (isNil attr2) then errorR(Deprecated(FSComp.SR.parsAttributesMustComeBeforeVal(),rhs parseState 4)) - let m = rhs2 parseState 3 11 + let m = rhs2 parseState 1 11 let valSpfn = ValSpfn((attr1@attr2),id,explicitValTyparDecls,ty,arity,isInline,isMutable,doc, vis2,konst,m) SynModuleSigDecl.Val(valSpfn,m) } @@ -965,21 +965,23 @@ classMemberSpfn: SynMemberSig.Inherit ($4,unionRanges (rhs parseState 3) ($4).Range) } | opt_attributes opt_declVisibility VAL fieldDecl - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - let fld = $4 $1 false - SynMemberSig.ValField(fld,rhs2 parseState 3 4) } + { let wholeRange = rhs2 parseState 1 4 + if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) + let fld = $4 $1 false wholeRange + SynMemberSig.ValField (fld, wholeRange) } | opt_attributes opt_declVisibility STATIC VAL fieldDecl - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - SynMemberSig.ValField($5 $1 true,rhs2 parseState 3 5) } + { let wholeRange = rhs2 parseState 1 5 + if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) + SynMemberSig.ValField($5 $1 true wholeRange, wholeRange) } | opt_attributes opt_declVisibility STATIC typeKeyword tyconSpfn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - SynMemberSig.NestedType($5,rhs2 parseState 3 5) } + SynMemberSig.NestedType($5,rhs2 parseState 1 5) } | opt_attributes opt_declVisibility NEW COLON topTypeWithTypeConstraints { let vis,doc,(ty,valSynInfo) = $2,grabXmlDoc(parseState,3),$5 - let m = unionRanges (rhs parseState 3) ty.Range + let m = unionRanges (rhs parseState 1) ty.Range let isInline = false let valSpfn = ValSpfn ($1, mkSynId (rhs parseState 3) "new", noInferredTypars, ty, valSynInfo, isInline, false, doc, vis, None, m) SynMemberSig.Member(valSpfn, CtorMemberFlags,m) } @@ -1254,7 +1256,7 @@ moduleDefn: | Choice2Of2 def -> if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()) let info = ComponentInfo(attribs,[],[],path,xml,false,vis,rhs parseState 3) - [ SynModuleDecl.NestedModule(info, isRec, def, false,(rhs2 parseState 3 4, def) ||> unionRangeWithListBy (fun d -> d.Range) ) ] } + [ SynModuleDecl.NestedModule(info, isRec, def, false,(rhs2 parseState 1 4, def) ||> unionRangeWithListBy (fun d -> d.Range) ) ] } /* unattached custom attributes */ | attributes recover @@ -1850,8 +1852,8 @@ classDefnMember: if Option.isSome $2 then errorR(Error(FSComp.SR.parsInterfacesHaveSameVisibilityAsEnclosingType(),rhs parseState 3)) let mWhole = match $5 with - | None -> rhs2 parseState 3 4 - | Some(mems) -> (rhs2 parseState 3 4, mems) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range) + | None -> rhs2 parseState 1 4 + | Some(mems) -> (rhs2 parseState 1 4, mems) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range) [ SynMemberDefn.Interface ($4, $5, mWhole) ] } | opt_attributes opt_declVisibility abstractMemberFlags opt_inline nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_ODECLEND @@ -1860,7 +1862,7 @@ classDefnMember: let getSetRangeOpt, getSet = $9 let getSetAdjuster arity = match arity,getSet with SynValInfo([],_),MemberKind.Member -> MemberKind.PropertyGet | _ -> getSet let wholeRange = - let m = rhs parseState 3 + let m = rhs parseState 1 match getSetRangeOpt with | None -> unionRanges m ty.Range | Some m2 -> unionRanges m m2 @@ -1875,11 +1877,13 @@ classDefnMember: | opt_attributes opt_declVisibility valDefnDecl opt_ODECLEND { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - $3 None $1 false } + let rangeStart = rhs parseState 1 + $3 rangeStart $1 false } | opt_attributes opt_declVisibility STATIC valDefnDecl opt_ODECLEND { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - $4 (Some (rhs parseState 3)) $1 true } + let rangeStart = rhs parseState 1 + $4 rangeStart $1 true } | opt_attributes opt_declVisibility memberFlags autoPropsDefnDecl opt_ODECLEND { let rangeStart = rhs parseState 1 @@ -1889,7 +1893,7 @@ classDefnMember: $4 $1 isStatic flags rangeStart } | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND - { let m = unionRanges (rhs2 parseState 3 6) $7.Range + { let m = unionRanges (rhs2 parseState 1 6) $7.Range let expr = $7 let valSynData = SynValData (Some CtorMemberFlags, SynValInfo([SynInfo.InferSynArgInfoFromPat $4],SynInfo.unnamedRetVal), $5) let vis = $2 @@ -1900,7 +1904,7 @@ classDefnMember: | opt_attributes opt_declVisibility STATIC typeKeyword tyconDefn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - [ SynMemberDefn.NestedType($5,None,rhs2 parseState 3 5) ] } + [ SynMemberDefn.NestedType($5,None,rhs2 parseState 1 5) ] } /* A 'val' definition in an object type definition */ @@ -1909,8 +1913,8 @@ valDefnDecl: { let mRhs = rhs2 parseState 4 6 let doc = grabXmlDoc(parseState,4) let mValDecl = rhs2 parseState 1 6 - (fun mLeft attribs isStatic -> - let mValDecl = match mLeft with None -> mValDecl | Some m -> unionRanges m mValDecl + (fun rangeStart attribs isStatic -> + let mValDecl = unionRanges rangeStart mValDecl let fld = Field(attribs,isStatic,Some $4,$6,$2,doc,$3,mRhs) [ SynMemberDefn.ValField(fld, mValDecl) ]) } @@ -2294,20 +2298,20 @@ attrUnionCaseDecl: | opt_attributes opt_access unionCaseName OF unionCaseRepr opt_OBLOCKSEP { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2)) - let mDecl = rhs2 parseState 3 5 + let mDecl = rhs2 parseState 1 5 (fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFields $5,xmlDoc,None,mDecl))) } | opt_attributes opt_access unionCaseName COLON topType opt_OBLOCKSEP { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2)) libraryOnlyWarning(lhs parseState) - let mDecl = rhs2 parseState 3 5 + let mDecl = rhs2 parseState 1 5 (fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFullType $5,xmlDoc,None,mDecl))) } | opt_attributes opt_access unionCaseName EQUALS constant opt_OBLOCKSEP { if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2)) - let mDecl = rhs2 parseState 3 5 + let mDecl = rhs2 parseState 1 5 (fun xmlDoc -> Choice1Of2 (EnumCase ( $1, $3,$5,xmlDoc,mDecl))) } @@ -2365,18 +2369,18 @@ recdFieldDeclList: /* A field declaration in a record type */ recdFieldDecl: - | opt_attributes fieldDecl - { let fld = $2 $1 false - let (Field(a,b,c,d,e,f,vis,g)) = fld - if Option.isSome vis then errorR(Error(FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2)) - Field(a,b,c,d,e,f,None,g) } + | opt_attributes fieldDecl + { let wholeRange = rhs2 parseState 1 2 + let fld = $2 $1 false wholeRange + let (Field (a, b, c, d, e, f, vis, wholeRange)) = fld + if Option.isSome vis then errorR (Error (FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations (), rhs parseState 2)) + Field (a, b, c, d, e, f, None, wholeRange) } /* Part of a field or val declaration in a record type or object type */ fieldDecl: | opt_mutable opt_access ident COLON typ - { let mRhs = rhs2 parseState 3 5 - let xmlDoc = grabXmlDoc(parseState,3) - (fun attrs stat -> Field(attrs, stat,Some $3,$5,$1,xmlDoc,$2,mRhs)) } + { let xmlDoc = grabXmlDoc (parseState, 3) + fun attrs stat wholeRange -> Field(attrs, stat, Some $3, $5, $1, xmlDoc, $2, wholeRange) } /* An exception definition */ diff --git a/tests/service/StructureTests.fs b/tests/service/StructureTests.fs index c3583fe5ab..028e05e4b3 100644 --- a/tests/service/StructureTests.fs +++ b/tests/service/StructureTests.fs @@ -66,8 +66,13 @@ let ``nested module``() = """ module MyModule = () + +[] +module Module = + () """ - => [ (2, 0, 3, 6), (2, 15, 3, 6) ] + => [ (2, 0, 3, 6), (2, 15, 3, 6) + (5, 0, 7, 6), (6, 13, 7, 6) ] [] let ``module with multiline function``() = @@ -113,10 +118,10 @@ type Color = let ``record with interface``() = """ type Color = - { Red: int - Green: int - Blue: int - } + { Red: + int + mutable Blue: + int } interface IDisposable with member __.Dispose() = @@ -124,8 +129,9 @@ type Color = """ => [ (2, 5, 10, 55), (2, 11, 10, 55) - (3, 4, 4, 14), (3, 4, 4, 14) + (3, 4, 6, 15), (3, 4, 6, 15) (3, 6, 4, 13), (3, 6, 4, 13) + (5, 6, 6, 13), (5, 6, 6, 13) (8, 4, 10, 55), (8, 25, 10, 55) (9, 8, 10, 55), (9, 27, 10, 55) (9, 15, 10, 55), (9, 27, 10, 55) ] @@ -607,3 +613,65 @@ module NestedModule = """ => [ (4, 0, 5, 15), (4, 13, 5, 15) (9, 0, 10, 15), (9, 19, 10, 15) ] + +[] +let ``Member val`` () = + """ +type T() = + member val field1 = + () + + [] + member val field2 = + () + + static member val field3 = + () + + [] + static member val field4 = + () +""" + => [ (2, 5, 15, 10), (2, 7, 15, 10) + (3, 4, 4, 10), (3, 4, 4, 10) + (6, 4, 8, 10), (6, 4, 8, 10) + (10, 4, 11, 10), (10, 4, 11, 10) + (13, 4, 15, 10), (13, 4, 15, 10) ] + +[] +let ``Secondary constructors`` () = + """ +type T() = + new () = + T () + + internal new () = + T () + + [] + new () = + T () +""" + => [ (2, 5, 11, 12), (2, 7, 11, 12) + (3, 4, 4, 12), (3, 7, 4, 12) + (3, 4, 4, 12), (4, 8, 4, 12) + (6, 4, 7, 12), (6, 16, 7, 12) + (6, 4, 7, 12), (7, 8, 7, 12) + (9, 4, 11, 12), (10, 7, 11, 12) + (9, 4, 11, 12), (11, 8, 11, 12) ] + + +[] +let ``Abstract members`` () = + """ +type T() = + abstract Foo: + int + + [] + abstract Foo: + int +""" + => [ (2, 5, 8, 11), (2, 7, 8, 11) + (3, 4, 4, 11), (4, 8, 4, 11) + (6, 4, 8, 11), (8, 8, 8, 11) ] From f263e0617d9d097b19a1bd9729028acb707b4bf5 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 3 Mar 2020 21:47:07 +0300 Subject: [PATCH 11/14] Recover type checking inherit ctor arg expression (#8653) * Recover type checking inherit ctor expression * Add test --- src/fsharp/TypeChecker.fs | 7 ++++++- tests/service/Common.fs | 10 ++++++---- tests/service/EditorTests.fs | 11 +++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 2cf45098b9..a3f38aacad 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -13982,7 +13982,12 @@ module MutRecBindingChecking = | Phase2AInherit (synBaseTy, arg, baseValOpt, m) -> let baseTy, tpenv = TcType cenv NoNewTypars CheckCxs ItemOccurence.Use envInstance tpenv synBaseTy let baseTy = baseTy |> convertToTypeWithMetadataIfPossible g - let inheritsExpr, tpenv = TcNewExpr cenv envInstance tpenv baseTy (Some synBaseTy.Range) true arg m + let inheritsExpr, tpenv = + try + TcNewExpr cenv envInstance tpenv baseTy (Some synBaseTy.Range) true arg m + with e -> + errorRecovery e m + mkUnit g m, tpenv let envInstance = match baseValOpt with Some baseVal -> AddLocalVal cenv.tcSink scopem baseVal envInstance | None -> envInstance let envNonRec = match baseValOpt with Some baseVal -> AddLocalVal cenv.tcSink scopem baseVal envNonRec | None -> envNonRec let innerState = (tpenv, envInstance, envStatic, envNonRec, generalizedRecBinds, preGeneralizationRecBinds, uncheckedRecBindsTable) diff --git a/tests/service/Common.fs b/tests/service/Common.fs index cd180a0900..e62233448b 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -312,8 +312,8 @@ let getSymbolUses (source: string) = typeCheckResults.GetAllUsesOfAllSymbolsInFile() |> Async.RunSynchronously let getSymbols (source: string) = - getSymbolUses source - |> Array.map (fun symbolUse -> symbolUse.Symbol) + let symbolUses = getSymbolUses source + symbolUses |> Array.map (fun symbolUse -> symbolUse.Symbol) let getSymbolName (symbol: FSharpSymbol) = @@ -329,8 +329,10 @@ let getSymbolName (symbol: FSharpSymbol) = let assertContainsSymbolWithName name source = - getSymbols source - |> Array.choose getSymbolName + let symbols = getSymbols source + let names = symbols |> Array.choose getSymbolName + + names |> Array.contains name |> shouldEqual true diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index 9ed74c96f2..459aa75ea9 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -1361,3 +1361,14 @@ type R = y """ assertContainsSymbolWithName "y" source + + +[] +let ``Inherit ctor arg recovery`` () = + let source = """ + type T() as this = + inherit System.Exception('a', 'a') + + let x = this + """ + assertContainsSymbolWithName "x" source From d3860980201f874e6785fd6947cb37e9fe6c2498 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 3 Mar 2020 14:53:10 -0800 Subject: [PATCH 12/14] Fixed destNullableTy internal error (#8655) * Fixed internal error for destNullableTy by removing rule for optional * Added test --- src/fsharp/MethodCalls.fs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 341664d873..5f55249644 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -189,7 +189,7 @@ let AdjustCalledArgTypeForOptionals (g: TcGlobals) enforceNullableOptionalsKnown // CSharpMethod(x = arg), optional C#-style argument, may have type Nullable. // The arg should have type ty. However for backwards compat, we also allow arg to have type Nullable | CallerSide _ -> - if isNullableTy g calledArgTy && g.langVersion.SupportsFeature LanguageFeature.NullableOptionalInterop then + if isNullableTy g calledArgTy && g.langVersion.SupportsFeature LanguageFeature.NullableOptionalInterop then // If inference has worked out it's a nullable then use this if isNullableTy g callerArg.CallerArgumentType then calledArgTy @@ -1186,11 +1186,6 @@ let AdjustCallerArgForOptional tcFieldInit eCallerMemberName (infoReader: InfoRe let minfo = GetIntrinsicConstructorInfosOfType infoReader m calledArgTy |> List.head let callerArgExprCoerced = mkCoerceIfNeeded g calledNonOptTy callerArgTy callerArgExpr MakeMethInfoCall amap m minfo [] [callerArgExprCoerced] - elif isOptionTy g calledArgTy then - // CSharpMethod(x=b) when 'b' has nullable type and 'x' has optional type --> CSharpMethod(Some b.Value) - let calledNonOptTy = destOptionTy g calledArgTy - let callerArgExprCoerced = mkCoerceIfNeeded g calledNonOptTy callerArgTy callerArgExpr - mkSome g (destNullableTy g callerArgTy) callerArgExprCoerced m else // CSharpMethod(x=b) --> CSharpMethod(?x=b) callerArgExpr From 10c3c1793d9c23639e2a5eca0c0527bd023c555d Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 4 Mar 2020 11:40:59 -0800 Subject: [PATCH 13/14] Refactor Native /Assembly resolution (#8606) * Refactor native resolution * Fcs -- compile * typo * buildy * Linux * Update src/fsharp/CompileOps.fs Co-Authored-By: Phillip Carter * feedback * temp * c# * fix delete and fsharpcore reference. * improve surface area Co-authored-by: Phillip Carter --- .../FSharp.Compiler.Service.fsproj | 20 +- src/fsharp/CompileOps.fs | 81 +++++--- .../FSDependencyManager.txt | 3 + .../FSharp.DependencyManager.ProjectFile.fs | 2 +- .../FSharp.DependencyManager.Utilities.fs | 36 ++-- .../FSharp.DependencyManager.fs | 52 +++-- .../FSharp.DependencyManager.fsi | 28 ++- .../xlf/FSDependencyManager.txt.cs.xlf | 15 ++ .../xlf/FSDependencyManager.txt.de.xlf | 15 ++ .../xlf/FSDependencyManager.txt.es.xlf | 15 ++ .../xlf/FSDependencyManager.txt.fr.xlf | 15 ++ .../xlf/FSDependencyManager.txt.it.xlf | 15 ++ .../xlf/FSDependencyManager.txt.ja.xlf | 15 ++ .../xlf/FSDependencyManager.txt.ko.xlf | 15 ++ .../xlf/FSDependencyManager.txt.pl.xlf | 15 ++ .../xlf/FSDependencyManager.txt.pt-BR.xlf | 15 ++ .../xlf/FSDependencyManager.txt.ru.xlf | 15 ++ .../xlf/FSDependencyManager.txt.tr.xlf | 15 ++ .../xlf/FSDependencyManager.txt.zh-Hans.xlf | 15 ++ .../xlf/FSDependencyManager.txt.zh-Hant.xlf | 15 ++ .../AssemblyResolveHandler.fs | 69 +++++++ .../AssemblyResolveHandler.fsi | 19 ++ .../DependencyManager.fsi | 53 ----- ...ndencyManager.fs => DependencyProvider.fs} | 195 ++++++++++++++---- .../DependencyProvider.fsi | 81 ++++++++ .../Interactive.DependencyManager.fsproj | 13 +- .../NativeDllResolveHandler.fs | 129 ++++++++++++ .../NativeDllResolveHandler.fsi | 19 ++ src/fsharp/fsi/fsi.fs | 171 +++------------ 29 files changed, 861 insertions(+), 305 deletions(-) create mode 100644 src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fs create mode 100644 src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fsi delete mode 100644 src/fsharp/Interactive.DependencyManager/DependencyManager.fsi rename src/fsharp/Interactive.DependencyManager/{DependencyManager.fs => DependencyProvider.fs} (54%) create mode 100644 src/fsharp/Interactive.DependencyManager/DependencyProvider.fsi create mode 100644 src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fs create mode 100644 src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fsi diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index d88f41a1ca..105eb66405 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -525,11 +525,23 @@ Driver\DotNetFrameworkDependencies.fs - - Driver/DependencyManager.fsi + + Driver\AssemblyResolveHandler.fsi - - Driver/DependencyManager.fs + + Driver\AssemblyResolveHandler.fs + + + Driver\NativeDllResolveHandler.fsi + + + Driver\NativeDllResolveHandler.fs + + + Driver/DependencyProvider.fsi + + + Driver/DependencyProvider.fs Driver/CompileOps.fsi diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index dcc6c32839..2b5e4f88a6 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2199,7 +2199,7 @@ type TcConfigBuilder = mutable productNameForBannerText: string /// show the MS (c) notice, e.g. with help or fsi? mutable showBanner: bool - + /// show times between passes? mutable showTimes: bool mutable showLoadedAssemblies: bool @@ -2229,7 +2229,7 @@ type TcConfigBuilder = mutable emitDebugInfoInQuotations: bool mutable exename: string option - + // If true - the compiler will copy FSharp.Core.dll along the produced binaries mutable copyFSharpCore: CopyFSharpCoreFlag @@ -2390,9 +2390,24 @@ type TcConfigBuilder = noConditionalErasure = false pathMap = PathMap.empty langVersion = LanguageVersion("default") - dependencyProvider = new DependencyProvider() + dependencyProvider = Unchecked.defaultof } + // Directories to start probing in + // Algorithm: + // Search for native libraries using: + // 1. Include directories + // 2. compilerToolPath directories + // 3. reference dll's + // 4. The implicit include directory + member private tcConfigB.nativeProbingRoots () = + seq { + yield! tcConfigB.includes + yield! tcConfigB.compilerToolPaths + yield! (tcConfigB.referencedDLLs |> Seq.map(fun ref -> Path.GetDirectoryName(ref.Text))) + yield tcConfigB.implicitIncludeDir + } |> Seq.distinct + static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, isInteractive, isInvalidationSupported, defaultCopyFSharpCore, tryGetMetadataSnapshot) = @@ -2401,17 +2416,20 @@ type TcConfigBuilder = if (String.IsNullOrEmpty defaultFSharpBinariesDir) then failwith "Expected a valid defaultFSharpBinariesDir" - { TcConfigBuilder.Initial with - implicitIncludeDir = implicitIncludeDir - defaultFSharpBinariesDir = defaultFSharpBinariesDir - reduceMemoryUsage = reduceMemoryUsage - legacyReferenceResolver = legacyReferenceResolver - isInteractive = isInteractive - isInvalidationSupported = isInvalidationSupported - copyFSharpCore = defaultCopyFSharpCore - tryGetMetadataSnapshot = tryGetMetadataSnapshot - useFsiAuxLib = isInteractive - } + let tcConfigBuilder = + { TcConfigBuilder.Initial with + implicitIncludeDir = implicitIncludeDir + defaultFSharpBinariesDir = defaultFSharpBinariesDir + reduceMemoryUsage = reduceMemoryUsage + legacyReferenceResolver = legacyReferenceResolver + isInteractive = isInteractive + isInvalidationSupported = isInvalidationSupported + copyFSharpCore = defaultCopyFSharpCore + tryGetMetadataSnapshot = tryGetMetadataSnapshot + useFsiAuxLib = isInteractive + } + tcConfigBuilder.dependencyProvider <- new DependencyProvider(NativeResolutionProbe(tcConfigBuilder.nativeProbingRoots)) + tcConfigBuilder member tcConfigB.ResolveSourceFile(m, nm, pathLoadedFrom) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter @@ -4964,10 +4982,13 @@ let ProcessMetaCommandsFromInput if not canHaveScriptMetaCommands then errorR(HashReferenceNotAllowedInNonScript m) - let reportError errorType error = - match errorType with - | ErrorReportType.Warning -> warning(Error(error,m)) - | ErrorReportType.Error -> errorR(Error(error, m)) + let reportError = + let report errorType err msg = + let error = err, msg + match errorType with + | ErrorReportType.Warning -> warning(Error(error, m)) + | ErrorReportType.Error -> errorR(Error(error, m)) + ResolvingErrorReport (report) match args with | [path] -> @@ -5257,10 +5278,13 @@ module ScriptPreprocessClosure = match packageManagerLines with | [] -> () | (_, _, m)::_ -> - let reportError errorType error = - match errorType with - | ErrorReportType.Warning -> warning(Error(error,m)) - | ErrorReportType.Error -> errorR(Error(error, m)) + let reportError = + let report errorType err msg = + let error = err, msg + match errorType with + | ErrorReportType.Warning -> warning(Error(error, m)) + | ErrorReportType.Error -> errorR(Error(error, m)) + ResolvingErrorReport (report) match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with | Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> () @@ -5273,22 +5297,23 @@ module ScriptPreprocessClosure = | dependencyManager -> let inline snd3 (_, b, _) = b let packageManagerTextLines = packageManagerLines |> List.map snd3 - match tcConfig.dependencyProvider.Resolve(dependencyManager, tcConfig.implicitIncludeDir, mainFile, scriptName, ".fsx", packageManagerTextLines, reportError, executionTfm) with - | true, _references, generatedScripts, additionalIncludeFolders -> + let result = tcConfig.dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError, executionTfm, tcConfig.implicitIncludeDir, mainFile, scriptName) + match result.Success with + | true -> // Resolution produced no errors - if not (Seq.isEmpty additionalIncludeFolders) then + if not (Seq.isEmpty result.Roots) then let tcConfigB = tcConfig.CloneOfOriginalBuilder - for folder in additionalIncludeFolders do + for folder in result.Roots do tcConfigB.AddIncludePath(m, folder, "") tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) tcConfig <- TcConfig.Create(tcConfigB, validate=false) - for script in generatedScripts do + for script in result.SourceFiles do let scriptText = File.ReadAllText script loadScripts.Add script |> ignore let iSourceText = SourceText.ofString scriptText yield! loop (ClosureSource(script, m, iSourceText, true)) - | false, _, _, _ -> + | false -> // Resolution produced errors update packagerManagerLines entries to note these failure // failed resolutions will no longer be considered let tcConfigB = tcConfig.CloneOfOriginalBuilder diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSDependencyManager.txt b/src/fsharp/FSharp.DependencyManager.Nuget/FSDependencyManager.txt index a163aafc0f..2905c0ec88 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSDependencyManager.txt +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSDependencyManager.txt @@ -1,2 +1,5 @@ # FSharp.Build resource strings +cantReferenceSystemPackage,"PackageManager can not reference the System Package '%s'" +requiresAValue,"%s requires a value" +unableToApplyImplicitArgument,"Unable to apply implicit argument number %d" notUsed,"Not used." \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index 7d9478148f..a4945da4c7 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -187,7 +187,7 @@ $(PACKAGEREFERENCES) diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs index 4f6d78e78c..a5038fd984 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs @@ -152,16 +152,16 @@ module internal Utilities = else None - let drainStreamToFile (stream: StreamReader) filename = - use file = File.OpenWrite(filename) - use writer = new StreamWriter(file) + let drainStreamToMemory (stream: StreamReader) = + let mutable list = ResizeArray() let rec copyLines () = match stream.ReadLine() with | null -> () | line -> - writer.WriteLine(line) + list.Add line copyLines () copyLines () + list.ToArray() let executeBuild pathToExe arguments workingDir = match pathToExe with @@ -179,24 +179,24 @@ module internal Utilities = p.StartInfo <- psi p.Start() |> ignore - let standardOutput = Path.Combine(workingDir, "StandardOutput.txt") - let standardError = Path.Combine(workingDir, "StandardError.txt") - drainStreamToFile p.StandardOutput (Path.Combine(workingDir, standardOutput)) - drainStreamToFile p.StandardError (Path.Combine(workingDir, standardError)) + let stdOut = drainStreamToMemory p.StandardOutput + let stdErr = drainStreamToMemory p.StandardError + +#if Debug + File.WriteAllLines(Path.Combine(workingDir, "StandardOutput.txt"), stdOut) + File.WriteAllLines(Path.Combine(workingDir, "StandardError.txt"), stdErr) +#endif p.WaitForExit() + if p.ExitCode <> 0 then //Write StandardError.txt to err stream - let text = File.ReadAllText(standardOutput) - Console.Out.Write(text) - - //Write StandardOutput.txt to out stream - let text = File.ReadAllText(standardError) - Console.Out.Write(text) + for line in stdOut do Console.Out.WriteLine(line) + for line in stdErr do Console.Error.WriteLine(line) - p.ExitCode = 0 + p.ExitCode = 0, stdOut, stdErr - | None -> false + | None -> false, Array.empty, Array.empty let buildProject projectPath binLogPath = let binLoggingArguments = @@ -213,7 +213,7 @@ module internal Utilities = let workingDir = Path.GetDirectoryName projectPath - let succeeded = + let succeeded, stdOut, stdErr = if not (isRunningOnCoreClr) then // The Desktop build uses "msbuild" to build executeBuild msbuildExePath (arguments "") workingDir @@ -223,4 +223,4 @@ module internal Utilities = let outputFile = projectPath + ".resolvedReferences.paths" let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None - succeeded, resultOutFile + succeeded, stdOut, stdErr, resultOutFile diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs index bc6bee837f..9848577272 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fs @@ -10,7 +10,7 @@ open System.IO open FSharp.DependencyManager.Nuget open FSharp.DependencyManager.Nuget.Utilities open FSharp.DependencyManager.Nuget.ProjectFile - +open FSDependencyManager module FSharpDependencyManager = @@ -43,7 +43,7 @@ module FSharpDependencyManager = let parsePackageReferenceOption (line: string) = let validatePackageName package packageName = if String.Compare(packageName, package, StringComparison.OrdinalIgnoreCase) = 0 then - raise (ArgumentException(sprintf "PackageManager can not reference the System Package '%s'" packageName)) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + raise (ArgumentException(SR.cantReferenceSystemPackage(packageName))) let rec parsePackageReferenceOption' (options: (string option * string option) list) (implicitArgumentCount: int) (packageReference: PackageReference option) = let current = match packageReference with @@ -61,11 +61,11 @@ module FSharpDependencyManager = let setVersion v = Some { current with Version = v } match opt with | Some "include", Some v -> addInclude v |> parsePackageReferenceOption' rest implicitArgumentCount - | Some "include", None -> raise (ArgumentException(sprintf "%s requires a value" "Include")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "include", None -> raise (ArgumentException(SR.requiresAValue("Include"))) | Some "version", Some v -> setVersion v |> parsePackageReferenceOption' rest implicitArgumentCount - | Some "version", None -> raise (ArgumentException(sprintf "%s requires a value" "Version")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "version", None -> setVersion "*" |> parsePackageReferenceOption' rest implicitArgumentCount | Some "restoresources", Some v -> Some { current with RestoreSources = concat current.RestoreSources v } |> parsePackageReferenceOption' rest implicitArgumentCount - | Some "restoresources", None -> raise (ArgumentException(sprintf "%s requires a value" "RestoreSources")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "restoresources", None -> raise (ArgumentException(SR.requiresAValue("RestoreSources"))) | Some "script", Some v -> Some { current with Script = v } |> parsePackageReferenceOption' rest implicitArgumentCount | Some "bl", value -> match value with @@ -88,7 +88,7 @@ module FSharpDependencyManager = match implicitArgumentCount with | 0 -> addInclude v | 1 -> setVersion v - | _ -> raise (ArgumentException(sprintf "Unable to apply implicit argument number %d" (implicitArgumentCount + 1))) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | _ -> raise (ArgumentException(SR.unableToApplyImplicitArgument(implicitArgumentCount + 1))) |> parsePackageReferenceOption' rest (implicitArgumentCount + 1) | _ -> parsePackageReferenceOption' rest implicitArgumentCount packageReference let options = getOptions line @@ -98,12 +98,34 @@ module FSharpDependencyManager = |> List.distinct |> (fun l -> l, binLogPath) + +/// The results of ResolveDependencies +type ResolveDependenciesResult (success: bool, stdOut: string array, stdError: string array, resolutions: string seq, sourceFiles: string seq, roots: string seq) = + + /// Succeded? + member __.Success = success + + /// The resolution output log + member __.StdOut = stdOut + + /// The resolution error log (* process stderror *) + member __.StdError = stdError + + /// The resolution paths + member __.Resolutions = resolutions + + /// The source code file paths + member __.SourceFiles = sourceFiles + + /// The roots to package directories + member __.Roots = roots + type [] FSharpDependencyManager (outputDir:string option) = let key = "nuget" let name = "MsBuild Nuget DependencyManager" let scriptsPath = - let path = Path.Combine(Path.GetTempPath(), key, Process.GetCurrentProcess().Id.ToString()) + let path = Path.Combine(Path.GetTempPath(), key, Process.GetCurrentProcess().Id.ToString() + "--"+ Guid.NewGuid().ToString()) match outputDir with | None -> path | Some v -> Path.Combine(path, v) @@ -112,8 +134,12 @@ type [] FSharpDependencyManager (outputDir:string op let deleteScripts () = try +#if !Debug if Directory.Exists(scriptsPath) then - () //Directory.Delete(scriptsPath, true) + Directory.Delete(scriptsPath, true) +#else + () +#endif with | _ -> () let deleteAtExit = @@ -136,7 +162,7 @@ type [] FSharpDependencyManager (outputDir:string op member __.Key = key - member __.ResolveDependencies(scriptExt:string, packageManagerTextLines:string seq, tfm: string) : bool * string seq * string seq * string seq = + member __.ResolveDependencies(scriptExt:string, packageManagerTextLines:string seq, tfm: string) : obj = let scriptExt, poundRprefix = match scriptExt with @@ -170,7 +196,7 @@ type [] FSharpDependencyManager (outputDir:string op writeFile projectPath generateProjBody - let result, resolutionsFile = buildProject projectPath binLogPath + let result, stdOut, stdErr, resolutionsFile = buildProject projectPath binLogPath match resolutionsFile with | Some file -> let resolutions = getResolutionsFromFile file @@ -183,10 +209,10 @@ type [] FSharpDependencyManager (outputDir:string op List.concat [ [scriptPath]; loads] |> List.toSeq let includes = (findIncludesFromResolutions resolutions) |> Array.toSeq - result, references, scripts, includes + ResolveDependenciesResult(result, stdOut, stdErr, references, scripts, includes) | None -> let empty = Seq.empty - result, empty, empty, empty + ResolveDependenciesResult(result, stdOut, stdErr, empty, empty, empty) - generateAndBuildProjectArtifacts + generateAndBuildProjectArtifacts :> obj diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi index 38b535bc8b..bdb4791ed9 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.fsi @@ -2,14 +2,36 @@ namespace FSharp.DependencyManager.Nuget -open System.Collections.Generic - module internal FSharpDependencyManager = val formatPackageReference: PackageReference -> seq val parsePackageReference: string list -> PackageReference list * string option option + +/// The results of ResolveDependencies +[] +type ResolveDependenciesResult = + + /// Succeded? + member Success: bool + + /// The resolution output log + member StdOut: string array + + /// The resolution error log (* process stderror *) + member StdError: string array + + /// The resolution paths + member Resolutions: string seq + + /// The source code file paths + member SourceFiles: string seq + + /// The roots to package directories + member Roots: string seq + + type [] FSharpDependencyManager = new: outputDir:string option -> FSharpDependencyManager member Name: string member Key:string - member ResolveDependencies: scriptExt:string * packageManagerTextLines:string seq * tfm: string -> bool * string seq * string seq * string seq + member ResolveDependencies: scriptExt:string * packageManagerTextLines:string seq * tfm: string -> obj diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.cs.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.cs.xlf index 1b2b789124..c5e96b0cc1 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.cs.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.cs.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.de.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.de.xlf index fad4a92c19..3be8fa52cc 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.de.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.de.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.es.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.es.xlf index af7ece6ad9..b9350a2106 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.es.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.es.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.fr.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.fr.xlf index 42aa351aa0..db01670254 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.fr.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.fr.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.it.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.it.xlf index da872e4f39..c9d68b1285 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.it.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.it.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ja.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ja.xlf index e9e3444fcf..0d7cb1551c 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ja.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ja.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ko.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ko.xlf index 13f0865b93..0d6afc0342 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ko.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ko.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pl.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pl.xlf index e9718434a1..4534d68b47 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pl.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pl.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pt-BR.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pt-BR.xlf index 6fb3374c22..788b984148 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pt-BR.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.pt-BR.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ru.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ru.xlf index 98624d7996..4d363d34d3 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ru.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.ru.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.tr.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.tr.xlf index a94d8e068e..db70fe17c1 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.tr.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.tr.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hans.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hans.xlf index 44e599a414..b18683e476 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hans.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hans.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hant.xlf b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hant.xlf index 83fa3521e6..5f1d2a019e 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hant.xlf +++ b/src/fsharp/FSharp.DependencyManager.Nuget/xlf/FSDependencyManager.txt.zh-Hant.xlf @@ -2,11 +2,26 @@ + + PackageManager can not reference the System Package '{0}' + PackageManager can not reference the System Package '{0}' + + Not used. Not used. + + {0} requires a value + {0} requires a value + + + + Unable to apply implicit argument number {0} + Unable to apply implicit argument number {0} + + \ No newline at end of file diff --git a/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fs b/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fs new file mode 100644 index 0000000000..bc40a0dfd7 --- /dev/null +++ b/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Interactive.DependencyManager + +open System +open System.Collections.Generic +open System.IO +open System.Reflection + +#if NETSTANDARD +open System.Runtime.Loader +#endif + +/// Signature for ResolutionProbe callback +/// host implements this, it's job is to return a list of assembly paths to probe. +type AssemblyResolutionProbe = delegate of Unit -> IEnumerable + + +/// Type that encapsulates AssemblyResolveHandler for managed packages +type AssemblyResolveHandler (assemblyProbingPaths: AssemblyResolutionProbe) = + +#if NETSTANDARD + let resolveAssemblyNetStandard (ctxt: AssemblyLoadContext) (assemblyName: AssemblyName): Assembly = + + let loadAssembly path = + ctxt.LoadFromAssemblyPath(path) + +#else + let resolveAssemblyNET (assemblyName: AssemblyName): Assembly = + + let loadAssembly assemblyPath = + Assembly.LoadFrom(assemblyPath) + +#endif + + let assemblyPaths = + match assemblyProbingPaths with + | null -> Seq.empty + | _ -> assemblyProbingPaths.Invoke() + + try + // args.Name is a displayname formatted assembly version. + // E.g: "System.IO.FileSystem, Version=4.1.1.0, Culture=en-US, PublicKeyToken=b03f5f7f11d50a3a" + let simpleName = assemblyName.Name + let assemblyPathOpt = assemblyPaths |> Seq.tryFind(fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + match assemblyPathOpt with + | Some path -> + loadAssembly path + | None -> Unchecked.defaultof + + with | _ -> Unchecked.defaultof + +#if NETSTANDARD + let handler = Func(resolveAssemblyNetStandard) + do AssemblyLoadContext.Default.add_Resolving(handler) + + interface IDisposable with + member _x.Dispose() = + AssemblyLoadContext.Default.remove_Resolving(handler) + +#else + let handler = new ResolveEventHandler(fun _ (args: ResolveEventArgs) -> resolveAssemblyNET (new AssemblyName(args.Name))) + do AppDomain.CurrentDomain.add_AssemblyResolve(handler) + + interface IDisposable with + member _x.Dispose() = + AppDomain.CurrentDomain.remove_AssemblyResolve(handler) + +#endif diff --git a/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fsi b/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fsi new file mode 100644 index 0000000000..b2314e0d31 --- /dev/null +++ b/src/fsharp/Interactive.DependencyManager/AssemblyResolveHandler.fsi @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Interactive.DependencyManager + +open System +open System.Collections.Generic + +/// Signature for ResolutionProbe callback +/// host implements this, it's job is to return a list of assembly paths to probe. +type AssemblyResolutionProbe = delegate of Unit -> IEnumerable + + +/// Handle Assembly resolution +type AssemblyResolveHandler = + + /// Construct a new DependencyProvider + new: assemblyProbingPaths: AssemblyResolutionProbe -> AssemblyResolveHandler + + interface IDisposable diff --git a/src/fsharp/Interactive.DependencyManager/DependencyManager.fsi b/src/fsharp/Interactive.DependencyManager/DependencyManager.fsi deleted file mode 100644 index b1163c0597..0000000000 --- a/src/fsharp/Interactive.DependencyManager/DependencyManager.fsi +++ /dev/null @@ -1,53 +0,0 @@ - -// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -/// Helper members to integrate DependencyManagers into F# codebase -namespace Interactive.DependencyManager - -open System - -/// Wraps access to a DependencyManager implementation -[] -type IDependencyManagerProvider = - /// Name of the dependency manager - abstract Name: string - - /// Key that identifies the types of dependencies that this DependencyManager operates on - /// E.g - /// nuget: indicates that this DM is for nuget packages - /// paket: indicates that this DM is for paket scripts, which manage nuget packages, github source dependencies etc ... - abstract Key: string - - /// Resolve the dependencies, for the given set of arguments, go find the .dll references, scripts and additional include values. - abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string seq * string seq * string seq - -/// Indicates to the Error reporting callbacks, severity of the error -[] -type ErrorReportType = - | Warning - | Error - - -/// Provides DependencyManagement functions. -/// Class is IDisposable -type DependencyProvider = - interface System.IDisposable - - /// Construct a new DependencyProvider - new : unit -> DependencyProvider - - /// Returns a formatted error message for the host to present - member CreatePackageManagerUnknownError : compilerTools:seq * outputDir:string * packageManagerKey:string * reportError:(ErrorReportType ->int * string -> unit) -> int * string - - /// Remove the dependency mager with the specified key - member RemoveDependencyManagerKey : packageManagerKey:string * path:string -> string - - /// Resolve reference for a list of package manager lines - member Resolve : packageManager:IDependencyManagerProvider * implicitIncludeDir:string * mainScriptName:string * fileName:string * scriptExt:string * packageManagerTextLines:seq * reportError:(ErrorReportType -> int * string -> unit) * executionTfm:string -> bool * seq * seq * seq - - /// Fetch a dependencymanager that supports a specific key - member TryFindDependencyManagerByKey : compilerTools:seq * outputDir:string * reportError:(ErrorReportType -> int * string -> unit) * key:string -> IDependencyManagerProvider - - /// TryFindDependencyManagerInPath - given a #r "key:sometext" go and find a DependencyManager that satisfies the key - member TryFindDependencyManagerInPath : compilerTools:seq * outputDir:string * reportError:(ErrorReportType -> int * string -> unit) * path:string -> string * IDependencyManagerProvider - diff --git a/src/fsharp/Interactive.DependencyManager/DependencyManager.fs b/src/fsharp/Interactive.DependencyManager/DependencyProvider.fs similarity index 54% rename from src/fsharp/Interactive.DependencyManager/DependencyManager.fs rename to src/fsharp/Interactive.DependencyManager/DependencyProvider.fs index 6434d3ff5e..306532a95f 100644 --- a/src/fsharp/Interactive.DependencyManager/DependencyManager.fs +++ b/src/fsharp/Interactive.DependencyManager/DependencyProvider.fs @@ -5,7 +5,7 @@ namespace Interactive.DependencyManager open System open System.IO open System.Reflection -open FSharp.Reflection +open System.Runtime.InteropServices open Internal.Utilities.FSharpEnvironment module ReflectionHelper = @@ -14,6 +14,7 @@ module ReflectionHelper = let resolveDependenciesMethodName = "ResolveDependencies" let namePropertyName = "Name" let keyPropertyName = "Key" + let arrEmpty = Array.empty let seqEmpty = Seq.empty let assemblyHasAttribute (theAssembly: Assembly) attributeName = @@ -30,7 +31,7 @@ module ReflectionHelper = let getInstanceProperty<'treturn> (theType: Type) propertyName = try - let property = theType.GetProperty(propertyName, typeof<'treturn>) + let property = theType.GetProperty(propertyName, BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance, Unchecked.defaultof, typeof<'treturn>, Array.empty, Array.empty) if isNull property then None elif not (property.GetGetMethod().IsStatic) @@ -57,19 +58,48 @@ module ReflectionHelper = | _ -> e open ReflectionHelper +open Microsoft.FSharp.Reflection -(* Shape of Dependency Manager contract, resolved using reflection *) -[] -type IDependencyManagerProvider = - abstract Name: string - abstract Key: string - abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * scriptExt: string * packageManagerTextLines: string seq * tfm: string -> bool * string seq * string seq * string seq +/// Indicate the type of error to report [] type ErrorReportType = | Warning | Error + +type ResolvingErrorReport = delegate of ErrorReportType * int * string -> unit + + +(* Shape of Dependency Manager contract, resolved using reflection *) +/// The results of ResolveDependencies +type IResolveDependenciesResult = + + /// Succeded? + abstract Success: bool + + /// The resolution output log + abstract StdOut: string array + + /// The resolution error log (* process stderror *) + abstract StdError: string array + + /// The resolution paths + abstract Resolutions: string seq + + /// The source code file paths + abstract SourceFiles: string seq + + /// The roots to package directories + abstract Roots: string seq + + +[] +type IDependencyManagerProvider = + abstract Name: string + abstract Key: string + abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * scriptExt: string * packageManagerTextLines: string seq * tfm: string -> IResolveDependenciesResult + type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyInfo, keyProperty: PropertyInfo, resolveDeps: MethodInfo option, resolveDepsEx: MethodInfo option,outputDir: string option) = let instance = Activator.CreateInstance(theType, [|outputDir :> obj|]) let nameProperty = nameProperty.GetValue >> string @@ -88,6 +118,67 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn let resolveMethodEx = getInstanceMethod theType [| typeof; typeof; typeof |] resolveDependenciesMethodName Some (fun () -> new ReflectionDependencyManagerProvider(theType, nameProperty, keyProperty, resolveMethod, resolveMethodEx, outputDir) :> IDependencyManagerProvider) + static member MakeResultFromObject(result: obj) = { + new IResolveDependenciesResult with + /// Succeded? + member __.Success = + match getInstanceProperty (result.GetType()) "Success" with + | None -> false + | Some p -> p.GetValue(result) :?> bool + + /// The resolution output log + member __.StdOut = + match getInstanceProperty (result.GetType()) "StdOut" with + | None -> Array.empty + | Some p -> p.GetValue(result) :?> string array + + /// The resolution error log (* process stderror *) + member __.StdError = + match getInstanceProperty (result.GetType()) "StdError" with + | None -> Array.empty + | Some p -> p.GetValue(result) :?> string array + + /// The resolution paths + member __.Resolutions = + match getInstanceProperty (result.GetType()) "Resolutions" with + | None -> Seq.empty + | Some p -> p.GetValue(result) :?> string seq + + /// The source code file paths + member __.SourceFiles = + match getInstanceProperty (result.GetType()) "SourceFiles" with + | None -> Seq.empty + | Some p -> p.GetValue(result) :?> string seq + + /// The roots to package directories + member __.Roots = + match getInstanceProperty (result.GetType()) "Roots" with + | None -> Seq.empty + | Some p -> p.GetValue(result) :?> string seq + } + + static member MakeResultFromFields(success: bool, stdOut: string array, stdError: string array, resolutions: string seq, sourceFiles: string seq, roots: string seq) = { + new IResolveDependenciesResult with + /// Succeded? + member __.Success = success + + /// The resolution output log + member __.StdOut = stdOut + + /// The resolution error log (* process stderror *) + member __.StdError = stdError + + /// The resolution paths + member __.Resolutions = resolutions + + /// The source code file paths + member __.SourceFiles = sourceFiles + + /// The roots to package directories + member __.Roots = roots + } + + interface IDependencyManagerProvider with /// Name of dependency Manager @@ -97,8 +188,7 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn member __.Key = instance |> keyProperty /// Resolve the dependencies for the given arguments - /// - member this.ResolveDependencies(scriptDir, mainScriptName, scriptName, scriptExt, packageManagerTextLines, tfm): bool * string seq * string seq * string seq = + member this.ResolveDependencies(scriptDir, mainScriptName, scriptName, scriptExt, packageManagerTextLines, tfm): IResolveDependenciesResult = // The ResolveDependencies method, has two signatures, the original signaature in the variable resolveDeps and the updated signature resoveDepsEx // The resolve method can return values in two different tuples: @@ -115,27 +205,37 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn else None, [||] - let succeeded, references, generatedScripts, additionalIncludeFolders = - let result = - match method with - | Some m -> m.Invoke(instance, arguments) :?> _ - | None -> false, seqEmpty, seqEmpty, seqEmpty + match method with + | Some m -> + let result = m.Invoke(instance, arguments) // Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be: - // 4 - (bool * string list * string list * string list) + // 1 - object with properties // 3 - (bool * string list * string list) - let tupleFields = result |> FSharpValue.GetTupleFields - match tupleFields |> Array.length with - | 4 -> tupleFields.[0] :?> bool, tupleFields.[1] :?> string seq, tupleFields.[2] :?> string seq, tupleFields.[3] :?> string seq - | 3 -> tupleFields.[0] :?> bool, seqEmpty, tupleFields.[1] :?> string list |> List.toSeq, tupleFields.[2] :?> string list |> List.toSeq - | _ -> false, seqEmpty, seqEmpty, seqEmpty - succeeded, references, generatedScripts, additionalIncludeFolders + // Support legacy api return shape (bool, string seq, string seq) --- original paket packagemanager + if Microsoft.FSharp.Reflection.FSharpType.IsTuple (result.GetType()) then + // Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be: + // 3 - (bool * string list * string list) + let success, sourceFiles, packageRoots = + let tupleFields = result |> FSharpValue.GetTupleFields + match tupleFields |> Array.length with + | 3 -> tupleFields.[0] :?> bool, tupleFields.[1] :?> string list |> List.toSeq, tupleFields.[2] :?> string list |> List.toSeq + | _ -> false, seqEmpty, seqEmpty + ReflectionDependencyManagerProvider.MakeResultFromFields(success, Array.empty, Array.empty, Seq.empty, sourceFiles, packageRoots) + else + ReflectionDependencyManagerProvider.MakeResultFromObject(result) + + | None -> + ReflectionDependencyManagerProvider.MakeResultFromFields(false, Array.empty, Array.empty, Seq.empty, Seq.empty, Seq.empty) /// Provides DependencyManagement functions. /// Class is IDisposable -type DependencyProvider () = +type DependencyProvider (assemblyProbingPaths: AssemblyResolutionProbe, nativeProbingRoots: NativeResolutionProbe) = + + let dllResolveHandler = new NativeDllResolveHandler(nativeProbingRoots) :> IDisposable + let assemblyResolveHandler = new AssemblyResolveHandler(assemblyProbingPaths) :> IDisposable // Resolution Path = Location of FSharp.Compiler.Private.dll let assemblySearchPaths = lazy ( @@ -145,7 +245,7 @@ type DependencyProvider () = yield AppDomain.CurrentDomain.BaseDirectory ]) - let enumerateDependencyManagerAssemblies compilerTools reportError = + let enumerateDependencyManagerAssemblies compilerTools (reportError: ResolvingErrorReport) = getCompilerToolsDesignTimeAssemblyPaths compilerTools |> Seq.append (assemblySearchPaths.Force()) |> Seq.collect (fun path -> @@ -159,13 +259,14 @@ type DependencyProvider () = with | e -> let e = stripTieWrapper e - reportError ErrorReportType.Warning (InteractiveDependencyManager.SR.couldNotLoadDependencyManagerExtension(path,e.Message)) + let n, m = InteractiveDependencyManager.SR.couldNotLoadDependencyManagerExtension(path,e.Message) + reportError.Invoke(ErrorReportType.Warning, n, m) None) |> Seq.filter (fun a -> assemblyHasAttribute a dependencyManagerAttributeName) let mutable registeredDependencyManagers: Map option= None - let RegisteredDependencyManagers (compilerTools: string seq) (outputDir: string option) (reportError: ErrorReportType -> int * string -> unit) = + let RegisteredDependencyManagers (compilerTools: string seq) (outputDir: string option) (reportError: ResolvingErrorReport) = match registeredDependencyManagers with | Some managers -> managers @@ -191,22 +292,26 @@ type DependencyProvider () = None managers - /// Returns a formatted error message for the host to present - member _.CreatePackageManagerUnknownError(compilerTools: string seq, outputDir: string, packageManagerKey: string, reportError: ErrorReportType -> int * string -> unit) = + /// Returns a formatted error message for the host to presentconstruct with just nativeProbing handler + new (nativeProbingRoots: NativeResolutionProbe) = + new DependencyProvider(Unchecked.defaultof, nativeProbingRoots) + /// Returns a formatted error message for the host to present + member __.CreatePackageManagerUnknownError (compilerTools: string seq, outputDir: string, packageManagerKey: string, reportError: ResolvingErrorReport) = let registeredKeys = String.Join(", ", RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError |> Seq.map (fun kv -> kv.Value.Key)) let searchPaths = assemblySearchPaths.Force() InteractiveDependencyManager.SR.packageManagerUnknown(packageManagerKey, String.Join(", ", searchPaths, compilerTools), registeredKeys) /// Fetch a dependencymanager that supports a specific key - member this.TryFindDependencyManagerInPath (compilerTools: string seq, outputDir: string, reportError: ErrorReportType -> int * string -> unit, path: string): string * IDependencyManagerProvider = + member this.TryFindDependencyManagerInPath (compilerTools: string seq, outputDir: string, reportError: ResolvingErrorReport, path: string): string * IDependencyManagerProvider = try if path.Contains ":" && not (Path.IsPathRooted path) then let managers = RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with | None -> - reportError ErrorReportType.Error (this.CreatePackageManagerUnknownError(compilerTools, outputDir, (path.Split(':').[0]), reportError)) + let err, msg = this.CreatePackageManagerUnknownError(compilerTools, outputDir, (path.Split(':').[0]), reportError) + reportError.Invoke(ErrorReportType.Error, err, msg) null, Unchecked.defaultof | Some kv -> path, kv.Value @@ -215,16 +320,17 @@ type DependencyProvider () = with | e -> let e = stripTieWrapper e - reportError ErrorReportType.Error (InteractiveDependencyManager.SR.packageManagerError(e.Message)) + let err, msg = InteractiveDependencyManager.SR.packageManagerError(e.Message) + reportError.Invoke(ErrorReportType.Error, err, msg) null, Unchecked.defaultof /// Remove the dependency mager with the specified key - member _.RemoveDependencyManagerKey(packageManagerKey:string, path:string): string = + member __.RemoveDependencyManagerKey(packageManagerKey:string, path:string): string = path.Substring(packageManagerKey.Length + 1).Trim() /// Fetch a dependencymanager that supports a specific key - member _.TryFindDependencyManagerByKey (compilerTools: string seq, outputDir: string, reportError: ErrorReportType -> int * string -> unit, key: string): IDependencyManagerProvider = + member __.TryFindDependencyManagerByKey (compilerTools: string seq, outputDir: string, reportError: ResolvingErrorReport, key: string): IDependencyManagerProvider = try RegisteredDependencyManagers compilerTools (Option.ofString outputDir) reportError @@ -234,21 +340,34 @@ type DependencyProvider () = with | e -> let e = stripTieWrapper e - reportError ErrorReportType.Error (InteractiveDependencyManager.SR.packageManagerError(e.Message)) + let err, msg = InteractiveDependencyManager.SR.packageManagerError(e.Message) + reportError.Invoke(ErrorReportType.Error, err, msg) Unchecked.defaultof /// Resolve reference for a list of package manager lines - member _.Resolve (packageManager:IDependencyManagerProvider, implicitIncludeDir: string, mainScriptName: string, fileName: string, scriptExt: string, packageManagerTextLines: string seq, reportError: ErrorReportType -> int * string -> unit, executionTfm: string): bool * string seq * string seq * string seq = + member __.Resolve (packageManager:IDependencyManagerProvider, + scriptExt: string, + packageManagerTextLines: string seq, + reportError: ResolvingErrorReport, + executionTfm: string, + []implicitIncludeDir: string, + []mainScriptName: string, + []fileName: string): IResolveDependenciesResult = try packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, scriptExt, packageManagerTextLines, executionTfm) with e -> let e = stripTieWrapper e - reportError ErrorReportType.Error (InteractiveDependencyManager.SR.packageManagerError(e.Message)) - false, Seq.empty, Seq.empty, Seq.empty + let err, msg = (InteractiveDependencyManager.SR.packageManagerError(e.Message)) + reportError.Invoke(ErrorReportType.Error, err, msg) + ReflectionDependencyManagerProvider.MakeResultFromFields(false, arrEmpty, arrEmpty, seqEmpty, seqEmpty, seqEmpty) interface IDisposable with - member _.Dispose() = + + member __.Dispose() = + // Unregister everything registeredDependencyManagers <- None + dllResolveHandler.Dispose() + assemblyResolveHandler.Dispose() diff --git a/src/fsharp/Interactive.DependencyManager/DependencyProvider.fsi b/src/fsharp/Interactive.DependencyManager/DependencyProvider.fsi new file mode 100644 index 0000000000..742bb35fb5 --- /dev/null +++ b/src/fsharp/Interactive.DependencyManager/DependencyProvider.fsi @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// Helper members to integrate DependencyManagers into F# codebase +namespace Interactive.DependencyManager + +open System +open System.Runtime.InteropServices + + +/// The results of ResolveDependencies +type IResolveDependenciesResult = + + /// Succeded? + abstract Success: bool + + /// The resolution output log + abstract StdOut: string array + + /// The resolution error log (* process stderror *) + abstract StdError: string array + + /// The resolution paths + abstract Resolutions: string seq + + /// The source code file paths + abstract SourceFiles: string seq + + /// The roots to package directories + abstract Roots: string seq + + +/// Wraps access to a DependencyManager implementation +[] +type IDependencyManagerProvider = + + /// Name of the dependency manager + abstract Name: string + + /// Key that identifies the types of dependencies that this DependencyManager operates on + /// E.g + /// nuget: indicates that this DM is for nuget packages + /// paket: indicates that this DM is for paket scripts, which manage nuget packages, github source dependencies etc ... + abstract Key: string + + /// Resolve the dependencies, for the given set of arguments, go find the .dll references, scripts and additional include values. + abstract ResolveDependencies: scriptDir: string * mainScriptName: string * scriptName: string * scriptExt: string * packageManagerTextLines: string seq * tfm: string -> IResolveDependenciesResult + + +/// Todo describe this API +[] +type ErrorReportType = + | Warning + | Error + + +type ResolvingErrorReport = delegate of ErrorReportType * int * string -> unit + + +/// Provides DependencyManagement functions. +/// Class is IDisposable +type DependencyProvider = + interface System.IDisposable + + /// Construct a new DependencyProvider + new: assemblyProbingPaths: AssemblyResolutionProbe * nativeProbingRoots: NativeResolutionProbe -> DependencyProvider + new: nativeProbingRoots: NativeResolutionProbe -> DependencyProvider + + /// Returns a formatted error message for the host to present + member CreatePackageManagerUnknownError: string seq * string * string * ResolvingErrorReport -> int * string + + /// Remove the dependency mager with the specified key + member RemoveDependencyManagerKey: packageManagerKey: string * path: string -> string + + /// Resolve reference for a list of package manager lines + member Resolve : packageManager: IDependencyManagerProvider * scriptExt: string * packageManagerTextLines: string seq * reportError: ResolvingErrorReport * executionTfm: string * []implicitIncludeDir: string * []mainScriptName: string * []fileName: string -> IResolveDependenciesResult + + /// Fetch a dependencymanager that supports a specific key + member TryFindDependencyManagerByKey: compilerTools: string seq * outputDir: string * reportError: ResolvingErrorReport * key: string -> IDependencyManagerProvider + + /// TryFindDependencyManagerInPath - given a #r "key:sometext" go and find a DependencyManager that satisfies the key + member TryFindDependencyManagerInPath: compilerTools: string seq * outputDir: string * reportError: ResolvingErrorReport * path: string -> string * IDependencyManagerProvider diff --git a/src/fsharp/Interactive.DependencyManager/Interactive.DependencyManager.fsproj b/src/fsharp/Interactive.DependencyManager/Interactive.DependencyManager.fsproj index fdf516baf5..901a3ba65a 100644 --- a/src/fsharp/Interactive.DependencyManager/Interactive.DependencyManager.fsproj +++ b/src/fsharp/Interactive.DependencyManager/Interactive.DependencyManager.fsproj @@ -4,7 +4,8 @@ Library - netstandard2.0 + net472;netstandard2.0 + netstandard2.0 Interactive.DependencyManager $(NoWarn);45;55;62;75;1204 true @@ -23,8 +24,13 @@ - - + + + + + + + @@ -49,6 +55,7 @@ + diff --git a/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fs b/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fs new file mode 100644 index 0000000000..ee15f5cb31 --- /dev/null +++ b/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Interactive.DependencyManager + +open System +open System.Collections.Generic +open System.IO +open System.Reflection +open System.Runtime.InteropServices + +#if NETSTANDARD +open System.Runtime.Loader + +// Cut down AssemblyLoadContext, for loading native libraries +type NativeAssemblyLoadContext () = + inherit AssemblyLoadContext() + + member this.LoadNativeLibrary(path: string): IntPtr = + base.LoadUnmanagedDllFromPath(path) + + override _.Load(_path: AssemblyName): Assembly = + raise (NotImplementedException()) + + static member NativeLoadContext = new NativeAssemblyLoadContext() +#endif + + +/// Signature for Native library resolution probe callback +/// host implements this, it's job is to return a list of package roots to probe. +type NativeResolutionProbe = delegate of Unit -> IEnumerable + + +/// Type that encapsulates Native library probing for managed packages +type NativeDllResolveHandler (_nativeProbingRoots: NativeResolutionProbe) = +#if NETSTANDARD + let probingFileNames (name: string) = + // coreclr native library probing algorithm: https://github.com/dotnet/coreclr/blob/9773db1e7b1acb3ec75c9cc0e36bd62dcbacd6d5/src/System.Private.CoreLib/shared/System/Runtime/Loader/LibraryNameVariation.Unix.cs + let isRooted = Path.IsPathRooted name + let useSuffix s = not (name.Contains(s + ".") || name.EndsWith(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 + let usePrefix = name.IndexOf(Path.DirectorySeparatorChar) = -1 // If name has directory information no add no prefix + && name.IndexOf(Path.AltDirectorySeparatorChar) = -1 + && name.IndexOf(Path.PathSeparator) = -1 + && name.IndexOf(Path.VolumeSeparatorChar) = -1 + let prefix = [| "lib" |] + let suffix = [| + if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then + ".dll" + ".exe" + elif RuntimeInformation.IsOSPlatform(OSPlatform.OSX) then + ".dylib" + else + ".so" + |] + + [| + yield name // Bare name + if not (isRooted) then + for s in suffix do + if useSuffix s then // Suffix without prefix + yield (sprintf "%s%s" name s) + if usePrefix then + for p in prefix do // Suffix with prefix + yield (sprintf "%s%s%s" p name s) + elif usePrefix then + for p in prefix do // Prefix + yield (sprintf "%s%s" p name) + |] + + // Computer valid dotnet-rids for this environment: + // https://docs.microsoft.com/en-us/dotnet/core/rid-catalog + // + // Where rid is: win, win-x64, win-x86, osx-x64, linux-x64 etc ... + let probingRids = + let processArchitecture = RuntimeInformation.ProcessArchitecture + let baseRid = + if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then "win" + elif RuntimeInformation.IsOSPlatform(OSPlatform.OSX) then "osx" + else "linux" + let platformRid = + match processArchitecture with + | Architecture.X64 -> baseRid + "-x64" + | Architecture.X86 -> baseRid + "-x86" + | Architecture.Arm64 -> baseRid + "-arm64" + | _ -> baseRid + "arm" + [| "any"; baseRid; platformRid |] + + let _resolveUnmanagedDll (_: Assembly) (name: string): IntPtr = + + // Enumerate probing roots looking for a dll that matches the probing name in the probed locations + let probeForNativeLibrary root rid name = + // Look for name in root + probingFileNames name |> Array.tryPick(fun name -> + let path = Path.Combine(root, "runtimes", rid, "native", name) + if File.Exists(path) then + Some path + else + None) + + let probe = + match _nativeProbingRoots with + | null -> None + | _ -> _nativeProbingRoots.Invoke() + |> Seq.tryPick(fun root -> + probingFileNames name |> Seq.tryPick(fun name -> + let path = Path.Combine(root, name) + if File.Exists(path) then + Some path + else + probingRids |> Seq.tryPick(fun rid -> probeForNativeLibrary root rid name))) + + match probe with + | Some path -> NativeAssemblyLoadContext.NativeLoadContext.LoadNativeLibrary(path) + | None -> IntPtr.Zero + + // netstandard 2.1 has this property, unfortunately we don't build with that yet + //public event Func ResolvingUnmanagedDll + let eventInfo = typeof.GetEvent("ResolvingUnmanagedDll") + let handler = Func (_resolveUnmanagedDll) + + do if not (isNull eventInfo) then eventInfo.AddEventHandler(AssemblyLoadContext.Default, handler) +#endif + + interface IDisposable with + member _x.Dispose() = +#if NETSTANDARD + if not (isNull eventInfo) then + eventInfo.RemoveEventHandler(AssemblyLoadContext.Default, handler) +#endif + () \ No newline at end of file diff --git a/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fsi b/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fsi new file mode 100644 index 0000000000..233632b678 --- /dev/null +++ b/src/fsharp/Interactive.DependencyManager/NativeDllResolveHandler.fsi @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Interactive.DependencyManager + +open System +open System.Collections.Generic + +/// Signature for Native library resolution probe callback +/// host implements this, it's job is to return a list of package roots to probe. +type NativeResolutionProbe = delegate of Unit -> IEnumerable + + +// Cut down AssemblyLoadContext, for loading native libraries +type NativeDllResolveHandler = + + /// Construct a new DependencyProvider + new: nativeProbingRoots: NativeResolutionProbe -> NativeDllResolveHandler + + interface IDisposable diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index ad1cf10bbc..098ede415c 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -19,9 +19,6 @@ open System.Threading open System.Reflection open System.Runtime.CompilerServices open System.Runtime.InteropServices -#if NETSTANDARD -open System.Runtime.Loader -#endif open FSharp.Compiler open FSharp.Compiler.AbstractIL @@ -1288,10 +1285,14 @@ type internal FsiDynamicCompiler match packageManagerLines with | [] -> istate | (_, _, m)::_ -> - let reportError errorType error = - match errorType with - | ErrorReportType.Warning -> warning(Error(error,m)) - | ErrorReportType.Error -> errorR(Error(error, m)) + let reportError = + let report errorType err msg = + let error = err, msg + match errorType with + | ErrorReportType.Warning -> warning(Error(error, m)) + | ErrorReportType.Error -> errorR(Error(error, m)) + ResolvingErrorReport (report) + let outputDir = tcConfigB.outputDir |> Option.defaultValue "" match tcConfigB.dependencyProvider.TryFindDependencyManagerByKey(tcConfigB.compilerToolPaths, outputDir, reportError, packageManagerKey) with @@ -1303,17 +1304,17 @@ type internal FsiDynamicCompiler let removeErrorLinesFromScript () = tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.filter(fun (tried, _, _) -> tried)) try - match tcConfigB.dependencyProvider.Resolve(dependencyManager, tcConfigB.implicitIncludeDir, "stdin.fsx", "stdin.fsx", ".fsx", packageManagerTextLines, reportError, executionTfm) with - | false, _, _, _ -> istate // error already reported - | succeeded, _references, generatedScripts, additionalIncludeFolders -> - if succeeded then - tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) - else - removeErrorLinesFromScript () - for folder in additionalIncludeFolders do + let result = tcConfigB.dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError, executionTfm, tcConfigB.implicitIncludeDir, "stdin.fsx", "stdin.fsx") + match result.Success with + | false -> + removeErrorLinesFromScript () + istate // error already reported + | true -> + tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) + for folder in result.Roots do tcConfigB.AddIncludePath(m, folder, "") - let scripts = generatedScripts |> Seq.toList - if generatedScripts |> Seq.length > 0 then + let scripts = result.SourceFiles |> Seq.toList + if scripts |> Seq.length > 0 then fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, scripts, lexResourceManager, errorLogger) else istate with _ -> @@ -1557,20 +1558,6 @@ type internal FsiInterruptController(fsiOptions: FsiCommandLineOptions, fsiConso module internal MagicAssemblyResolution = -#if NETSTANDARD - // Cut down AssemblyLoadContext, for loading native libraries - type FsiNativeAssemblyLoadContext () = - inherit AssemblyLoadContext() - - member this.LoadNativeLibrary(path: string): IntPtr = - base.LoadUnmanagedDllFromPath(path) - - override _.Load(_path: AssemblyName): Assembly = - raise (NotImplementedException()) - - static member NativeLoadContext = new FsiNativeAssemblyLoadContext() -#endif - // See bug 5501 for details on decision to use UnsafeLoadFrom here. // Summary: // It is an explicit user trust decision to load an assembly with #r. Scripts are not run automatically (for example, by double-clicking in explorer). @@ -1579,7 +1566,7 @@ module internal MagicAssemblyResolution = [] let private assemblyLoadFrom (path:string) = Assembly.UnsafeLoadFrom(path) - let Install(tcConfigB, tcImports: TcImports, fsiDynamicCompiler: FsiDynamicCompiler, fsiConsoleOutput: FsiConsoleOutput) = + let Install(tcConfigB, tcImports: TcImports, fsiDynamicCompiler: FsiDynamicCompiler, fsiConsoleOutput: FsiConsoleOutput) = let ResolveAssembly (ctok, m, tcConfigB, tcImports: TcImports, fsiDynamicCompiler: FsiDynamicCompiler, fsiConsoleOutput: FsiConsoleOutput, fullAssemName: string) = @@ -1672,100 +1659,6 @@ module internal MagicAssemblyResolution = stopProcessingRecovery e range0 null -#if NETSTANDARD - let probingFileNames (name: string) = - // coreclr native library probing algorithm: https://github.com/dotnet/coreclr/blob/9773db1e7b1acb3ec75c9cc0e36bd62dcbacd6d5/src/System.Private.CoreLib/shared/System/Runtime/Loader/LibraryNameVariation.Unix.cs - let isRooted = Path.IsPathRooted name - let useSuffix s = not (name.Contains(s + ".") || name.EndsWith(s)) // linux devs often append version # to libraries I.e mydll.so.5.3.2 - let usePrefix = name.IndexOf(Path.DirectorySeparatorChar) = -1 // If name has directory information no add no prefix - && name.IndexOf(Path.AltDirectorySeparatorChar) = -1 - && name.IndexOf(Path.PathSeparator) = -1 - && name.IndexOf(Path.VolumeSeparatorChar) = -1 - let prefix = [| "lib" |] - let suffix = [| - if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then - ".dll" - ".exe" - elif RuntimeInformation.IsOSPlatform(OSPlatform.OSX) then - ".dylib" - else - ".so" - |] - - [| - yield name // Bare name - if not (isRooted) then - for s in suffix do - if useSuffix s then // Suffix without prefix - yield (sprintf "%s%s" name s) - if usePrefix then - for p in prefix do // Suffix with prefix - yield (sprintf "%s%s%s" p name s) - elif usePrefix then - for p in prefix do // Prefix - yield (sprintf "%s%s" p name) - |] - - // Directories to start probing in - // Algorithm: - // Search for native libraries using: - // 1. Include directories - // 2. compilerToolPath directories - // 3. reference dll's - // 4. The implicit include directory - let probingRoots = - seq { - yield! tcConfigB.includes - yield! tcConfigB.compilerToolPaths - yield! (tcConfigB.referencedDLLs |> Seq.map(fun ref -> Path.GetDirectoryName(ref.Text))) - yield tcConfigB.implicitIncludeDir - } |>Seq.distinct - - // Computer valid dotnet-rids for this environment: - // https://docs.microsoft.com/en-us/dotnet/core/rid-catalog - // - // Where rid is: win, win-x64, win-x86, osx-x64, linux-x64 etc ... - let probingRids = - let processArchitecture = RuntimeInformation.ProcessArchitecture - let baseRid = - if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then "win" - elif RuntimeInformation.IsOSPlatform(OSPlatform.OSX) then "osx" - else "linux" - let platformRid = - match processArchitecture with - | Architecture.X64 -> baseRid + "-x64" - | Architecture.X86 -> baseRid + "-x86" - | Architecture.Arm64 -> baseRid + "-arm64" - | _ -> baseRid + "arm" - [| "any"; baseRid; platformRid |] - - let resolveUnmanagedDll (assembly : Assembly) (name : string) : IntPtr = - ignore assembly - - // Enumerate probing roots looking for a dll that matches the probing name in the probed locations - let probeForNativeLibrary root rid name = - // Look for name in root - probingFileNames name |> Array.tryPick(fun name -> - let path = Path.Combine(root, "runtimes", rid, "native", name) - if File.Exists(path) then - Some path - else - None) - - let probe = - probingRoots |> Seq.tryPick(fun root -> - probingFileNames name |> Seq.tryPick(fun name -> - let path = Path.Combine(root, name) - if File.Exists(path) then - Some path - else - probingRids |> Seq.tryPick(fun rid -> probeForNativeLibrary root rid name))) - - match probe with - | Some path -> FsiNativeAssemblyLoadContext.NativeLoadContext.LoadNativeLibrary(path) - | None -> IntPtr.Zero -#endif - let rangeStdin = rangeN Lexhelp.stdinMockFilename 0 let resolveAssembly = new ResolveEventHandler(fun _ args -> @@ -1776,22 +1669,9 @@ module internal MagicAssemblyResolution = AppDomain.CurrentDomain.add_AssemblyResolve(resolveAssembly) -#if NETSTANDARD - // netstandard 2.1 has this property, unfortunately we don't build with that yet - //public event Func ResolvingUnmanagedDll - let resolveUnmanagedHandler = Func (resolveUnmanagedDll) - let eventInfo = typeof.GetEvent("ResolvingUnmanagedDll") - if not (isNull eventInfo) then - eventInfo.AddEventHandler(AssemblyLoadContext.Default, resolveUnmanagedHandler) -#endif - { new System.IDisposable with member x.Dispose() = AppDomain.CurrentDomain.remove_AssemblyResolve(resolveAssembly) -#if NETSTANDARD - if not (isNull eventInfo) then - eventInfo.RemoveEventHandler(AssemblyLoadContext.Default, resolveUnmanagedHandler) -#endif } //---------------------------------------------------------------------------- @@ -1994,10 +1874,13 @@ type internal FsiInteractionProcessor fsiDynamicCompiler.EvalSourceFiles (ctok, istate, m, sourceFiles, lexResourceManager, errorLogger),Completed None | IHash (ParsedHashDirective(("reference" | "r"), [path], m), _) -> - let reportError errorType error = - match errorType with - | ErrorReportType.Warning -> warning(Error(error,m)) - | ErrorReportType.Error -> errorR(Error(error, m)) + let reportError = + let report errorType err msg = + let error = err, msg + match errorType with + | ErrorReportType.Warning -> warning(Error(error, m)) + | ErrorReportType.Error -> errorR(Error(error, m)) + ResolvingErrorReport (report) let dm = tcConfigB.dependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, tcConfigB.outputDir |> Option.defaultValue "", reportError, path) match dm with @@ -2660,7 +2543,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i /// This reference cell holds the most recent interactive state let initialInteractiveState = fsiDynamicCompiler.GetInitialInteractiveState () - + let fsiStdinLexerProvider = FsiStdinLexerProvider(tcConfigB, fsiStdinSyphon, fsiConsoleInput, fsiConsoleOutput, fsiOptions, lexResourceManager) let fsiInteractionProcessor = FsiInteractionProcessor(fsi, tcConfigB, fsiOptions, fsiDynamicCompiler, fsiConsolePrompt, fsiConsoleOutput, fsiInterruptController, fsiStdinLexerProvider, lexResourceManager, initialInteractiveState) From 5b4d3760831227bc0d94b9b2664c0dcd23ef332f Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Wed, 4 Mar 2020 15:11:45 -0600 Subject: [PATCH 14/14] update release notes --- fcs/RELEASE_NOTES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fcs/RELEASE_NOTES.md b/fcs/RELEASE_NOTES.md index f9127d499c..77b8cd8e40 100644 --- a/fcs/RELEASE_NOTES.md +++ b/fcs/RELEASE_NOTES.md @@ -1,3 +1,14 @@ +#### 34.1.1 + +From dotnet/fsharp:3777cd4d8..836da28c0: + +* Slight tweaks to error messages around numeric literals (Thanks @Happypig375) +* Deny taking native address of an immutable local value (Thanks @TIHan) +* Fixes to reported ranges for wildcard self-identifiers, module abbreviations, nested modules, attributes, nested types, and fields (Thanks @auduchinok) +* Better compiler error recovery for errors in constructor expressions (Thanks @auduchinok) +* Fix handling of F# Options in C# members with regards to nullable type interop (Thanks @TIHan) +* Move dependency handling of native dlls to the DependencyManager (Thanks @KevinRansom) + #### 34.1.0 From dotnet/fsharp:3af8959b6..9d69b49b7: