Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IFileSystem.SourceFileReadShim returning char[] #4948

Closed
wants to merge 2 commits into from
Closed
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
19 changes: 18 additions & 1 deletion src/absil/illib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,9 @@ module Shim =
/// A shim over FileStream with FileMode.Open,FileAccess.Read,FileShare.ReadWrite
abstract FileStreamReadShim: fileName:string -> Stream

/// A shim used for lexing F# source files
abstract SourceFileReadShim: fileName: string * codepage: int option -> char[]

/// A shim over FileStream with FileMode.Create,FileAccess.Write,FileShare.Read
abstract FileStreamCreateShim: fileName:string -> Stream

Expand Down Expand Up @@ -1232,6 +1235,10 @@ module Shim =


type DefaultFileSystem() =

let fileStremReadShim fileName =
new FileStream(fileName,FileMode.Open,FileAccess.Read,FileShare.ReadWrite) :> Stream

interface IFileSystem with

member __.AssemblyLoadFrom(fileName: string) =
Expand All @@ -1242,7 +1249,17 @@ module Shim =

member __.ReadAllBytesShim (fileName: string) = File.ReadAllBytes fileName

member __.FileStreamReadShim (fileName: string) = new FileStream(fileName,FileMode.Open,FileAccess.Read,FileShare.ReadWrite) :> Stream
member __.FileStreamReadShim (fileName: string) =
fileStremReadShim fileName

member __.SourceFileReadShim(fileName: string, codepage: int option) =
// Use the .NET functionality to auto-detect the unicode encoding
use stream = fileStremReadShim fileName
use reader =
match codepage with
| None -> new StreamReader(stream,true)
| Some n -> new StreamReader(stream,System.Text.Encoding.GetEncoding(n))
reader.ReadToEnd().ToCharArray()

member __.FileStreamCreateShim (fileName: string) = new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.Read ,0x1000,false) :> Stream

Expand Down
17 changes: 6 additions & 11 deletions src/fsharp/CompileOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5020,7 +5020,7 @@ module private ScriptPreprocessClosure =
open Internal.Utilities.Text.Lexing

/// Represents an input to the closure finding process
type ClosureSource = ClosureSource of filename: string * referenceRange: range * sourceText: string * parseRequired: bool
type ClosureSource = ClosureSource of filename: string * referenceRange: range * source: char[] * parseRequired: bool

/// Represents an output of the closure finding process
type ClosureFile = ClosureFile of string * range * ParsedInput option * (PhasedDiagnostic * bool) list * (PhasedDiagnostic * bool) list * (string * range) list // filename, range, errors, warnings, nowarns
Expand All @@ -5035,7 +5035,7 @@ module private ScriptPreprocessClosure =
seen.ContainsKey(check)

/// Parse a script from source.
let ParseScriptText(filename:string, source:string, tcConfig:TcConfig, codeContext, lexResourceManager:Lexhelp.LexResourceManager, errorLogger:ErrorLogger) =
let ParseScriptText(filename:string, source: char[], tcConfig:TcConfig, codeContext, lexResourceManager:Lexhelp.LexResourceManager, errorLogger:ErrorLogger) =

// fsc.exe -- COMPILED\!INTERACTIVE
// fsi.exe -- !COMPILED\INTERACTIVE
Expand All @@ -5047,7 +5047,7 @@ module private ScriptPreprocessClosure =
| CodeContext.CompilationAndEvaluation -> ["INTERACTIVE"]
| CodeContext.Compilation -> ["COMPILED"]
| CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"])
let lexbuf = UnicodeLexing.StringAsLexbuf source
let lexbuf = LexBuffer<_>.FromChars(source)

