diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 2600981e3c5..0c6c6881251 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,7 +1,7 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
{
"name": "F#",
- "image": "mcr.microsoft.com/dotnet/sdk:9.0.100-rc.1",
+ "image": "mcr.microsoft.com/dotnet/sdk:9.0.100-rc.2",
"features": {
"ghcr.io/devcontainers/features/common-utils:2.5.1": {},
"ghcr.io/devcontainers/features/git:1.3.2": {},
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 6a22a1cca73..11f7848a276 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,7 +4,7 @@ about: Create a report to help us improve F#
title: ''
labels: [Bug, Needs-Triage]
assignees: ''
-
+type: 'Bug'
---
Please provide a succinct description of the issue.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 9902369d951..a23d1feb39e 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -4,7 +4,7 @@ about: Suggest an idea for the F# tools or compiler
title: ''
labels: [Feature Request, Needs-Triage]
assignees: ''
-
+type: 'Feature'
---
**Is your feature request related to a problem? Please describe.**
diff --git a/Directory.Build.props b/Directory.Build.props
index 7f5b362cb34..8802ca237b5 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -10,6 +10,11 @@
$(DotNetBuildSourceOnly)
+
+
+ $(NoWarn);FS0064;FS1182
+
+
- false
+ true
true
$(MSBuildThisFileDirectory)artifacts/
diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml
index 0c7bc9b5a17..9a5c59441e2 100644
--- a/azure-pipelines-PR.yml
+++ b/azure-pipelines-PR.yml
@@ -488,6 +488,8 @@ stages:
displayName: Publish Test Results
inputs:
testResultsFormat: 'XUnit'
+ testRunTitle: WindowsCompressedMetadata $(_testKind)
+ mergeTestResults: true
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_configuration)'
continueOnError: true
@@ -558,7 +560,9 @@ stages:
displayName: Publish Test Results
inputs:
testResultsFormat: 'XUnit'
+ testRunTitle: Linux
testResultsFiles: '*.xml'
+ mergeTestResults: true
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)'
continueOnError: true
condition: always()
@@ -602,6 +606,8 @@ stages:
inputs:
testResultsFormat: 'XUnit'
testResultsFiles: '*.xml'
+ testRunTitle: MacOS
+ mergeTestResults: true
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)'
continueOnError: true
condition: always()
diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md
index d350b30edbe..51115b5ead0 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md
@@ -32,7 +32,7 @@
* Allow access modifies to auto properties getters and setters ([Language suggestion #430](https://github.com/fsharp/fslang-suggestions/issues/430), [PR 16687](https://github.com/dotnet/fsharp/pull/16687), [PR 16861](https://github.com/dotnet/fsharp/pull/16861), [PR 17522](https://github.com/dotnet/fsharp/pull/17522))
* Render C# nullable-analysis attributes in tooltips ([PR #17485](https://github.com/dotnet/fsharp/pull/17485))
* Allow object expression without overrides. ([Language suggestion #632](https://github.com/fsharp/fslang-suggestions/issues/632), [PR #17387](https://github.com/dotnet/fsharp/pull/17387))
-* Enable FSharp 9.0 Language Version ([Issue #17497](https://github.com/dotnet/fsharp/issues/17438)), [PR](https://github.com/dotnet/fsharp/pull/17500)))
+* Enable FSharp 9.0 Language Version ([Issue #17497](https://github.com/dotnet/fsharp/issues/17497)), [PR](https://github.com/dotnet/fsharp/pull/17500)))
* Enable LanguageFeature.EnforceAttributeTargets in F# 9.0. ([Issue #17514](https://github.com/dotnet/fsharp/issues/17558), [PR #17516](https://github.com/dotnet/fsharp/pull/17558))
* Parser: better recovery for unfinished patterns ([PR #17231](https://github.com/dotnet/fsharp/pull/17231), [PR #17232](https://github.com/dotnet/fsharp/pull/17232)))
* Enable consuming generic arguments defined as `allows ref struct` in C# ([Issue #17597](https://github.com/dotnet/fsharp/issues/17597), display them in tooltips [PR #17706](https://github.com/dotnet/fsharp/pull/17706))
diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md
index 28f20ca2be2..185fa3a015f 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md
@@ -5,6 +5,7 @@
* Fix extension methods support for non-reference system assemblies ([PR #17799](https://github.com/dotnet/fsharp/pull/17799))
* Ensure `frameworkTcImportsCache` mutations are thread-safe. ([PR #17795](https://github.com/dotnet/fsharp/pull/17795))
* Fix concurrency issue in `ILPreTypeDefImpl` ([PR #17812](https://github.com/dotnet/fsharp/pull/17812))
+* Fix nullness inference for member val and other OO scenarios ([PR #17845](https://github.com/dotnet/fsharp/pull/17845))
### Added
@@ -18,5 +19,7 @@
* Better ranges for CE `do!` error reporting. ([PR #17779](https://github.com/dotnet/fsharp/pull/17779))
* Better ranges for CE `return, yield, return! and yield!` error reporting. ([PR #17792](https://github.com/dotnet/fsharp/pull/17792))
* Better ranges for CE `match!`. ([PR #17789](https://github.com/dotnet/fsharp/pull/17789))
+* Better ranges for CE `use` error reporting. ([PR #17811](https://github.com/dotnet/fsharp/pull/17811))
+* Better ranges for `inherit` error reporting. ([PR #17879](https://github.com/dotnet/fsharp/pull/17879))
### Breaking Changes
diff --git a/eng/TSAConfig.gdntsa b/eng/TSAConfig.gdntsa
index 56d3d0d457a..f4621b68272 100644
--- a/eng/TSAConfig.gdntsa
+++ b/eng/TSAConfig.gdntsa
@@ -1,7 +1,7 @@
{
"codebaseName": "FSharp-GitHub",
"notificationAliases": [
- "mlinfraswat@microsoft.com"
+ "fsharp@microsoft.com"
],
"codebaseAdmins": [
"EUROPE\\vlza",
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index a6fe9dd9339..e9557ab4f4e 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,9 +1,9 @@
-
+
https://github.com/dotnet/source-build-reference-packages
- 08649fed58d668737a54913f7d4c649a8da5dc6e
+ fd609e3b427601180d23633e2f1a4cdac6c42c20
diff --git a/eng/Versions.props b/eng/Versions.props
index d89aec3f3cd..4252f548c66 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -37,7 +37,7 @@
$(FSMajorVersion).$(FSMinorVersion).$(FSBuildVersion)
- 8.0.400
+ 9.0.100-beta.24466.6
$(FSCorePackageVersionValue)-$(PreReleaseVersionLabel).*
diff --git a/global.json b/global.json
index b66eed16d21..3f653af33e0 100644
--- a/global.json
+++ b/global.json
@@ -1,10 +1,10 @@
{
"sdk": {
- "version": "9.0.100-rc.1.24452.12",
+ "version": "9.0.100-rc.2.24474.11",
"allowPrerelease": true
},
"tools": {
- "dotnet": "9.0.100-rc.1.24452.12",
+ "dotnet": "9.0.100-rc.2.24474.11",
"vs": {
"version": "17.8",
"components": [
diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs
index e739169ea9c..814374417d3 100644
--- a/src/Compiler/Checking/CheckDeclarations.fs
+++ b/src/Compiler/Checking/CheckDeclarations.fs
@@ -3622,7 +3622,11 @@ module EstablishTypeDefinitionCores =
// Note: for a mutually recursive set we can't check this condition
// until "isSealedTy" and "isClassTy" give reliable results.
superTy |> Option.iter (fun ty ->
- let m = match inherits with | [] -> m | (_, m, _) :: _ -> m
+ let m =
+ match inherits with
+ | [] -> m
+ | (synType, _, _) :: _ -> synType.Range
+
if isSealedTy g ty then
errorR(Error(FSComp.SR.tcCannotInheritFromSealedType(), m))
elif not (isClassTy g ty) then
@@ -4292,7 +4296,7 @@ module TcDeclarations =
| SynMemberDefn.AutoProperty (range=m) :: _ -> errorR(InternalError("List.takeUntil is wrong, have auto property", m))
| SynMemberDefn.ImplicitInherit (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypeDefinitionsWithImplicitConstructionMustHaveOneInherit(), m))
| SynMemberDefn.LetBindings (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypeDefinitionsWithImplicitConstructionMustHaveLocalBindingsBeforeMembers(), m))
- | SynMemberDefn.Inherit (range=m) :: _ -> errorR(Error(FSComp.SR.tcInheritDeclarationMissingArguments(), m))
+ | SynMemberDefn.Inherit (trivia= { InheritKeyword = m }) :: _ -> errorR(Error(FSComp.SR.tcInheritDeclarationMissingArguments(), m))
| SynMemberDefn.NestedType (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypesCannotContainNestedTypes(), m))
| _ -> ()
| ds ->
@@ -4464,7 +4468,7 @@ module TcDeclarations =
let implements2 = members |> List.choose (function SynMemberDefn.Interface (interfaceType=ty) -> Some(ty, ty.Range) | _ -> None)
let inherits =
members |> List.choose (function
- | SynMemberDefn.Inherit (ty, idOpt, m) -> Some(ty, m, idOpt)
+ | SynMemberDefn.Inherit (ty, idOpt, m, _) -> Some(ty, m, idOpt)
| SynMemberDefn.ImplicitInherit (ty, _, idOpt, m) -> Some(ty, m, idOpt)
| _ -> None)
diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
index c1aa4dafc5d..645897a6793 100644
--- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
@@ -1805,11 +1805,8 @@ let rec TryTranslateComputationExpression
| SynExpr.LetOrUse(
isUse = true
bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ]
- body = innerComp) ->
- let mBind =
- match spBind with
- | DebugPointAtBinding.Yes m -> m
- | _ -> rhsExpr.Range
+ body = innerComp
+ trivia = { LetOrUseKeyword = mBind }) ->
if ceenv.isQuery then
error (Error(FSComp.SR.tcUseMayNotBeUsedInQueries (), mBind))
diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
index 781060c8af4..3154d3e1e74 100644
--- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
@@ -232,9 +232,10 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
// 'use x = expr in expr'
| SynExpr.LetOrUse(
isUse = true
- bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ]
+ bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr) ]
body = innerComp
- range = wholeExprMark) ->
+ range = wholeExprMark
+ trivia = { LetOrUseKeyword = mBind }) ->
let bindPatTy = NewInferenceType g
let inputExprTy = NewInferenceType g
@@ -252,11 +253,6 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
let envinner = { envinner with eIsControlFlow = true }
tcSequenceExprBody envinner genOuterTy tpenv innerComp
- let mBind =
- match spBind with
- | DebugPointAtBinding.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Binding)
- | _ -> inputExpr.Range
-
let inputExprMark = inputExpr.Range
let matchv, matchExpr =
diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
index 5fd190b1995..938034623ba 100644
--- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
+++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
@@ -220,7 +220,7 @@ let visitSynMemberDefn (md: SynMemberDefn) : FileContentEntry list =
| SynMemberDefn.Interface(interfaceType, _, members, _) ->
yield! visitSynType interfaceType
yield! collectFromOption (List.collect visitSynMemberDefn) members
- | SynMemberDefn.Inherit(baseType, _, _) -> yield! visitSynType baseType
+ | SynMemberDefn.Inherit(baseType = t) -> yield! visitSynType t
| SynMemberDefn.ValField(fieldInfo, _) -> yield! visitSynField fieldInfo
| SynMemberDefn.NestedType _ -> ()
| SynMemberDefn.AutoProperty(attributes = attributes; typeOpt = typeOpt; synExpr = synExpr) ->
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index 45b5bda0d10..36b184502f1 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -24,8 +24,11 @@
$(FSharpNetCoreProductDefaultTargetFramework);$(TargetFrameworks)
$(DefineConstants);FSHARPCORE_USE_PACKAGE
$(OtherFlags) --extraoptimizationloops:1
+
+
- $(OtherFlags) --warnon:1182
+ $(OtherFlags) --nowarn:1182
+
$(OtherFlags) --warnon:3218
diff --git a/src/Compiler/Facilities/prim-parsing.fs b/src/Compiler/Facilities/prim-parsing.fs
index bb61e76e5f3..7fb0d7fca41 100644
--- a/src/Compiler/Facilities/prim-parsing.fs
+++ b/src/Compiler/Facilities/prim-parsing.fs
@@ -151,7 +151,10 @@ module internal Implementation =
//-------------------------------------------------------------------------
// Read the tables written by FSYACC.
- type AssocTable(elemTab: uint16[], offsetTab: uint16[], cache: int[], cacheSize: int) =
+ type AssocTable(elemTab: uint16[], offsetTab: uint16[], cache: int[]) =
+
+ do Array.fill cache 0 cache.Length -1
+ let cacheSize = cache.Length / 2
member t.ReadAssoc(minElemNum, maxElemNum, defaultValueOfAssoc, keyToFind) =
// do a binary chop on the table
@@ -273,13 +276,8 @@ module internal Implementation =
let lhsPos = (Array.zeroCreate 2: Position[])
let reductions = tables.reductions
let cacheSize = 7919 // the 1000'th prime
- // Use a simpler hash table with faster lookup, but only one
- // hash bucket per key.
let actionTableCache = ArrayPool.Shared.Rent(cacheSize * 2)
let gotoTableCache = ArrayPool.Shared.Rent(cacheSize * 2)
- // Clear the arrays since ArrayPool does not
- Array.Clear(actionTableCache, 0, actionTableCache.Length)
- Array.Clear(gotoTableCache, 0, gotoTableCache.Length)
use _cacheDisposal =
{ new IDisposable with
@@ -289,10 +287,10 @@ module internal Implementation =
}
let actionTable =
- AssocTable(tables.actionTableElements, tables.actionTableRowOffsets, actionTableCache, cacheSize)
+ AssocTable(tables.actionTableElements, tables.actionTableRowOffsets, actionTableCache)
let gotoTable =
- AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets, gotoTableCache, cacheSize)
+ AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets, gotoTableCache)
let stateToProdIdxsTable =
IdxToIdxListTable(tables.stateToProdIdxsTableElements, tables.stateToProdIdxsTableRowOffsets)
diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs
index 2623cbde347..7b273f71430 100644
--- a/src/Compiler/Service/FSharpParseFileResults.fs
+++ b/src/Compiler/Service/FSharpParseFileResults.fs
@@ -814,7 +814,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
| SynMemberDefn.Interface(members = Some membs) ->
for m in membs do
yield! walkMember m
- | SynMemberDefn.Inherit(_, _, m) ->
+ | SynMemberDefn.Inherit(range = m) ->
// can break on the "inherit" clause
yield! checkRange m
| SynMemberDefn.ImplicitInherit(_, arg, _, m) ->
diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs
index 37990b026d1..083bae1d6d8 100644
--- a/src/Compiler/Service/ServiceLexing.fs
+++ b/src/Compiler/Service/ServiceLexing.fs
@@ -734,7 +734,7 @@ module internal LexerStateEncoding =
)
| LexCont.EndLine(ifdefs, stringNest, econt) ->
match econt with
- | LexerEndlineContinuation.Skip(n, m) ->
+ | LexerEndlineContinuation.IfdefSkip(n, m) ->
encodeLexCont (
FSharpTokenizerColorState.EndLineThenSkip,
int64 n,
@@ -834,7 +834,7 @@ module internal LexerStateEncoding =
| FSharpTokenizerColorState.ExtendedInterpolatedString ->
LexCont.String(ifdefs, stringNest, LexerStringStyle.ExtendedInterpolated, stringKind, delimLen, mkRange "file" p1 p1)
| FSharpTokenizerColorState.EndLineThenSkip ->
- LexCont.EndLine(ifdefs, stringNest, LexerEndlineContinuation.Skip(n1, mkRange "file" p1 p1))
+ LexCont.EndLine(ifdefs, stringNest, LexerEndlineContinuation.IfdefSkip(n1, mkRange "file" p1 p1))
| FSharpTokenizerColorState.EndLineThenToken -> LexCont.EndLine(ifdefs, stringNest, LexerEndlineContinuation.Token)
| _ -> LexCont.Token([], stringNest)
diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs
index e0957fe0140..ca1a1c5e657 100644
--- a/src/Compiler/Service/ServiceParseTreeWalk.fs
+++ b/src/Compiler/Service/ServiceParseTreeWalk.fs
@@ -996,7 +996,7 @@ module SyntaxTraversal =
|> pick x
| ok -> ok
- | SynMemberDefn.Inherit(synType, _identOption, range) -> traverseInherit (synType, range)
+ | SynMemberDefn.Inherit(synType, _identOption, range, _) -> traverseInherit (synType, range)
| SynMemberDefn.ValField _ -> None
| SynMemberDefn.NestedType(synTypeDefn, _synAccessOption, _range) -> traverseSynTypeDefn path synTypeDefn
diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs
index 0b3f0134545..cfbefd49ade 100644
--- a/src/Compiler/Service/ServiceParsedInputOps.fs
+++ b/src/Compiler/Service/ServiceParsedInputOps.fs
@@ -913,7 +913,7 @@ module ParsedInput =
walkType t
|> Option.orElseWith (fun () -> members |> Option.bind (List.tryPick walkMember))
- | SynMemberDefn.Inherit(t, _, _) -> walkType t
+ | SynMemberDefn.Inherit(baseType = t) -> walkType t
| SynMemberDefn.ValField(fieldInfo = field) -> walkField field
@@ -2240,7 +2240,7 @@ module ParsedInput =
| SynMemberDefn.Interface(interfaceType = t; members = members) ->
walkType t
members |> Option.iter (List.iter walkMember)
- | SynMemberDefn.Inherit(t, _, _) -> walkType t
+ | SynMemberDefn.Inherit(baseType = t) -> walkType t
| SynMemberDefn.ValField(fieldInfo = field) -> walkField field
| SynMemberDefn.NestedType(tdef, _, _) -> walkTypeDefn tdef
| SynMemberDefn.AutoProperty(attributes = Attributes attrs; typeOpt = t; synExpr = e) ->
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 525faf3be3d..5f6588bd770 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -72,10 +72,10 @@ module CompileHelpers =
try
f exiter
- 0
+ None
with e ->
stopProcessingRecovery e range0
- 1
+ Some e
/// Compile using the given flags. Source files names are resolved via the FileSystem API. The output file must be given by a -o flag.
let compileFromArgs (ctok, argv: string[], legacyReferenceResolver, tcImportsCapture, dynamicAssemblyCreator) =
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 0e48a0d6360..3e4fde2229c 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -400,11 +400,12 @@ type public FSharpChecker =
/// Compile using the given flags. Source files names are resolved via the FileSystem API.
/// The output file must be given by a -o flag.
/// The first argument is ignored and can just be "fsc.exe".
+ /// The method returns the collected diagnostics, and (possibly) a terminating exception.
///
///
/// The command line arguments for the project build.
/// An optional string used for tracing compiler operations associated with this request.
- member Compile: argv: string[] * ?userOpName: string -> Async
+ member Compile: argv: string[] * ?userOpName: string -> Async
///
/// Try to get type check results for a file. This looks up the results of recent type checks of the
diff --git a/src/Compiler/SyntaxTree/LexHelpers.fs b/src/Compiler/SyntaxTree/LexHelpers.fs
index 736e4be04f5..96b4a9a570b 100644
--- a/src/Compiler/SyntaxTree/LexHelpers.fs
+++ b/src/Compiler/SyntaxTree/LexHelpers.fs
@@ -249,7 +249,7 @@ let errorsInByteStringBuffer (buf: ByteBuffer) =
else
None
-let newline (lexbuf: LexBuffer<_>) = lexbuf.EndPos <- lexbuf.EndPos.NextLine
+let incrLine (lexbuf: LexBuffer<_>) = lexbuf.EndPos <- lexbuf.EndPos.NextLine
let advanceColumnBy (lexbuf: LexBuffer<_>) n =
lexbuf.EndPos <- lexbuf.EndPos.ShiftColumnBy(n)
diff --git a/src/Compiler/SyntaxTree/LexHelpers.fsi b/src/Compiler/SyntaxTree/LexHelpers.fsi
index 0ba901a05e0..63997f08988 100644
--- a/src/Compiler/SyntaxTree/LexHelpers.fsi
+++ b/src/Compiler/SyntaxTree/LexHelpers.fsi
@@ -101,7 +101,7 @@ type LargerThanOneByte = int
type LargerThan127ButInsideByte = int
val errorsInByteStringBuffer: ByteBuffer -> Option
-val newline: Lexing.LexBuffer<'a> -> unit
+val incrLine: Lexing.LexBuffer<'a> -> unit
val advanceColumnBy: Lexing.LexBuffer<'a> -> n: int -> unit
diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs
index 8d62a724972..c11647ab0a5 100644
--- a/src/Compiler/SyntaxTree/ParseHelpers.fs
+++ b/src/Compiler/SyntaxTree/ParseHelpers.fs
@@ -165,9 +165,10 @@ type LexerIfdefStack = LexerIfdefStackEntries
/// Specifies how the 'endline' function in the lexer should continue after
/// it reaches end of line or eof. The options are to continue with 'token' function
/// or to continue with 'skip' function.
+[]
type LexerEndlineContinuation =
| Token
- | Skip of int * range: range
+ | IfdefSkip of int * range: range
type LexerIfdefExpression =
| IfdefAnd of LexerIfdefExpression * LexerIfdefExpression
@@ -967,7 +968,7 @@ let checkEndOfFileError t =
| LexCont.MLOnly(_, _, m) -> reportParseErrorAt m (FSComp.SR.parsEofInIfOcaml ())
- | LexCont.EndLine(_, _, LexerEndlineContinuation.Skip(_, m)) -> reportParseErrorAt m (FSComp.SR.parsEofInDirective ())
+ | LexCont.EndLine(_, _, LexerEndlineContinuation.IfdefSkip(_, m)) -> reportParseErrorAt m (FSComp.SR.parsEofInDirective ())
| LexCont.EndLine(endifs, nesting, LexerEndlineContinuation.Token)
| LexCont.Token(endifs, nesting) ->
@@ -1049,7 +1050,22 @@ let mkLocalBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs,
else
Some mIn)
- SynExpr.LetOrUse(isRec, isUse, decls, body, mWhole, { InKeyword = mIn })
+ let mLetOrUse =
+ match decls with
+ | SynBinding(trivia = trivia) :: _ -> trivia.LeadingKeyword.Range
+ | _ -> Range.Zero
+
+ SynExpr.LetOrUse(
+ isRec,
+ isUse,
+ decls,
+ body,
+ mWhole,
+ {
+ LetOrUseKeyword = mLetOrUse
+ InKeyword = mIn
+ }
+ )
let mkDefnBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, _bindingSetRange), attrs, vis, attrsm) =
if isUse then
diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi
index 52f4257d4c2..c98e7897a32 100644
--- a/src/Compiler/SyntaxTree/ParseHelpers.fsi
+++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi
@@ -67,7 +67,7 @@ type LexerIfdefStack = LexerIfdefStackEntries
type LexerEndlineContinuation =
| Token
- | Skip of int * range: range
+ | IfdefSkip of int * range: range
type LexerIfdefExpression =
| IfdefAnd of LexerIfdefExpression * LexerIfdefExpression
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index fc0c811e55d..81e893592b8 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -1496,7 +1496,7 @@ type SynMemberDefn =
| Interface of interfaceType: SynType * withKeyword: range option * members: SynMemberDefns option * range: range
- | Inherit of baseType: SynType * asIdent: Ident option * range: range
+ | Inherit of baseType: SynType * asIdent: Ident option * range: range * trivia: SynMemberDefnInheritTrivia
| ValField of fieldInfo: SynField * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi
index 45b03ad3b75..379362f407c 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi
@@ -1670,7 +1670,7 @@ type SynMemberDefn =
| Interface of interfaceType: SynType * withKeyword: range option * members: SynMemberDefns option * range: range
/// An 'inherit' definition within a class
- | Inherit of baseType: SynType * asIdent: Ident option * range: range
+ | Inherit of baseType: SynType * asIdent: Ident option * range: range * trivia: SynMemberDefnInheritTrivia
/// A 'val' definition within a class
| ValField of fieldInfo: SynField * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
index 10aee262292..2cd42701e70 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
@@ -85,10 +85,15 @@ type SynExprDotLambdaTrivia =
[]
type SynExprLetOrUseTrivia =
{
+ LetOrUseKeyword: range
InKeyword: range option
}
- static member Zero: SynExprLetOrUseTrivia = { InKeyword = None }
+ static member Zero: SynExprLetOrUseTrivia =
+ {
+ InKeyword = None
+ LetOrUseKeyword = Range.Zero
+ }
[]
type SynExprLetOrUseBangTrivia =
@@ -415,6 +420,9 @@ type SynMemberDefnAbstractSlotTrivia =
static member Zero = { GetSetKeywords = None }
+[]
+type SynMemberDefnInheritTrivia = { InheritKeyword: range }
+
[]
type SynFieldTrivia =
{
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
index fff834beb41..ab6525bc010 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
@@ -129,6 +129,8 @@ type SynExprDotLambdaTrivia =
[]
type SynExprLetOrUseTrivia =
{
+ /// The syntax range of the `let` or `use` keyword.
+ LetOrUseKeyword: range
/// The syntax range of the `in` keyword.
InKeyword: range option
}
@@ -520,6 +522,10 @@ type SynMemberDefnAbstractSlotTrivia =
static member Zero: SynMemberDefnAbstractSlotTrivia
+/// Represents additional information for SynMemberDefn.Inherit
+[]
+type SynMemberDefnInheritTrivia = { InheritKeyword: range }
+
/// Represents additional information for SynField
[]
type SynFieldTrivia =
diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs
index b948e91fb65..b5e620c6bd6 100644
--- a/src/Compiler/TypedTree/TypedTree.fs
+++ b/src/Compiler/TypedTree/TypedTree.fs
@@ -4358,6 +4358,12 @@ type NullnessVar() =
member nv.IsSolved = solution.IsSome
+ member nv.IsFullySolved =
+ match solution with
+ | None -> false
+ | Some (Nullness.Known _) -> true
+ | Some (Nullness.Variable v) -> v.IsFullySolved
+
member nv.Set(nullness) =
assert (not nv.IsSolved)
solution <- Some nullness
diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi
index d357895728d..5f96fba2266 100644
--- a/src/Compiler/TypedTree/TypedTree.fsi
+++ b/src/Compiler/TypedTree/TypedTree.fsi
@@ -3100,6 +3100,7 @@ type NullnessVar =
member Evaluate: unit -> NullnessInfo
member TryEvaluate: unit -> NullnessInfo voption
member IsSolved: bool
+ member IsFullySolved: bool
member Set: Nullness -> unit
member Unset: unit -> unit
member Solution: Nullness
diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs
index c8268ffcf8a..0ad62482b6a 100644
--- a/src/Compiler/TypedTree/TypedTreeBasics.fs
+++ b/src/Compiler/TypedTree/TypedTreeBasics.fs
@@ -284,7 +284,7 @@ let tryAddNullnessToTy nullnessNew (ty:TType) =
let addNullnessToTy (nullness: Nullness) (ty:TType) =
match nullness with
| Nullness.Known NullnessInfo.WithoutNull -> ty
- | Nullness.Variable nv when nv.IsSolved && nv.Evaluate() = NullnessInfo.WithoutNull -> ty
+ | Nullness.Variable nv when nv.IsFullySolved && nv.TryEvaluate() = ValueSome NullnessInfo.WithoutNull -> ty
| _ ->
match ty with
| TType_var (tp, nullnessOrig) -> TType_var (tp, combineNullness nullnessOrig nullness)
diff --git a/src/Compiler/lex.fsl b/src/Compiler/lex.fsl
index fd95cd3ebce..9de91ebab74 100644
--- a/src/Compiler/lex.fsl
+++ b/src/Compiler/lex.fsl
@@ -194,9 +194,8 @@ let tryAppendXmlDoc (buff: (range * StringBuilder) option) (s:string) =
// Utilities for parsing #if/#else/#endif
-let shouldStartLine args lexbuf (m:range) err tok =
- if (m.StartColumn <> 0) then fail args lexbuf err tok
- else tok
+let shouldStartLine args lexbuf (m:range) err =
+ if (m.StartColumn <> 0) then fail args lexbuf err ()
let shouldStartFile args lexbuf (m:range) err tok =
if (m.StartColumn <> 0 || m.StartLine <> 1) then fail args lexbuf err tok
@@ -334,6 +333,8 @@ let ident_char =
let ident = ident_start_char ident_char*
+// skip = true: skip whitespace (used by compiler, fsi etc)
+// skip = false: send artificial tokens for whitespace (used by VS)
rule token (args: LexArgs) (skip: bool) = parse
| ident
{ Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf) }
@@ -752,7 +753,7 @@ rule token (args: LexArgs) (skip: bool) = parse
else singleLineComment (None,1,m,m,args) skip lexbuf }
| newline
- { newline lexbuf
+ { incrLine lexbuf
if not skip then WHITESPACE (LexCont.Token(args.ifdefStack, args.stringNest))
else token args skip lexbuf }
@@ -819,12 +820,12 @@ rule token (args: LexArgs) (skip: bool) = parse
lexbuf.EndPos <- pos.ApplyLineDirective((match file with Some f -> FileIndex.fileIndexOfFile f | None -> pos.FileIndex), line)
else
// add a newline when we don't apply a directive since we consumed a newline getting here
- newline lexbuf
+ incrLine lexbuf
token args skip lexbuf
else
// add a newline when we don't apply a directive since we consumed a newline getting here
- newline lexbuf
+ incrLine lexbuf
HASH_LINE (LexCont.Token (args.ifdefStack, args.stringNest))
}
@@ -1030,56 +1031,47 @@ rule token (args: LexArgs) (skip: bool) = parse
| anywhite* "#if" anywhite+ anystring
{ let m = lexbuf.LexemeRange
+ shouldStartLine args lexbuf m (FSComp.SR.lexHashIfMustBeFirst())
let lookup id = List.contains id args.conditionalDefines
let lexed = lexeme lexbuf
let isTrue, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed
args.ifdefStack <- (IfDefIf,m) :: args.ifdefStack
LexbufIfdefStore.SaveIfHash(lexbuf, lexed, expr, m)
+ let contCase = if isTrue then LexerEndlineContinuation.Token else LexerEndlineContinuation.IfdefSkip(0, m)
+ let tok = HASH_IF(m, lexed, LexCont.EndLine(args.ifdefStack, args.stringNest, contCase))
+ if skip then endline contCase args skip lexbuf else tok }
- // Get the token; make sure it starts at zero position & return
- let cont, f =
- if isTrue then
- let cont = LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Token)
- let f = endline LexerEndlineContinuation.Token args skip
- cont, f
- else
- let cont = LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(0, m))
- let f = endline (LexerEndlineContinuation.Skip(0, m)) args skip
- cont, f
-
- let tok = shouldStartLine args lexbuf m (FSComp.SR.lexHashIfMustBeFirst()) (HASH_IF(m,lexed,cont))
- if not skip then tok else f lexbuf }
-
- | anywhite* "#else" anywhite* ("//" [^'\n''\r']*)?
+ | anywhite* "#else" anywhite* ("//" anystring)?
{ let lexed = (lexeme lexbuf)
match args.ifdefStack with
| [] -> LEX_FAILURE (FSComp.SR.lexHashElseNoMatchingIf())
| (IfDefElse,_) :: _rest -> LEX_FAILURE (FSComp.SR.lexHashEndifRequiredForElse())
| (IfDefIf,_) :: rest ->
let m = lexbuf.LexemeRange
+ shouldStartLine args lexbuf m (FSComp.SR.lexHashElseMustBeFirst())
args.ifdefStack <- (IfDefElse,m) :: rest
LexbufIfdefStore.SaveElseHash(lexbuf, lexed, m)
- let tok = HASH_ELSE(m, lexed, LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(0, m)))
- let tok = shouldStartLine args lexbuf m (FSComp.SR.lexHashElseMustBeFirst()) tok
- if not skip then tok else endline (LexerEndlineContinuation.Skip(0, m)) args skip lexbuf }
+ let tok = HASH_ELSE(m, lexed, LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(0, m)))
+ if skip then endline (LexerEndlineContinuation.IfdefSkip(0, m)) args skip lexbuf else tok }
- | anywhite* "#endif" anywhite* ("//" [^'\n''\r']*)?
+ | anywhite* "#endif" anywhite* ("//" anystring)?
{ let lexed = (lexeme lexbuf)
let m = lexbuf.LexemeRange
match args.ifdefStack with
| []-> LEX_FAILURE (FSComp.SR.lexHashEndingNoMatchingIf())
| _ :: rest ->
+ shouldStartLine args lexbuf m (FSComp.SR.lexHashEndifMustBeFirst())
args.ifdefStack <- rest
LexbufIfdefStore.SaveEndIfHash(lexbuf, lexed, m)
let tok = HASH_ENDIF(m,lexed,LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Token))
- let tok = shouldStartLine args lexbuf m (FSComp.SR.lexHashEndifMustBeFirst()) tok
if not skip then tok else endline LexerEndlineContinuation.Token args skip lexbuf }
| "#if"
{ let tok = WHITESPACE (LexCont.Token (args.ifdefStack, args.stringNest))
let tok = fail args lexbuf (FSComp.SR.lexHashIfMustHaveIdent()) tok
- if not skip then tok else token args skip lexbuf }
+ if skip then token args skip lexbuf else tok }
+ // Let the parser deal with these invalid directives
| anywhite* "#if" ident_char+
| anywhite* "#else" ident_char+
| anywhite* "#endif" ident_char+
@@ -1104,17 +1096,17 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
// If #if is the first thing on the line then increase depth, otherwise skip, because it is invalid (e.g. "(**) #if ...")
if (m.StartColumn <> 0) then
- if not skip then INACTIVECODE (LexCont.IfDefSkip(args.ifdefStack, args.stringNest, n, m))
- else ifdefSkip n m args skip lexbuf
+ if skip then ifdefSkip n m args skip lexbuf
+ else INACTIVECODE (LexCont.IfDefSkip(args.ifdefStack, args.stringNest, n, m))
else
let lexed = lexeme lexbuf
let lookup id = List.contains id args.conditionalDefines
let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed
LexbufIfdefStore.SaveIfHash(lexbuf, lexed, expr, m)
- let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(n+1, m)))
- if not skip then tok else endline (LexerEndlineContinuation.Skip(n+1, m)) args skip lexbuf }
+ let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(n+1, m)))
+ if skip then endline (LexerEndlineContinuation.IfdefSkip(n+1, m)) args skip lexbuf else tok }
- | anywhite* "#else" anywhite* ("//" [^'\n''\r']*)?
+ | anywhite* "#else" anywhite* ("//" anystring)?
{ let lexed = (lexeme lexbuf)
let m = lexbuf.LexemeRange
@@ -1132,12 +1124,12 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
args.ifdefStack <- (IfDefElse,m) :: rest
if not skip then HASH_ELSE(m,lexed,LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Token))
else endline LexerEndlineContinuation.Token args skip lexbuf
- else
+ else
LexbufIfdefStore.SaveElseHash(lexbuf, lexed, m)
- if not skip then INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(n, m)))
- else endline (LexerEndlineContinuation.Skip(n, m)) args skip lexbuf }
+ if not skip then INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(n, m)))
+ else endline (LexerEndlineContinuation.IfdefSkip(n, m)) args skip lexbuf }
- | anywhite* "#endif" anywhite* ("//" [^'\n''\r']*)?
+ | anywhite* "#endif" anywhite* ("//" anystring)?
{ let lexed = lexeme lexbuf
let m = lexbuf.LexemeRange
@@ -1154,13 +1146,13 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
if not skip then HASH_ENDIF(m,lexed,LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Token))
else endline LexerEndlineContinuation.Token args skip lexbuf
else
+ shouldStartLine args lexbuf m (FSComp.SR.lexWrongNestedHashEndif())
LexbufIfdefStore.SaveEndIfHash(lexbuf, lexed, m)
- let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(n-1, m)))
- let tok = shouldStartLine args lexbuf m (FSComp.SR.lexWrongNestedHashEndif()) tok
- if not skip then tok else endline (LexerEndlineContinuation.Skip(n-1, m)) args skip lexbuf }
+ let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(n-1, m)))
+ if not skip then tok else endline (LexerEndlineContinuation.IfdefSkip(n-1, m)) args skip lexbuf }
| newline
- { newline lexbuf; ifdefSkip n m args skip lexbuf }
+ { incrLine lexbuf; ifdefSkip n m args skip lexbuf }
| [^ ' ' '\n' '\r' ]+
@@ -1180,13 +1172,13 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
// or end of file and then calls the lexing function specified by 'cont' - either token or ifdefSkip
and endline (cont: LexerEndlineContinuation) (args: LexArgs) (skip: bool) = parse
| newline
- { newline lexbuf
+ { incrLine lexbuf
match cont with
| LexerEndlineContinuation.Token ->
if not skip then WHITESPACE(LexCont.Token (args.ifdefStack, args.stringNest))
else token args skip lexbuf
- | LexerEndlineContinuation.Skip(n, m) ->
+ | LexerEndlineContinuation.IfdefSkip(n, m) ->
if not skip then INACTIVECODE (LexCont.IfDefSkip(args.ifdefStack, args.stringNest, n, m))
else ifdefSkip n m args skip lexbuf
}
@@ -1195,7 +1187,7 @@ and endline (cont: LexerEndlineContinuation) (args: LexArgs) (skip: bool) = pars
{ match cont with
| LexerEndlineContinuation.Token ->
EOF(LexCont.Token(args.ifdefStack, args.stringNest))
- | LexerEndlineContinuation.Skip(n, m) ->
+ | LexerEndlineContinuation.IfdefSkip(n, m) ->
EOF(LexCont.IfDefSkip(args.ifdefStack, args.stringNest, n, m))
}
@@ -1209,7 +1201,7 @@ and endline (cont: LexerEndlineContinuation) (args: LexArgs) (skip: bool) = pars
and singleQuoteString (sargs: LexerStringArgs) (skip: bool) = parse
| '\\' newline anywhite*
{ let (_buf, _fin, m, kind, args) = sargs
- newline lexbuf
+ incrLine lexbuf
let text = lexeme lexbuf
let text2 = text |> String.filter (fun c -> c <> ' ' && c <> '\t')
advanceColumnBy lexbuf (text.Length - text2.Length)
@@ -1338,7 +1330,7 @@ and singleQuoteString (sargs: LexerStringArgs) (skip: bool) = parse
| newline
{ let (buf, _fin, m, kind, args) = sargs
- newline lexbuf
+ incrLine lexbuf
addUnicodeString buf (lexeme lexbuf)
if not skip then
STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.SingleQuote, kind, args.interpolationDelimiterLength, m))
@@ -1407,7 +1399,7 @@ and verbatimString (sargs: LexerStringArgs) (skip: bool) = parse
| newline
{ let (buf, _fin, m, kind, args) = sargs
- newline lexbuf
+ incrLine lexbuf
addUnicodeString buf (lexeme lexbuf)
if not skip then
STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.Verbatim, kind, args.interpolationDelimiterLength, m))
@@ -1500,7 +1492,7 @@ and tripleQuoteString (sargs: LexerStringArgs) (skip: bool) = parse
| newline
{ let (buf, _fin, m, kind, args) = sargs
- newline lexbuf
+ incrLine lexbuf
addUnicodeString buf (lexeme lexbuf)
if not skip then
STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.TripleQuote, kind, args.interpolationDelimiterLength, m))
@@ -1594,7 +1586,7 @@ and extendedInterpolatedString (sargs: LexerStringArgs) (skip: bool) = parse
| newline
{ let (buf, _fin, m, kind, args) = sargs
- newline lexbuf
+ incrLine lexbuf
addUnicodeString buf (lexeme lexbuf)
if not skip then
STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.ExtendedInterpolated, kind, args.interpolationDelimiterLength, m))
@@ -1711,7 +1703,7 @@ and singleLineComment (cargs: SingleLineCommentArgs) (skip: bool) = parse
| newline
{ let buff,_n, mStart, mEnd, args = cargs
trySaveXmlDoc lexbuf buff
- newline lexbuf
+ incrLine lexbuf
// Saves the documentation (if we're collecting any) into a buffer-local variable.
if not skip then LINE_COMMENT (LexCont.Token(args.ifdefStack, args.stringNest))
else
@@ -1773,7 +1765,7 @@ and comment (cargs: BlockCommentArgs) (skip: bool) = parse
| newline
{ let n, m, args = cargs
- newline lexbuf
+ incrLine lexbuf
if not skip then COMMENT (LexCont.Comment(args.ifdefStack, args.stringNest, n, m))
else comment cargs skip lexbuf }
| "*)"
@@ -1807,7 +1799,7 @@ and comment (cargs: BlockCommentArgs) (skip: bool) = parse
and stringInComment (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
// Follow string lexing, skipping tokens until it finishes
| '\\' newline anywhite*
- { newline lexbuf
+ { incrLine lexbuf
if not skip then COMMENT (LexCont.StringInComment(args.ifdefStack, args.stringNest, LexerStringStyle.SingleQuote, n, m))
else stringInComment n m args skip lexbuf }
@@ -1829,7 +1821,7 @@ and stringInComment (n: int) (m: range) (args: LexArgs) (skip: bool) = parse
else comment (n, m, args) skip lexbuf }
| newline
- { newline lexbuf
+ { incrLine lexbuf
if not skip then COMMENT (LexCont.StringInComment(args.ifdefStack, args.stringNest, LexerStringStyle.SingleQuote, n, m))
else stringInComment n m args skip lexbuf }
@@ -1859,7 +1851,7 @@ and verbatimStringInComment (n: int) (m: range) (args: LexArgs) (skip: bool) = p
else verbatimStringInComment n m args skip lexbuf }
| newline
- { newline lexbuf
+ { incrLine lexbuf
if not skip then COMMENT (LexCont.StringInComment(args.ifdefStack, args.stringNest, LexerStringStyle.Verbatim, n, m))
else verbatimStringInComment n m args skip lexbuf }
@@ -1885,7 +1877,7 @@ and tripleQuoteStringInComment (n: int) (m: range) (args: LexArgs) (skip: bool)
else tripleQuoteStringInComment n m args skip lexbuf }
| newline
- { newline lexbuf
+ { incrLine lexbuf
if not skip then COMMENT (LexCont.StringInComment(args.ifdefStack, args.stringNest, LexerStringStyle.TripleQuote, n, m))
else tripleQuoteStringInComment n m args skip lexbuf }
@@ -1907,7 +1899,7 @@ and mlOnly (m: range) (args: LexArgs) (skip: bool) = parse
else mlOnly m args skip lexbuf }
| newline
- { newline lexbuf
+ { incrLine lexbuf
if not skip then COMMENT (LexCont.MLOnly(args.ifdefStack, args.stringNest, m))
else mlOnly m args skip lexbuf }
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 185bd1ed842..fac3f30a073 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -2316,7 +2316,8 @@ opt_classDefn:
inheritsDefn:
| INHERIT atomTypeNonAtomicDeprecated optBaseSpec
{ let mDecl = unionRanges (rhs parseState 1) $2.Range
- SynMemberDefn.Inherit($2, $3, mDecl) }
+ let trivia = { InheritKeyword = rhs parseState 1 }
+ SynMemberDefn.Inherit($2, $3, mDecl, trivia) }
| INHERIT atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType optBaseSpec
{ let mDecl = unionRanges (rhs parseState 1) $4.Range
@@ -2324,8 +2325,9 @@ inheritsDefn:
| INHERIT ends_coming_soon_or_recover
{ let mDecl = (rhs parseState 1)
+ let trivia = { InheritKeyword = (rhs parseState 1) }
if not $2 then errorR (Error(FSComp.SR.parsTypeNameCannotBeEmpty (), mDecl))
- SynMemberDefn.Inherit(SynType.LongIdent(SynLongIdent([], [], [])), None, mDecl) }
+ SynMemberDefn.Inherit(SynType.LongIdent(SynLongIdent([], [], [])), None, mDecl, trivia) }
optAsSpec:
| asSpec
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs
new file mode 100644
index 00000000000..99d019504d6
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs
@@ -0,0 +1,57 @@
+namespace CompilerDirectives
+
+open Xunit
+open FSharp.Test.Compiler
+
+module Ifdef =
+
+ let ifdefSource = """
+[]
+let main _ =
+ #if MYDEFINE1
+ 1
+ #else
+ 2
+ #endif
+"""
+
+ []
+ []
+ []
+ let ifdefTest (mydefine, expectedExitCode) =
+
+ FSharp ifdefSource
+ |> withDefines [mydefine]
+ |> compileExeAndRun
+ |> withExitCode expectedExitCode
+
+
+ let sourceExtraEndif = """
+#if MYDEFINE1
+printf "1"
+#endif
+(**)#endif(**)
+0
+"""
+
+ []
+ let extraEndif () =
+
+ FSharp sourceExtraEndif
+ |> withDefines ["MYDEFINE1"]
+ |> asExe
+ |> compile
+ |> withDiagnosticMessage "#endif has no matching #if in implementation file"
+
+ let sourceUnknownHash = """
+module A
+#ifxx
+#abc
+"""
+
+ []
+ let unknownHashDirectiveIsIgnored () =
+
+ FSharp sourceUnknownHash
+ |> compile
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 72dd62e397c..7b65ba798fe 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -2,164 +2,149 @@ module CompilerService.AsyncMemoize
open System
open System.Threading
-open Xunit
open Internal.Utilities.Collections
open System.Threading.Tasks
open System.Diagnostics
-open System.Collections.Concurrent
+
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.Diagnostics
-open FSharp.Compiler.BuildGraph
+open Xunit
-let timeout = TimeSpan.FromSeconds 10.
+[]
+module internal JobEvents =
-let waitFor (mre: ManualResetEvent) =
- if not <| mre.WaitOne timeout then
- failwith "waitFor timed out"
+ let publishEvent (cache: AsyncMemoize<_, _, _>) =
+ let wrapper = Event<_>()
+ cache.OnEvent (fun e -> lock wrapper <| fun () -> wrapper.Trigger e)
+ wrapper.Publish |> Event.map (fun (jobEvent, (_,k,_)) -> jobEvent, k)
-let waitUntil condition value =
- task {
- let sw = Stopwatch.StartNew()
- while not <| condition value do
- if sw.Elapsed > timeout then
- failwith "waitUntil timed out"
- do! Task.Delay 10
- }
+ let collectEvents cache =
+ cache |> publishEvent |> Event.scan (fun es e -> e :: es) [] |> Event.map List.rev
-let rec internal spinFor (duration: TimeSpan) =
- async {
- let sw = Stopwatch.StartNew()
- do! Async.Sleep 10
- let remaining = duration - sw.Elapsed
- if remaining > TimeSpan.Zero then
- return! spinFor remaining
- }
-
-#if BUILDING_WITH_LKG
-type internal EventRecorder<'a, 'b, 'c when 'a : equality and 'b : equality>(memoize: AsyncMemoize<'a,'b,'c>) as self =
-#else
-type internal EventRecorder<'a, 'b, 'c when 'a : equality and 'b : equality and 'a:not null and 'b:not null>(memoize: AsyncMemoize<'a,'b,'c>) as self =
-#endif
+ /// Exposes a live view of the list of JobEvents generated by AsyncMemoize.
+ let observe cache =
+ let updateAvailable = new AutoResetEvent(false)
+ let mutable recorded = []
- let events = ConcurrentQueue()
+ let update next =
+ Debug.WriteLine $"%A{next}"
+ recorded <- next
+ updateAvailable.Set() |> ignore
- do memoize.OnEvent self.Add
+ collectEvents cache |> Event.add update
- member _.Add (e, (_label, k, _version)) = events.Enqueue (e, k)
+ let waitForUpdate = updateAvailable |> Async.AwaitWaitHandle |> Async.Ignore
- member _.Received value = events |> Seq.exists (fst >> (=) value)
-
- member _.CountOf value count = events |> Seq.filter (fst >> (=) value) |> Seq.length |> (=) count
+ async {
+ Debug.WriteLine $"current: %A{recorded}"
+ return recorded, waitForUpdate
+ }
- member _.ShouldBe (expected) =
- let expected = expected |> Seq.toArray
- let actual = events |> Seq.toArray
- Assert.Equal<_ array>(expected, actual)
+ let countOf value count events = events |> Seq.filter (fst >> (=) value) |> Seq.length |> (=) count
- member _.Sequence = events |> Seq.map id
+ let received value events = events |> Seq.exists (fst >> (=) value)
+ let waitUntil observedCache condition =
+ let rec loop() = async {
+ let! current, waitForUpdate = observedCache
+ if current |> condition |> not then
+ do! waitForUpdate
+ return! loop()
+ }
+ loop()
[]
let ``Basics``() =
-
- let computation key = async {
- do! Async.Sleep 1
- return key * 2
- }
-
- let memoize = AsyncMemoize()
- let events = EventRecorder(memoize)
-
- let result =
- seq {
- memoize.Get'(5, computation 5)
- memoize.Get'(5, computation 5)
- memoize.Get'(2, computation 2)
- memoize.Get'(5, computation 5)
- memoize.Get'(3, computation 3)
- memoize.Get'(2, computation 2)
+ task {
+ let computation key = async {
+ do! Async.Sleep 1
+ return key * 2
}
- |> Async.Parallel
- |> Async.RunSynchronously
- let expected = [| 10; 10; 4; 10; 6; 4|]
+ let memoize = AsyncMemoize()
+ let events = observe memoize
+
+ let result =
+ seq {
+ memoize.Get'(5, computation 5)
+ memoize.Get'(5, computation 5)
+ memoize.Get'(2, computation 2)
+ memoize.Get'(5, computation 5)
+ memoize.Get'(3, computation 3)
+ memoize.Get'(2, computation 2)
+ }
+ |> Async.Parallel
+ |> Async.RunSynchronously
- Assert.Equal(expected, result)
+ let expected = [| 10; 10; 4; 10; 6; 4|]
- (waitUntil (events.CountOf Finished) 3).Wait()
+ Assert.Equal(expected, result)
- let groups = events.Sequence |> Seq.groupBy snd |> Seq.toList
- Assert.Equal(3, groups.Length)
- for key, events in groups do
- Assert.Equal>(Set [ Requested, key; Started, key; Finished, key ], Set events)
+ do! waitUntil events (countOf Finished 3)
+ let! current, _ = events
+ let groups = current |> Seq.groupBy snd |> Seq.toList
+ Assert.Equal(3, groups.Length)
+ for key, events in groups do
+ Assert.Equal>(Set [ Requested, key; Started, key; Finished, key ], Set events)
+ }
[]
let ``We can cancel a job`` () =
task {
- let jobStarted = new ManualResetEvent(false)
+ let jobStarted = new ManualResetEventSlim(false)
+ let cts = new CancellationTokenSource()
+ let ctsCancelled = new ManualResetEventSlim(false)
- let computation action = async {
- action() |> ignore
- do! spinFor timeout
+ let computation = async {
+ use! _catch = Async.OnCancel ignore
+ jobStarted.Set()
+ ctsCancelled.Wait()
+ do! async { }
failwith "Should be canceled before it gets here"
}
let memoize = AsyncMemoize<_, int, _>()
- let events = EventRecorder(memoize)
-
- use cts1 = new CancellationTokenSource()
- use cts2 = new CancellationTokenSource()
- use cts3 = new CancellationTokenSource()
+ let events = observe memoize
let key = 1
- let _task1 = Async.StartAsTask( memoize.Get'(key, computation jobStarted.Set), cancellationToken = cts1.Token)
-
- waitFor jobStarted
- jobStarted.Reset() |> ignore
+ let _task1 = Async.StartAsTask( memoize.Get'(1, computation), cancellationToken = cts.Token)
- let _task2 = Async.StartAsTask( memoize.Get'(key, computation ignore), cancellationToken = cts2.Token)
- let _task3 = Async.StartAsTask( memoize.Get'(key, computation ignore), cancellationToken = cts3.Token)
+ jobStarted.Wait()
+ cts.Cancel()
+ ctsCancelled.Set()
- do! waitUntil (events.CountOf Requested) 3
+ do! waitUntil events (received Canceled)
+ let! current, _ = events
- cts1.Cancel()
- cts2.Cancel()
-
- waitFor jobStarted
-
- cts3.Cancel()
-
- do! waitUntil events.Received Canceled
-
- events.ShouldBe [
- Requested, key
- Started, key
- Requested, key
- Requested, key
- Restarted, key
- Canceled, key
- ]
+ Assert.Equal<_ list>(
+ [
+ Requested, key
+ Started, key
+ Canceled, key
+ ],
+ current
+ )
}
[]
let ``Job is restarted if first requestor cancels`` () =
task {
- let jobStarted = new ManualResetEvent(false)
+ let jobStarted = new SemaphoreSlim(0)
- let jobCanComplete = new ManualResetEvent(false)
+ let jobCanComplete = new ManualResetEventSlim(false)
let computation key = async {
- jobStarted.Set() |> ignore
- waitFor jobCanComplete
+ jobStarted.Release() |> ignore
+
+ jobCanComplete.Wait()
return key * 2
}
let memoize = AsyncMemoize<_, int, _>()
- let events = EventRecorder(memoize)
-
+ let events = observe memoize
use cts1 = new CancellationTokenSource()
use cts2 = new CancellationTokenSource()
@@ -169,48 +154,49 @@ let ``Job is restarted if first requestor cancels`` () =
let _task1 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts1.Token)
- waitFor jobStarted
- jobStarted.Reset() |> ignore
-
+ do! jobStarted.WaitAsync()
let _task2 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts2.Token)
let _task3 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts3.Token)
- do! waitUntil (events.CountOf Requested) 3
+ do! waitUntil events (countOf Requested 3)
cts1.Cancel()
- waitFor jobStarted
-
jobCanComplete.Set() |> ignore
+ do! jobStarted.WaitAsync()
+
let! result = _task2
Assert.Equal(2, result)
- events.ShouldBe [
- Requested, key
+ let! current, _ = events
+
+ Assert.Equal<_ list>(
+ [ Requested, key
Started, key
Requested, key
Requested, key
Restarted, key
- Finished, key ]
+ Finished, key ],
+ current
+ )
}
[]
let ``Job is restarted if first requestor cancels but keeps running if second requestor cancels`` () =
task {
- let jobStarted = new ManualResetEvent(false)
+ let jobStarted = new ManualResetEventSlim(false)
- let jobCanComplete = new ManualResetEvent(false)
+ let jobCanComplete = new ManualResetEventSlim(false)
let computation key = async {
jobStarted.Set() |> ignore
- waitFor jobCanComplete
+ jobCanComplete.Wait()
return key * 2
}
let memoize = AsyncMemoize<_, int, _>()
- let events = EventRecorder(memoize)
-
+ let events = observe memoize
use cts1 = new CancellationTokenSource()
use cts2 = new CancellationTokenSource()
@@ -220,17 +206,17 @@ let ``Job is restarted if first requestor cancels but keeps running if second re
let _task1 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts1.Token)
- waitFor jobStarted
+ jobStarted.Wait()
jobStarted.Reset() |> ignore
let _task2 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts2.Token)
let _task3 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts3.Token)
- do! waitUntil (events.CountOf Requested) 3
+ do! waitUntil events (countOf Requested 3)
cts1.Cancel()
- waitFor jobStarted
+ jobStarted.Wait()
cts2.Cancel()
@@ -239,13 +225,17 @@ let ``Job is restarted if first requestor cancels but keeps running if second re
let! result = _task3
Assert.Equal(2, result)
- events.ShouldBe [
- Requested, key
+ let! current, _ = events
+
+ Assert.Equal<_ list>(
+ [ Requested, key
Started, key
Requested, key
Requested, key
Restarted, key
- Finished, key ]
+ Finished, key ],
+ current
+ )
}
@@ -376,59 +366,56 @@ let ``Stress test`` () =
[]
[]
let ``Cancel running jobs with the same key`` cancelDuplicate expectFinished =
- task {
- let cache = AsyncMemoize(cancelDuplicateRunningJobs=cancelDuplicate)
-
- let mutable started = 0
- let mutable finished = 0
+ let cache = AsyncMemoize(cancelDuplicateRunningJobs=cancelDuplicate)
- let job1started = new ManualResetEvent(false)
- let job1finished = new ManualResetEvent(false)
+ let mutable started = 0
+ let mutable finished = 0
- let jobCanContinue = new ManualResetEvent(false)
+ let job1started = new ManualResetEventSlim(false)
+ let job1finished = new ManualResetEventSlim(false)
- let job2started = new ManualResetEvent(false)
- let job2finished = new ManualResetEvent(false)
+ let jobCanContinue = new ManualResetEventSlim(false)
- let work onStart onFinish = async {
- Interlocked.Increment &started |> ignore
- onStart() |> ignore
- waitFor jobCanContinue
- do! spinFor (TimeSpan.FromMilliseconds 100)
- Interlocked.Increment &finished |> ignore
- onFinish() |> ignore
- }
+ let job2started = new ManualResetEventSlim(false)
+ let job2finished = new ManualResetEventSlim(false)
- let key1 =
- { new ICacheKey<_, _> with
- member _.GetKey() = 1
- member _.GetVersion() = 1
- member _.GetLabel() = "key1" }
+ let work onStart onFinish = async {
+ Interlocked.Increment &started |> ignore
+ onStart() |> ignore
+ jobCanContinue.Wait()
+ do! Async.Sleep 100
+ Interlocked.Increment &finished |> ignore
+ onFinish() |> ignore
+ }
- cache.Get(key1, work job1started.Set job1finished.Set) |> Async.Start
+ let key1 =
+ { new ICacheKey<_, _> with
+ member _.GetKey() = 1
+ member _.GetVersion() = 1
+ member _.GetLabel() = "key1" }
- waitFor job1started
+ cache.Get(key1, work job1started.Set job1finished.Set) |> Async.Catch |> Async.Ignore |> Async.Start
- let key2 =
- { new ICacheKey<_, _> with
- member _.GetKey() = key1.GetKey()
- member _.GetVersion() = key1.GetVersion() + 1
- member _.GetLabel() = "key2" }
+ job1started.Wait()
- cache.Get(key2, work job2started.Set job2finished.Set ) |> Async.Start
+ let key2 =
+ { new ICacheKey<_, _> with
+ member _.GetKey() = key1.GetKey()
+ member _.GetVersion() = key1.GetVersion() + 1
+ member _.GetLabel() = "key2" }
- waitFor job2started
+ cache.Get(key2, work job2started.Set job2finished.Set ) |> Async.Catch |> Async.Ignore |> Async.Start
- jobCanContinue.Set() |> ignore
+ job2started.Wait()
- waitFor job2finished
+ jobCanContinue.Set() |> ignore
- if not cancelDuplicate then
- waitFor job1finished
-
- Assert.Equal((2, expectFinished), (started, finished))
- }
+ job2finished.Wait()
+
+ if not cancelDuplicate then
+ job1finished.Wait()
+ Assert.Equal((2, expectFinished), (started, finished))
type DummyException(msg) =
inherit Exception(msg)
@@ -490,7 +477,7 @@ let ``Preserve thread static diagnostics`` () =
let diagnostics = diagnosticsLogger.GetDiagnostics()
- //Assert.Equal(3, diagnostics.Length)
+ Assert.Equal(4, diagnostics.Length)
return result, diagnostics
}
@@ -498,9 +485,9 @@ let ``Preserve thread static diagnostics`` () =
let results = (Task.WhenAll tasks).Result
- let _diagnosticCounts = results |> Seq.map snd |> Seq.map Array.length |> Seq.groupBy id |> Seq.map (fun (k, v) -> k, v |> Seq.length) |> Seq.sortBy fst |> Seq.toList
+ let diagnosticCounts = results |> Seq.map snd |> Seq.map Array.length |> Seq.groupBy id |> Seq.map (fun (k, v) -> k, v |> Seq.length) |> Seq.sortBy fst |> Seq.toList
- //Assert.Equal<(int * int) list>([4, 100], diagnosticCounts)
+ Assert.Equal<(int * int) list>([4, 100], diagnosticCounts)
let diagnosticMessages = results |> Seq.map snd |> Seq.map (Array.map (fun (d, _) -> d.Exception.Message) >> Array.toList) |> Set
@@ -523,7 +510,7 @@ let ``Preserve thread static diagnostics already completed job`` () =
return Ok input
}
- async {
+ task {
let diagnosticsLogger = CompilationDiagnosticLogger($"Testing", FSharpDiagnosticOptions.Default)
@@ -534,10 +521,9 @@ let ``Preserve thread static diagnostics already completed job`` () =
let diagnosticMessages = diagnosticsLogger.GetDiagnostics() |> Array.map (fun (d, _) -> d.Exception.Message) |> Array.toList
- Assert.Equal>(["job 1 error"; "job 1 error"], diagnosticMessages)
+ Assert.Equal<_ list>(["job 1 error"; "job 1 error"], diagnosticMessages)
}
- |> Async.StartAsTask
[]
@@ -550,34 +536,22 @@ let ``We get diagnostics from the job that failed`` () =
member _.GetVersion() = 1
member _.GetLabel() = "job1" }
- let job (input: int) = async {
- let ex = DummyException($"job {input} error")
- do! Async.Sleep 100
- DiagnosticsThreadStatics.DiagnosticsLogger.Error(ex)
+ let job = async {
+ let ex = DummyException($"job error")
+
+ // no recovery
+ DiagnosticsThreadStatics.DiagnosticsLogger.Error ex
return 5
}
- let result =
- [1; 2]
- |> Seq.map (fun i ->
- async {
- let diagnosticsLogger = CompilationDiagnosticLogger($"Testing", FSharpDiagnosticOptions.Default)
-
- use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Optimize)
- try
- let! _ = cache.Get(key, job i )
- ()
- with _ ->
- ()
- let diagnosticMessages = diagnosticsLogger.GetDiagnostics() |> Array.map (fun (d, _) -> d.Exception.Message) |> Array.toList
-
- return diagnosticMessages
- })
- |> Async.Parallel
- |> Async.StartAsTask
- |> (fun t -> t.Result)
- |> Array.toList
-
- Assert.True(
- result = [["job 1 error"]; ["job 1 error"]] ||
- result = [["job 2 error"]; ["job 2 error"]] )
+ task {
+ let logger = CapturingDiagnosticsLogger("AsyncMemoize diagnostics test")
+
+ SetThreadDiagnosticsLoggerNoUnwind logger
+
+ do! cache.Get(key, job ) |> Async.Catch |> Async.Ignore
+
+ let messages = logger.Diagnostics |> List.map fst |> List.map _.Exception.Message
+
+ Assert.Equal<_ list>(["job error"], messages)
+ }
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
index f6d8a0cc530..9b7cdc5a053 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
@@ -933,3 +933,36 @@ and []
|> verifyCompile
|> shouldSucceed
#endif
+
+ [] // Regression for https://github.com/dotnet/fsharp/issues/14304
+ let ``Construct an object with default and params parameters using parameterless constructor`` () =
+ Fsx """
+open System
+open System.Runtime.InteropServices
+
+type DefaultAndParams([]x: int, [] value: string[]) =
+ inherit Attribute()
+
+type ParamsOnly([] value: string[]) =
+ inherit Attribute()
+
+type DefaultOnly([]x: int) =
+ inherit Attribute()
+
+[]
+type Q1 = struct end
+
+[] // ok
+type Q11 = struct end
+
+[] // ok
+type Q12 = struct end
+
+[]
+type Q2 = struct end
+
+[]
+type Q3 = struct end
+ """
+ |> typecheck
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ExceptionDefinitions/ExceptionDefinitions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ExceptionDefinitions/ExceptionDefinitions.fs
index fb7785d3758..1ec630b6e98 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ExceptionDefinitions/ExceptionDefinitions.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ExceptionDefinitions/ExceptionDefinitions.fs
@@ -289,7 +289,7 @@ module ExceptionDefinition =
|> compile
|> shouldFail
|> withDiagnostics [
- (Error 945, Line 9, Col 5, Line 9, Col 24, "Cannot inherit a sealed type")
+ (Error 945, Line 9, Col 13, Line 9, Col 22, "Cannot inherit a sealed type")
(Error 1133, Line 9, Col 5, Line 9, Col 24, "No constructors are available for the type 'FSharpExn'")
]
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/TypeAbbreviations/TypeAbbreviations.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/TypeAbbreviations/TypeAbbreviations.fs
index 80db08b3025..365f1af46b7 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/TypeAbbreviations/TypeAbbreviations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/TypeAbbreviations/TypeAbbreviations.fs
@@ -157,7 +157,7 @@ module TypeAbbreviations =
|> verifyCompile
|> shouldFail
|> withDiagnostics [
- (Error 945, Line 9, Col 9, Line 9, Col 22, "Cannot inherit a sealed type")
+ (Error 945, Line 9, Col 17, Line 9, Col 22, "Cannot inherit a sealed type")
]
//SOURCE=E_PrivateTypeAbbreviation02.fs SCFLAGS="--test:ErrorRanges" # E_PrivateTypeAbbreviation02.fs
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs
index 26acb4b9d0f..0c61d444a9d 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs
@@ -195,8 +195,8 @@ module UnionTypes =
|> verifyCompile
|> shouldFail
|> withDiagnostics [
- (Error 961, Line 10, Col 5, Line 10, Col 22, "This 'inherit' declaration specifies the inherited type but no arguments. Consider supplying arguments, e.g. 'inherit BaseType(args)'.")
- (Error 945, Line 10, Col 5, Line 10, Col 22, "Cannot inherit a sealed type")
+ (Error 961, Line 10, Col 5, Line 10, Col 12, "This 'inherit' declaration specifies the inherited type but no arguments. Consider supplying arguments, e.g. 'inherit BaseType(args)'.")
+ (Error 945, Line 10, Col 13, Line 10, Col 22, "Cannot inherit a sealed type")
]
//SOURCE=E_LowercaseDT.fs # E_LowercaseDT.fs
diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
index b3c33031acb..c560008da0c 100644
--- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
@@ -45,7 +45,6 @@ else ()
|> compile
|> run
|> shouldSucceed
- |> withExitCode 0
[]
let ``Respect nowarn 957 for extension method`` () =
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
index d2dc41a3235..1477db7754c 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
@@ -176,37 +176,118 @@ let [] x = System.Int32.MaxValue + 1
}
[]
- let ``Arithmetic can be used for constructing decimal literals``() =
+ let ``Decimal literals are properly initialized``() =
FSharp """
-module LiteralArithmetic
+module DecimalInit
[]
-let x = 1m + 2m
+let x = 5.5m
"""
|> withLangVersion80
|> compile
|> shouldSucceed
|> verifyIL [
- """.field public static initonly valuetype [runtime]System.Decimal x"""
- """.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ """
+.class public abstract auto ansi sealed DecimalInit
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .field public static initonly valuetype [runtime]System.Decimal x
+ .custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
int32,
int32,
- int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00
- 00 00 )"""
- """.maxstack 8"""
- """IL_0000: ldc.i4.3"""
- """IL_0001: ldc.i4.0"""
- """IL_0002: ldc.i4.0"""
- """IL_0003: ldc.i4.0"""
- """IL_0004: ldc.i4.0"""
- """IL_0005: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 37 00 00 00
+ 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
+ .method private specialname rtspecialname static void .cctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: stsfld int32 ''.$DecimalInit::init@
+ IL_0006: ldsfld int32 ''.$DecimalInit::init@
+ IL_000b: pop
+ IL_000c: ret
+ }
+
+ .method assembly specialname static void staticInitialization@() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldc.i4.s 55
+ IL_0002: ldc.i4.0
+ IL_0003: ldc.i4.0
+ IL_0004: ldc.i4.0
+ IL_0005: ldc.i4.1
+ IL_0006: newobj instance void [runtime]System.Decimal::.ctor(int32,
int32,
int32,
bool,
- uint8)"""
- """IL_000a: stsfld valuetype [runtime]System.Decimal LiteralArithmetic::x"""
- """IL_000f: ret"""
+ uint8)
+ IL_000b: stsfld valuetype [runtime]System.Decimal DecimalInit::x
+ IL_0010: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$DecimalInit
+ extends [runtime]System.Object
+{
+ .field static assembly int32 init@
+ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+ .method private specialname rtspecialname static void .cctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: call void DecimalInit::staticInitialization@()
+ IL_0005: ret
+ }
+
+}
+"""
+ ]
+
+ []
+ let ``Arithmetic can be used for constructing decimal literals``() =
+ FSharp """
+module LiteralArithmetic
+
+[]
+let x = 1m + 2m
+ """
+ |> withLangVersion80
+ |> compile
+ |> shouldSucceed
+ |> verifyIL [
+ """.field public static initonly valuetype [runtime]System.Decimal x
+.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00
+ 00 00 )"""
+ """
+.method assembly specialname static void staticInitialization@() cil managed
+{
+
+.maxstack 8
+IL_0000: ldc.i4.3
+IL_0001: ldc.i4.0
+IL_0002: ldc.i4.0
+IL_0003: ldc.i4.0
+IL_0004: ldc.i4.0
+IL_0005: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+IL_000a: stsfld valuetype [runtime]System.Decimal LiteralArithmetic::x
+IL_000f: ret
+}
+"""
]
[]
@@ -226,28 +307,45 @@ let test () =
|> compile
|> shouldSucceed
|> verifyIL [
- """.field public static initonly valuetype [runtime]System.Decimal x"""
- """ .custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
- uint8,
- int32,
- int32,
- int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00
- 00 00 )"""
- """IL_0016: call bool [netstandard]System.Decimal::op_Equality(valuetype [netstandard]System.Decimal,
- valuetype [netstandard]System.Decimal)"""
- """.maxstack 8"""
- """IL_0000: ldc.i4.5"""
- """IL_0001: ldc.i4.0"""
- """IL_0002: ldc.i4.0"""
- """IL_0003: ldc.i4.0"""
- """IL_0004: ldc.i4.0"""
- """IL_0005: newobj instance void [runtime]System.Decimal::.ctor(int32,
- int32,
- int32,
- bool,
- uint8)"""
- """IL_000a: stsfld valuetype [runtime]System.Decimal PatternMatch::x"""
- """IL_000f: ret"""
+ """
+.field public static initonly valuetype [runtime]System.Decimal x
+.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00
+ 00 00 )"""
+ """
+.method public static int32 test() cil managed
+ {
+
+.maxstack 8
+.locals init (valuetype [runtime]System.Decimal V_0)
+IL_0000: ldc.i4.5
+IL_0001: ldc.i4.0
+IL_0002: ldc.i4.0
+IL_0003: ldc.i4.0
+IL_0004: ldc.i4.0
+IL_0005: newobj instance void [netstandard]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+IL_000a: stloc.0
+IL_000b: ldloc.0
+IL_000c: ldc.i4.5
+IL_000d: ldc.i4.0
+IL_000e: ldc.i4.0
+IL_000f: ldc.i4.0
+IL_0010: ldc.i4.0
+IL_0011: newobj instance void [netstandard]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+IL_0016: call bool [netstandard]System.Decimal::op_Equality(valuetype [netstandard]System.Decimal,
+ valuetype [netstandard]System.Decimal)
+ """
]
[]
@@ -264,6 +362,56 @@ let y = 42m
|> withLangVersion80
|> compile
|> shouldSucceed
+ |> verifyIL [
+ """
+.field public static initonly valuetype [runtime]System.Decimal x
+.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 29 00 00 00
+ 00 00 )
+"""
+ """
+.field public static initonly valuetype [runtime]System.Decimal y
+.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 2A 00 00 00
+ 00 00 )
+"""
+ """
+.method assembly specialname static void staticInitialization@() cil managed
+{
+
+.maxstack 8
+IL_0000: ldc.i4.s 41
+IL_0002: ldc.i4.0
+IL_0003: ldc.i4.0
+IL_0004: ldc.i4.0
+IL_0005: ldc.i4.0
+IL_0006: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+IL_000b: stsfld valuetype [runtime]System.Decimal DecimalLiterals::x
+IL_0010: ldc.i4.s 42
+IL_0012: ldc.i4.0
+IL_0013: ldc.i4.0
+IL_0014: ldc.i4.0
+IL_0015: ldc.i4.0
+IL_0016: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)
+IL_001b: stsfld valuetype [runtime]System.Decimal DecimalLiterals::y
+IL_0020: ret
+}
+"""
+ ]
[]
let ``Compilation fails when using arithmetic with a non-literal in literal``() =
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
index 9a43d34d429..1e5187167a7 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
@@ -56,9 +56,9 @@ let ``Stackoverflow reproduction`` compilation =
| CompilationResult.Success ({OutputPath = Some dllFile} as s) ->
let fsharpCoreFile = typeof>.Assembly.Location
File.Copy(fsharpCoreFile, Path.Combine(Path.GetDirectoryName(dllFile), Path.GetFileName(fsharpCoreFile)), true)
- let exitCode, _stdout, _stderr = CompilerAssert.ExecuteAndReturnResult (dllFile, isFsx=false, deps = s.Dependencies, newProcess=true)
+ let _exitCode, _stdout, stderr, _exn = CompilerAssert.ExecuteAndReturnResult (dllFile, isFsx=false, deps = s.Dependencies, newProcess=true)
- Assert.NotEqual(0,exitCode)
+ Assert.True(stderr.Contains "stack overflow" || stderr.Contains "StackOverflow")
| _ -> failwith (sprintf "%A" compilationResult)
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
index 55f4d1cbf1b..44e8e202a94 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
@@ -815,4 +815,19 @@ type A() =
default this.M() = ()
"""
|> typecheck
- |> shouldSucceed
\ No newline at end of file
+ |> shouldSucceed
+
+ []
+ let ``This 'inherit' declaration specifies the inherited type but no arguments. Consider supplying arguments, e. g. 'inherit BaseType(args)'`` () =
+ Fsx """
+type IA = interface end
+
+type Class() =
+ inherit IA
+ """
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 961, Line 5, Col 5, Line 5, Col 12, "This 'inherit' declaration specifies the inherited type but no arguments. Consider supplying arguments, e.g. 'inherit BaseType(args)'.")
+ (Error 946, Line 5, Col 13, Line 5, Col 15, "Cannot inherit from interface type. Use interface ... with instead.")
+ ]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 4b50b28aa12..029ec14b0b4 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -32,6 +32,7 @@
FsUnit.fs
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
index 9d276c13629..3555e97fd2d 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
@@ -644,4 +644,85 @@ let indexHandler (): Task =
'string'
but here has type
'Task' ")
+ ]
+
+ []
+ let ``use expressions may not be used in queries(SynExpr.Sequential)`` () =
+ Fsx """
+let x11 =
+ query { for c in [1..10] do
+ use x = { new System.IDisposable with __.Dispose() = () }
+ yield 1 }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3142, Line 4, Col 13, Line 4, Col 16, "'use' expressions may not be used in queries")
+ ]
+
+ []
+ let ``use, This control construct may only be used if the computation expression builder defines a 'Using' method`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+
+ member _.YieldReturn(x: Result<'T,'U>) = x
+ member _.Return(x: 'T) = Ok x
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ use b = r2
+ return Ok 0
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 20, Col 9, Line 20, Col 12, "This control construct may only be used if the computation expression builder defines a 'Using' method")
+ ]
+
+ []
+ let ``This 'let' definition may not be used in a query. Only simple value definitions may be used in queries.`` () =
+ Fsx """
+let x18rec2 =
+ query {
+ for d in [1..10] do
+ let rec f x = x + 1 // error expected here - no recursive functions
+ and g x = f x + 2
+ select (f d)
+ }
+
+let x18inline =
+ query {
+ for d in [1..10] do
+ let inline f x = x + 1 // error expected here - no inline functions
+ select (f d)
+ }
+
+let x18mutable =
+ query {
+ for d in [1..10] do
+ let mutable v = 1 // error expected here - no mutable values
+ select (f d)
+ }
+
+ """
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3147, Line 5, Col 17, Line 5, Col 20, "This 'let' definition may not be used in a query. Only simple value definitions may be used in queries.")
+ (Error 3147, Line 13, Col 20, Line 13, Col 23, "This 'let' definition may not be used in a query. Only simple value definitions may be used in queries.")
+ (Error 3147, Line 20, Col 21, Line 20, Col 22, "This 'let' definition may not be used in a query. Only simple value definitions may be used in queries.")
]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
index 1edfbfd7961..0da1169b9a8 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
@@ -144,6 +144,21 @@ let nonStrictFunc(x:string | null) = strictFunc(x)
|> shouldFail
|> withDiagnostics [
Error 3261, Line 4, Col 49, Line 4, Col 50, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."]
+
+[]
+let ``Can have nullable prop of same type T within a custom type T``() =
+ FSharp """
+module MyLib
+type T () =
+ let mutable v : T | null = null
+ member val P : T | null = null with get, set
+ member this.M() =
+ v <- null
+ this.P <- null
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldSucceed
[]
[]
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
index 9cfbbb9df80..294db344223 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
@@ -38,12 +38,12 @@ module CompilationFromCmdlineArgsTests =
yield! methodOptions method
|]
- let diagnostics, exitCode = checker.Compile(args) |> Async.RunSynchronously
+ let diagnostics, exn = checker.Compile(args) |> Async.RunSynchronously
for diag in diagnostics do
printfn "%A" diag
- Assert.Equal(exitCode, 0)
+ Assert.Equal(exn, None)
finally
Environment.CurrentDirectory <- oldWorkDir
diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
index aff47308ad2..bf3a9cbaac6 100644
--- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
+++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
@@ -12,12 +12,16 @@ open System.Threading.Tasks
open FSharp.Compiler.Interactive
open FSharp.Compiler.Interactive.Shell
open FSharp.Test.ScriptHelpers
-open FSharp.Test.Utilities
open Xunit
type InteractiveTests() =
+ let copyHousingToTemp() =
+ let tempName = TestFramework.getTemporaryFileName()
+ File.Copy(__SOURCE_DIRECTORY__ ++ "housing.csv", tempName + ".csv")
+ tempName
+
[]
member _.``ValueRestriction error message should not have type variables fully solved``() =
use script = new FSharpScript()
@@ -248,10 +252,10 @@ System.Configuration.ConfigurationManager.AppSettings.Item "Environment" <- "LOC
if RuntimeInformation.ProcessArchitecture = Architecture.Arm64 then
()
else
- let code = @"
-#r ""nuget:Microsoft.ML,version=1.4.0-preview""
-#r ""nuget:Microsoft.ML.AutoML,version=0.16.0-preview""
-#r ""nuget:Microsoft.Data.Analysis,version=0.4.0""
+ let code = $"""
+#r "nuget:Microsoft.ML,version=1.4.0-preview"
+#r "nuget:Microsoft.ML.AutoML,version=0.16.0-preview"
+#r "nuget:Microsoft.Data.Analysis,version=0.4.0"
open System
open System.IO
@@ -267,7 +271,7 @@ let Shuffle (arr:int[]) =
arr.[i] <- temp
arr
-let housingPath = ""housing.csv""
+let housingPath = @"{copyHousingToTemp()}.csv"
let housingData = DataFrame.LoadCsv(housingPath)
let randomIndices = (Shuffle(Enumerable.Range(0, (int (housingData.Rows.Count) - 1)).ToArray()))
let testSize = int (float (housingData.Rows.Count) * 0.1)
@@ -281,11 +285,11 @@ open Microsoft.ML.AutoML
let mlContext = MLContext()
let experiment = mlContext.Auto().CreateRegressionExperiment(maxExperimentTimeInSeconds = 15u)
-let result = experiment.Execute(housing_train, labelColumnName = ""median_house_value"")
+let result = experiment.Execute(housing_train, labelColumnName = "median_house_value")
let details = result.RunDetails
-printfn ""%A"" result
+printfn "{@"%A"}" result
123
-"
+"""
use script = new FSharpScript(additionalArgs=[| |])
let opt = script.Eval(code) |> getValue
let value = opt.Value
@@ -511,3 +515,4 @@ let add (col:IServiceCollection) =
use script = new FSharpScript(additionalArgs=[| |])
let _value,diag = script.Eval(code)
Assert.Empty(diag)
+
diff --git a/tests/FSharp.Compiler.Service.Tests/BuildGraphTests.fs b/tests/FSharp.Compiler.Service.Tests/BuildGraphTests.fs
index 16b0ff7b878..4769b4c322d 100644
--- a/tests/FSharp.Compiler.Service.Tests/BuildGraphTests.fs
+++ b/tests/FSharp.Compiler.Service.Tests/BuildGraphTests.fs
@@ -385,22 +385,17 @@ module BuildGraphTests =
for i in 1 .. 300 do
async {
- Interlocked.Increment(&count) |> ignore
- errorR (ExampleException $"{i}")
+ errorR (ExampleException $"{Interlocked.Increment(&count)}")
+ error (ExampleException $"{Interlocked.Increment(&count)}")
}
]
- let run =
- tasks |> MultipleDiagnosticsLoggers.Parallel |> Async.Catch |> Async.StartAsTask
-
- Assert.True(
- run.Wait(1000),
- "MultipleDiagnosticsLoggers.Parallel did not finish."
- )
-
- // Diagnostics from all started tasks should be collected despite the exception.
- errorCountShouldBe count
+ task {
+ do! tasks |> MultipleDiagnosticsLoggers.Parallel |> Async.Catch |> Async.Ignore
+ // Diagnostics from all started tasks should be collected despite the exception.
+ errorCountShouldBe count
+ }
[]
let ``AsyncLocal diagnostics context flows correctly`` () =
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
index 42ec38ee366..f08d67883b7 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl
@@ -2166,7 +2166,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectSnapshotFromScript(System.String, FSharp.Compiler.Text.ISourceTextNew, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
-FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],System.Int32]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],Microsoft.FSharp.Core.FSharpOption`1[System.Exception]]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions],FSharp.Compiler.CodeAnalysis.FSharpProjectOptions] ProjectChecked
@@ -8151,7 +8151,13 @@ FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAu
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
-FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
+FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
+FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: FSharp.Compiler.Text.Range InheritKeyword
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: FSharp.Compiler.Text.Range get_InheritKeyword()
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: System.String ToString()
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: Void .ctor(FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInterface(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn]], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewLetBindings(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Boolean, Boolean, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewMember(FSharp.Compiler.Syntax.SynBinding, FSharp.Compiler.Text.Range)
@@ -10231,7 +10237,9 @@ FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.SyntaxTrivia
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] InKeyword
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_InKeyword()
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: System.String ToString()
-FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.Text.Range LetOrUseKeyword
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.Text.Range get_LetOrUseKeyword()
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Void .ctor(FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range MatchBangKeyword
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range WithKeyword
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range get_MatchBangKeyword()
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
index 42ec38ee366..f08d67883b7 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
@@ -2166,7 +2166,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectSnapshotFromScript(System.String, FSharp.Compiler.Text.ISourceTextNew, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
-FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],System.Int32]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],Microsoft.FSharp.Core.FSharpOption`1[System.Exception]]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions],FSharp.Compiler.CodeAnalysis.FSharpProjectOptions] ProjectChecked
@@ -8151,7 +8151,13 @@ FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAu
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
-FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
+FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
+FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
+FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: FSharp.Compiler.Text.Range InheritKeyword
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: FSharp.Compiler.Text.Range get_InheritKeyword()
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: System.String ToString()
+FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia: Void .ctor(FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInterface(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn]], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewLetBindings(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Boolean, Boolean, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewMember(FSharp.Compiler.Syntax.SynBinding, FSharp.Compiler.Text.Range)
@@ -10231,7 +10237,9 @@ FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.SyntaxTrivia
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] InKeyword
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_InKeyword()
FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: System.String ToString()
-FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.Text.Range LetOrUseKeyword
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: FSharp.Compiler.Text.Range get_LetOrUseKeyword()
+FSharp.Compiler.SyntaxTrivia.SynExprLetOrUseTrivia: Void .ctor(FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range MatchBangKeyword
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range WithKeyword
FSharp.Compiler.SyntaxTrivia.SynExprMatchBangTrivia: FSharp.Compiler.Text.Range get_MatchBangKeyword()
diff --git a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs
index 78d03ac8a9b..5752f9de41c 100644
--- a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs
+++ b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs
@@ -123,7 +123,14 @@ let ``Test project1 and make sure TcImports gets cleaned up`` () =
let weakTcImports = test ()
checker.InvalidateConfiguration Project1.options
checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
- GC.Collect(2, GCCollectionMode.Forced, blocking = true)
+
+ //collect 2 more times for good measure,
+ // See for example: https://github.com/dotnet/runtime/discussions/108081
+ GC.Collect()
+ GC.WaitForPendingFinalizers()
+ GC.Collect()
+ GC.WaitForPendingFinalizers()
+
Assert.False weakTcImports.IsAlive
[]
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs
index 145d9a70c3e..213ff435adf 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs
@@ -7,6 +7,7 @@ namespace FSharp.Core.UnitTests.Control
open System
open System.Threading
+open System.Threading.Tasks
open FSharp.Core.UnitTests.LibraryTestFx
open Xunit
open FsCheck
@@ -273,8 +274,7 @@ type AsyncModule() =
}
Async.RunSynchronously test
- // test is flaky: https://github.com/dotnet/fsharp/issues/11586
- //[]
+ []
member _.``OnCancel.RaceBetweenCancellationHandlerAndDisposingHandlerRegistration``() =
let test() =
use flag = new ManualResetEvent(false)
@@ -297,8 +297,7 @@ type AsyncModule() =
for _i = 1 to 300 do test()
- // test is flaky: https://github.com/dotnet/fsharp/issues/11586
- //[]
+ []
member _.``OnCancel.RaceBetweenCancellationAndDispose``() =
let mutable flag = 0
let cts = new System.Threading.CancellationTokenSource()
@@ -316,8 +315,7 @@ type AsyncModule() =
:? System.OperationCanceledException -> ()
Assert.AreEqual(1, flag)
- // test is flaky: https://github.com/dotnet/fsharp/issues/11586
- //[]
+ []
member _.``OnCancel.CancelThatWasSignalledBeforeRunningTheComputation``() =
let test() =
let cts = new System.Threading.CancellationTokenSource()
@@ -379,23 +377,25 @@ type AsyncModule() =
[]
member _.``AwaitWaitHandle.DisposedWaitHandle2``() =
- let wh = new System.Threading.ManualResetEvent(false)
- let barrier = new System.Threading.ManualResetEvent(false)
+ let wh = new ManualResetEvent(false)
+ let started = new ManualResetEventSlim(false)
- let test = async {
- let! timeout = Async.AwaitWaitHandle(wh, 10000)
- Assert.False(timeout, "Timeout expected")
- barrier.Set() |> ignore
+ let test =
+ async {
+ started.Set()
+ let! timeout = Async.AwaitWaitHandle(wh, 5000)
+ Assert.False(timeout, "Timeout expected")
}
- Async.Start test
-
- // await 3 secs then dispose waithandle - nothing should happen
- let timeout = wait barrier 3000
- Assert.False(timeout, "Barrier was reached too early")
- dispose wh
-
- let ok = wait barrier 10000
- if not ok then Assert.Fail("Async computation was not completed in given time")
+ |> Async.StartAsTask
+
+ task {
+ started.Wait()
+ // Wait a moment then dispose waithandle - nothing should happen
+ do! Task.Delay 500
+ Assert.False(test.IsCompleted, "Test completed too early")
+ dispose wh
+ do! test
+ }
[]
member _.``RunSynchronously.NoThreadJumpsAndTimeout``() =
@@ -467,22 +467,24 @@ type AsyncModule() =
[]
member _.``error on one workflow should cancel all others``() =
- let counter =
- async {
- let mutable counter = 0
- let job i = async {
- if i = 55 then failwith "boom"
- else
- do! Async.Sleep 1000
- counter <- counter + 1
- }
-
- let! _ = Async.Parallel [ for i in 1 .. 100 -> job i ] |> Async.Catch
- do! Async.Sleep 5000
- return counter
- } |> Async.RunSynchronously
+ task {
+ use failOnlyOne = new Semaphore(0, 1)
+ let mutable cancelled = 0
+ let mutable started = 0
+
+ let job i = async {
+ Interlocked.Increment &started |> ignore
+ use! holder = Async.OnCancel (fun () -> Interlocked.Increment &cancelled |> ignore)
+ do! failOnlyOne |> Async.AwaitWaitHandle |> Async.Ignore
+ failwith "boom"
+ }
- Assert.AreEqual(0, counter)
+ let test = Async.Parallel [ for i in 1 .. 100 -> job i ] |> Async.Catch |> Async.Ignore |> Async.StartAsTask
+ do! Task.Delay 100
+ failOnlyOne.Release() |> ignore
+ do! test
+ Assert.Equal(started - 1, cancelled)
+ }
[]
member _.``AwaitWaitHandle.ExceptionsAfterTimeout``() =
@@ -641,7 +643,6 @@ type AsyncModule() =
member _.``Parallel with maxDegreeOfParallelism`` () =
let mutable i = 1
let action j = async {
- do! Async.Sleep 1
Assert.Equal(j, i)
i <- i + 1
}
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncType.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncType.fs
index 950432ccc8e..1b15be8fa98 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncType.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncType.fs
@@ -54,16 +54,20 @@ type AsyncType() =
[]
member _.AsyncRunSynchronouslyReusesThreadPoolThread() =
- let action = async { async { () } |> Async.RunSynchronously }
- let computation =
- [| for i in 1 .. 1000 -> action |]
- |> Async.Parallel
+ let action _ =
+ async {
+ return
+ async { return Thread.CurrentThread.ManagedThreadId }
+ |> Async.RunSynchronously
+ }
// This test needs approximately 1000 ThreadPool threads
// if Async.RunSynchronously doesn't reuse them.
- // In such case TimeoutException is raised
- // since ThreadPool cannot provide 1000 threads in 1 second
- // (the number of threads in ThreadPool is adjusted slowly).
- Async.RunSynchronously(computation, timeout = 1000) |> ignore
+ let usedThreads =
+ Seq.init 1000 action
+ |> Async.Parallel
+ |> Async.RunSynchronously
+ |> Set.ofArray
+ Assert.True(usedThreads.Count < 256, $"RunSynchronously used {usedThreads.Count} threads.")
[]
[]
@@ -231,7 +235,8 @@ type AsyncType() =
use t = Async.StartAsTask a
let mutable exceptionThrown = false
try
- waitASec t
+ // waitASec t
+ t.Wait()
with
e -> exceptionThrown <- true
Assert.True (t.IsFaulted)
@@ -269,7 +274,7 @@ type AsyncType() =
// printfn "%A" t.Status
let mutable exceptionThrown = false
try
- waitASec t
+ t.Wait()
with e -> exceptionThrown <- true
Assert.True (exceptionThrown)
Assert.True(t.IsCanceled)
@@ -302,56 +307,50 @@ type AsyncType() =
use t = Async.StartImmediateAsTask a
let mutable exceptionThrown = false
try
- waitASec t
+ t.Wait()
with
e -> exceptionThrown <- true
Assert.True (t.IsFaulted)
Assert.True(exceptionThrown)
-#if IGNORED
[]
- []
member _.CancellationPropagatesToImmediateTask () =
let a = async {
- while true do ()
+ while true do
+ do! Async.Sleep 100
}
use t = Async.StartImmediateAsTask a
Async.CancelDefaultToken ()
let mutable exceptionThrown = false
try
- waitASec t
+ t.Wait()
with e -> exceptionThrown <- true
Assert.True (exceptionThrown)
Assert.True(t.IsCanceled)
-#endif
-#if IGNORED
[]
- []
member _.CancellationPropagatesToGroupImmediate () =
let ewh = new ManualResetEvent(false)
- let cancelled = ref false
+ let mutable cancelled = false
let a = async {
- use! holder = Async.OnCancel (fun _ -> cancelled := true)
+ use! holder = Async.OnCancel (fun _ -> cancelled <- true)
ewh.Set() |> Assert.True
- while true do ()
+ while true do
+ do! Async.Sleep 100
}
let cts = new CancellationTokenSource()
let token = cts.Token
use t =
Async.StartImmediateAsTask(a, cancellationToken=token)
-// printfn "%A" t.Status
ewh.WaitOne() |> Assert.True
cts.Cancel()
-// printfn "%A" t.Status
let mutable exceptionThrown = false
try
- waitASec t
+ t.Wait()
with e -> exceptionThrown <- true
Assert.True (exceptionThrown)
Assert.True(t.IsCanceled)
- Assert.True(!cancelled)
-#endif
+ Assert.True(cancelled)
[]
member _.TaskAsyncValue () =
@@ -411,8 +410,7 @@ type AsyncType() =
}
Async.RunSynchronously(a) |> Assert.True
- // test is flaky: https://github.com/dotnet/fsharp/issues/11586
- //[]
+ []
member _.TaskAsyncValueCancellation () =
use ewh = new ManualResetEvent(false)
let cts = new CancellationTokenSource()
@@ -430,9 +428,11 @@ type AsyncType() =
:? TaskCanceledException ->
ewh.Set() |> ignore // this is ok
}
- Async.Start a
+ let t1 = Async.StartAsTask a
cts.Cancel()
ewh.WaitOne(10000) |> ignore
+ // Don't leave unobserved background tasks, because they can crash the test run.
+ t1.Wait()
[]
member _.NonGenericTaskAsyncValue () =
@@ -473,9 +473,10 @@ type AsyncType() =
:? TaskCanceledException ->
ewh.Set() |> ignore // this is ok
}
- Async.Start a
+ let t1 = Async.StartAsTask a
cts.Cancel()
ewh.WaitOne(10000) |> ignore
+ t1.Wait()
[]
member _.CancellationExceptionThrown () =
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Cancellation.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Cancellation.fs
index 4e04f64bc1f..cecfaec7590 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Cancellation.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Cancellation.fs
@@ -5,7 +5,9 @@ namespace FSharp.Core.UnitTests.Control
open System
open FSharp.Core.UnitTests.LibraryTestFx
open Xunit
+open FSharp.Test
open System.Threading
+open System.Threading.Tasks
type CancellationType() =
@@ -229,6 +231,7 @@ type CancellationType() =
}
asyncs |> Async.Parallel |> Async.RunSynchronously |> ignore
+ // See https://github.com/dotnet/fsharp/issues/3254
[]
member this.AwaitTaskCancellationAfterAsyncTokenCancellation() =
let StartCatchCancellation cancellationToken (work) =
@@ -262,11 +265,11 @@ type CancellationType() =
let cts = new CancellationTokenSource()
let tcs = System.Threading.Tasks.TaskCompletionSource<_>()
- let t =
+ let test() =
async {
do! tcs.Task |> Async.AwaitTask
}
- |> StartAsTaskProperCancel None (Some cts.Token)
+ |> StartAsTaskProperCancel None (Some cts.Token) :> Task
// First cancel the token, then set the task as cancelled.
async {
@@ -274,15 +277,31 @@ type CancellationType() =
cts.Cancel()
do! Async.Sleep 100
tcs.TrySetException (TimeoutException "Task timed out after token.")
- |> ignore
+ |> ignore
} |> Async.Start
- try
- let res = t.Wait(2000)
- let msg = sprintf "Excepted TimeoutException wrapped in an AggregateException, but got %A" res
- printfn "failure msg: %s" msg
- Assert.Fail (msg)
- with :? AggregateException as agg -> ()
+ task {
+ let! agg = Assert.ThrowsAsync(test)
+ let inner = agg.InnerException
+ Assert.True(inner :? TimeoutException, $"Excepted TimeoutException wrapped in an AggregateException, but got %A{inner}")
+ }
+
+ // Simpler regression test for https://github.com/dotnet/fsharp/issues/3254
+ []
+ member this.AwaitTaskCancellationAfterAsyncTokenCancellation2() =
+ let tcs = new TaskCompletionSource()
+ let cts = new CancellationTokenSource()
+ let _ = cts.Token.Register(fun () -> tcs.SetResult 42)
+ Assert.ThrowsAsync( fun () ->
+ Async.StartAsTask(
+ async {
+ cts.CancelAfter 100
+ let! result = tcs.Task |> Async.AwaitTask
+ return result
+ },
+ cancellationToken = cts.Token
+ )
+ )
[]
member this.Equality() =
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/MailboxProcessorType.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/MailboxProcessorType.fs
index 904bc7dc622..f3964aaa78c 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/MailboxProcessorType.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/MailboxProcessorType.fs
@@ -125,7 +125,7 @@ type MailboxProcessorType() =
use mre2 = new ManualResetEventSlim(false)
// https://github.com/dotnet/fsharp/issues/3337
- let cts = new CancellationTokenSource ()
+ use cts = new CancellationTokenSource ()
let addMsg msg =
match result with
@@ -204,25 +204,24 @@ type MailboxProcessorType() =
[]
member this.``Receive Races with Post``() =
- let receiveEv = new ManualResetEvent(false)
- let postEv = new ManualResetEvent(false)
- let finishedEv = new ManualResetEvent(false)
+ let receiveEv = new AutoResetEvent(false)
+ let postEv = new AutoResetEvent(false)
+ let finishedEv = new AutoResetEvent(false)
+ use cts = new CancellationTokenSource()
let mb =
MailboxProcessor.Start (
fun inbox -> async {
while true do
- let w = receiveEv.WaitOne()
- receiveEv.Reset() |> ignore
+ receiveEv.WaitOne() |> ignore
let! (msg) = inbox.Receive ()
finishedEv.Set() |> ignore
})
let post =
async {
- while true do
- let r = postEv.WaitOne()
- postEv.Reset() |> ignore
+ while not cts.IsCancellationRequested do
+ postEv.WaitOne() |> ignore
mb.Post(fun () -> ())
- } |> Async.Start
+ } |> Async.StartAsTask
for i in 0 .. 100000 do
if i % 2 = 0 then
receiveEv.Set() |> ignore
@@ -232,19 +231,23 @@ type MailboxProcessorType() =
receiveEv.Set() |> ignore
finishedEv.WaitOne() |> ignore
- finishedEv.Reset() |> ignore
+
+ cts.Cancel()
+ // Let the post task finish.
+ postEv.Set() |> ignore
+ post.Wait()
[]
member this.``Receive Races with Post on timeout``() =
- let receiveEv = new ManualResetEvent(false)
- let postEv = new ManualResetEvent(false)
- let finishedEv = new ManualResetEvent(false)
+ let receiveEv = new AutoResetEvent(false)
+ let postEv = new AutoResetEvent(false)
+ let finishedEv = new AutoResetEvent(false)
+ use cts = new CancellationTokenSource()
let mb =
MailboxProcessor.Start (
fun inbox -> async {
while true do
- let w = receiveEv.WaitOne()
- receiveEv.Reset() |> ignore
+ receiveEv.WaitOne() |> ignore
let! (msg) = inbox.Receive (5000)
finishedEv.Set() |> ignore
})
@@ -252,12 +255,11 @@ type MailboxProcessorType() =
let isErrored = mb.Error |> Async.AwaitEvent |> Async.StartAsTask
let post =
- async {
- while true do
- let r = postEv.WaitOne()
- postEv.Reset() |> ignore
+ backgroundTask {
+ while not cts.IsCancellationRequested do
+ postEv.WaitOne() |> ignore
mb.Post(fun () -> ())
- } |> Async.Start
+ }
for i in 0 .. 10000 do
if i % 2 = 0 then
@@ -271,32 +273,35 @@ type MailboxProcessorType() =
if isErrored.IsCompleted then
raise <| Exception("Mailbox should not fail!", isErrored.Result)
- finishedEv.Reset() |> ignore
+ cts.Cancel()
+ // Let the post task finish.
+ postEv.Set() |> ignore
+ post.Wait()
[]
member this.``TryReceive Races with Post on timeout``() =
- let receiveEv = new ManualResetEvent(false)
- let postEv = new ManualResetEvent(false)
- let finishedEv = new ManualResetEvent(false)
+ let receiveEv = new AutoResetEvent(false)
+ let postEv = new AutoResetEvent(false)
+ let finishedEv = new AutoResetEvent(false)
+ use cts = new CancellationTokenSource()
let mb =
MailboxProcessor.Start (
fun inbox -> async {
while true do
- let w = receiveEv.WaitOne()
- receiveEv.Reset() |> ignore
+ receiveEv.WaitOne() |> ignore
let! (msg) = inbox.TryReceive (5000)
finishedEv.Set() |> ignore
- })
+ }
+ )
let isErrored = mb.Error |> Async.AwaitEvent |> Async.StartAsTask
let post =
- async {
- while true do
- let r = postEv.WaitOne()
- postEv.Reset() |> ignore
+ backgroundTask {
+ while not cts.IsCancellationRequested do
+ postEv.WaitOne() |> ignore
mb.Post(fun () -> ())
- } |> Async.Start
+ }
for i in 0 .. 10000 do
if i % 2 = 0 then
@@ -310,7 +315,9 @@ type MailboxProcessorType() =
if isErrored.IsCompleted then
raise <| Exception("Mailbox should not fail!", isErrored.Result)
- finishedEv.Reset() |> ignore
+ cts.Cancel()
+ postEv.Set() |> ignore
+ post.Wait()
[]
member this.``After dispose is called, mailbox should stop receiving and processing messages``() = task {
@@ -397,6 +404,7 @@ type MailboxProcessorType() =
Assert.Equal(expectedMessagesCount, actualMessagesCount)
Assert.Equal(0, actualSkipMessagesCount)
Assert.Equal(0, mb.CurrentQueueLength)
+
}
[]
@@ -496,3 +504,56 @@ type MailboxProcessorType() =
// If StartImmediate worked correctly, the information should be identical since
// the threads should be the same.
Assert.Equal(callingThreadInfo, mailboxThreadInfo)
+
+module MailboxProcessorType =
+
+ []
+ let TryScan () =
+ let tcs = TaskCompletionSource<_>()
+ use mailbox =
+ new MailboxProcessor(fun inbox -> async {
+ do!
+ inbox.TryScan( function
+ | Reset -> async { tcs.SetResult "Reset processed" } |> Some
+ | _ -> None)
+ |> Async.Ignore
+ })
+ mailbox.Start()
+
+ for i in 1 .. 100 do
+ mailbox.Post(Increment i)
+ mailbox.Post Reset
+
+ Assert.Equal("Reset processed", tcs.Task.Result)
+ Assert.Equal(100, mailbox.CurrentQueueLength)
+
+ []
+ let ``TryScan with timeout`` () =
+ let tcs = TaskCompletionSource<_>()
+ use mailbox =
+ new MailboxProcessor(fun inbox ->
+ let rec loop i = async {
+ match!
+ inbox.TryScan( function
+ | Reset -> async { tcs.SetResult i } |> Some
+ | _ -> None)
+ with
+ | None -> do! loop (i + 1)
+ | _ -> ()
+ }
+ loop 1
+ )
+ mailbox.DefaultTimeout <- 10
+ mailbox.Start()
+
+ let iteration =
+ task {
+ for i in 1 .. 100 do
+ mailbox.Post(Increment 1)
+ do! Task.Delay 10
+ mailbox.Post Reset
+
+ return! tcs.Task
+ }
+
+ Assert.True(iteration.Result > 1, "TryScan did not timeout")
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs
index 5d533b880c3..8097c2d10f5 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs
@@ -236,15 +236,16 @@ type Basics() =
[]
member _.testNonBlocking() =
printfn "Running testNonBlocking..."
- let sw = Stopwatch()
- sw.Start()
+ let allowContinue = new SemaphoreSlim(0)
+ let finished = new ManualResetEventSlim()
let t =
task {
- do! Task.Yield()
+ do! allowContinue.WaitAsync()
Thread.Sleep(100)
+ finished.Set()
}
- sw.Stop()
- require (sw.ElapsedMilliseconds < 50L) "sleep blocked caller"
+ allowContinue.Release() |> ignore
+ require (not finished.IsSet) "sleep blocked caller"
t.Wait()
[]
@@ -908,58 +909,60 @@ type Basics() =
[]
member _.testExceptionThrownInFinally() =
printfn "running testExceptionThrownInFinally"
- for i in 1 .. 5 do
- let mutable ranInitial = false
- let mutable ranNext = false
+ for i in 1 .. 5 do
+ use stepOutside = new SemaphoreSlim(0)
+ use ranInitial = new ManualResetEventSlim()
+ use ranNext = new ManualResetEventSlim()
let mutable ranFinally = 0
let t =
task {
try
- ranInitial <- true
+ ranInitial.Set()
do! Task.Yield()
Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes
- ranNext <- true
+ ranNext.Set()
finally
ranFinally <- ranFinally + 1
failtest "finally exn!"
}
- require ranInitial "didn't run initial"
- require (not ranNext) "ran next too early"
+ require ranInitial.IsSet "didn't run initial"
+ require (not ranNext.IsSet) "ran next too early"
try
t.Wait()
require false "shouldn't get here"
with
| _ -> ()
- require ranNext "didn't run next"
+ require ranNext.IsSet "didn't run next"
require (ranFinally = 1) "didn't run finally exactly once"
[]
member _.test2ndExceptionThrownInFinally() =
printfn "running test2ndExceptionThrownInFinally"
for i in 1 .. 5 do
- let mutable ranInitial = false
- let mutable ranNext = false
+ use ranInitial = new ManualResetEventSlim()
+ use continueTask = new SemaphoreSlim(0)
+ use ranNext = new ManualResetEventSlim()
let mutable ranFinally = 0
let t =
task {
try
- ranInitial <- true
+ ranInitial.Set()
+ do! continueTask.WaitAsync()
+ ranNext.Set()
do! Task.Yield()
- Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes
- ranNext <- true
failtest "uhoh"
finally
ranFinally <- ranFinally + 1
failtest "2nd exn!"
}
- require ranInitial "didn't run initial"
- require (not ranNext) "ran next too early"
+ ranInitial.Wait()
+ continueTask.Release() |> ignore
try
t.Wait()
require false "shouldn't get here"
with
| _ -> ()
- require ranNext "didn't run next"
+ require ranNext.IsSet "didn't run next"
require (ranFinally = 1) "didn't run finally exactly once"
[]
diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs
index c811aecaa5c..7f844e99d96 100644
--- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs
+++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs
@@ -357,15 +357,16 @@ type Basics() =
[]
member _.testNonBlocking() =
printfn "Running testNonBlocking..."
- let sw = Stopwatch()
- sw.Start()
+ let allowContinue = new SemaphoreSlim(0)
+ let finished = new ManualResetEventSlim()
let t =
taskDynamic {
- do! Task.Yield()
+ do! allowContinue.WaitAsync()
Thread.Sleep(100)
+ finished.Set()
}
- sw.Stop()
- require (sw.ElapsedMilliseconds < 50L) "sleep blocked caller"
+ allowContinue.Release() |> ignore
+ require (not finished.IsSet) "sleep blocked caller"
t.Wait()
[]
@@ -982,58 +983,60 @@ type Basics() =
[]
member _.testExceptionThrownInFinally() =
printfn "running testExceptionThrownInFinally"
- for i in 1 .. 5 do
- let mutable ranInitial = false
- let mutable ranNext = false
+ for i in 1 .. 5 do
+ use stepOutside = new SemaphoreSlim(0)
+ use ranInitial = new ManualResetEventSlim()
+ use ranNext = new ManualResetEventSlim()
let mutable ranFinally = 0
let t =
taskDynamic {
try
- ranInitial <- true
+ ranInitial.Set()
do! Task.Yield()
Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes
- ranNext <- true
+ ranNext.Set()
finally
ranFinally <- ranFinally + 1
failtest "finally exn!"
}
- require ranInitial "didn't run initial"
- require (not ranNext) "ran next too early"
+ require ranInitial.IsSet "didn't run initial"
+ require (not ranNext.IsSet) "ran next too early"
try
t.Wait()
require false "shouldn't get here"
with
| _ -> ()
- require ranNext "didn't run next"
+ require ranNext.IsSet "didn't run next"
require (ranFinally = 1) "didn't run finally exactly once"
[]
member _.test2ndExceptionThrownInFinally() =
printfn "running test2ndExceptionThrownInFinally"
for i in 1 .. 5 do
- let mutable ranInitial = false
- let mutable ranNext = false
+ use ranInitial = new ManualResetEventSlim()
+ use continueTask = new SemaphoreSlim(0)
+ use ranNext = new ManualResetEventSlim()
let mutable ranFinally = 0
let t =
taskDynamic {
try
- ranInitial <- true
+ ranInitial.Set()
+ do! continueTask.WaitAsync()
+ ranNext.Set()
do! Task.Yield()
- Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes
- ranNext <- true
failtest "uhoh"
finally
ranFinally <- ranFinally + 1
failtest "2nd exn!"
}
- require ranInitial "didn't run initial"
- require (not ranNext) "ran next too early"
+ ranInitial.Wait()
+ continueTask.Release() |> ignore
try
t.Wait()
require false "shouldn't get here"
with
| _ -> ()
- require ranNext "didn't run next"
+ require ranNext.IsSet "didn't run next"
require (ranFinally = 1) "didn't run finally exactly once"
[]
diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs
index f535bc21c5a..5e5629b089f 100644
--- a/tests/FSharp.Test.Utilities/Compiler.fs
+++ b/tests/FSharp.Test.Utilities/Compiler.fs
@@ -170,10 +170,13 @@ module rec Compiler =
Message: string
SubCategory: string }
+ // This type is used either for the output of the compiler (typically in CompilationResult coming from 'compile')
+ // or for the output of the code generated by the compiler (in CompilationResult coming from 'run')
type ExecutionOutput =
- { ExitCode: int
+ { ExitCode: int option
StdOut: string
- StdErr: string }
+ StdErr: string
+ Exn: exn option }
type RunOutput =
| EvalOutput of Result
@@ -699,7 +702,7 @@ module rec Compiler =
let private compileFSharpCompilation compilation ignoreWarnings (cUnit: CompilationUnit) : CompilationResult =
use redirect = new RedirectConsole()
- let ((err: FSharpDiagnostic[], rc: int, outputFilePath: string), deps) =
+ let ((err: FSharpDiagnostic[], exn, outputFilePath: string), deps) =
CompilerAssert.CompileRaw(compilation, ignoreWarnings)
// Create and stash the console output
@@ -711,7 +714,7 @@ module rec Compiler =
Adjust = 0
PerFileErrors = diagnostics
Diagnostics = diagnostics |> List.map snd
- Output = Some (RunOutput.ExecutionOutput { ExitCode = rc; StdOut = redirect.Output(); StdErr = redirect.ErrorOutput() })
+ Output = Some (RunOutput.ExecutionOutput { ExitCode = None; StdOut = redirect.Output(); StdErr = redirect.ErrorOutput(); Exn = exn })
Compilation = cUnit
}
@@ -978,14 +981,13 @@ module rec Compiler =
| SourceCodeFileKind.Fsx _ -> true
| _ -> false
| _ -> false
- let exitCode, output, errors = CompilerAssert.ExecuteAndReturnResult (p, isFsx, s.Dependencies, false)
+ let exitCode, output, errors, exn = CompilerAssert.ExecuteAndReturnResult (p, isFsx, s.Dependencies, false)
printfn "---------output-------\n%s\n-------" output
printfn "---------errors-------\n%s\n-------" errors
- let executionResult = { s with Output = Some (ExecutionOutput { ExitCode = exitCode; StdOut = output; StdErr = errors }) }
- if exitCode = 0 then
- CompilationResult.Success executionResult
- else
- CompilationResult.Failure executionResult
+ let executionResult = { s with Output = Some (ExecutionOutput { ExitCode = exitCode; StdOut = output; StdErr = errors; Exn = exn }) }
+ match exn with
+ | None -> CompilationResult.Success executionResult
+ | Some _ -> CompilationResult.Failure executionResult
let compileAndRun = compile >> run
@@ -1080,27 +1082,25 @@ module rec Compiler =
opts.ToArray()
let errors, stdOut = CompilerAssert.RunScriptWithOptionsAndReturnResult options source
- let executionOutputwithStdOut: RunOutput option =
- ExecutionOutput { StdOut = stdOut; ExitCode = 0; StdErr = "" }
- |> Some
- let result =
+ let mkResult output =
{ OutputPath = None
Dependencies = []
Adjust = 0
Diagnostics = []
PerFileErrors= []
- Output = executionOutputwithStdOut
+ Output = Some output
Compilation = cUnit }
-
- if errors.Count > 0 then
- let output = ExecutionOutput {
- ExitCode = -1
- StdOut = String.Empty
- StdErr = ((errors |> String.concat "\n").Replace("\r\n","\n")) }
- CompilationResult.Failure { result with Output = Some output }
+
+ if errors.Count = 0 then
+ let output =
+ ExecutionOutput { ExitCode = None; StdOut = stdOut; StdErr = ""; Exn = None }
+ CompilationResult.Success (mkResult output)
else
- CompilationResult.Success result
-
+ let err = (errors |> String.concat "\n").Replace("\r\n","\n")
+ let output =
+ ExecutionOutput {ExitCode = None; StdOut = String.Empty; StdErr = err; Exn = None }
+ CompilationResult.Failure (mkResult output)
+
finally
disposals
|> Seq.iter (fun x -> x.Dispose())
@@ -1190,7 +1190,7 @@ Actual:
| Some p ->
match ILChecker.verifyILAndReturnActual [] p expected with
| true, _, _ -> result
- | false, errorMsg, _actualIL -> CompilationResult.Failure( {s with Output = Some (ExecutionOutput { StdOut = errorMsg; ExitCode = 0; StdErr = "" })} )
+ | false, errorMsg, _actualIL -> CompilationResult.Failure( {s with Output = Some (ExecutionOutput {ExitCode = None; StdOut = errorMsg; StdErr = ""; Exn = None })} )
| CompilationResult.Failure f -> failwith $"Result should be \"Success\" in order to get IL. Failure: {Environment.NewLine}{f}"
@@ -1706,7 +1706,7 @@ Actual:
| None -> failwith "Execution output is missing, cannot check exit code."
| Some o ->
match o with
- | ExecutionOutput e -> Assert.Equal(expectedExitCode, e.ExitCode)
+ | ExecutionOutput {ExitCode = Some exitCode} -> Assert.Equal(expectedExitCode, exitCode)
| _ -> failwith "Cannot check exit code on this run result."
result
diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs
index fc2875d8955..37a8e25e164 100644
--- a/tests/FSharp.Test.Utilities/CompilerAssert.fs
+++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs
@@ -322,7 +322,7 @@ module rec CompilerAssertHelpers =
else
entryPoint
let args = mkDefaultArgs entryPoint
- captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args) |> ignore)
+ captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args))
#if NETCOREAPP
let executeBuiltApp assembly deps isFsx =
@@ -409,8 +409,8 @@ module rec CompilerAssertHelpers =
// Generate a response file, purely for diagnostic reasons.
File.WriteAllLines(Path.ChangeExtension(outputFilePath, ".rsp"), args)
- let errors, rc = checker.Compile args |> Async.RunImmediate
- errors, rc, outputFilePath
+ let errors, ex = checker.Compile args |> Async.RunImmediate
+ errors, ex, outputFilePath
let compileDisposable (outputDirectory:DirectoryInfo) isExe options targetFramework nameOpt (sources:SourceCodeFileKind list) =
let disposeFile path =
@@ -537,7 +537,7 @@ module rec CompilerAssertHelpers =
let tmp = Path.Combine(outputPath.FullName, Path.ChangeExtension(fileName, ".dll"))
disposals.Add({ new IDisposable with member _.Dispose() = File.Delete tmp })
cmpl.EmitAsFile tmp
- (([||], 0, tmp), []), false)
+ (([||], None, tmp), []), false)
let compilationRefs =
compiledRefs
@@ -559,7 +559,7 @@ module rec CompilerAssertHelpers =
compilationRefs, deps
- let compileCompilationAux outputDirectory (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * int * string) * string list =
+ let compileCompilationAux outputDirectory (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * exn option * string) * string list =
let compilationRefs, deps = evaluateReferences outputDirectory disposals ignoreWarnings cmpl
let isExe, sources, options, targetFramework, name =
@@ -604,7 +604,7 @@ module rec CompilerAssertHelpers =
outputDirectory.Create()
compileCompilationAux outputDirectory (ResizeArray()) ignoreWarnings cmpl
- let captureConsoleOutputs (func: unit -> unit) =
+ let captureConsoleOutputs (func: unit -> obj) =
let out = Console.Out
let err = Console.Error
@@ -614,29 +614,30 @@ module rec CompilerAssertHelpers =
use outWriter = new StringWriter (stdout)
use errWriter = new StringWriter (stderr)
- let succeeded, exn =
+ let rc, exn =
try
try
Console.SetOut outWriter
Console.SetError errWriter
- func ()
- true, None
+ let rc = func()
+ match rc with
+ | :? int as rc -> Some rc, None
+ | _ -> None, None
with e ->
let errorMessage = if e.InnerException <> null then e.InnerException.ToString() else e.ToString()
stderr.Append errorMessage |> ignore
- false, Some e
+ None, Some e
finally
Console.SetOut out
Console.SetError err
outWriter.Close()
errWriter.Close()
- succeeded, stdout.ToString(), stderr.ToString(), exn
+ rc, stdout.ToString(), stderr.ToString(), exn
- let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) isFsx : (int * string * string) =
- let succeeded, stdout, stderr, _ = executeBuiltApp outputFilePath deps isFsx
- let exitCode = if succeeded then 0 else -1
- exitCode, stdout, stderr
+ let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) isFsx : (int option * string * string * exn option) =
+ let rc, stdout, stderr, exn = executeBuiltApp outputFilePath deps isFsx
+ rc, stdout, stderr, exn
let executeBuiltAppNewProcessAndReturnResult (outputFilePath: string) : (int * string * string) =
#if !NETCOREAPP
@@ -663,7 +664,7 @@ module rec CompilerAssertHelpers =
member _.Dispose() = try File.Delete runtimeconfigPath with | _ -> () }
#endif
let timeout = 30000
- let exitCode, output, errors = Commands.executeProcess (Some fileName) arguments (Path.GetDirectoryName(outputFilePath)) timeout
+ let exitCode, output, errors = Commands.executeProcess fileName arguments (Path.GetDirectoryName(outputFilePath)) timeout
(exitCode, output |> String.concat "\n", errors |> String.concat "\n")
open CompilerAssertHelpers
@@ -677,7 +678,7 @@ type CompilerAssert private () =
if errors.Length > 0 then
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)
- executeBuiltApp outputExe [] false |> ignore
+ executeBuiltApp outputExe [] false |> ignore
)
static let compileLibraryAndVerifyILWithOptions options (source: SourceCodeFileKind) (f: ILVerifier -> unit) =
@@ -739,11 +740,13 @@ Updated automatically, please check diffs in your pull request, changes must be
returnCompilation cmpl (defaultArg ignoreWarnings false)
static member ExecuteAndReturnResult (outputFilePath: string, isFsx: bool, deps: string list, newProcess: bool) =
- // If we execute in-process (true by default), then the only way of getting STDOUT is to redirect it to SB, and STDERR is from catching an exception.
if not newProcess then
- executeBuiltAppAndReturnResult outputFilePath deps isFsx
+ let entryPointReturnCode, deps, isFsx, exn = executeBuiltAppAndReturnResult outputFilePath deps isFsx
+ entryPointReturnCode, deps, isFsx, exn
else
- executeBuiltAppNewProcessAndReturnResult outputFilePath
+ let processExitCode, deps, isFsx = executeBuiltAppNewProcessAndReturnResult outputFilePath
+ Some processExitCode, deps, isFsx, None
+
static member Execute(cmpl: Compilation, ?ignoreWarnings, ?beforeExecute, ?newProcess, ?onOutput) =
@@ -767,7 +770,7 @@ Updated automatically, please check diffs in your pull request, changes must be
Assert.Fail errors
onOutput output
else
- let _succeeded, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false
+ let _rc, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false
exn |> Option.iter raise)
static member ExecutionHasOutput(cmpl: Compilation, expectedOutput: string) =
diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs
index 4474ef01c10..de0fbd8050b 100644
--- a/tests/FSharp.Test.Utilities/ILChecker.fs
+++ b/tests/FSharp.Test.Utilities/ILChecker.fs
@@ -16,7 +16,7 @@ module ILChecker =
let private exec exe args =
let arguments = args |> String.concat " "
let timeout = 30000
- let exitCode, _output, errors = Commands.executeProcess (Some exe) arguments "" timeout
+ let exitCode, _output, errors = Commands.executeProcess exe arguments "" timeout
let errors = errors |> String.concat Environment.NewLine
errors, exitCode
diff --git a/tests/FSharp.Test.Utilities/Peverifier.fs b/tests/FSharp.Test.Utilities/Peverifier.fs
index 35db5b208fb..f3ccc7de2b1 100644
--- a/tests/FSharp.Test.Utilities/Peverifier.fs
+++ b/tests/FSharp.Test.Utilities/Peverifier.fs
@@ -25,7 +25,7 @@ module PEVerifier =
let private exec exe args =
let arguments = args |> String.concat " "
let timeout = 30000
- let exitCode, _output, errors = Commands.executeProcess (Some exe) arguments "" timeout
+ let exitCode, _output, errors = Commands.executeProcess exe arguments "" timeout
let errors = errors |> String.concat Environment.NewLine
errors, exitCode
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 78feb049435..a75784240dd 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -1360,9 +1360,8 @@ type ProjectWorkflowBuilder
yield! projectOptions.OtherOptions
yield! projectOptions.SourceFiles
|]
- let! _diagnostics, exitCode = checker.Compile(arguments)
- if exitCode <> 0 then
- exn $"Compilation failed with exit code {exitCode}" |> raise
+ let! _diagnostics, ex = checker.Compile(arguments)
+ if ex.IsSome then raise ex.Value
return ctx
}
diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs
index 6e1611beb5c..dfde63f2352 100644
--- a/tests/FSharp.Test.Utilities/TestFramework.fs
+++ b/tests/FSharp.Test.Utilities/TestFramework.fs
@@ -63,69 +63,66 @@ module Commands =
// Execute the process pathToExe passing the arguments: arguments with the working directory: workingDir timeout after timeout milliseconds -1 = wait forever
// returns exit code, stdio and stderr as string arrays
let executeProcess pathToExe arguments workingDir (timeout:int) =
- match pathToExe with
- | Some path ->
- let commandLine = ResizeArray()
- let errorsList = ResizeArray()
- let outputList = ResizeArray()
- let errorslock = obj()
- let outputlock = obj()
- let outputDataReceived (message: string) =
- if not (isNull message) then
- lock outputlock (fun () -> outputList.Add(message))
-
- let errorDataReceived (message: string) =
- if not (isNull message) then
- lock errorslock (fun () -> errorsList.Add(message))
-
- commandLine.Add $"cd {workingDir}"
- commandLine.Add $"{path} {arguments} /bl"
-
- let psi = ProcessStartInfo()
- psi.FileName <- path
- psi.WorkingDirectory <- workingDir
- psi.RedirectStandardOutput <- true
- psi.RedirectStandardError <- true
- psi.Arguments <- arguments
- psi.CreateNoWindow <- true
- // When running tests, we want to roll forward to minor versions (including previews).
- psi.EnvironmentVariables["DOTNET_ROLL_FORWARD"] <- "LatestMajor"
- psi.EnvironmentVariables["DOTNET_ROLL_FORWARD_TO_PRERELEASE"] <- "1"
- psi.EnvironmentVariables.Remove("MSBuildSDKsPath") // Host can sometimes add this, and it can break things
- psi.UseShellExecute <- false
-
- use p = new Process()
- p.StartInfo <- psi
-
- p.OutputDataReceived.Add(fun a -> outputDataReceived a.Data)
- p.ErrorDataReceived.Add(fun a -> errorDataReceived a.Data)
-
- if p.Start() then
- p.BeginOutputReadLine()
- p.BeginErrorReadLine()
- if not(p.WaitForExit(timeout)) then
- // Timed out resolving throw a diagnostic.
- raise (new TimeoutException(sprintf "Timeout executing command '%s' '%s'" (psi.FileName) (psi.Arguments)))
- else
- p.WaitForExit()
- #if DEBUG
- let workingDir' =
- if workingDir = ""
- then
- // Assign working dir to prevent default to C:\Windows\System32
- let executionLocation = Assembly.GetExecutingAssembly().Location
- Path.GetDirectoryName executionLocation
- else
- workingDir
-
- lock gate (fun () ->
- File.WriteAllLines(Path.Combine(workingDir', "commandline.txt"), commandLine)
- File.WriteAllLines(Path.Combine(workingDir', "StandardOutput.txt"), outputList)
- File.WriteAllLines(Path.Combine(workingDir', "StandardError.txt"), errorsList)
- )
- #endif
- p.ExitCode, outputList.ToArray(), errorsList.ToArray()
- | None -> -1, Array.empty, Array.empty
+ let commandLine = ResizeArray()
+ let errorsList = ResizeArray()
+ let outputList = ResizeArray()
+ let errorslock = obj()
+ let outputlock = obj()
+ let outputDataReceived (message: string) =
+ if not (isNull message) then
+ lock outputlock (fun () -> outputList.Add(message))
+
+ let errorDataReceived (message: string) =
+ if not (isNull message) then
+ lock errorslock (fun () -> errorsList.Add(message))
+
+ commandLine.Add $"cd {workingDir}"
+ commandLine.Add $"{pathToExe} {arguments} /bl"
+
+ let psi = ProcessStartInfo()
+ psi.FileName <- pathToExe
+ psi.WorkingDirectory <- workingDir
+ psi.RedirectStandardOutput <- true
+ psi.RedirectStandardError <- true
+ psi.Arguments <- arguments
+ psi.CreateNoWindow <- true
+ // When running tests, we want to roll forward to minor versions (including previews).
+ psi.EnvironmentVariables["DOTNET_ROLL_FORWARD"] <- "LatestMajor"
+ psi.EnvironmentVariables["DOTNET_ROLL_FORWARD_TO_PRERELEASE"] <- "1"
+ psi.EnvironmentVariables.Remove("MSBuildSDKsPath") // Host can sometimes add this, and it can break things
+ psi.UseShellExecute <- false
+
+ use p = new Process()
+ p.StartInfo <- psi
+
+ p.OutputDataReceived.Add(fun a -> outputDataReceived a.Data)
+ p.ErrorDataReceived.Add(fun a -> errorDataReceived a.Data)
+
+ if p.Start() then
+ p.BeginOutputReadLine()
+ p.BeginErrorReadLine()
+ if not(p.WaitForExit(timeout)) then
+ // Timed out resolving throw a diagnostic.
+ raise (new TimeoutException(sprintf "Timeout executing command '%s' '%s'" (psi.FileName) (psi.Arguments)))
+ else
+ p.WaitForExit()
+#if DEBUG
+ let workingDir' =
+ if workingDir = ""
+ then
+ // Assign working dir to prevent default to C:\Windows\System32
+ let executionLocation = Assembly.GetExecutingAssembly().Location
+ Path.GetDirectoryName executionLocation
+ else
+ workingDir
+
+ lock gate (fun () ->
+ File.WriteAllLines(Path.Combine(workingDir', "commandline.txt"), commandLine)
+ File.WriteAllLines(Path.Combine(workingDir', "StandardOutput.txt"), outputList)
+ File.WriteAllLines(Path.Combine(workingDir', "StandardError.txt"), errorsList)
+ )
+#endif
+ p.ExitCode, outputList.ToArray(), errorsList.ToArray()
let getfullpath workDir (path:string) =
let rooted =
diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs
index 6ed885d4e44..1a6d0ff60f8 100644
--- a/tests/FSharp.Test.Utilities/Utilities.fs
+++ b/tests/FSharp.Test.Utilities/Utilities.fs
@@ -245,7 +245,7 @@ let main argv = 0"""
File.WriteAllText(directoryBuildTargetsFileName, directoryBuildTargets)
let timeout = 120000
- let exitCode, dotnetoutput, dotneterrors = Commands.executeProcess (Some config.DotNetExe) "build" projectDirectory timeout
+ let exitCode, dotnetoutput, dotneterrors = Commands.executeProcess config.DotNetExe "build" projectDirectory timeout
if exitCode <> 0 || errors.Length > 0 then
errors <- dotneterrors
diff --git a/tests/fsharp/Compiler/Libraries/Core/Async/AsyncTests.fs b/tests/fsharp/Compiler/Libraries/Core/Async/AsyncTests.fs
index 708e7e58e2e..3b83b97db7a 100644
--- a/tests/fsharp/Compiler/Libraries/Core/Async/AsyncTests.fs
+++ b/tests/fsharp/Compiler/Libraries/Core/Async/AsyncTests.fs
@@ -8,7 +8,7 @@ open FSharp.Test
module AsyncTests =
// Regression for FSHARP1.0:5969
// Async.StartChild: error when wait async is executed more than once
- []
+ []
let ``Execute Async multiple times``() =
CompilerAssert.CompileExeAndRun
"""
@@ -24,13 +24,12 @@ let a = async {
return result
} |> Async.RunSynchronously
-exit 0
"""
// Regression for FSHARP1.0:5970
// Async.StartChild: race in implementation of ResultCell in FSharp.Core
- []
+ []
let ``Joining StartChild``() =
CompilerAssert.CompileExeAndRun
"""
@@ -54,12 +53,10 @@ let r =
with _ ->
(0,0)
-exit 0
-
"""
// Regression test for FSHARP1.0:6086
- []
+ []
let ``Mailbox Async dot not StackOverflow``() =
CompilerAssert.CompileExeAndRun
"""
@@ -128,12 +125,11 @@ for meet in meets do
printfn "%d" meet
printfn "Total: %d in %O" (Seq.sum meets) (watch.Elapsed)
-exit 0
"""
// Regression for FSHARP1.0:5971
- []
+ []
let ``StartChild do not throw ObjectDisposedException``() =
CompilerAssert.CompileExeAndRun
"""
@@ -142,10 +138,9 @@ module M
let b = async {return 5} |> Async.StartChild
printfn "%A" (b |> Async.RunSynchronously |> Async.RunSynchronously)
-exit 0
"""
- []
+ []
let ``StartChild test Trampoline HijackLimit``() =
CompilerAssert.CompileExeAndRun
"""
@@ -164,5 +159,4 @@ let r =
()
} |> Async.RunSynchronously
-exit 0
"""
diff --git a/tests/fsharp/core/controlMailbox/test.fsx b/tests/fsharp/core/controlMailbox/test.fsx
index 98d6a7d2f31..5aa65035ecd 100644
--- a/tests/fsharp/core/controlMailbox/test.fsx
+++ b/tests/fsharp/core/controlMailbox/test.fsx
@@ -6,9 +6,7 @@ module Core_controlMailBox
#nowarn "40" // recursive references
-#if NETCOREAPP
open System.Threading.Tasks
-#endif
let biggerThanTrampoliningLimit = 10000
@@ -49,22 +47,27 @@ let checkQuiet s x1 x2 =
(test s false;
log (sprintf "expected: %A, got %A" x2 x1))
-let check s x1 x2 =
+let check s x1 x2 =
if x1 = x2 then test s true
else (test s false; log (sprintf "expected: %A, got %A" x2 x1))
+let checkAsync s (x1: Task<_>) x2 = check s x1.Result x2
+
open Microsoft.FSharp.Control
-open Microsoft.FSharp.Control.WebExtensions
module MailboxProcessorBasicTests =
+
let test() =
check
"c32398u6: MailboxProcessor null"
- (let mb1 = new MailboxProcessor(fun inbox -> async { return () })
- mb1.Start();
- 100)
- 100
+ (
+ let mb1 = new MailboxProcessor(fun inbox -> async { return () })
+ mb1.Start()
+ 100
+ )
+
+ 100
check
"c32398u7: MailboxProcessor Receive/PostAndReply"
@@ -197,9 +200,10 @@ module MailboxProcessorBasicTests =
200
for n in [0; 1; 100; 1000; 100000 ] do
- check
+ checkAsync
(sprintf "c32398u: MailboxProcessor Post/Receive, n=%d" n)
- (let received = ref 0
+ (task {
+ let received = ref 0
let mb1 = new MailboxProcessor(fun inbox ->
async { for i in 0 .. n-1 do
let! _ = inbox.Receive()
@@ -208,48 +212,37 @@ module MailboxProcessorBasicTests =
for i in 0 .. n-1 do
mb1.Post(i)
while !received < n do
- if !received % 100 = 0 then
- printfn "received = %d" !received
-#if NETCOREAPP
- Task.Delay(1).Wait()
-#else
- System.Threading.Thread.Sleep(1)
-#endif
- !received)
+ do! Task.Yield()
+ return !received})
n
for timeout in [0; 10] do
for n in [0; 1; 100] do
- check
+ checkAsync
(sprintf "c32398u: MailboxProcessor Post/TryReceive, n=%d, timeout=%d" n timeout)
- (let received = ref 0
+ (task {
+ let received = ref 0
let mb1 = new MailboxProcessor(fun inbox ->
async { while !received < n do
- let! msgOpt = inbox.TryReceive(timeout=timeout)
- match msgOpt with
- | None ->
- do if !received % 100 = 0 then
- printfn "timeout!, received = %d" !received
- | Some _ -> do incr received })
+ match! inbox.TryReceive(timeout=timeout) with
+ | Some _ -> incr received
+ | _ -> ()
+ })
+
+ mb1.Post(0)
+
mb1.Start();
for i in 0 .. n-1 do
-#if NETCOREAPP
- Task.Delay(1).Wait();
-#else
- System.Threading.Thread.Sleep(1)
-#endif
mb1.Post(i)
+ do! Task.Yield()
while !received < n do
- if !received % 100 = 0 then
- printfn "main thread: received = %d" !received
-#if NETCOREAPP
- Task.Delay(1).Wait();
-#else
- System.Threading.Thread.Sleep(1)
-#endif
- !received)
+ do! Task.Yield()
+ return !received})
n
+
+(* Disabled for timing issues. Some replacement TryScan tests were added to FSharp.Core.UnitTests.
+
for i in 1..10 do
for sleep in [0;1;10] do
for timeout in [10;1;0] do
@@ -284,8 +277,11 @@ module MailboxProcessorBasicTests =
!timedOut)
(Some true)
- check "cf72361: MailboxProcessor TryScan wo/timeout"
- (let timedOut = ref None
+*)
+
+ checkAsync "cf72361: MailboxProcessor TryScan wo/timeout"
+ (task {
+ let timedOut = ref None
let mb = new MailboxProcessor(fun inbox ->
async {
let! result = inbox.TryScan((fun i -> if i then async { return () } |> Some else None))
@@ -298,65 +294,58 @@ module MailboxProcessorBasicTests =
w.Start()
while w.ElapsedMilliseconds < 100L do
mb.Post(false)
-#if NETCOREAPP
- Task.Delay(0).Wait();
-#else
- System.Threading.Thread.Sleep(0)
-#endif
+ do! Task.Yield()
let r = !timedOut
mb.Post(true)
- r)
+ return r})
None
module MailboxProcessorErrorEventTests =
exception Err of int
let test() =
// Make sure the event doesn't get raised if no error
- check
+ checkAsync
"c32398u9330: MailboxProcessor Error (0)"
- (let mb1 = new MailboxProcessor(fun inbox -> async { return () })
- let res = ref 100
- mb1.Error.Add(fun _ -> res := 0)
+ (task {
+ let mb1 = new MailboxProcessor(fun inbox -> async { return () })
+ mb1.Error.Add(fun _ -> failwith "unexpected error event")
mb1.Start();
-#if NETCOREAPP
- Task.Delay(200).Wait();
-#else
- System.Threading.Thread.Sleep(200)
-#endif
- !res)
+ do! Task.Delay(200)
+ return 100})
100
// Make sure the event does get raised if error
- check
+ check
"c32398u9331: MailboxProcessor Error (1)"
(let mb1 = new MailboxProcessor(fun inbox -> async { failwith "fail" })
- let res = ref 0
- mb1.Error.Add(fun _ -> res := 100)
+ use res = new System.Threading.ManualResetEventSlim(false)
+ mb1.Error.Add(fun _ -> res.Set())
mb1.Start();
-#if NETCOREAPP
- Task.Delay(200).Wait();
-#else
- System.Threading.Thread.Sleep(200)
-#endif
- !res)
- 100
+ res.Wait()
+ true)
+ true
// Make sure the event does get raised after message receive
- check
+ checkAsync
"c32398u9332: MailboxProcessor Error (2)"
- (let mb1 = new MailboxProcessor(fun inbox ->
- async { let! msg = inbox.Receive()
- raise (Err msg) })
- let res = ref 0
- mb1.Error.Add(function Err n -> res := n | _ -> check "rwe90r - unexpected error" 0 1)
- mb1.Start();
- mb1.Post 100
-#if NETCOREAPP
- Task.Delay(200).Wait();
-#else
- System.Threading.Thread.Sleep(200)
-#endif
- !res)
+ (
+ let errorNumber = TaskCompletionSource<_>()
+
+ let mb1 = new MailboxProcessor( fun inbox -> async {
+ let! msg = inbox.Receive()
+ raise (Err msg)
+ })
+
+ mb1.Error.Add(function
+ | Err n -> errorNumber.SetResult n
+ | _ ->
+ check "rwe90r - unexpected error" 0 1 )
+
+ mb1.Start();
+ mb1.Post 100
+
+ errorNumber.Task
+ )
100
type msg = Increment of int | Fetch of AsyncReplyChannel | Reset
@@ -472,13 +461,10 @@ let test7() =
let timeoutboxes str = new MailboxProcessor<'b>(fun inbox ->
- async { for i in 1 .. 10 do
-#if NETCOREAPP
- Task.Delay(200).Wait()
-#else
- do System.Threading.Thread.Sleep 200
-#endif
- })
+ async {
+ for i in 1 .. 10 do
+ do! Async.Sleep 200
+ })
// Timeout
let timeout_tpar() =
@@ -553,17 +539,9 @@ let timeout_para_def() =
test "default timeout & PostAndAsyncReply" false
with _ -> test "default timeout & PostAndAsyncReply" true
-// Useful class: put "checkpoints" in the code.
-// Check they are called in the right order.
-type Path(str) =
- let mutable current = 0
- member p.Check n = check (str + " #" + string (current+1)) n (current+1)
- current <- n
-
-
-
module LotsOfMessages =
let test () =
+ task {
let N = 200000
let count = ref N
@@ -586,12 +564,9 @@ module LotsOfMessages =
check "celrv09ervkn" (queueLength >= logger.CurrentQueueLength) true
queueLength <- logger.CurrentQueueLength
-#if NETCOREAPP
- Task.Delay(10).Wait()
-#else
- System.Threading.Thread.Sleep(10)
-#endif
+ do! Task.Delay(10)
check "celrv09ervknf3ew" logger.CurrentQueueLength 0
+ }
let RunAll() =
MailboxProcessorBasicTests.test()
@@ -608,11 +583,11 @@ let RunAll() =
timeout_tpar_def()
// ToDo: 7/31/2008: Disabled because of probable timing issue. QA needs to re-enable post-CTP.
// Tracked by bug FSharp 1.0:2891
- //test15()
+ // test15()
// ToDo: 7/31/2008: Disabled because of probable timing issue. QA needs to re-enable post-CTP.
// Tracked by bug FSharp 1.0:2891
- //test15b()
- LotsOfMessages.test()
+ // test15b()
+ LotsOfMessages.test().Wait()
#if TESTS_AS_APP
let RUN() = RunAll(); failures
@@ -621,6 +596,9 @@ RunAll()
let aa =
if not failures.IsEmpty then
stdout.WriteLine "Test Failed"
+ stdout.WriteLine()
+ stdout.WriteLine "failures:"
+ failures |> List.iter stdout.WriteLine
exit 1
else
stdout.WriteLine "Test Passed"
diff --git a/tests/fsharp/typecheck/sigs/neg06.bsl b/tests/fsharp/typecheck/sigs/neg06.bsl
index d55e3e948d2..4e28da2b6d7 100644
--- a/tests/fsharp/typecheck/sigs/neg06.bsl
+++ b/tests/fsharp/typecheck/sigs/neg06.bsl
@@ -10,7 +10,7 @@ neg06.fs(24,6,24,30): typecheck error FS0944: Abbreviated types cannot be given
neg06.fs(27,6,27,33): typecheck error FS0942: Delegate types are always sealed
-neg06.fs(31,9,31,29): typecheck error FS0945: Cannot inherit a sealed type
+neg06.fs(31,17,31,27): typecheck error FS0945: Cannot inherit a sealed type
neg06.fs(37,6,37,29): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation
diff --git a/tests/fsharp/typecheck/sigs/neg10.bsl b/tests/fsharp/typecheck/sigs/neg10.bsl
index 60e9056de56..31bcdb1882e 100644
--- a/tests/fsharp/typecheck/sigs/neg10.bsl
+++ b/tests/fsharp/typecheck/sigs/neg10.bsl
@@ -1,9 +1,9 @@
neg10.fsi(9,6,9,7): typecheck error FS0249: Two type definitions named 'x' occur in namespace 'N' in two parts of this assembly
-neg10.fs(11,17,11,27): typecheck error FS0946: Cannot inherit from interface type. Use interface ... with instead.
+neg10.fs(11,25,11,27): typecheck error FS0946: Cannot inherit from interface type. Use interface ... with instead.
-neg10.fs(13,17,13,26): typecheck error FS0945: Cannot inherit a sealed type
+neg10.fs(13,25,13,26): typecheck error FS0945: Cannot inherit a sealed type
neg10.fs(15,22,15,32): typecheck error FS0887: The type 'C1' is not an interface type
diff --git a/tests/fsharp/typecheck/sigs/neg59.bsl b/tests/fsharp/typecheck/sigs/neg59.bsl
index a938f0d271c..77a9c8caf46 100644
--- a/tests/fsharp/typecheck/sigs/neg59.bsl
+++ b/tests/fsharp/typecheck/sigs/neg59.bsl
@@ -33,9 +33,9 @@ neg59.fs(89,15,89,18): typecheck error FS3141: 'try/finally' expressions may not
neg59.fs(95,15,95,18): typecheck error FS3141: 'try/finally' expressions may not be used in queries
-neg59.fs(102,15,102,64): typecheck error FS3142: 'use' expressions may not be used in queries
+neg59.fs(102,15,102,18): typecheck error FS3142: 'use' expressions may not be used in queries
-neg59.fs(108,15,108,64): typecheck error FS3142: 'use' expressions may not be used in queries
+neg59.fs(108,15,108,18): typecheck error FS3142: 'use' expressions may not be used in queries
neg59.fs(113,15,113,25): typecheck error FS3140: 'while' expressions may not be used in queries
diff --git a/tests/fsharp/typecheck/sigs/neg61.bsl b/tests/fsharp/typecheck/sigs/neg61.bsl
index b0e6b151a2c..d7011cef5ef 100644
--- a/tests/fsharp/typecheck/sigs/neg61.bsl
+++ b/tests/fsharp/typecheck/sigs/neg61.bsl
@@ -57,7 +57,7 @@ neg61.fs(79,13,79,16): typecheck error FS3146: 'try/with' expressions may not be
neg61.fs(86,13,86,16): typecheck error FS3141: 'try/finally' expressions may not be used in queries
-neg61.fs(92,13,92,70): typecheck error FS3142: 'use' expressions may not be used in queries
+neg61.fs(92,13,92,16): typecheck error FS3142: 'use' expressions may not be used in queries
neg61.fs(97,13,97,17): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries
diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingUsing.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingUsing.fs
index 90018a3a6a5..e83604cfdf9 100644
--- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingUsing.fs
+++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingUsing.fs
@@ -1,6 +1,6 @@
// #Regression #Conformance #DataExpressions #ComputationExpressions
// Regression test for FSHARP1.0:6149
-//This control construct may only be used if the computation expression builder defines a 'Using' method$
+//This control construct may only be used if the computation expression builder defines a 'Using' method$
type R = S of string
diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructInheritance01b.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructInheritance01b.fs
index c8771146df5..38184a2ac82 100644
--- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructInheritance01b.fs
+++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/StructTypes/E_StructInheritance01b.fs
@@ -2,7 +2,7 @@
// Verify error when trying to inherit from a struct type
// Regression test for FSHARP1.0:2803
//FS0191: Cannot inherit from interface type
-//Cannot inherit a sealed type
+//Cannot inherit a sealed type
type StructType = struct
diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeKindInference/infer_interface002e.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeKindInference/infer_interface002e.fs
index 4f9a24e00a8..e5998a72c51 100644
--- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeKindInference/infer_interface002e.fs
+++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeKindInference/infer_interface002e.fs
@@ -2,10 +2,10 @@
// attribute must match inferred type
//The kind of the type specified by its attributes does not match the kind implied by its definition
//Structs, interfaces, enums and delegates cannot inherit from other types
-//Cannot inherit from interface type\. Use interface \.\.\. with instead
+//Cannot inherit from interface type\. Use interface \.\.\. with instead
//The kind of the type specified by its attributes does not match the kind implied by its definition
//Structs, interfaces, enums and delegates cannot inherit from other types
-//Cannot inherit from interface type\. Use interface \.\.\. with instead
+//Cannot inherit from interface type\. Use interface \.\.\. with instead
// An interface
type TK_I_003 = interface
diff --git a/tests/service/data/SyntaxTree/Binding/InlineKeywordInBinding.fs.bsl b/tests/service/data/SyntaxTree/Binding/InlineKeywordInBinding.fs.bsl
index 5a7bf976186..596eb100812 100644
--- a/tests/service/data/SyntaxTree/Binding/InlineKeywordInBinding.fs.bsl
+++ b/tests/service/data/SyntaxTree/Binding/InlineKeywordInBinding.fs.bsl
@@ -44,11 +44,12 @@ ImplFile
{ LeadingKeyword = Let (3,4--3,7)
InlineKeyword = Some (3,8--3,14)
EqualsRange = Some (3,21--3,22) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,11--2,16), NoneAtLet, { LeadingKeyword = Let (2,0--2,3)
- InlineKeyword = Some (2,4--2,10)
- EqualsRange = Some (2,17--2,18) })],
- (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }), (2,11--2,16), NoneAtLet,
+ { LeadingKeyword = Let (2,0--2,3)
+ InlineKeyword = Some (2,4--2,10)
+ EqualsRange = Some (2,17--2,18) })], (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBinding.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBinding.fs.bsl
index 844946e66c3..e3156b5c3b5 100644
--- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBinding.fs.bsl
+++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBinding.fs.bsl
@@ -20,8 +20,9 @@ ImplFile
Yes (3,4--3,13), { LeadingKeyword = Let (3,4--3,7)
InlineKeyword = None
EqualsRange = Some (3,10--3,11) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,0--4,6)), (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }), (2,0--4,6)), (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBindingTyped.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBindingTyped.fs.bsl
index b0e567ed3bd..93dabea4c82 100644
--- a/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBindingTyped.fs.bsl
+++ b/tests/service/data/SyntaxTree/Binding/RangeOfEqualSignShouldBePresentInLocalLetBindingTyped.fs.bsl
@@ -30,8 +30,9 @@ ImplFile
{ LeadingKeyword = Let (3,4--3,7)
InlineKeyword = None
EqualsRange = Some (3,15--3,16) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,0--4,6)), (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }), (2,0--4,6)), (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Binding/RangeOfLetKeywordShouldBePresentInSynExprLetOrUseBinding.fs.bsl b/tests/service/data/SyntaxTree/Binding/RangeOfLetKeywordShouldBePresentInSynExprLetOrUseBinding.fs.bsl
index 31febede5b6..86775dec80c 100644
--- a/tests/service/data/SyntaxTree/Binding/RangeOfLetKeywordShouldBePresentInSynExprLetOrUseBinding.fs.bsl
+++ b/tests/service/data/SyntaxTree/Binding/RangeOfLetKeywordShouldBePresentInSynExprLetOrUseBinding.fs.bsl
@@ -34,11 +34,12 @@ ImplFile
NoneAtLet, { LeadingKeyword = Let (3,4--3,7)
InlineKeyword = None
EqualsRange = Some (3,12--3,13) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,4--2,5), NoneAtLet, { LeadingKeyword = Let (2,0--2,3)
- InlineKeyword = None
- EqualsRange = Some (2,6--2,7) })],
- (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }), (2,4--2,5), NoneAtLet,
+ { LeadingKeyword = Let (2,0--2,3)
+ InlineKeyword = None
+ EqualsRange = Some (2,6--2,7) })], (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Expression/NestedSynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/NestedSynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
index 132e7030303..791f6099b9e 100644
--- a/tests/service/data/SyntaxTree/Expression/NestedSynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/NestedSynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
@@ -55,8 +55,10 @@ ImplFile
[Some (OriginalNotation "+")]), None,
(5,6--5,7)), Ident x, (5,4--5,7)), Ident y,
(5,4--5,9)), (4,4--5,9),
- { InKeyword = Some (4,14--4,16) }), (3,4--5,9),
- { InKeyword = Some (3,14--3,16) }), (2,4--2,8), NoneAtLet,
+ { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = Some (4,14--4,16) }), (3,4--5,9),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = Some (3,14--3,16) }), (2,4--2,8), NoneAtLet,
{ LeadingKeyword = Let (2,0--2,3)
InlineKeyword = None
EqualsRange = Some (2,9--2,10) })], (2,0--5,9))],
diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
index f9ce333429a..5408f5d71d1 100644
--- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseContainsTheRangeOfInKeyword.fs.bsl
@@ -19,7 +19,8 @@ ImplFile
InlineKeyword = None
EqualsRange = Some (2,6--2,7) })],
Const (Unit, (2,13--2,15)), (2,0--2,15),
- { InKeyword = Some (2,10--2,12) }), (2,0--2,15))],
+ { LetOrUseKeyword = (2,0--2,3)
+ InKeyword = Some (2,10--2,12) }), (2,0--2,15))],
PreXmlDocEmpty, [], None, (2,0--2,15), { LeadingKeyword = None })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseDoesNotContainTheRangeOfInKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseDoesNotContainTheRangeOfInKeyword.fs.bsl
index 54c3f8180e4..bb9dcafe15f 100644
--- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseDoesNotContainTheRangeOfInKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseDoesNotContainTheRangeOfInKeyword.fs.bsl
@@ -21,8 +21,9 @@ ImplFile
Yes (3,0--3,9), { LeadingKeyword = Let (3,0--3,3)
InlineKeyword = None
EqualsRange = Some (3,6--3,7) })],
- Const (Unit, (4,0--4,2)), (3,0--4,2), { InKeyword = None }),
- (2,0--4,2)), (2,0--4,2))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,0--4,2)), (3,0--4,2),
+ { LetOrUseKeyword = (3,0--3,3)
+ InKeyword = None }), (2,0--4,2)), (2,0--4,2))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWhereBodyExprStartsWithTokenOfTwoCharactersDoesNotContainTheRangeOfInKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWhereBodyExprStartsWithTokenOfTwoCharactersDoesNotContainTheRangeOfInKeyword.fs.bsl
index a5d102356f1..554f4eb21ef 100644
--- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWhereBodyExprStartsWithTokenOfTwoCharactersDoesNotContainTheRangeOfInKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWhereBodyExprStartsWithTokenOfTwoCharactersDoesNotContainTheRangeOfInKeyword.fs.bsl
@@ -40,7 +40,8 @@ ImplFile
SynLongIdent
([e1; Value], [(4,10--4,11)], [None; None]), None,
(4,8--4,16))], [(4,6--4,7)], (4,0--4,16)),
- (3,0--4,16), { InKeyword = None }), (2,0--4,16)),
+ (3,0--4,16), { LetOrUseKeyword = (3,0--3,3)
+ InKeyword = None }), (2,0--4,16)),
(2,0--4,16))], PreXmlDocEmpty, [], None, (2,0--5,0),
{ LeadingKeyword = None })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWithRecursiveBindingContainsTheRangeOfInKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWithRecursiveBindingContainsTheRangeOfInKeyword.fs.bsl
index 72352706810..8b57f33b953 100644
--- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWithRecursiveBindingContainsTheRangeOfInKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseWithRecursiveBindingContainsTheRangeOfInKeyword.fs.bsl
@@ -35,7 +35,8 @@ ImplFile
InlineKeyword = None
EqualsRange = Some (4,10--4,11) })],
Const (Unit, (5,4--5,6)), (3,4--5,6),
- { InKeyword = Some (4,15--4,17) }), (2,0--5,6)), (2,0--5,6))],
+ { LetOrUseKeyword = (3,4--3,11)
+ InKeyword = Some (4,15--4,17) }), (2,0--5,6)), (2,0--5,6))],
PreXmlDocEmpty, [], None, (2,0--6,0), { LeadingKeyword = None })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 04.fs.bsl
index 94ee31ce8d1..74221e70a5f 100644
--- a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 04.fs.bsl
+++ b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 04.fs.bsl
@@ -19,7 +19,8 @@ ImplFile
InlineKeyword = None
EqualsRange = Some (5,6--5,7) })],
ArbitraryAfterError ("seqExpr", (5,10--5,10)), (5,0--5,10),
- { InKeyword = None }), [], (3,0--5,10), Yes (3,0--3,3),
+ { LetOrUseKeyword = (5,0--5,3)
+ InKeyword = None }), [], (3,0--5,10), Yes (3,0--3,3),
Yes (5,10--5,10), { TryKeyword = (3,0--3,3)
TryToWithRange = (3,0--5,10)
WithKeyword = (5,10--5,10)
diff --git a/tests/service/data/SyntaxTree/LeadingKeyword/UseKeyword.fs.bsl b/tests/service/data/SyntaxTree/LeadingKeyword/UseKeyword.fs.bsl
index b2b3420c806..4571189344f 100644
--- a/tests/service/data/SyntaxTree/LeadingKeyword/UseKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/LeadingKeyword/UseKeyword.fs.bsl
@@ -22,8 +22,9 @@ ImplFile
{ LeadingKeyword = Use (3,4--3,7)
InlineKeyword = None
EqualsRange = Some (3,10--3,11) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,0--4,6)), (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }), (2,0--4,6)), (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/LeadingKeyword/UseRecKeyword.fs.bsl b/tests/service/data/SyntaxTree/LeadingKeyword/UseRecKeyword.fs.bsl
index 7dbbc35edd7..ac1d1ce9819 100644
--- a/tests/service/data/SyntaxTree/LeadingKeyword/UseRecKeyword.fs.bsl
+++ b/tests/service/data/SyntaxTree/LeadingKeyword/UseRecKeyword.fs.bsl
@@ -22,8 +22,9 @@ ImplFile
{ LeadingKeyword = UseRec ((3,4--3,7), (3,8--3,11))
InlineKeyword = None
EqualsRange = Some (3,14--3,15) })],
- Const (Unit, (4,4--4,6)), (3,4--4,6), { InKeyword = None }),
- (2,0--4,6)), (2,0--4,6))], PreXmlDocEmpty, [], None, (2,0--5,0),
- { LeadingKeyword = None })], (true, true),
- { ConditionalDirectives = []
- CodeComments = [] }, set []))
+ Const (Unit, (4,4--4,6)), (3,4--4,6),
+ { LetOrUseKeyword = (3,4--3,11)
+ InKeyword = None }), (2,0--4,6)), (2,0--4,6))],
+ PreXmlDocEmpty, [], None, (2,0--5,0), { LeadingKeyword = None })],
+ (true, true), { ConditionalDirectives = []
+ CodeComments = [] }, set []))
diff --git a/tests/service/data/SyntaxTree/MatchClause/RangeOfMultipleSynMatchClause.fs.bsl b/tests/service/data/SyntaxTree/MatchClause/RangeOfMultipleSynMatchClause.fs.bsl
index 84ce5019498..f4b3b9f7a39 100644
--- a/tests/service/data/SyntaxTree/MatchClause/RangeOfMultipleSynMatchClause.fs.bsl
+++ b/tests/service/data/SyntaxTree/MatchClause/RangeOfMultipleSynMatchClause.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
EqualsRange = Some (3,16--3,17) })],
App
(NonAtomic, false, Ident Some, Ident content, (4,4--4,16)),
- (3,4--4,16), { InKeyword = None }),
+ (3,4--4,16), { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }),
[SynMatchClause
(Named (SynIdent (ex, None), false, None, (6,2--6,4)), None,
Sequential
diff --git a/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClause.fs.bsl b/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClause.fs.bsl
index dfa2ad58587..324463e7b2e 100644
--- a/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClause.fs.bsl
+++ b/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClause.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
EqualsRange = Some (3,16--3,17) })],
App
(NonAtomic, false, Ident Some, Ident content, (4,4--4,16)),
- (3,4--4,16), { InKeyword = None }),
+ (3,4--4,16), { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }),
[SynMatchClause
(Named (SynIdent (ex, None), false, None, (5,5--5,7)), None,
Sequential
diff --git a/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClauseFollowedByBar.fs.bsl b/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClauseFollowedByBar.fs.bsl
index ea10cf70558..132cbd01cc0 100644
--- a/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClauseFollowedByBar.fs.bsl
+++ b/tests/service/data/SyntaxTree/MatchClause/RangeOfSingleSynMatchClauseFollowedByBar.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
EqualsRange = Some (3,16--3,17) })],
App
(NonAtomic, false, Ident Some, Ident content, (4,4--4,16)),
- (3,4--4,16), { InKeyword = None }),
+ (3,4--4,16), { LetOrUseKeyword = (3,4--3,7)
+ InKeyword = None }),
[SynMatchClause
(Named (SynIdent (ex, None), false, None, (6,2--6,4)), None,
Const (Unit, (7,4--7,6)), (6,2--7,6), Yes,
diff --git a/tests/service/data/SyntaxTree/Member/Inherit 01.fs.bsl b/tests/service/data/SyntaxTree/Member/Inherit 01.fs.bsl
index e138535c113..f10dc2c0997 100644
--- a/tests/service/data/SyntaxTree/Member/Inherit 01.fs.bsl
+++ b/tests/service/data/SyntaxTree/Member/Inherit 01.fs.bsl
@@ -13,7 +13,8 @@ ImplFile
(Unspecified,
[Inherit
(LongIdent (SynLongIdent ([I], [], [None])), None,
- (4,4--4,13))], (4,4--4,13)), [], None, (3,5--4,13),
+ (4,4--4,13), { InheritKeyword = (4,4--4,11) })],
+ (4,4--4,13)), [], None, (3,5--4,13),
{ LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--4,13))],
diff --git a/tests/service/data/SyntaxTree/Member/Inherit 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Inherit 03.fs.bsl
index eeab1704856..d0101bb0dd4 100644
--- a/tests/service/data/SyntaxTree/Member/Inherit 03.fs.bsl
+++ b/tests/service/data/SyntaxTree/Member/Inherit 03.fs.bsl
@@ -13,7 +13,8 @@ ImplFile
(Unspecified,
[Inherit
(LongIdent (SynLongIdent ([], [], [])), None,
- (4,4--4,11))], (4,4--4,11)), [], None, (3,5--4,11),
+ (4,4--4,11), { InheritKeyword = (4,4--4,11) })],
+ (4,4--4,11)), [], None, (3,5--4,11),
{ LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--4,11))],
diff --git a/tests/service/data/SyntaxTree/Member/Inherit 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Inherit 04.fs.bsl
index 9c03baf2b56..7d0dcfc450c 100644
--- a/tests/service/data/SyntaxTree/Member/Inherit 04.fs.bsl
+++ b/tests/service/data/SyntaxTree/Member/Inherit 04.fs.bsl
@@ -13,7 +13,8 @@ ImplFile
(Unspecified,
[Inherit
(LongIdent (SynLongIdent ([], [], [])), None,
- (4,4--4,11))], (4,4--4,11)), [], None, (3,5--4,11),
+ (4,4--4,11), { InheritKeyword = (4,4--4,11) })],
+ (4,4--4,11)), [], None, (3,5--4,11),
{ LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--4,11));
diff --git a/tests/service/data/SyntaxTree/Member/Inherit 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Inherit 05.fs.bsl
index ddb47eb7ecc..ab71c976fe7 100644
--- a/tests/service/data/SyntaxTree/Member/Inherit 05.fs.bsl
+++ b/tests/service/data/SyntaxTree/Member/Inherit 05.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
(Unspecified,
[Inherit
(LongIdent (SynLongIdent ([], [], [])), None,
- (4,4--4,11));
+ (4,4--4,11), { InheritKeyword = (4,4--4,11) });
Member
(SynBinding
(None, Normal, false, false, [],
diff --git a/tests/service/data/SyntaxTree/Member/Inherit 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Inherit 08.fs.bsl
index fa0211259a4..757d0a30638 100644
--- a/tests/service/data/SyntaxTree/Member/Inherit 08.fs.bsl
+++ b/tests/service/data/SyntaxTree/Member/Inherit 08.fs.bsl
@@ -13,7 +13,7 @@ ImplFile
(Unspecified,
[Inherit
(LongIdent (SynLongIdent ([], [], [])), None,
- (4,4--4,11));
+ (4,4--4,11), { InheritKeyword = (4,4--4,11) });
Member
(SynBinding
(None, Normal, false, false, [],
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl
index 54749497087..7bd27b958c6 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl
@@ -30,7 +30,8 @@ ImplFile
InlineKeyword = None
EqualsRange = None })],
ArbitraryAfterError ("seqExpr", (4,10--4,10)),
- (4,4--4,10), { InKeyword = None }), (4,4--4,10)),
+ (4,4--4,10), { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (4,4--4,10)),
(3,0--4,10)), (3,0--4,10))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl
index 55a07b60288..6120ff4f5fd 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl
@@ -26,8 +26,9 @@ ImplFile
{ LeadingKeyword = Let (4,4--4,7)
InlineKeyword = None
EqualsRange = Some (4,11--4,12) })],
- Const (Unit, (6,4--6,6)), (4,4--6,6), { InKeyword = None }),
- (3,0--6,6)), (3,0--6,6))],
+ Const (Unit, (6,4--6,6)), (4,4--6,6),
+ { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 09.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 09.fs.bsl
index 89a4af5ce5c..0f2e4604d2b 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 09.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 09.fs.bsl
@@ -25,7 +25,8 @@ ImplFile
{ LeadingKeyword = Let (4,4--4,7)
InlineKeyword = None
EqualsRange = None })], Const (Unit, (6,4--6,6)),
- (4,4--6,6), { InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
+ (4,4--6,6), { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 10.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 10.fs.bsl
index f3fa83db96a..5e8ab0f26fd 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 10.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 10.fs.bsl
@@ -24,8 +24,9 @@ ImplFile
{ LeadingKeyword = Let (4,4--4,7)
InlineKeyword = None
EqualsRange = Some (4,13--4,14) })],
- Const (Unit, (6,4--6,6)), (4,4--6,6), { InKeyword = None }),
- (3,0--6,6)), (3,0--6,6))],
+ Const (Unit, (6,4--6,6)), (4,4--6,6),
+ { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 11.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 11.fs.bsl
index e89431a48e0..dbf43bcf3b1 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 11.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 11.fs.bsl
@@ -30,8 +30,9 @@ ImplFile
{ LeadingKeyword = Let (4,4--4,7)
InlineKeyword = None
EqualsRange = Some (4,15--4,16) })],
- Const (Unit, (6,4--6,6)), (4,4--6,6), { InKeyword = None }),
- (3,0--6,6)), (3,0--6,6))],
+ Const (Unit, (6,4--6,6)), (4,4--6,6),
+ { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 12.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 12.fs.bsl
index 97ad7191e25..416dc67c859 100644
--- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 12.fs.bsl
+++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 12.fs.bsl
@@ -38,8 +38,9 @@ ImplFile
{ LeadingKeyword = Let (4,4--4,7)
InlineKeyword = None
EqualsRange = Some (4,18--4,19) })],
- Const (Unit, (6,4--6,6)), (4,4--6,6), { InKeyword = None }),
- (3,0--6,6)), (3,0--6,6))],
+ Const (Unit, (6,4--6,6)), (4,4--6,6),
+ { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }), (3,0--6,6)), (3,0--6,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
diff --git a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl
index d91bffd331d..1dfe5586b56 100644
--- a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl
+++ b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl
@@ -31,7 +31,8 @@ ImplFile
{ LeadingKeyword = Let (2,4--2,7)
InlineKeyword = None
EqualsRange = Some (2,10--2,11) })], Ident b,
- (2,4--5,5), { InKeyword = None }), (1,4--1,5), NoneAtLet,
+ (2,4--5,5), { LetOrUseKeyword = (2,4--2,7)
+ InKeyword = None }), (1,4--1,5), NoneAtLet,
{ LeadingKeyword = Let (1,0--1,3)
InlineKeyword = None
EqualsRange = Some (1,6--1,7) })], (1,0--5,5))],