Skip to content

Commit 2c962f8

Browse files
committed
[WIP] Fixes
1 parent 0279acf commit 2c962f8

File tree

5 files changed

+88
-69
lines changed

5 files changed

+88
-69
lines changed

src/fsharp/absil/ilread.fs

+31-16
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,31 @@ type BinaryFile =
116116
/// Gives views over a raw chunk of memory, for example those returned to us by the memory manager in Roslyn's
117117
/// Visual Studio integration. 'obj' must keep the memory alive. The object will capture it and thus also keep the memory alive for
118118
/// the lifetime of this object.
119-
type RawMemoryFile(fileName: string, obj: obj, addr: nativeint, length: int) =
120-
do stats.rawMemoryFileCount <- stats.rawMemoryFileCount + 1
121-
let view = ByteMemory.FromUnsafePointer(addr, length, obj).AsReadOnly()
122-
member _.HoldObj() = obj // make sure we capture 'obj'
123-
member _.FileName = fileName
119+
type RawMemoryFile =
120+
val mutable private holder: obj
121+
val mutable private fileName: string
122+
val mutable private view: ReadOnlyByteMemory
123+
124+
new (fileName: string, obj: obj, addr: nativeint, length: int) =
125+
stats.rawMemoryFileCount <- stats.rawMemoryFileCount + 1
126+
{
127+
holder = obj
128+
fileName = fileName
129+
view = ByteMemory.FromUnsafePointer(addr, length, obj).AsReadOnly()
130+
}
131+
132+
new (fileName: string, holder: obj, bmem: ByteMemory) =
133+
{
134+
holder = holder // gonna be finalized due to how we pass the holder when create RawByteMemory
135+
fileName = fileName
136+
view = bmem.AsReadOnly()
137+
}
138+
139+
member r.HoldObj() = r.holder // make sure we capture the holder.
140+
member r.FileName = r.fileName
141+
124142
interface BinaryFile with
125-
override _.GetView() = view
143+
override r.GetView() = r.view
126144

127145
/// Gives a view over any ByteMemory, can be stream-based, mmap-ed, or just byte array.
128146
type ByteMemoryFile(fileName: string, view: ByteMemory) =
@@ -3893,25 +3911,22 @@ let createByteFileChunk opts fileName chunk =
38933911

38943912
ByteFile(fileName, bytes) :> BinaryFile
38953913

3896-
let _createMemoryMapFile fileName =
3897-
let mmf, accessor, length =
3898-
// TODO: Need to integrate with FileSystem
3899-
let fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)
3900-
let length = fileStream.Length
3901-
let mmf = MemoryMappedFile.CreateFromFile(fileStream, null, length, MemoryMappedFileAccess.Read, HandleInheritability.None, leaveOpen=false)
3902-
mmf, mmf.CreateViewAccessor(0L, fileStream.Length, MemoryMappedFileAccess.Read), length
3914+
let createMemoryMapFile fileName =
3915+
let byteMem = FileSystem.OpenFileForReadShim(fileName)
3916+
39033917
let safeHolder =
39043918
{ new obj() with
39053919
override x.Finalize() =
39063920
(x :?> IDisposable).Dispose()
39073921
interface IDisposable with
39083922
member x.Dispose() =
39093923
GC.SuppressFinalize x
3910-
accessor.Dispose()
3911-
mmf.Dispose()
3924+
byteMem.AsStream().Dispose()
39123925
stats.memoryMapFileClosedCount <- stats.memoryMapFileClosedCount + 1 }
3926+
39133927
stats.memoryMapFileOpenedCount <- stats.memoryMapFileOpenedCount + 1
3914-
safeHolder, RawMemoryFile(fileName, safeHolder, accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length) :> BinaryFile
3928+
3929+
safeHolder, RawMemoryFile(fileName, safeHolder, byteMem) :> BinaryFile
39153930

39163931
let OpenILModuleReaderFromBytes fileName assemblyContents options =
39173932
let pefile = ByteFile(fileName, assemblyContents) :> BinaryFile

src/fsharp/service/ItemKey.fs

+1-2
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,7 @@ and [<Sealed>] ItemKeyStoreBuilder() =
418418

419419
fixup.WriteInt32(postCount - preCount)
420420

421-
// TODO: Needs to use FileSystem APIs?
422-
member _._TryBuildAndReset() =
421+
member _.TryBuildAndReset() =
423422
if b.Count > 0 then
424423
let length = int64 b.Count
425424
let mmf =

src/fsharp/service/SemanticClassificationKey.fs

+1-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ type SemanticClassificationKeyStoreBuilder() =
6363
use ptr = fixed semanticClassification
6464
b.WriteBytes(NativePtr.ofNativeInt (NativePtr.toNativeInt ptr), semanticClassification.Length * sizeof<SemanticClassificationItem>)
6565

66-
// TODO: Needs to use FileSystem APIs?
67-
member _._TryBuildAndReset() =
66+
member _.TryBuildAndReset() =
6867
if b.Count > 0 then
6968
let length = int64 b.Count
7069
let mmf =