let isLastCompiland = (IsScript filename), tcConfig.target.IsExe // The root compiland is last in the list of compilands.
ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, errorLogger)
Expand Down Expand Up @@ -5078,12 +5078,7 @@ module private ScriptPreprocessClosure =
let ClosureSourceOfFilename(filename, m, inputCodePage, parseRequired) =
try
let filename = FileSystem.GetFullPathShim(filename)
use stream = FileSystem.FileStreamReadShim filename
use reader =
match inputCodePage with
| None -> new StreamReader(stream, true)
| Some (n: int) -> new StreamReader(stream, Encoding.GetEncoding(n))
let source = reader.ReadToEnd()
let source = FileSystem.SourceFileReadShim(filename, inputCodePage)
[ClosureSource(filename, m, source, parseRequired)]
with e ->
errorRecovery e m
Expand Down Expand Up @@ -5251,9 +5246,9 @@ type LoadClosure with
//
/// A temporary TcConfig is created along the way, is why this routine takes so many arguments. We want to be sure to use exactly the
/// same arguments as the rest of the application.
static member ComputeClosureOfScriptText(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename:string, source:string, codeContext, useSimpleResolution:bool, useFsiAuxLib, lexResourceManager:Lexhelp.LexResourceManager, applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) : LoadClosure =
static member ComputeClosureOfScriptText(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename:string, source: string, codeContext, useSimpleResolution:bool, useFsiAuxLib, lexResourceManager:Lexhelp.LexResourceManager, applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) : LoadClosure =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
ScriptPreprocessClosure.GetFullClosureOfScriptText(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, source, codeContext, useSimpleResolution, useFsiAuxLib, lexResourceManager, applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)
ScriptPreprocessClosure.GetFullClosureOfScriptText(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, source.ToCharArray(), codeContext, useSimpleResolution, useFsiAuxLib, lexResourceManager, applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)

/// Analyze a set of script files and find the closure of their references. The resulting references are then added to the given TcConfig.
/// Used from fsi.fs and fsc.fs, for #load and command line.
Expand Down
16 changes: 5 additions & 11 deletions src/fsharp/UnicodeLexing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,12 @@ let numRetries = 60
/// we can't just return the LexBuffer object, since the file it wraps wouldn't
/// get closed when we're finished with the LexBuffer. Hence we return the stream,
/// the reader and the LexBuffer. The caller should dispose the first two when done.
let UnicodeFileAsLexbuf (filename,codePage : int option, retryLocked:bool) : Lexbuf =
let UnicodeFileAsLexbuf (filename, codepage: int option, retryLocked: bool): Lexbuf =
// Retry multiple times since other processes may be writing to this file.
let rec getSource retryNumber =
try
// Use the .NET functionality to auto-detect the unicode encoding
use stream = FileSystem.FileStreamReadShim(filename)
use reader =
match codePage with
| None -> new StreamReader(stream,true)
| Some n -> new StreamReader(stream,System.Text.Encoding.GetEncoding(n))
reader.ReadToEnd()
with
try
FileSystem.SourceFileReadShim(filename, codepage)
with
// We can get here if the file is locked--like when VS is saving a file--we don't have direct
// access to the HRESULT to see that this is EONOACCESS.
| :? System.IO.IOException as err when retryLocked && err.GetType() = typeof<System.IO.IOException> ->
Expand All @@ -65,5 +59,5 @@ let UnicodeFileAsLexbuf (filename,codePage : int option, retryLocked:bool) : Le
else
reraise()
let source = getSource 0
let lexbuf = LexBuffer<_>.FromChars(source.ToCharArray())
let lexbuf = LexBuffer<_>.FromChars(source)
lexbuf
2 changes: 2 additions & 0 deletions tests/service/FileSystemTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ let B = File1.A + File1.A"""
member __.AssemblyLoadFrom(fileName) = defaultFileSystem.AssemblyLoadFrom fileName
member __.AssemblyLoad(assemblyName) = defaultFileSystem.AssemblyLoad assemblyName

member __.SourceFileReadShim(fileName, codepage) = defaultFileSystem.SourceFileReadShim(fileName, codepage)

let UseMyFileSystem() =
let myFileSystem = MyFileSystem(Shim.FileSystem)
Shim.FileSystem <- myFileSystem
Expand Down