Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3081,6 +3081,9 @@ type internal FsiDynamicCompiler

member _.ValueBound = valueBoundEvent.Publish

member _.PeekNextFragmentPath() =
FsiDynamicModulePrefix + $"%04d{fragmentId + 1}"

//----------------------------------------------------------------------------
// ctrl-c handling
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -4450,13 +4453,22 @@ type FsiInteractionProcessor
let names = names |> List.filter (fun name -> name.StartsWithOrdinal(stem))
names

member _.ParseAndCheckInteraction(legacyReferenceResolver, istate, text: string) =
member _.ParseAndCheckInteraction(legacyReferenceResolver, istate, text: string, ?keepAssemblyContents: bool) =
let tcConfig = TcConfig.Create(tcConfigB, validate = false)

let nextFragmentPath = fsiDynamicCompiler.PeekNextFragmentPath()

let fsiInteractiveChecker =
FsiInteractiveChecker(legacyReferenceResolver, tcConfig, istate.tcGlobals, istate.tcImports, istate.tcState)
FsiInteractiveChecker(
legacyReferenceResolver,
tcConfig,
istate.tcGlobals,
istate.tcImports,
istate.tcState,
?keepAssemblyContents = keepAssemblyContents
)

fsiInteractiveChecker.ParseAndCheckInteraction(SourceText.ofString text)
fsiInteractiveChecker.ParseAndCheckInteraction(SourceText.ofString text, asmName = nextFragmentPath)

//----------------------------------------------------------------------------
// Server mode:
Expand Down Expand Up @@ -4808,8 +4820,13 @@ type FsiEvaluationSession
fsiInteractionProcessor.CompletionsForPartialLID(fsiInteractionProcessor.CurrentState, longIdent)
|> Seq.ofList

member _.ParseAndCheckInteraction(code) =
fsiInteractionProcessor.ParseAndCheckInteraction(legacyReferenceResolver, fsiInteractionProcessor.CurrentState, code)
member _.ParseAndCheckInteraction(code, ?keepAssemblyContents) =
fsiInteractionProcessor.ParseAndCheckInteraction(
legacyReferenceResolver,
fsiInteractionProcessor.CurrentState,
code,
?keepAssemblyContents = keepAssemblyContents
)
|> Cancellable.runWithoutCancellation

member _.InteractiveChecker = checker
Expand Down
17 changes: 12 additions & 5 deletions src/Compiler/Interactive/fsi.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,20 @@ type FsiEvaluationSession =
/// This event is triggered after parsing and checking, either via input from 'stdin', or via a call to EvalInteraction.
member PartialAssemblySignatureUpdated: IEvent<unit>

/// Typecheck the given script fragment in the type checking context implied by the current state
/// of F# Interactive. The results can be used to access intellisense, perform resolutions,
/// check brace matching and other information.
/// <summary>
/// <para>Typecheck the given script fragment in the type checking context implied by the current state
/// of F# Interactive. The results can be used to access intellisense, perform resolutions,
/// check brace matching and other information. Accessing assembly contents need 'keepAssemblyContents'
/// set to 'true'.</para>
/// <para></para>
/// <para>Operations may be run concurrently with other requests to the InteractiveChecker.</para>
/// </summary>
///
/// Operations may be run concurrently with other requests to the InteractiveChecker.
/// <param name="code">Source code of the interaction to check.</param>
/// <param name="keepAssemblyContents">Keep the checked contents of the interaction.</param>
member ParseAndCheckInteraction:
code: string -> FSharpParseFileResults * FSharpCheckFileResults * FSharpCheckProjectResults
code: string * ?keepAssemblyContents: bool ->
FSharpParseFileResults * FSharpCheckFileResults * FSharpCheckProjectResults

/// The single, global interactive checker to use in conjunction with other operations
/// on the FsiEvaluationSession.
Expand Down
20 changes: 14 additions & 6 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3990,14 +3990,16 @@ type FSharpCheckProjectResults
override _.ToString() =
"FSharpCheckProjectResults(" + projectFileName + ")"