src/fsharp/utils/FileSystem.fs

+3-4
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,8 @@ type ReadOnlyByteMemory(bytes: ByteMemory) =
285285

286286
[<AutoOpen>]
287287
module MemoryMappedFileExtensions =
288-
289288
type MemoryMappedFile with
290-
291-
// TODO: Needs to use FileSystem APIs?
292-
static member _TryFromByteMemory(bytes: ReadOnlyByteMemory) =
289+
static member TryFromByteMemory(bytes: ReadOnlyByteMemory) =
293290
let length = int64 bytes.Length
294291
if length = 0L then
295292
None
@@ -396,8 +393,10 @@ type DefaultAssemblyLoader() =
396393

397394
type IFileSystem =
398395
abstract AssemblyLoader: IAssemblyLoader
396+
399397
abstract OpenFileForReadShim: filePath: string * ?shouldShadowCopy: bool -> ByteMemory
400398
abstract OpenFileForWriteShim: filePath: string * ?fileMode: FileMode * ?fileAccess: FileAccess * ?fileShare: FileShare -> Stream
399+
401400
abstract GetFullPathShim: fileName: string -> string
402401
abstract GetFullFilePathInDirectoryShim: dir: string -> fileName: string -> string
403402
abstract IsPathRootedShim: path: string -> bool

tests/service/FileSystemTests.fs

+52-45
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ open FSharp.Compiler.Service.Tests.Common
2020
let fileName1 = @"c:\mycode\test1.fs" // note, the path doesn' exist
2121
let fileName2 = @"c:\mycode\test2.fs" // note, the path doesn' exist
2222

23-
type internal MyFileSystem(defaultFileSystem:IFileSystem) =
23+
type internal MyFileSystem(defaultFileSystem:IFileSystem) =
2424
let file1 = """
2525
module File1
2626
@@ -31,25 +31,26 @@ let B = File1.A + File1.A"""
3131
let files = dict [(fileName1, file1); (fileName2, file2)]
3232

3333
interface IFileSystem with
34+
35+
member _.AssemblyLoader = DefaultAssemblyLoader() :> IAssemblyLoader
3436
// Implement the service to open files for reading and writing
35-
member _.FileStreamReadShim(fileName) =
36-
match files.TryGetValue fileName with
37-
| true, text -> new MemoryStream(Encoding.UTF8.GetBytes(text)) :> Stream
38-
| _ -> defaultFileSystem.FileStreamReadShim(fileName)
39-
40-
member _.FileStreamCreateShim(fileName) =
41-
defaultFileSystem.FileStreamCreateShim(fileName)
42-
43-
member _.IsStableFileHeuristic(fileName) =
37+
member _.OpenFileForReadShim(filePath, ?shouldShadowCopy: bool) =
38+
let shouldShadowCopy = defaultArg shouldShadowCopy false
39+
match files.TryGetValue filePath with
40+
| true, text ->
41+
let bytes = Encoding.UTF8.GetBytes(text)
42+
ByteArrayMemory(bytes, 0, bytes.Length) :> ByteMemory
43+
| _ -> defaultFileSystem.OpenFileForReadShim(filePath, shouldShadowCopy)
44+
45+
member _.OpenFileForWriteShim(filePath, ?fileMode: FileMode, ?fileAccess: FileAccess, ?fileShare: FileShare) =
46+
let fileMode = defaultArg fileMode FileMode.OpenOrCreate
47+
let fileAccess = defaultArg fileAccess FileAccess.ReadWrite
48+
let fileShare = defaultArg fileShare FileShare.Read
49+
defaultFileSystem.OpenFileForWriteShim(filePath, fileMode, fileAccess, fileShare)
50+
51+
member _.IsStableFileHeuristic(fileName) =
4452
defaultFileSystem.IsStableFileHeuristic(fileName)
4553

46-
member _.FileStreamWriteExistingShim(fileName) =
47-
defaultFileSystem.FileStreamWriteExistingShim(fileName)
48-
49-
member _.ReadAllBytesShim(fileName) =
50-
match files.TryGetValue fileName with
51-
| true, text -> Encoding.UTF8.GetBytes(text)
52-
| _ -> defaultFileSystem.ReadAllBytesShim(fileName)
5354

