Re-enable TransparentCompiler tests (#17966)

This commit is contained in:
Jakub Majocha 2024-11-09 15:26:08 +01:00 коммит произвёл GitHub
Родитель 87587f8917
Коммит a88665c4ec
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 539 добавлений и 692 удалений

Просмотреть файл

@ -21,14 +21,14 @@
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CodeAnalysis.Hosted.CompilerHelpers::fscCompile([FSharp.Compiler.Service]FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver, string, string[])][offset 0x00000082][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CodeAnalysis.Hosted.CompilerHelpers::fscCompile([FSharp.Compiler.Service]FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver, string, string[])][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+MagicAssemblyResolution::ResolveAssemblyCore([FSharp.Compiler.Service]Internal.Utilities.Library.CompilationThreadToken, [FSharp.Compiler.Service]FSharp.Compiler.Text.Range, [FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, [FSharp.Compiler.Service]FSharp.Compiler.CompilerImports+TcImports, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiDynamicCompiler, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiConsoleOutput, string)][offset 0x00000015][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3508-780::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3508-779::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [UnmanagedPointer]: : FSharp.Compiler.Interactive.Shell+Utilities+pointerToNativeInt@110::Invoke(object)][offset 0x00000007] Unmanaged pointers are not a verifiable type.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2205::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000094][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000094][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.StaticLinking+TypeForwarding::followTypeForwardForILTypeRef([FSharp.Compiler.Service]FSharp.Compiler.AbstractIL.IL+ILTypeRef)][offset 0x00000010][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerOptions::getCompilerOption([FSharp.Compiler.Service]FSharp.Compiler.CompilerOptions+CompilerOption, [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1<int32>)][offset 0x000000E6][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerOptions::AddPathMapping([FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, string)][offset 0x0000000B][found Char] Unexpected type on the stack.

Просмотреть файл

@ -28,18 +28,18 @@
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CodeAnalysis.Hosted.CompilerHelpers::fscCompile([FSharp.Compiler.Service]FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver, string, string[])][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+FsiStdinSyphon::GetLine(string, int32)][offset 0x00000039][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+MagicAssemblyResolution::ResolveAssemblyCore([FSharp.Compiler.Service]Internal.Utilities.Library.CompilationThreadToken, [FSharp.Compiler.Service]FSharp.Compiler.Text.Range, [FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, [FSharp.Compiler.Service]FSharp.Compiler.CompilerImports+TcImports, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiDynamicCompiler, [FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiConsoleOutput, string)][offset 0x00000015][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3508-780::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+clo@3508-779::Invoke([S.P.CoreLib]System.Tuple`3<char[],int32,int32>)][offset 0x000001E5][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.Interactive.Shell+FsiInteractionProcessor::CompletionsForPartialLID([FSharp.Compiler.Service]FSharp.Compiler.Interactive.Shell+FsiDynamicCompilerState, string)][offset 0x0000001B][found Char] Unexpected type on the stack.
[IL]: Error [UnmanagedPointer]: : FSharp.Compiler.Interactive.Shell+Utilities+pointerToNativeInt@110::Invoke(object)][offset 0x00000007] Unmanaged pointers are not a verifiable type.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$FSharpCheckerResults+dataTipOfReferences@2205::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000084][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.AssemblyContent+traverseMemberFunctionAndValues@176::Invoke([FSharp.Compiler.Service]FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue)][offset 0x00000059][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.AssemblyContent+traverseEntity@218::GenerateNext([S.P.CoreLib]System.Collections.Generic.IEnumerable`1<FSharp.Compiler.EditorServices.AssemblySymbol>&)][offset 0x000000DA][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.EditorServices.ParsedInput+visitor@1423-6::VisitExpr([FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<FSharp.Compiler.Syntax.SyntaxNode>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1<FSharp.Compiler.EditorServices.CompletionContext>>, [FSharp.Compiler.Service]FSharp.Compiler.Syntax.SynExpr)][offset 0x00000605][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-492::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000094][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000032][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000003B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000082][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x0000008B][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$ServiceLexing+clo@921-491::Invoke([FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<System.Tuple`3<FSharp.Compiler.Parser+token,int32,int32>,Microsoft.FSharp.Core.Unit>)][offset 0x00000094][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : <StartupCode$FSharp-Compiler-Service>.$Symbols+fullName@2490-1::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x00000015][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.CreateILModule+MainModuleBuilder::ConvertProductVersionToILVersionInfo(string)][offset 0x00000011][found Char] Unexpected type on the stack.
[IL]: Error [StackUnexpected]: : FSharp.Compiler.StaticLinking+TypeForwarding::followTypeForwardForILTypeRef([FSharp.Compiler.Service]FSharp.Compiler.AbstractIL.IL+ILTypeRef)][offset 0x00000010][found Char] Unexpected type on the stack.

Просмотреть файл

@ -172,6 +172,8 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
let mutable strengthened = 0
let mutable cleared = 0
let mutable updates_in_flight = 0
let mutable cancel_ct_registration_original = 0
let mutable cancel_exception_original = 0
let mutable cancel_original_processed = 0
@ -325,154 +327,154 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
// raise ex -- Suppose there's no need to raise here - where does it even go?
let processStateUpdate post (key: KeyData<_, _>, action: StateUpdate<_>) =
task {
do! Task.Yield()
lock.Do(fun () ->
task {
do!
lock.Do(fun () ->
task {
let cached = cache.TryGet(key.Key, key.Version)
let cached = cache.TryGet(key.Key, key.Version)
match action, cached with
match action, cached with
| OriginatorCanceled, Some(Running(tcs, cts, computation, _, _)) ->
| OriginatorCanceled, Some(Running(tcs, cts, computation, _, _)) ->
Interlocked.Increment &cancel_original_processed |> ignore
Interlocked.Increment &cancel_original_processed |> ignore
decrRequestCount key
decrRequestCount key
if requestCounts[key] < 1 then
cancelRegistration key
cts.Cancel()
tcs.TrySetCanceled() |> ignore
// Remember the job in case it completes after cancellation
cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now)
requestCounts.Remove key |> ignore
log (Canceled, key)
Interlocked.Increment &canceled |> ignore
use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |]
()
if requestCounts[key] < 1 then
cancelRegistration key
cts.Cancel()
tcs.TrySetCanceled() |> ignore
// Remember the job in case it completes after cancellation
cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now)
requestCounts.Remove key |> ignore
log (Canceled, key)
Interlocked.Increment &canceled |> ignore
use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |]
()
else
// We need to restart the computation
Task.Run(fun () ->
Async.StartAsTask(
async {
else
// We need to restart the computation
Task.Run(fun () ->
Async.StartAsTask(
async {
let cachingLogger = new CachingDiagnosticsLogger(None)
let cachingLogger = new CachingDiagnosticsLogger(None)
try
// TODO: Should unify starting and restarting
log (Restarted, key)
Interlocked.Increment &restarted |> ignore
System.Diagnostics.Trace.TraceInformation $"{name} Restarted {key.Label}"
let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger
DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger
try
// TODO: Should unify starting and restarting
log (Restarted, key)
Interlocked.Increment &restarted |> ignore
System.Diagnostics.Trace.TraceInformation $"{name} Restarted {key.Label}"
let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger
DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger
try
let! result = computation
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
return ()
finally
DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger
with
| TaskCancelled _ ->
Interlocked.Increment &cancel_exception_subsequent |> ignore
post (key, CancelRequest)
()
| ex -> post (key, (JobFailed(ex, cachingLogger.CapturedDiagnostics)))
}
),
cts.Token)
|> ignore
try
let! result = computation
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
return ()
finally
DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger
with
| TaskCancelled _ ->
Interlocked.Increment &cancel_exception_subsequent |> ignore
post (key, CancelRequest)
()
| ex -> post (key, (JobFailed(ex, cachingLogger.CapturedDiagnostics)))
}
),
cts.Token)
|> ignore
| CancelRequest, Some(Running(tcs, cts, _c, _, _)) ->
| CancelRequest, Some(Running(tcs, cts, _c, _, _)) ->
Interlocked.Increment &cancel_subsequent_processed |> ignore
Interlocked.Increment &cancel_subsequent_processed |> ignore
decrRequestCount key
decrRequestCount key
if requestCounts[key] < 1 then
cancelRegistration key
cts.Cancel()
tcs.TrySetCanceled() |> ignore
// Remember the job in case it completes after cancellation
cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now)
requestCounts.Remove key |> ignore
log (Canceled, key)
Interlocked.Increment &canceled |> ignore
use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |]
()
if requestCounts[key] < 1 then
cancelRegistration key
cts.Cancel()
tcs.TrySetCanceled() |> ignore
// Remember the job in case it completes after cancellation
cache.Set(key.Key, key.Version, key.Label, Job.Canceled DateTime.Now)
requestCounts.Remove key |> ignore
log (Canceled, key)
Interlocked.Increment &canceled |> ignore
use _ = Activity.start $"{name}: Canceled job" [| "key", key.Label |]
()
// Probably in some cases cancellation can be fired off even after we just unregistered it
| CancelRequest, None
| CancelRequest, Some(Completed _)
| CancelRequest, Some(Job.Canceled _)
| CancelRequest, Some(Job.Failed _)
| OriginatorCanceled, None
| OriginatorCanceled, Some(Completed _)
| OriginatorCanceled, Some(Job.Canceled _)
| OriginatorCanceled, Some(Job.Failed _) -> ()
// Probably in some cases cancellation can be fired off even after we just unregistered it
| CancelRequest, None
| CancelRequest, Some(Completed _)
| CancelRequest, Some(Job.Canceled _)
| CancelRequest, Some(Job.Failed _)
| OriginatorCanceled, None
| OriginatorCanceled, Some(Completed _)
| OriginatorCanceled, Some(Job.Canceled _)
| OriginatorCanceled, Some(Job.Failed _) -> ()
| JobFailed(ex, diags), Some(Running(tcs, _cts, _c, _ts, loggers)) ->
cancelRegistration key
cache.Set(key.Key, key.Version, key.Label, Job.Failed(DateTime.Now, ex))
requestCounts.Remove key |> ignore
log (Failed, key)
Interlocked.Increment &failed |> ignore
failures.Add(key.Label, ex)
| JobFailed(ex, diags), Some(Running(tcs, _cts, _c, _ts, loggers)) ->
cancelRegistration key
cache.Set(key.Key, key.Version, key.Label, Job.Failed(DateTime.Now, ex))
requestCounts.Remove key |> ignore
log (Failed, key)
Interlocked.Increment &failed |> ignore
failures.Add(key.Label, ex)
for logger in loggers do
diags |> replayDiagnostics logger
for logger in loggers do
diags |> replayDiagnostics logger
tcs.TrySetException ex |> ignore
tcs.TrySetException ex |> ignore
| JobCompleted(result, diags), Some(Running(tcs, _cts, _c, started, loggers)) ->
cancelRegistration key
cache.Set(key.Key, key.Version, key.Label, (Completed(result, diags)))
requestCounts.Remove key |> ignore
log (Finished, key)
Interlocked.Increment &completed |> ignore
let duration = float (DateTime.Now - started).Milliseconds
| JobCompleted(result, diags), Some(Running(tcs, _cts, _c, started, loggers)) ->
cancelRegistration key
cache.Set(key.Key, key.Version, key.Label, (Completed(result, diags)))
requestCounts.Remove key |> ignore
log (Finished, key)
Interlocked.Increment &completed |> ignore
let duration = float (DateTime.Now - started).Milliseconds
avgDurationMs <-
if completed < 2 then
duration
else
avgDurationMs + (duration - avgDurationMs) / float completed
avgDurationMs <-
if completed < 2 then
duration
else
avgDurationMs + (duration - avgDurationMs) / float completed
for logger in loggers do
diags |> replayDiagnostics logger
for logger in loggers do
diags |> replayDiagnostics logger
if tcs.TrySetResult result = false then
internalError key.Label "Invalid state: Completed job already completed"
if tcs.TrySetResult result = false then
internalError key.Label "Invalid state: Completed job already completed"
// Sometimes job can be canceled but it still manages to complete (or fail)
| JobFailed _, Some(Job.Canceled _)
| JobCompleted _, Some(Job.Canceled _) -> ()
// Sometimes job can be canceled but it still manages to complete (or fail)
| JobFailed _, Some(Job.Canceled _)
| JobCompleted _, Some(Job.Canceled _) -> ()
// Job can't be evicted from cache while it's running because then subsequent requesters would be waiting forever
| JobFailed _, None -> internalError key.Label "Invalid state: Running job missing in cache (failed)"
// Job can't be evicted from cache while it's running because then subsequent requesters would be waiting forever
| JobFailed _, None -> internalError key.Label "Invalid state: Running job missing in cache (failed)"
| JobCompleted _, None -> internalError key.Label "Invalid state: Running job missing in cache (completed)"
| JobCompleted _, None -> internalError key.Label "Invalid state: Running job missing in cache (completed)"
| JobFailed(ex, _diags), Some(Completed(_job, _diags2)) ->
internalError key.Label $"Invalid state: Failed Completed job \n%A{ex}"
| JobFailed(ex, _diags), Some(Completed(_job, _diags2)) ->
internalError key.Label $"Invalid state: Failed Completed job \n%A{ex}"
| JobCompleted(_result, _diags), Some(Completed(_job, _diags2)) ->
internalError key.Label "Invalid state: Double-Completed job"
| JobCompleted(_result, _diags), Some(Completed(_job, _diags2)) ->
internalError key.Label "Invalid state: Double-Completed job"
| JobFailed(ex, _diags), Some(Job.Failed(_, ex2)) ->
internalError key.Label $"Invalid state: Double-Failed job \n%A{ex} \n%A{ex2}"
| JobFailed(ex, _diags), Some(Job.Failed(_, ex2)) ->
internalError key.Label $"Invalid state: Double-Failed job \n%A{ex} \n%A{ex2}"
| JobCompleted(_result, _diags), Some(Job.Failed(_, ex2)) ->
internalError key.Label $"Invalid state: Completed Failed job \n%A{ex2}"
})
}
| JobCompleted(_result, _diags), Some(Job.Failed(_, ex2)) ->
internalError key.Label $"Invalid state: Completed Failed job \n%A{ex2}"
})
let rec post msg =
Task.Run(fun () -> processStateUpdate post msg :> Task) |> ignore
Interlocked.Increment &updates_in_flight |> ignore
backgroundTask {
do! processStateUpdate post msg
Interlocked.Decrement &updates_in_flight |> ignore
}
|> ignore
member this.Get'(key, computation) =
@ -564,7 +566,9 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
member this.OnEvent = this.Event.Add
member this.Count = cache.Count
member _.Count = lock.Do(fun () -> Task.FromResult cache.Count).Result
member _.Updating = updates_in_flight > 0
member _.Locked = lock.Semaphore.CurrentCount < 1

Просмотреть файл

@ -83,6 +83,8 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
member Count: int
member Updating: bool
/// A drop-in replacement for AsyncMemoize that disables caching and just runs the computation every time.
type internal AsyncMemoizeDisabled<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVersion: equality> =

Просмотреть файл

@ -11,83 +11,72 @@ open FSharp.Compiler.Diagnostics
open Xunit
[<AutoOpen>]
module internal JobEvents =
let tap f x = f x; x
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 internal record (cache: AsyncMemoize<_,_,_>) =
let collectEvents cache =
cache |> publishEvent |> Event.scan (fun es e -> e :: es) [] |> Event.map List.rev
let events = ResizeArray()
/// Exposes a live view of the list of JobEvents generated by AsyncMemoize.
let observe cache =
let updateAvailable = new AutoResetEvent(false)
let mutable recorded = []
let waitForIdle() = SpinWait.SpinUntil(fun () -> not cache.Updating)
let update next =
Debug.WriteLine $"%A{next}"
recorded <- next
updateAvailable.Set() |> ignore
waitForIdle()
cache.Event
|> Event.map (fun (e, (_, k, _)) -> e, k)
|> Event.add events.Add
collectEvents cache |> Event.add update
let getEvents () =
waitForIdle()
events |> List.ofSeq |> tap (printfn "events: %A")
let waitForUpdate = updateAvailable |> Async.AwaitWaitHandle |> Async.Ignore
getEvents
async {
Debug.WriteLine $"current: %A{recorded}"
return recorded, waitForUpdate
}
let check getEvents assertFunction =
let actual = getEvents()
assertFunction actual
let countOf value count events = events |> Seq.filter (fst >> (=) value) |> Seq.length |> (=) count
let waitUntil getEvents condition =
while getEvents() |> condition |> not do ()
let received value events = events |> Seq.exists (fst >> (=) value)
let recorded (expected: 't list) (actual: 't list) =
Assert.Equal<'t>(expected, actual)
let waitUntil observedCache condition =
let rec loop() = async {
let! current, waitForUpdate = observedCache
if current |> condition |> not then
do! waitForUpdate
return! loop()
}
loop()
let countOf value count events =
events |> Seq.filter (fst >> (=) value) |> Seq.length |> (=) count
let received value events =
events |> List.tryLast |> Option.map (fst >> (=) value) |> Option.defaultValue false
[<Fact>]
let ``Basics``() =
task {
let computation key = async {
do! Async.Sleep 1
return key * 2
let computation key = async {
do! Async.Sleep 1
return key * 2
}
let memoize = AsyncMemoize<int, int, int>()
let events = record 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
let memoize = AsyncMemoize<int, int, int>()
let events = observe memoize
let expected = [| 10; 10; 4; 10; 6; 4|]
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<int array>(expected, result)
let expected = [| 10; 10; 4; 10; 6; 4|]
Assert.Equal<int array>(expected, result)
do! waitUntil events (countOf Finished 3)
let! current, _ = events
let groups = current |> Seq.groupBy snd |> Seq.toList
check events <| fun events ->
let groups = events |> Seq.groupBy snd |> Seq.toList
Assert.Equal(3, groups.Length)
for key, events in groups do
Assert.Equal<Set<(JobEvent * int)>>(Set [ Requested, key; Started, key; Finished, key ], Set events)
}
[<Fact>]
let ``We can cancel a job`` () =
@ -106,7 +95,7 @@ let ``We can cancel a job`` () =
}
let memoize = AsyncMemoize<_, int, _>()
let events = observe memoize
let events = record memoize
let key = 1
@ -116,22 +105,14 @@ let ``We can cancel a job`` () =
cts.Cancel()
ctsCancelled.Set()
do! waitUntil events (received Canceled)
let! current, _ = events
Assert.Equal<_ list>(
[
Requested, key
Started, key
Canceled, key
],
current
)
check events recorded
[ Requested, key
Started, key
Canceled, key ]
}
[<Fact>]
let ``Job is restarted if first requestor cancels`` () =
task {
let jobStarted = new SemaphoreSlim(0)
let jobCanComplete = new ManualResetEventSlim(false)
@ -144,47 +125,39 @@ let ``Job is restarted if first requestor cancels`` () =
}
let memoize = AsyncMemoize<_, int, _>()
let events = observe memoize
let events = record memoize
use cts1 = new CancellationTokenSource()
use cts2 = new CancellationTokenSource()
use cts3 = new CancellationTokenSource()
let key = 1
let _task1 = Async.StartAsTask( memoize.Get'(key, computation key), cancellationToken = cts1.Token)
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)
jobStarted.Wait()
let task2 = Async.StartAsTask( memoize.Get'(key, computation key))
let task3 = Async.StartAsTask( memoize.Get'(key, computation key))
do! waitUntil events (countOf Requested 3)
waitUntil events (countOf Requested 3)
cts1.Cancel()
jobCanComplete.Set() |> ignore
do! jobStarted.WaitAsync()
jobStarted.Wait()
let! result = _task2
Assert.Equal(2, result)
Assert.Equal(2, task2.Result)
Assert.Equal(2, task3.Result)
let! current, _ = events
Assert.Equal<_ list>(
[ Requested, key
Started, key
Requested, key
Requested, key
Restarted, key
Finished, key ],
current
)
}
check events recorded
[ Requested, key
Started, key
Requested, key
Requested, key
Restarted, key
Finished, key ]
[<Fact>]
let ``Job is restarted if first requestor cancels but keeps running if second requestor cancels`` () =
task {
let jobStarted = new ManualResetEventSlim(false)
let jobCanComplete = new ManualResetEventSlim(false)
@ -196,11 +169,10 @@ let ``Job is restarted if first requestor cancels but keeps running if second re
}
let memoize = AsyncMemoize<_, int, _>()
let events = observe memoize
let events = record memoize
use cts1 = new CancellationTokenSource()
use cts2 = new CancellationTokenSource()
use cts3 = new CancellationTokenSource()
let key = 1
@ -210,9 +182,9 @@ let ``Job is restarted if first requestor cancels but keeps running if second re
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)
let task3 = Async.StartAsTask( memoize.Get'(key, computation key))
do! waitUntil events (countOf Requested 3)
waitUntil events (countOf Requested 3)
cts1.Cancel()
@ -222,27 +194,21 @@ let ``Job is restarted if first requestor cancels but keeps running if second re
jobCanComplete.Set() |> ignore
let! result = _task3
Assert.Equal(2, result)
Assert.Equal(2, task3.Result)
let! current, _ = events
Assert.Equal<_ list>(
check events recorded
[ Requested, key
Started, key
Requested, key
Requested, key
Restarted, key
Finished, key ],
current
)
}
Finished, key ]
type ExpectedException() =
inherit Exception()
[<Fact(Skip="Flaky")>]
[<Fact>]
let ``Stress test`` () =
let seed = System.Random().Next()

Просмотреть файл

@ -13,6 +13,7 @@ open FSharp.Compiler.Diagnostics
open Xunit
open FSharp.Test
open FSharp.Test.ProjectGeneration
open FSharp.Test.ProjectGeneration.Helpers
open System.IO
@ -26,10 +27,46 @@ open OpenTelemetry
open OpenTelemetry.Resources
open OpenTelemetry.Trace
let fileName fileId = $"File%s{fileId}.fs"
let internal recordAllEvents groupBy =
let mutable cache : AsyncMemoize<_,_,_> option = None
let events = ResizeArray()
let waitForIdle() = SpinWait.SpinUntil(fun () -> not cache.Value.Updating)
let observe (getCache: CompilerCaches -> AsyncMemoize<_,_,_>) (checker: FSharpChecker) =
cache <- Some (getCache checker.Caches)
waitForIdle()
cache.Value.Event
|> Event.map (fun (e, k) -> groupBy k, e)
|> Event.add events.Add
let getEvents () =
waitForIdle()
events |> List.ofSeq
observe, getEvents
let getFileNameKey (_l, (f: string, _p), _) = Path.GetFileName f
// TODO: currently the label for DependecyGraph cache is $"%d{fileSnapshots.Length} files ending with {lastFile}"
let getDependecyGraphKey (_l, _, _) = failwith "not implemented"
let internal recordEvents groupBy =
let observe, getEvents = recordAllEvents groupBy
let check key expected =
let events = getEvents()
let actual = events |> Seq.filter (fun e -> fst e = key) |> Seq.map snd |> Seq.toList
printfn $"{key}: %A{actual}"
Assert.Equal<JobEvent>(expected, actual)
observe, check
#nowarn "57"
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Use Transparent Compiler`` () =
let size = 20
@ -59,7 +96,7 @@ let ``Use Transparent Compiler`` () =
checkFile last expectSignatureChanged
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Parallel processing`` () =
let project = SyntheticProject.Create(
@ -77,7 +114,7 @@ let ``Parallel processing`` () =
checkFile "E" expectSignatureChanged
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Parallel processing with signatures`` () =
let project = SyntheticProject.Create(
@ -112,7 +149,7 @@ let makeTestProject () =
let testWorkflow () =
ProjectWorkflowBuilder(makeTestProject(), useTransparentCompiler = true)
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Edit file, check it, then check dependent file`` () =
testWorkflow() {
updateFile "First" breakDependentFiles
@ -120,21 +157,21 @@ let ``Edit file, check it, then check dependent file`` () =
checkFile "Second" expectErrors
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Edit file, don't check it, check dependent file`` () =
testWorkflow() {
updateFile "First" breakDependentFiles
checkFile "Second" expectErrors
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Check transitive dependency`` () =
testWorkflow() {
updateFile "First" breakDependentFiles
checkFile "Last" expectSignatureChanged
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Change multiple files at once`` () =
testWorkflow() {
updateFile "First" (setPublicVersion 2)
@ -143,7 +180,7 @@ let ``Change multiple files at once`` () =
checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_2<'a> * ModuleSecond.TSecondV_2<'a>) * (ModuleFirst.TFirstV_2<'a> * ModuleThird.TThirdV_2<'a>) * TLastV_1<'a>")
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Files depend on signature file if present`` () =
let project = makeTestProject() |> updateFile "First" addSignatureFile
@ -153,7 +190,7 @@ let ``Files depend on signature file if present`` () =
checkFile "Second" expectNoChanges
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Project with signatures`` () =
let project = SyntheticProject.Create(
@ -168,7 +205,7 @@ let ``Project with signatures`` () =
checkFile "Second" expectOk
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Signature update`` () =
let project = SyntheticProject.Create(
@ -184,7 +221,7 @@ let ``Signature update`` () =
checkFile "Second" expectSignatureChanged
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Adding a file`` () =
testWorkflow() {
addFileAbove "Second" (sourceFile "New" [])
@ -192,14 +229,14 @@ let ``Adding a file`` () =
checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_1<'a> * ModuleNew.TNewV_1<'a> * ModuleSecond.TSecondV_1<'a>) * (ModuleFirst.TFirstV_1<'a> * ModuleThird.TThirdV_1<'a>) * TLastV_1<'a>")
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Removing a file`` () =
testWorkflow() {
removeFile "Second"
checkFile "Last" expectErrors
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Changes in a referenced project`` () =
let library = SyntheticProject.Create("library", sourceFile "Library" [])
@ -218,55 +255,35 @@ let ``Changes in a referenced project`` () =
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``File is not checked twice`` () =
let cacheEvents = ConcurrentQueue()
let observe, check = recordEvents getFileNameKey
testWorkflow() {
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue
})
withChecker (observe _.TcIntermediate)
updateFile "First" updatePublicSurface
checkFile "Third" expectOk
} |> ignore
let intermediateTypeChecks =
cacheEvents
|> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> f |> Path.GetFileName)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
check (fileName "First") [Weakened; Requested; Started; Finished]
check (fileName "Third") [Weakened; Requested; Started; Finished]
Assert.Equal<JobEvent list>([Weakened; Requested; Started; Finished], intermediateTypeChecks["FileFirst.fs"])
Assert.Equal<JobEvent list>([Weakened; Requested; Started; Finished], intermediateTypeChecks["FileThird.fs"])
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``If a file is checked as a dependency it's not re-checked later`` () =
let cacheEvents = ConcurrentQueue()
let observe, check = recordEvents getFileNameKey
testWorkflow() {
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue
})
withChecker (observe _.TcIntermediate)
updateFile "First" updatePublicSurface
checkFile "Last" expectOk
checkFile "Third" expectOk
} |> ignore
let intermediateTypeChecks =
cacheEvents
|> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> f |> Path.GetFileName)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
check (fileName "Third") [Weakened; Requested; Started; Finished; Requested]
Assert.Equal<JobEvent list>([Weakened; Requested; Started; Finished; Requested], intermediateTypeChecks["FileThird.fs"])
// [<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>] TODO: differentiate complete and minimal checking requests
[<Fact>] // TODO: differentiate complete and minimal checking requests
let ``We don't check files that are not depended on`` () =
let project = SyntheticProject.Create(
sourceFile "First" [],
@ -274,29 +291,19 @@ let ``We don't check files that are not depended on`` () =
sourceFile "Third" ["First"],
sourceFile "Last" ["Third"])
let cacheEvents = ConcurrentQueue()
let observe, check = recordEvents getFileNameKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue
})
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
withChecker (observe _.TcIntermediate)
updateFile "First" updatePublicSurface
checkFile "Last" expectOk
} |> ignore
let intermediateTypeChecks =
cacheEvents
|> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> Path.GetFileName f)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
check "FileFirst.fs" [Weakened; Requested; Started; Finished]
check "FileThird.fs" [Weakened; Requested; Started; Finished]
// check "FileSecond.fs" [] // TODO: assert does not hold.
Assert.Equal<JobEvent list>([Started; Finished], intermediateTypeChecks["FileFirst.fs"])
Assert.Equal<JobEvent list>([Started; Finished], intermediateTypeChecks["FileThird.fs"])
Assert.False (intermediateTypeChecks.ContainsKey "FileSecond.fs")
// [<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>] TODO: differentiate complete and minimal checking requests
[<Fact(Skip="needs fixing")>] // TODO: differentiate complete and minimal checking requests
let ``Files that are not depended on don't invalidate cache`` () =
let project = SyntheticProject.Create(
sourceFile "First" [],
@ -304,40 +311,22 @@ let ``Files that are not depended on don't invalidate cache`` () =
sourceFile "Third" ["First"],
sourceFile "Last" ["Third"])
let cacheTcIntermediateEvents = ConcurrentQueue()
let cacheGraphConstructionEvents = ConcurrentQueue()
let observeTcIntermediateEvents, _getTcIntermediateEvents = recordAllEvents getFileNameKey
// let observeGraphConstructionEvents, checkGraphConstructionEvents = record getDependecyGraphKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
updateFile "First" updatePublicSurface
checkFile "Last" expectOk
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheTcIntermediateEvents.Enqueue
checker.Caches.DependencyGraph.OnEvent cacheGraphConstructionEvents.Enqueue
})
withChecker (observeTcIntermediateEvents _.TcIntermediate)
// withChecker (observeGraphConstructionEvents _.DependencyGraph)
updateFile "Second" updatePublicSurface
checkFile "Last" expectOk
} |> ignore
let intermediateTypeChecks =
cacheTcIntermediateEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
// Assert.Empty(getTcIntermediateEvents()) TODO: assert does not hold
// checkGraphConstructionEvents "FileLast.fs" [Started; Finished]
let graphConstructions =
cacheGraphConstructionEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
Assert.Equal<JobEvent list>([Started; Finished], graphConstructions["FileLast.fs"])
Assert.Equal<string * JobEvent list>([], intermediateTypeChecks |> Map.toList)
// [<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>] TODO: differentiate complete and minimal checking requests
[<Fact(Skip="needs fixing")>] // TODO: differentiate complete and minimal checking requests
let ``Files that are not depended on don't invalidate cache part 2`` () =
let project = SyntheticProject.Create(
sourceFile "A" [],
@ -346,67 +335,41 @@ let ``Files that are not depended on don't invalidate cache part 2`` () =
sourceFile "D" ["B"; "C"],
sourceFile "E" ["C"])
let cacheTcIntermediateEvents = ConcurrentQueue()
let cacheGraphConstructionEvents = ConcurrentQueue()
let observeTcIntermediateEvents, checkTcIntermediateEvents = recordEvents getFileNameKey
// let observeGraphConstructionEvents, checkGraphConstructionEvents = record getDependecyGraphKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
updateFile "A" updatePublicSurface
checkFile "D" expectOk
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheTcIntermediateEvents.Enqueue
checker.Caches.DependencyGraph.OnEvent cacheGraphConstructionEvents.Enqueue
})
withChecker (observeTcIntermediateEvents _.TcIntermediate)
// withChecker (observeGraphConstructionEvents _.DependencyGraph)
updateFile "B" updatePublicSurface
checkFile "E" expectOk
} |> ignore
let intermediateTypeChecks =
cacheTcIntermediateEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Seq.toList
checkTcIntermediateEvents "FileE.fs" [Weakened; Requested; Started; Finished]
// checkGraphConstructionEvents "FileE.fs" [Weakened; Requested; Started; Finished]
let graphConstructions =
cacheGraphConstructionEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Seq.toList
Assert.Equal<string * JobEvent list>(["FileE.fs", [Started; Finished]], graphConstructions)
Assert.Equal<string * JobEvent list>(["FileE.fs", [Started; Finished]], intermediateTypeChecks)
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Changing impl files doesn't invalidate cache when they have signatures`` () =
let project = SyntheticProject.Create(
{ sourceFile "A" [] with SignatureFile = AutoGenerated },
{ sourceFile "B" ["A"] with SignatureFile = AutoGenerated },
{ sourceFile "C" ["B"] with SignatureFile = AutoGenerated })
let cacheEvents = ConcurrentQueue()
let observe, getEvents = recordAllEvents getFileNameKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
updateFile "A" updatePublicSurface
checkFile "C" expectOk
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue
})
withChecker ( observe _.TcIntermediate)
updateFile "A" updateInternal
checkFile "C" expectOk
} |> ignore
let intermediateTypeChecks =
cacheEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Seq.toList
Assert.Empty(getEvents())
Assert.Equal<string * JobEvent list>([], intermediateTypeChecks)
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Changing impl file doesn't invalidate an in-memory referenced project`` () =
let library = SyntheticProject.Create("library", { sourceFile "A" [] with SignatureFile = AutoGenerated })
@ -414,27 +377,19 @@ let ``Changing impl file doesn't invalidate an in-memory referenced project`` ()
SyntheticProject.Create("project", sourceFile "B" ["A"] )
with DependsOn = [library] }
let cacheEvents = ConcurrentQueue()
let mutable count = 0
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
checkFile "B" expectOk
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.TcIntermediate.OnEvent cacheEvents.Enqueue
checker.Caches.TcIntermediate.OnEvent (fun _ -> Interlocked.Increment &count |> ignore)
})
updateFile "A" updateInternal
checkFile "B" expectOk
} |> ignore
let intermediateTypeChecks =
cacheEvents
|> Seq.groupBy (fun (_e, (l, _k, _)) -> l)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Seq.toList
Assert.Equal<string * JobEvent list>([], intermediateTypeChecks)
Assert.Equal(0, count)
[<Theory>]
[<InlineData true>]
@ -645,13 +600,10 @@ let fuzzingTest seed (project: SyntheticProject) = task {
builder.DeleteProjectDir()
}
(* This gets in the way of insertions too often now, uncomment when stable.
[<Theory>]
[<InlineData(SignatureFiles.Yes)>]
[<InlineData(SignatureFiles.No)>]
[<InlineData(SignatureFiles.Some)>]
*)
let Fuzzing signatureFiles =
let seed = System.Random().Next()
@ -789,7 +741,7 @@ module Stuff =
let fileName, snapshot, checker = singleFileChecker source
checker.ParseFile(fileName, snapshot) |> Async.RunSynchronously
//[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
//[<Fact>]
let ``Hash stays the same when whitespace changes`` () =
//let parseResult = getParseResult source
@ -845,61 +797,41 @@ let ``TypeCheck last file in project with transparent compiler`` useTransparentC
checkFile lastFile expectOk
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``LoadClosure for script is computed once`` () =
let project = SyntheticProject.CreateForScript(
sourceFile "First" [])
let project = SyntheticProject.CreateForScript(
sourceFile "First" [])
let cacheEvents = ConcurrentQueue()
let observe, getEvents = recordAllEvents getFileNameKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.ScriptClosure.OnEvent cacheEvents.Enqueue
})
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
withChecker (observe _.ScriptClosure)
checkFile "First" expectOk
}
|> ignore
checkFile "First" expectOk
} |> ignore
let closureComputations =
cacheEvents
|> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> Path.GetFileName f)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
Assert.Empty(getEvents())
Assert.Empty(closureComputations)
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``LoadClosure for script is recomputed after changes`` () =
let project = SyntheticProject.CreateForScript(
sourceFile "First" [])
let cacheEvents = ConcurrentQueue()
let observe, check = recordEvents getFileNameKey
ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
withChecker (fun checker ->
async {
do! Async.Sleep 50 // wait for events from initial project check
checker.Caches.ScriptClosure.OnEvent cacheEvents.Enqueue
})
withChecker (observe _.ScriptClosure)
checkFile "First" expectOk
updateFile "First" updateInternal
checkFile "First" expectOk
updateFile "First" updatePublicSurface
checkFile "First" expectOk
} |> ignore
let closureComputations =
cacheEvents
|> Seq.groupBy (fun (_e, (_l, (f, _p), _)) -> Path.GetFileName f)
|> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList)
|> Map
Assert.Equal<JobEvent list>([Weakened; Requested; Started; Finished; Weakened; Requested; Started; Finished], closureComputations["FileFirst.fs"])
check (fileName "First") [Weakened; Requested; Started; Finished; Weakened; Requested; Started; Finished]
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``TryGetRecentCheckResultsForFile returns None before first call to ParseAndCheckFileInProject`` () =
let project = SyntheticProject.Create(
sourceFile "First" [])
@ -909,7 +841,7 @@ let ``TryGetRecentCheckResultsForFile returns None before first call to ParseAnd
tryGetRecentCheckResults "First" expectNone
} |> ignore
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``TryGetRecentCheckResultsForFile returns result after first call to ParseAndCheckFileInProject`` () =
let project = SyntheticProject.Create(
sourceFile "First" [] )
@ -918,7 +850,7 @@ let ``TryGetRecentCheckResultsForFile returns result after first call to ParseAn
tryGetRecentCheckResults "First" expectSome
} |> ignore
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``TryGetRecentCheckResultsForFile returns no result after edit`` () =
let project = SyntheticProject.Create(
sourceFile "First" [])
@ -931,7 +863,7 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () =
tryGetRecentCheckResults "First" expectSome
} |> ignore
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` () =
let project = SyntheticProject.Create(
sourceFile "First" [],
@ -945,9 +877,9 @@ let ``TryGetRecentCheckResultsForFile returns result after edit of other file``
tryGetRecentCheckResults "Second" expectSome // file didn't change so we still want to get the recent result
} |> ignore
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact(Skip="TransparentCompiler assumeDotNetFramework differs from default checker")>]
let ``Background compiler and Transparent compiler return the same options`` () =
async {
task {
let backgroundChecker = FSharpChecker.Create(useTransparentCompiler = false)
let transparentChecker = FSharpChecker.Create(useTransparentCompiler = true)
let scriptName = Path.Combine(__SOURCE_DIRECTORY__, "script.fsx")
@ -1012,15 +944,14 @@ printfn "Hello from F#"
checkFile "As 01" expectTwoWarnings
}
[<Fact(Skip="Flaky. See https://github.com/dotnet/fsharp/issues/16766")>]
[<Fact>]
let ``Transparent Compiler ScriptClosure cache is populated after GetProjectOptionsFromScript`` () =
async {
task {
let transparentChecker = FSharpChecker.Create(useTransparentCompiler = true)
let scriptName = Path.Combine(__SOURCE_DIRECTORY__, "script.fsx")
let content = SourceTextNew.ofString ""
let! _ = transparentChecker.GetProjectOptionsFromScript(scriptName, content)
Assert.Equal(1, transparentChecker.Caches.ScriptClosure.Count)
}
type private LoadClosureTestShim(currentFileSystem: IFileSystem) =
@ -1064,67 +995,69 @@ type private LoadClosureTestShim(currentFileSystem: IFileSystem) =
?shouldShadowCopy = shouldShadowCopy
)
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``The script load closure should always be evaluated`` useTransparentCompiler =
async {
// The LoadScriptClosure uses the file system shim so we need to reset that.
let currentFileSystem = FileSystemAutoOpens.FileSystem
let assumeDotNetFramework =
// The old BackgroundCompiler uses assumeDotNetFramework = true
// This is not always correctly loading when this test runs on non-Windows.
if System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") then
None
else
Some false
module TestsMutatingFileSystem =
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``The script load closure should always be evaluated`` useTransparentCompiler =
async {
// The LoadScriptClosure uses the file system shim so we need to reset that.
let currentFileSystem = FileSystemAutoOpens.FileSystem
let assumeDotNetFramework =
// The old BackgroundCompiler uses assumeDotNetFramework = true
// This is not always correctly loading when this test runs on non-Windows.
if System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") then
None
else
Some false
try
let checker = FSharpChecker.Create(useTransparentCompiler = useTransparentCompiler)
let fileSystemShim = LoadClosureTestShim(currentFileSystem)
// Override the file system shim for loading b.fsx
FileSystem <- fileSystemShim
try
let checker = FSharpChecker.Create(useTransparentCompiler = useTransparentCompiler)
let fileSystemShim = LoadClosureTestShim(currentFileSystem)
// Override the file system shim for loading b.fsx
FileSystem <- fileSystemShim
let! initialSnapshot, _ =
checker.GetProjectSnapshotFromScript(
"a.fsx",
SourceTextNew.ofString fileSystemShim.aFsx,
documentSource = DocumentSource.Custom fileSystemShim.DocumentSource,
?assumeDotNetFramework = assumeDotNetFramework
)
let! initialSnapshot, _ =
checker.GetProjectSnapshotFromScript(
"a.fsx",
SourceTextNew.ofString fileSystemShim.aFsx,
documentSource = DocumentSource.Custom fileSystemShim.DocumentSource,
?assumeDotNetFramework = assumeDotNetFramework
)
// File b.fsx should also be included in the snapshot.
Assert.Equal(2, initialSnapshot.SourceFiles.Length)
// File b.fsx should also be included in the snapshot.
Assert.Equal(2, initialSnapshot.SourceFiles.Length)
let! checkResults = checker.ParseAndCheckFileInProject("a.fsx", initialSnapshot)
let! checkResults = checker.ParseAndCheckFileInProject("a.fsx", initialSnapshot)
match snd checkResults with
| FSharpCheckFileAnswer.Aborted -> failwith "Did not expected FSharpCheckFileAnswer.Aborted"
| FSharpCheckFileAnswer.Succeeded checkFileResults -> Assert.Equal(0, checkFileResults.Diagnostics.Length)
match snd checkResults with
| FSharpCheckFileAnswer.Aborted -> failwith "Did not expected FSharpCheckFileAnswer.Aborted"
| FSharpCheckFileAnswer.Succeeded checkFileResults -> Assert.Equal(0, checkFileResults.Diagnostics.Length)
// Update b.fsx, it should now load c.fsx
fileSystemShim.UpdateB()
// Update b.fsx, it should now load c.fsx
fileSystemShim.UpdateB()
// The constructed key for the load closure will the exactly the same as the first GetProjectSnapshotFromScript call.
// However, a none cached version will be computed first in GetProjectSnapshotFromScript and update the cache afterwards.
let! secondSnapshot, _ =
checker.GetProjectSnapshotFromScript(
"a.fsx",
SourceTextNew.ofString fileSystemShim.aFsx,
documentSource = DocumentSource.Custom fileSystemShim.DocumentSource,
?assumeDotNetFramework = assumeDotNetFramework
)
// The constructed key for the load closure will the exactly the same as the first GetProjectSnapshotFromScript call.
// However, a none cached version will be computed first in GetProjectSnapshotFromScript and update the cache afterwards.
let! secondSnapshot, _ =
checker.GetProjectSnapshotFromScript(
"a.fsx",
SourceTextNew.ofString fileSystemShim.aFsx,
documentSource = DocumentSource.Custom fileSystemShim.DocumentSource,
?assumeDotNetFramework = assumeDotNetFramework
)
Assert.Equal(3, secondSnapshot.SourceFiles.Length)
Assert.Equal(3, secondSnapshot.SourceFiles.Length)
let! checkResults = checker.ParseAndCheckFileInProject("a.fsx", secondSnapshot)
let! checkResults = checker.ParseAndCheckFileInProject("a.fsx", secondSnapshot)
match snd checkResults with
| FSharpCheckFileAnswer.Aborted -> failwith "Did not expected FSharpCheckFileAnswer.Aborted"
| FSharpCheckFileAnswer.Succeeded checkFileResults -> Assert.Equal(0, checkFileResults.Diagnostics.Length)
finally
FileSystemAutoOpens.FileSystem <- currentFileSystem
}
match snd checkResults with
| FSharpCheckFileAnswer.Aborted -> failwith "Did not expected FSharpCheckFileAnswer.Aborted"
| FSharpCheckFileAnswer.Succeeded checkFileResults -> Assert.Equal(0, checkFileResults.Diagnostics.Length)
finally
FileSystemAutoOpens.FileSystem <- currentFileSystem
}
[<Fact>]
let ``Parsing without cache and without project snapshot`` () =

Просмотреть файл

@ -1,6 +1,7 @@
module FSharp.Compiler.Service.Tests.ExprTests
open Xunit
open FSharp.Test
open FSharp.Test.Assert
open System
open System.Text
@ -656,13 +657,11 @@ let test{0}ToStringOperator (e1:{1}) = string e1
"""
/// This test is run in unison with its optimized counterpart below
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test Unoptimized Declarations Project1`` useTransparentCompiler =
[<Fact>]
let ``Test Unoptimized Declarations Project1`` () =
let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -797,13 +796,11 @@ let ``Test Unoptimized Declarations Project1`` useTransparentCompiler =
()
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test Optimized Declarations Project1`` useTransparentCompiler =
[<Fact>]
let ``Test Optimized Declarations Project1`` () =
let cleanup, options = Project1.createOptionsWithArgs [ "--langversion:preview" ]
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3136,14 +3133,12 @@ let BigSequenceExpression(outFileOpt,docFileOpt,baseAddressOpt) =
#if !NETFRAMEWORK && DEBUG
[<Theory(Skip = "Test is known to fail in DEBUG when not using NetFramework. Use RELEASE configuration or NetFramework to run it.")>]
#else
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
[<Fact>]
#endif
let ``Test expressions of declarations stress big expressions`` useTransparentCompiler =
let ``Test expressions of declarations stress big expressions`` () =
let cleanup, options = ProjectStressBigExpressions.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
wholeProjectResults.Diagnostics.Length |> shouldEqual 0
@ -3157,14 +3152,12 @@ let ``Test expressions of declarations stress big expressions`` useTransparentCo
#if !NETFRAMEWORK && DEBUG
[<Theory(Skip = "Test is known to fail in DEBUG when not using NetFramework. Use RELEASE configuration or NetFramework to run it.")>]
#else
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
[<Fact>]
#endif
let ``Test expressions of optimized declarations stress big expressions`` useTransparentCompiler =
let ``Test expressions of optimized declarations stress big expressions`` () =
let cleanup, options = ProjectStressBigExpressions.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
wholeProjectResults.Diagnostics.Length |> shouldEqual 0
@ -3220,13 +3213,11 @@ let f8() = callXY (D()) (C())
let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses1`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses1`` () =
let cleanup, options = ProjectForWitnesses1.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3266,13 +3257,11 @@ let ``Test ProjectForWitnesses1`` useTransparentCompiler =
|> shouldEqual expected
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses1 GetWitnessPassingInfo`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses1 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses1.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3348,13 +3337,11 @@ type MyNumberWrapper =
let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses2`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses2`` () =
let cleanup, options = ProjectForWitnesses2.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3406,13 +3393,11 @@ let s2 = sign p1
let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses3`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses3`` () =
let cleanup, options = createProjectOptions dirName [ ProjectForWitnesses3.fileSource1 ] ["--langversion:7.0"]
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3439,13 +3424,11 @@ let ``Test ProjectForWitnesses3`` useTransparentCompiler =
actual
|> shouldEqual expected
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses3 GetWitnessPassingInfo`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses3 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses3.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3504,13 +3487,11 @@ let isNullQuoted (ts : 't[]) =
let createOptions() = createProjectOptions dirName [fileSource1] ["--langversion:7.0"]
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` useTransparentCompiler =
[<Fact>]
let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` () =
let cleanup, options = ProjectForWitnesses4.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -3544,13 +3525,11 @@ let rec f = new System.EventHandler(fun _ _ -> f.Invoke(null,null))
let createOptions() = createProjectOptions dirName [fileSource1] []
[<Theory>]
[<InlineData(false)>]
[<InlineData(true)>]
let ``Test NoWarn HashDirective`` useTransparentCompiler =
[<Fact>]
let ``Test NoWarn HashDirective`` () =
let cleanup, options = ProjectForNoWarnHashDirective.createOptions()
use _holder = cleanup
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do

Просмотреть файл

@ -1,6 +1,7 @@
module FSharp.Compiler.Service.Tests.MultiProjectAnalysisTests
open Xunit
open FSharp.Test
open FSharp.Test.Assert
open System.IO
open System.Collections.Generic
@ -14,8 +15,7 @@ open TestFramework
let toIList (x: _ array) = x :> IList<_>
let numProjectsForStressTest = 100
let internal checker = FSharpChecker.Create(projectCacheSize=numProjectsForStressTest + 10)
let internal transparentCompilerChecker = FSharpChecker.Create(projectCacheSize=numProjectsForStressTest + 10, useTransparentCompiler=true)
let internal checker = FSharpChecker.Create(projectCacheSize=numProjectsForStressTest + 10, useTransparentCompiler = CompilerAssertHelpers.UseTransparentCompiler)
/// Extract range info
let internal tups (m:range) = (m.StartLine, m.StartColumn), (m.EndLine, m.EndColumn)
@ -124,12 +124,8 @@ let u = Case1 3
FSharpReferencedProject.FSharpReference(Project1B.dllName, Project1B.options); |] }
let cleanFileName a = if a = fileName1 then "file1" else "??"
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project 1 basic`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project 1 basic`` () =
let wholeProjectResults = checker.ParseAndCheckProject(MultiProject1.options) |> Async.RunImmediate
@ -141,12 +137,8 @@ let ``Test multi project 1 basic`` useTransparentCompiler =
[ for x in wholeProjectResults.AssemblySignature.Entities[0].MembersFunctionsAndValues -> x.DisplayName ]
|> shouldEqual ["p"; "c"; "u"]
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project 1 all symbols`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project 1 all symbols`` () =
let p1A = checker.ParseAndCheckProject(Project1A.options) |> Async.RunImmediate
let p1B = checker.ParseAndCheckProject(Project1B.options) |> Async.RunImmediate
@ -183,12 +175,8 @@ let ``Test multi project 1 all symbols`` useTransparentCompiler =
usesOfx1FromProject1AInMultiProject1 |> shouldEqual usesOfx1FromMultiProject1InMultiProject1
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project 1 xmldoc`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project 1 xmldoc`` () =
let p1A = checker.ParseAndCheckProject(Project1A.options) |> Async.RunImmediate
let p1B = checker.ParseAndCheckProject(Project1B.options) |> Async.RunImmediate
@ -263,12 +251,12 @@ let ``Test multi project 1 xmldoc`` useTransparentCompiler =
//------------------------------------------------------------------------------------
type private Project = { ModuleName: string; FileName: string; Options: FSharpProjectOptions; DllName: string }
// A project referencing many sub-projects
module internal ManyProjectsStressTest =
type private ManyProjectsStressTest() =
let numProjectsForStressTest = 100
type Project = { ModuleName: string; FileName: string; Options: FSharpProjectOptions; DllName: string }
let projects =
[ for i in 1 .. numProjectsForStressTest do
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
@ -325,18 +313,23 @@ let p = ("""
|> function Some x -> x | None -> if a = jointProject.FileName then "fileN" else "??"
let makeCheckerForStressTest ensureBigEnough useTransparentCompiler =
member _.JointProject = jointProject
member _.Projects = projects
member _.CleanFileName a = cleanFileName a
static member MakeCheckerForStressTest ensureBigEnough =
let size = (if ensureBigEnough then numProjectsForStressTest + 10 else numProjectsForStressTest / 2 )
FSharpChecker.Create(projectCacheSize=size, useTransparentCompiler=useTransparentCompiler)
FSharpChecker.Create(projectCacheSize=size, useTransparentCompiler = CompilerAssertHelpers.UseTransparentCompiler)
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test ManyProjectsStressTest basic`` useTransparentCompiler =
let checker = ManyProjectsStressTest.makeCheckerForStressTest true useTransparentCompiler
let wholeProjectResults = checker.ParseAndCheckProject(ManyProjectsStressTest.jointProject.Options) |> Async.RunImmediate
[<Fact>]
let ``Test ManyProjectsStressTest basic`` () =
let manyProjectsStressTest = ManyProjectsStressTest()
let checker = ManyProjectsStressTest.MakeCheckerForStressTest true
let wholeProjectResults = checker.ParseAndCheckProject(manyProjectsStressTest.JointProject.Options) |> Async.RunImmediate
[ for x in wholeProjectResults.AssemblySignature.Entities -> x.DisplayName ] |> shouldEqual ["JointProject"]
@ -345,14 +338,14 @@ let ``Test ManyProjectsStressTest basic`` useTransparentCompiler =
[ for x in wholeProjectResults.AssemblySignature.Entities[0].MembersFunctionsAndValues -> x.DisplayName ]
|> shouldEqual ["p"]
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test ManyProjectsStressTest cache too small`` useTransparentCompiler =
[<Fact>]
let ``Test ManyProjectsStressTest cache too small`` () =
let checker = ManyProjectsStressTest.makeCheckerForStressTest false useTransparentCompiler
let manyProjectsStressTest = ManyProjectsStressTest()
let wholeProjectResults = checker.ParseAndCheckProject(ManyProjectsStressTest.jointProject.Options) |> Async.RunImmediate
let checker = ManyProjectsStressTest.MakeCheckerForStressTest false
let wholeProjectResults = checker.ParseAndCheckProject(manyProjectsStressTest.JointProject.Options) |> Async.RunImmediate
[ for x in wholeProjectResults.AssemblySignature.Entities -> x.DisplayName ] |> shouldEqual ["JointProject"]
@ -361,16 +354,17 @@ let ``Test ManyProjectsStressTest cache too small`` useTransparentCompiler =
[ for x in wholeProjectResults.AssemblySignature.Entities[0].MembersFunctionsAndValues -> x.DisplayName ]
|> shouldEqual ["p"]
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test ManyProjectsStressTest all symbols`` useTransparentCompiler =
[<Fact>]
let ``Test ManyProjectsStressTest all symbols`` () =
let checker = ManyProjectsStressTest.makeCheckerForStressTest true useTransparentCompiler
let manyProjectsStressTest = ManyProjectsStressTest()
let checker = ManyProjectsStressTest.MakeCheckerForStressTest true
for i in 1 .. 10 do
printfn "stress test iteration %d (first may be slow, rest fast)" i
let projectsResults = [ for p in ManyProjectsStressTest.projects -> p, checker.ParseAndCheckProject(p.Options) |> Async.RunImmediate ]
let jointProjectResults = checker.ParseAndCheckProject(ManyProjectsStressTest.jointProject.Options) |> Async.RunImmediate
let projectsResults = [ for p in manyProjectsStressTest.Projects -> p, checker.ParseAndCheckProject(p.Options) |> Async.RunImmediate ]
let jointProjectResults = checker.ParseAndCheckProject(manyProjectsStressTest.JointProject.Options) |> Async.RunImmediate
let vsFromJointProject =
[ for s in jointProjectResults.GetAllUsesOfAllSymbols() do
@ -388,13 +382,13 @@ let ``Test ManyProjectsStressTest all symbols`` useTransparentCompiler =
let usesFromJointProject =
jointProjectResults.GetUsesOfSymbol(vFromProject)
|> Array.map (fun s -> s.Symbol.DisplayName, ManyProjectsStressTest.cleanFileName s.FileName, tups s.Symbol.DeclarationLocation.Value)
|> Array.map (fun s -> s.Symbol.DisplayName, manyProjectsStressTest.CleanFileName s.FileName, tups s.Symbol.DeclarationLocation.Value)
usesFromJointProject.Length |> shouldEqual 1
//-----------------------------------------------------------------------------------------
module internal MultiProjectDirty1 =
type internal MultiProjectDirty1(checker: FSharpChecker) =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let baseName = getTemporaryFileName()
@ -405,18 +399,20 @@ module internal MultiProjectDirty1 =
let x = "F#"
"""
FileSystem.OpenFileForWriteShim(fileName1).Write(content)
do FileSystem.OpenFileForWriteShim(fileName1).Write(content)
let cleanFileName a = if a = fileName1 then "Project1" else "??"
let fileNames = [|fileName1|]
let getOptions() =
member _.Content = content
member _.CleanFileName a = if a = fileName1 then "Project1" else "??"
member _.DllName = dllName
member _.FileName1 = fileName1
member _.GetOptions() =
let args = mkProjectCommandLineArgs (dllName, fileNames)
{ checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
module internal MultiProjectDirty2 =
type internal MultiProjectDirty2(checker: FSharpChecker, multiProjectDirty1: MultiProjectDirty1) =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let baseName = getTemporaryFileName ()
@ -430,43 +426,49 @@ open Project1
let y = x
let z = Project1.x
"""
FileSystem.OpenFileForWriteShim(fileName1).Write(content)
do FileSystem.OpenFileForWriteShim(fileName1).Write(content)
let cleanFileName a = if a = fileName1 then "Project2" else "??"
let fileNames = [|fileName1|]
let getOptions() =
member _.CleanFileName a = cleanFileName a
member _.DllName = dllName
member _.FileName1 = fileName1
member _.GetOptions() =
let args = mkProjectCommandLineArgs (dllName, fileNames)
let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
{ options with
OtherOptions = Array.append options.OtherOptions [| ("-r:" + MultiProjectDirty1.dllName) |]
ReferencedProjects = [| FSharpReferencedProject.FSharpReference(MultiProjectDirty1.dllName, MultiProjectDirty1.getOptions()) |] }
OtherOptions = Array.append options.OtherOptions [| ("-r:" + multiProjectDirty1.DllName) |]
ReferencedProjects = [| FSharpReferencedProject.FSharpReference(multiProjectDirty1.DllName, multiProjectDirty1.GetOptions()) |] }
[<Theory>]
// [<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project symbols should pick up changes in dependent projects`` useTransparentCompiler =
[<Fact>]
let ``Test multi project symbols should pick up changes in dependent projects`` () =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
// A private checker because we subscribe to FileChecked.
let checker = FSharpChecker.Create(useTransparentCompiler = CompilerAssertHelpers.UseTransparentCompiler)
let multiProjectDirty1 = MultiProjectDirty1(checker)
let multiProjectDirty2 = MultiProjectDirty2(checker, multiProjectDirty1)
// register to count the file checks
let count = ref 0
checker.FileChecked.Add (fun _ -> incr count)
let mutable count = 0
checker.FileChecked.Add (fun _ -> System.Threading.Interlocked.Increment &count |> ignore)
//---------------- Write the first version of the file in project 1 and check the project --------------------
let proj1options = MultiProjectDirty1.getOptions()
let proj1options = multiProjectDirty1.GetOptions()
let wholeProjectResults1 = checker.ParseAndCheckProject(proj1options) |> Async.RunImmediate
count.Value |> shouldEqual 1
count |> shouldEqual 1
let backgroundParseResults1, backgroundTypedParse1 =
checker.GetBackgroundCheckResultsForFileInProject(MultiProjectDirty1.fileName1, proj1options)
checker.GetBackgroundCheckResultsForFileInProject(multiProjectDirty1.FileName1, proj1options)
|> Async.RunImmediate
count.Value |> shouldEqual 1
count |> shouldEqual 1
//---------------- Get a symbol from project 1 and look up its uses in both projects --------------------
@ -476,19 +478,19 @@ let ``Test multi project symbols should pick up changes in dependent projects``
printfn "Symbol found. Checking symbol uses in another project..."
let proj2options = MultiProjectDirty2.getOptions()
let proj2options = multiProjectDirty2.GetOptions()
let wholeProjectResults2 = checker.ParseAndCheckProject(proj2options) |> Async.RunImmediate
count.Value |> shouldEqual 2
count |> shouldEqual 2
let _ = checker.ParseAndCheckProject(proj2options) |> Async.RunImmediate
count.Value |> shouldEqual 2 // cached
count |> shouldEqual 2 // cached
let usesOfXSymbolInProject1 =
wholeProjectResults1.GetUsesOfSymbol(xSymbol)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty1.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty1.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject1
|> shouldEqual
@ -496,7 +498,7 @@ let ``Test multi project symbols should pick up changes in dependent projects``
let usesOfXSymbolInProject2 =
wholeProjectResults2.GetUsesOfSymbol(xSymbol)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty2.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty2.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject2
|> shouldEqual
@ -506,22 +508,21 @@ let ``Test multi project symbols should pick up changes in dependent projects``
//---------------- Change the file by adding a line, then re-check everything --------------------
let wt0 = System.DateTime.UtcNow
let wt1 = FileSystem.GetLastWriteTimeShim MultiProjectDirty1.fileName1
printfn "Writing new content to file '%s'" MultiProjectDirty1.fileName1
System.Threading.Thread.Sleep(1000)
FileSystem.OpenFileForWriteShim(MultiProjectDirty1.fileName1).Write(System.Environment.NewLine + MultiProjectDirty1.content)
printfn "Wrote new content to file '%s'" MultiProjectDirty1.fileName1
let wt2 = FileSystem.GetLastWriteTimeShim MultiProjectDirty1.fileName1
let wt1 = FileSystem.GetLastWriteTimeShim multiProjectDirty1.FileName1
printfn "Writing new content to file '%s'" multiProjectDirty1.FileName1
FileSystem.OpenFileForWriteShim(multiProjectDirty1.FileName1).Write(System.Environment.NewLine + multiProjectDirty1.Content)
printfn "Wrote new content to file '%s'" multiProjectDirty1.FileName1
let wt2 = FileSystem.GetLastWriteTimeShim multiProjectDirty1.FileName1
Assert.NotEqual(wt1, wt2)
printfn "Current time: '%A', ticks = %d" wt0 wt0.Ticks
printfn "Old write time: '%A', ticks = %d" wt1 wt1.Ticks
printfn "New write time: '%A', ticks = %d" wt2 wt2.Ticks
let wholeProjectResults1AfterChange1 = checker.ParseAndCheckProject(proj1options) |> Async.RunImmediate
count.Value |> shouldEqual 3
count |> shouldEqual 3
let backgroundParseResults1AfterChange1, backgroundTypedParse1AfterChange1 =
checker.GetBackgroundCheckResultsForFileInProject(MultiProjectDirty1.fileName1, proj1options)
checker.GetBackgroundCheckResultsForFileInProject(multiProjectDirty1.FileName1, proj1options)
|> Async.RunImmediate
let xSymbolUseAfterChange1 = backgroundTypedParse1AfterChange1.GetSymbolUseAtLocation(4, 4, "", ["x"])
@ -533,11 +534,11 @@ let ``Test multi project symbols should pick up changes in dependent projects``
let wholeProjectResults2AfterChange1 = checker.ParseAndCheckProject(proj2options) |> Async.RunImmediate
count.Value |> shouldEqual 4
count |> shouldEqual 4
let usesOfXSymbolInProject1AfterChange1 =
wholeProjectResults1AfterChange1.GetUsesOfSymbol(xSymbolAfterChange1)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty1.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty1.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject1AfterChange1
|> shouldEqual
@ -545,7 +546,7 @@ let ``Test multi project symbols should pick up changes in dependent projects``
let usesOfXSymbolInProject2AfterChange1 =
wholeProjectResults2AfterChange1.GetUsesOfSymbol(xSymbolAfterChange1)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty2.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty2.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject2AfterChange1
|> shouldEqual
@ -555,29 +556,27 @@ let ``Test multi project symbols should pick up changes in dependent projects``
//---------------- Revert the change to the file --------------------
let wt0b = System.DateTime.UtcNow
let wt1b = FileSystem.GetLastWriteTimeShim MultiProjectDirty1.fileName1
printfn "Writing old content to file '%s'" MultiProjectDirty1.fileName1
System.Threading.Thread.Sleep(1000)
FileSystem.OpenFileForWriteShim(MultiProjectDirty1.fileName1).Write(MultiProjectDirty1.content)
printfn "Wrote old content to file '%s'" MultiProjectDirty1.fileName1
let wt2b = FileSystem.GetLastWriteTimeShim MultiProjectDirty1.fileName1
let wt1b = FileSystem.GetLastWriteTimeShim multiProjectDirty1.FileName1
printfn "Writing old content to file '%s'" multiProjectDirty1.FileName1
FileSystem.OpenFileForWriteShim(multiProjectDirty1.FileName1).Write(multiProjectDirty1.Content)
printfn "Wrote old content to file '%s'" multiProjectDirty1.FileName1
let wt2b = FileSystem.GetLastWriteTimeShim multiProjectDirty1.FileName1
Assert.NotEqual(wt1b, wt2b)
printfn "Current time: '%A', ticks = %d" wt0b wt0b.Ticks
printfn "Old write time: '%A', ticks = %d" wt1b wt1b.Ticks
printfn "New write time: '%A', ticks = %d" wt2b wt2b.Ticks
count.Value |> shouldEqual 4
count |> shouldEqual 4
let wholeProjectResults2AfterChange2 = checker.ParseAndCheckProject(proj2options) |> Async.RunImmediate
System.Threading.Thread.Sleep(1000)
count.Value |> shouldEqual 6 // note, causes two files to be type checked, one from each project
count |> shouldEqual 6 // note, causes two files to be type checked, one from each project
let wholeProjectResults1AfterChange2 = checker.ParseAndCheckProject(proj1options) |> Async.RunImmediate
count.Value |> shouldEqual 6 // the project is already checked
count |> shouldEqual 6 // the project is already checked
let backgroundParseResults1AfterChange2, backgroundTypedParse1AfterChange2 =
checker.GetBackgroundCheckResultsForFileInProject(MultiProjectDirty1.fileName1, proj1options)
checker.GetBackgroundCheckResultsForFileInProject(multiProjectDirty1.FileName1, proj1options)
|> Async.RunImmediate
let xSymbolUseAfterChange2 = backgroundTypedParse1AfterChange2.GetSymbolUseAtLocation(4, 4, "", ["x"])
@ -587,7 +586,7 @@ let ``Test multi project symbols should pick up changes in dependent projects``
let usesOfXSymbolInProject1AfterChange2 =
wholeProjectResults1AfterChange2.GetUsesOfSymbol(xSymbolAfterChange2)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty1.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty1.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject1AfterChange2
|> shouldEqual
@ -596,7 +595,7 @@ let ``Test multi project symbols should pick up changes in dependent projects``
let usesOfXSymbolInProject2AfterChange2 =
wholeProjectResults2AfterChange2.GetUsesOfSymbol(xSymbolAfterChange2)
|> Array.map (fun su -> su.Symbol.ToString(), MultiProjectDirty2.cleanFileName su.FileName, tups su.Range)
|> Array.map (fun su -> su.Symbol.ToString(), multiProjectDirty2.CleanFileName su.FileName, tups su.Range)
usesOfXSymbolInProject2AfterChange2
|> shouldEqual
@ -682,12 +681,8 @@ let v = Project2A.C().InternalMember // access an internal symbol
ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project2A.dllName, Project2A.options); |] }
let cleanFileName a = if a = fileName1 then "file1" else "??"
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project2 errors`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project2 errors`` () =
let wholeProjectResults = checker.ParseAndCheckProject(Project2B.options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -700,12 +695,8 @@ let ``Test multi project2 errors`` useTransparentCompiler =
wholeProjectResultsC.Diagnostics.Length |> shouldEqual 1
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project 2 all symbols`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project 2 all symbols`` () =
let mpA = checker.ParseAndCheckProject(Project2A.options) |> Async.RunImmediate
let mpB = checker.ParseAndCheckProject(Project2B.options) |> Async.RunImmediate
@ -783,12 +774,8 @@ let fizzBuzz = function
ReferencedProjects = [| FSharpReferencedProject.FSharpReference(Project3A.dllName, Project3A.options) |] }
let cleanFileName a = if a = fileName1 then "file1" else "??"
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test multi project 3 whole project errors`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test multi project 3 whole project errors`` () =
let wholeProjectResults = checker.ParseAndCheckProject(MultiProject3.options) |> Async.RunImmediate
for e in wholeProjectResults.Diagnostics do
@ -796,12 +783,8 @@ let ``Test multi project 3 whole project errors`` useTransparentCompiler =
wholeProjectResults.Diagnostics.Length |> shouldEqual 0
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``Test active patterns' XmlDocSig declared in referenced projects`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``Test active patterns' XmlDocSig declared in referenced projects`` () =
let wholeProjectResults = checker.ParseAndCheckProject(MultiProject3.options) |> Async.RunImmediate
let backgroundParseResults1, backgroundTypedParse1 =
@ -830,13 +813,9 @@ let ``Test active patterns' XmlDocSig declared in referenced projects`` useTrans
//------------------------------------------------------------------------------------
[<Theory>]
[<InlineData(true)>]
[<InlineData(false)>]
let ``In-memory cross-project references to projects using generative type provides should fallback to on-disk references`` useTransparentCompiler =
let checker = if useTransparentCompiler then transparentCompilerChecker else checker
[<Fact>]
let ``In-memory cross-project references to projects using generative type provides should fallback to on-disk references`` () =
// The type provider and its dependency are compiled as part of the solution build
#if DEBUG
let csDLL = __SOURCE_DIRECTORY__ + @"/../../artifacts/bin/TestTP/Debug/netstandard2.0/CSharp_Analysis.dll"

Просмотреть файл

@ -4639,11 +4639,9 @@ let callToOverload = B(5).Overload(4)
let fileNames = [|fileName1|]
let args = mkProjectCommandLineArgs (dllName, [])
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` useTransparentCompiler =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
[<Fact>]
let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` () =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames }
let wholeProjectResults =
keepAssemblyContentsChecker.ParseAndCheckProject(options)
@ -4656,11 +4654,9 @@ let ``Test project36 FSharpMemberOrFunctionOrValue.IsBaseValue`` useTransparentC
else None)
|> fun baseSymbol -> shouldEqual true baseSymbol.IsBaseValue
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMemberThisValue`` useTransparentCompiler =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
[<Fact>]
let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMemberThisValue`` () =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames }
let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(options) |> Async.RunImmediate
let declarations =
@ -4695,11 +4691,9 @@ let ``Test project36 FSharpMemberOrFunctionOrValue.IsConstructorThisValue & IsMe
| _ -> failwith "unexpected expression"
|> shouldEqual true
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Test project36 FSharpMemberOrFunctionOrValue.LiteralValue`` useTransparentCompiler =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
[<Fact>]
let ``Test project36 FSharpMemberOrFunctionOrValue.LiteralValue`` () =
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (Project36.projFileName, Project36.args) with SourceFiles = Project36.fileNames }
let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(options) |> Async.RunImmediate
let project36Module = wholeProjectResults.AssemblySignature.Entities[0]
@ -5316,11 +5310,9 @@ let foo (a: Foo): bool =
let args = mkProjectCommandLineArgs (dllName, [])
let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Test typed AST for struct unions`` useTransparentCompiler = // See https://github.com/fsharp/FSharp.Compiler.Service/issues/756
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
[<Fact>]
let ``Test typed AST for struct unions`` () = // See https://github.com/fsharp/FSharp.Compiler.Service/issues/756
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let wholeProjectResults = keepAssemblyContentsChecker.ParseAndCheckProject(ProjectStructUnions.options) |> Async.RunImmediate
let declarations =
@ -5406,10 +5398,8 @@ let ``Test diagnostics with line directives ignored`` () =
//------------------------------------------------------
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``ParseAndCheckFileResults contains ImplFile list if FSharpChecker is created with keepAssemblyContent flag set to true`` useTransparentCompiler =
[<Fact>]
let ``ParseAndCheckFileResults contains ImplFile list if FSharpChecker is created with keepAssemblyContent flag set to true`` () =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let base2 = getTemporaryFileName ()
@ -5424,7 +5414,7 @@ type A(i:int) =
let fileNames = [|fileName1|]
let args = mkProjectCommandLineArgs (dllName, [])
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
let fileCheckResults =
@ -5492,10 +5482,8 @@ let ``#4030, Incremental builder creation warnings 5`` () =
//------------------------------------------------------
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Unused opens in rec module smoke test 1`` useTransparentCompiler =
[<Fact>]
let ``Unused opens in rec module smoke test 1`` () =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let base2 = getTemporaryFileName ()
@ -5543,7 +5531,7 @@ type UseTheThings(i:int) =
let fileNames = [|fileName1|]
let args = mkProjectCommandLineArgs (dllName, [])
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
let fileCheckResults =
@ -5567,10 +5555,8 @@ type UseTheThings(i:int) =
(((25, 5), (25, 21)), "open SomeUnusedModule")]
unusedOpensData |> shouldEqual expected
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Unused opens in non rec module smoke test 1`` useTransparentCompiler =
[<Fact>]
let ``Unused opens in non rec module smoke test 1`` () =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let base2 = getTemporaryFileName ()
@ -5630,7 +5616,7 @@ type UseTheThings(i:int) =
let fileNames = [|fileName1|]
let args = mkProjectCommandLineArgs (dllName, [])
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
let fileCheckResults =
@ -5656,10 +5642,8 @@ type UseTheThings(i:int) =
(((37, 10), (37, 21)), "open type FSharpEnum2 // Unused, should appear.")]
unusedOpensData |> shouldEqual expected
[<Theory>]
// [<InlineData true>] // Flaky, reenable when stable
[<InlineData false>]
let ``Unused opens smoke test auto open`` useTransparentCompiler =
[<Fact>]
let ``Unused opens smoke test auto open`` () =
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
let base2 = getTemporaryFileName ()
@ -5715,7 +5699,7 @@ module M2 =
let fileNames = [|fileName1|]
let args = mkProjectCommandLineArgs (dllName, [])
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=useTransparentCompiler)
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
let fileCheckResults =