type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobals: TcGlobals, tcImports: TcImports, tcState) =
type FsiInteractiveChecker
(legacyReferenceResolver, tcConfig: TcConfig, tcGlobals: TcGlobals, tcImports: TcImports, tcState, ?keepAssemblyContents: bool) =

let keepAssemblyContents = false
let keepAssemblyContents = defaultArg keepAssemblyContents false

member _.ParseAndCheckInteraction(sourceText: ISourceText, ?userOpName: string) =
member _.ParseAndCheckInteraction(sourceText: ISourceText, ?userOpName: string, ?asmName: string) =
cancellable {
let userOpName = defaultArg userOpName "Unknown"
let fileName = Path.Combine(tcConfig.implicitIncludeDir, "stdin.fsx")
let asmName = defaultArg asmName "stdin"
let fileName = Path.Combine(tcConfig.implicitIncludeDir, asmName + ".fsx")
let suggestNamesForErrors = true // Will always be true, this is just for readability
// Note: projectSourceFiles is only used to compute isLastCompiland, and is ignored if Build.IsScript(mainInputFileName) is true (which it is in this case).
let parsingOptions =
Expand Down Expand Up @@ -4087,6 +4089,12 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobal
let typeCheckResults =
FSharpCheckFileResults(fileName, errors, Some tcFileInfo, dependencyFiles, None, false)

let checkedImplFiles =
if keepAssemblyContents then
tcFileInfo.ImplementationFile |> Option.map List.singleton
else
None

let details =
(tcGlobals,
tcImports,
Expand All @@ -4095,9 +4103,9 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobal
Choice2Of2(tcFileInfo.ScopeSymbolUses |> Seq.singleton |> async.Return),
None,
(fun () -> None),
mkSimpleAssemblyRef "stdin",
mkSimpleAssemblyRef asmName,
tcState.TcEnvFromImpls.AccessRights,
None,
checkedImplFiles,
dependencyFiles,
Some projectOptions)

Expand Down
9 changes: 7 additions & 2 deletions src/Compiler/Service/FSharpCheckerResults.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -620,11 +620,16 @@ module internal ParseAndCheckFile =
// Used internally to provide intellisense over F# Interactive.
type internal FsiInteractiveChecker =
internal new:
LegacyReferenceResolver * tcConfig: TcConfig * tcGlobals: TcGlobals * tcImports: TcImports * tcState: TcState ->
LegacyReferenceResolver *
tcConfig: TcConfig *
tcGlobals: TcGlobals *
tcImports: TcImports *
tcState: TcState *
?keepAssemblyContents: bool ->
FsiInteractiveChecker

member internal ParseAndCheckInteraction:
sourceText: ISourceText * ?userOpName: string ->
sourceText: ISourceText * ?userOpName: string * ?asmName: string ->
Cancellable<FSharpParseFileResults * FSharpCheckFileResults * FSharpCheckProjectResults>

module internal FSharpCheckerResultsSettings =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4984,7 +4984,7 @@ FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`2[Microsoft
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`2[Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Interactive.Shell+FsiValue],System.Exception],FSharp.Compiler.Diagnostics.FSharpDiagnostic[]] EvalInteractionNonThrowing(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken])
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`2[Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Interactive.Shell+FsiValue],System.Exception],FSharp.Compiler.Diagnostics.FSharpDiagnostic[]] EvalInteractionNonThrowing(System.String, System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken])
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`2[Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,System.Exception],FSharp.Compiler.Diagnostics.FSharpDiagnostic[]] EvalScriptNonThrowing(System.String)
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckInteraction(System.String)
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckInteraction(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: Void AddBoundValue(System.String, System.Object)
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: Void EvalInteraction(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken])
FSharp.Compiler.Interactive.Shell+FsiEvaluationSession: Void EvalInteraction(System.String, System.String, Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken])
Expand Down
Loading