5455
// Implement the service related to temporary paths and file time stamps
5556
member _.GetTempPathShim() = defaultFileSystem.GetTempPathShim()
@@ -58,16 +59,23 @@ let B = File1.A + File1.A"""
5859
member _.IsInvalidPathShim(fileName) = defaultFileSystem.IsInvalidPathShim(fileName)
5960
member _.IsPathRootedShim(fileName) = defaultFileSystem.IsPathRootedShim(fileName)
6061

61-
// Implement the service related to file existence and deletion
62-
member _.SafeExists(fileName) = files.ContainsKey(fileName) || defaultFileSystem.SafeExists(fileName)
63-
member _.FileDelete(fileName) = defaultFileSystem.FileDelete(fileName)
62+
member _.CopyShim(src, dest, overwrite) = defaultFileSystem.CopyShim(src, dest, overwrite)
63+
member _.DirectoryCreateShim(path) = defaultFileSystem.DirectoryCreateShim(path)
64+
member _.DirectoryDeleteShim(path) = defaultFileSystem.DirectoryDeleteShim(path)
65+
member _.DirectoryExistsShim(path) = defaultFileSystem.DirectoryExistsShim(path)
66+
member _.EnumerateDirectoriesShim(path) = defaultFileSystem.EnumerateDirectoriesShim(path)
67+
member _.EnumerateFilesShim(path, pattern) = defaultFileSystem.EnumerateFilesShim(path, pattern)
68+
member _.FileDeleteShim(fileName) = defaultFileSystem.FileDeleteShim(fileName)
69+
member _.FileExistsShim(fileName) = defaultFileSystem.FileExistsShim(fileName)
70+
member _.GetCreationTimeShim(path) = defaultFileSystem.GetCreationTimeShim(path)
71+
member _.GetDirectoryNameShim(path) = defaultFileSystem.GetDirectoryNameShim(path)
72+
member _.GetFullFilePathInDirectoryShim(dir) (fileName) = defaultFileSystem.GetFullFilePathInDirectoryShim dir fileName
73+
member _.NormalizePathShim(path) = defaultFileSystem.NormalizePathShim(path)
74+
6475

65-
// Implement the service related to assembly loading, used to load type providers
66-
// and for F# interactive.
67-
member _.AssemblyLoadFrom(fileName) = defaultFileSystem.AssemblyLoadFrom fileName
68-
member _.AssemblyLoad(assemblyName) = defaultFileSystem.AssemblyLoad assemblyName
6976

70-
let UseMyFileSystem() =
77+
78+
let UseMyFileSystem() =
7179
let myFileSystem = MyFileSystem(FileSystemAutoOpens.FileSystem)
7280
FileSystemAutoOpens.FileSystem <- myFileSystem
7381
{ new IDisposable with member x.Dispose() = FileSystemAutoOpens.FileSystem <- myFileSystem }
@@ -77,35 +85,35 @@ let UseMyFileSystem() =
7785
#if NETCOREAPP
7886
[<Ignore("SKIPPED: need to check if these tests can be enabled for .NET Core testing of FSharp.Compiler.Service")>]
7987
#endif
80-
let ``FileSystem compilation test``() =
81-
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
88+
let ``FileSystem compilation test``() =
89+
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
8290
use myFileSystem = UseMyFileSystem()
8391
let programFilesx86Folder = System.Environment.GetEnvironmentVariable("PROGRAMFILES(X86)")
8492

85-
let projectOptions =
86-
let allFlags =
87-
[| yield "--simpleresolution";
88-
yield "--noframework";
89-
yield "--debug:full";
90-
yield "--define:DEBUG";
91-
yield "--optimize-";
92-
yield "--doc:test.xml";
93-
yield "--warn:3";
94-
yield "--fullpaths";
95-
yield "--flaterrors";
96-
yield "--target:library";
97-
for r in [ sysLib "mscorlib"; sysLib "System"; sysLib "System.Core"; fsCoreDefaultReference() ] do
93+
let projectOptions =
94+
let allFlags =
95+
[| yield "--simpleresolution";
96+
yield "--noframework";
97+
yield "--debug:full";
98+
yield "--define:DEBUG";
99+
yield "--optimize-";
100+
yield "--doc:test.xml";
101+
yield "--warn:3";
102+
yield "--fullpaths";
103+
yield "--flaterrors";
104+
yield "--target:library";
105+
for r in [ sysLib "mscorlib"; sysLib "System"; sysLib "System.Core"; fsCoreDefaultReference() ] do
98106
yield "-r:" + r |]
99-
107+
100108
{ ProjectFileName = @"c:\mycode\compilation.fsproj" // Make a name that is unique in this directory.
101109
ProjectId = None
102110
SourceFiles = [| fileName1; fileName2 |]
103-
OtherOptions = allFlags
111+
OtherOptions = allFlags
104112
ReferencedProjects = [| |];
105113
IsIncompleteTypeCheckEnvironment = false
106-
UseScriptResolutionRules = true
114+
UseScriptResolutionRules = true
107115
LoadTime = System.DateTime.Now // Not 'now', we don't want to force reloading
108-
UnresolvedReferences = None
116+
UnresolvedReferences = None
109117
OriginalLoadReferences = []
110118
Stamp = None }
111119

@@ -115,4 +123,3 @@ let ``FileSystem compilation test``() =
115123
results.AssemblySignature.Entities.Count |> shouldEqual 2
116124
results.AssemblySignature.Entities.[0].MembersFunctionsAndValues.Count |> shouldEqual 1
117125
results.AssemblySignature.Entities.[0].MembersFunctionsAndValues.[0].DisplayName |> shouldEqual "B"
118-

0 commit comments

Comments
 (0)