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

[WIP] In-Memory documents for FCS #11588

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
89defe7
Initial work with Vlad on in-memory documents
TIHan May 20, 2021
0d38e9e
update baseline
TIHan May 20, 2021
adb3f3d
Fixing tests
TIHan May 20, 2021
a2f2cf8
Merge remote-tracking branch 'upstream/main' into in-memory-documents
vzarytovskii May 21, 2021
fbe307b
FileSystem: return stream by default, have extension method to conver…
vzarytovskii May 21, 2021
3571ea2
Merge upstream/main
vzarytovskii May 27, 2021
726ee79
Post-merge fixes
vzarytovskii May 31, 2021
06c70b3
Merge remote-tracking branch 'upstream/main' into in-memory-documents
vzarytovskii May 31, 2021
fa6d1ec
Merging
TIHan Jun 8, 2021
566ec8c
Merge branch 'in-memory-documents' of github.com:TIHan/visualfsharp i…
TIHan Jun 8, 2021
dd595cc
Added MainState to IncrementalBuilder
TIHan Jun 8, 2021
30ad116
Using MainState
TIHan Jun 8, 2021
6acdc4d
Fixing surface area
TIHan Jun 9, 2021
0d60029
Merge branch 'main' into in-memory-documents
TIHan Jun 9, 2021
a59e5d3
Fixed a few issues with events
TIHan Jun 9, 2021
2ff5a2b
Merge branch 'main' into in-memory-documents
vzarytovskii Jun 9, 2021
a5fa3ec
Fixing incremental build
TIHan Jun 9, 2021
15f3fa6
Merge branch 'in-memory-documents' of github.com:TIHan/visualfsharp i…
TIHan Jun 9, 2021
7905665
Some cleanup
TIHan Jun 9, 2021
2f0007b
More cleanup
TIHan Jun 9, 2021
2654229
Added UpdateDocuments
TIHan Jun 9, 2021
3a75d31
More cleanup
TIHan Jun 9, 2021
64bb362
Fix
TIHan Jun 9, 2021
098aa43
Merge remote-tracking branch 'remote/main' into in-memory-documents
TIHan Jun 9, 2021
b6892a1
Sort by slot
TIHan Jun 9, 2021
6e61087
Getting VS to use background results. No more foreground.
TIHan Jun 10, 2021
db56ab1
Added IsOpen to FSharpDocument
TIHan Jun 10, 2021
b6985a3
Merge remote-tracking branch 'remote/main' into in-memory-documents
TIHan Jun 15, 2021
824bf1c
Fixed a few issues
TIHan Jun 16, 2021
1a5fbf0
Renamed UpdateDocuments to UpdateBackgroundDocuments
TIHan Jun 16, 2021
8f08191
Update SurfaceArea.netstandard.fs
TIHan Jun 16, 2021
f60f747
merged
TIHan Jun 16, 2021
2e33c40
minor fix
TIHan Jun 16, 2021
f719a2b
another fix
TIHan Jun 17, 2021
4230a17
another fix
TIHan Jun 17, 2021
d59782f
Trying to fix
TIHan Jun 17, 2021
08fdc6e
Fixed thigns
TIHan Jun 17, 2021
47431bb
Merge remote-tracking branch 'remote/main' into in-memory-documents
TIHan Jun 17, 2021
9e5b691
Merge remote-tracking branch 'remote/main' into in-memory-documents
TIHan Jun 18, 2021
31894a5
Updating surface area
TIHan Jun 18, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,12 @@
<Compile Include="..\service\SemanticClassificationKey.fs">
<Link>Service/SemanticClassificationKey.fs</Link>
</Compile>
<Compile Include="..\service\FSharpDocument.fsi">
<Link>Service/FSharpDocument.fsi</Link>
</Compile>
<Compile Include="..\service\FSharpDocument.fs">
<Link>Service/FSharpDocument.fs</Link>
</Compile>
<Compile Include="..\service\IncrementalBuild.fsi">
<Link>Service/IncrementalBuild.fsi</Link>
</Compile>
Expand Down
32 changes: 32 additions & 0 deletions src/fsharp/ParseAndCheckInputs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,22 @@ let checkInputFile (tcConfig: TcConfig) filename =
else
error(Error(FSComp.SR.buildInvalidSourceFileExtension(SanitizeFileName filename tcConfig.implicitIncludeDir), rangeStartup))

let parseInputStreamAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) =
use reader = stream.GetReader(tcConfig.inputCodePage, retryLocked)

// Set up the LexBuffer for the file
let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion.SupportsFeature, reader)

// Parse the file drawing tokens from the lexbuf
ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger)

let parseInputSourceTextAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText: ISourceText) =
// Set up the LexBuffer for the file
let lexbuf = UnicodeLexing.SourceTextAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion.SupportsFeature, sourceText)

// Parse the file drawing tokens from the lexbuf
ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger)

let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) =
// Get a stream reader for the file
use fileStream = FileSystem.OpenFileForReadShim(filename)
Expand All @@ -422,6 +438,22 @@ let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompil
errorRecovery e rangeStartup
EmptyParsedInput(filename, isLastCompiland)

/// Parse an input from stream
let ParseOneInputStream (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) =
try
parseInputStreamAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream)
with e ->
errorRecovery e rangeStartup
EmptyParsedInput(filename, isLastCompiland)

/// Parse an input from source text
let ParseOneInputSourceText (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText: ISourceText) =
try
parseInputSourceTextAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText)
with e ->
errorRecovery e rangeStartup
EmptyParsedInput(filename, isLastCompiland)

/// Parse multiple input files from disk
let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, sourceFiles, errorLogger: ErrorLogger, exiter: Exiter, createErrorLogger: (Exiter -> CapturingErrorLogger), retryLocked) =
try
Expand Down
7 changes: 7 additions & 0 deletions src/fsharp/ParseAndCheckInputs.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/// Contains logic to coordinate the parsing and checking of one or a group of files
module internal FSharp.Compiler.ParseAndCheckInputs

open System.IO
open Internal.Utilities.Library
open FSharp.Compiler.CheckExpressions
open FSharp.Compiler.CheckDeclarations
Expand Down Expand Up @@ -49,6 +50,12 @@ val ApplyNoWarnsToTcConfig: TcConfig * ParsedInput * string -> TcConfig
/// Parse one input file
val ParseOneInputFile: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * retryLocked: bool -> ParsedInput

/// Parse one input stream
val ParseOneInputStream: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * retryLocked: bool * stream: Stream -> ParsedInput

/// Parse one input source text
val ParseOneInputSourceText: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * sourceText: ISourceText -> ParsedInput

/// Parse multiple input files from disk
val ParseInputFiles: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string list * ErrorLogger * Exiter * createErrorLogger: (Exiter -> CapturingErrorLogger) * retryLocked: bool -> (ParsedInput * string) list

Expand Down
3 changes: 1 addition & 2 deletions src/fsharp/absil/ilread.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3913,7 +3913,6 @@ let createByteFileChunk opts fileName chunk =

let getBinaryFile fileName useMemoryMappedFile =
let stream = FileSystem.OpenFileForReadShim(fileName, useMemoryMappedFile = useMemoryMappedFile)
let byteMem = stream.AsByteMemory()

let safeHolder =
{ new obj() with
Expand All @@ -3927,7 +3926,7 @@ let getBinaryFile fileName useMemoryMappedFile =

stats.memoryMapFileOpenedCount <- stats.memoryMapFileOpenedCount + 1

safeHolder, RawMemoryFile(fileName, safeHolder, byteMem) :> BinaryFile
safeHolder, RawMemoryFile(fileName, safeHolder, stream.AsByteMemory()) :> BinaryFile

let OpenILModuleReaderFromBytes fileName assemblyContents options =
let pefile = ByteFile(fileName, assemblyContents) :> BinaryFile
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/service/FSharpCheckerResults.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type public FSharpProjectOptions =
/// This is the unique identifier for the project, it is case sensitive. If it's None, will key off of ProjectFileName in our caching.
ProjectId: string option

/// The files in the project
/// The source files in the project
SourceFiles: string[]

/// Additional command line argument options for the project. These can include additional files and references.
Expand Down
125 changes: 125 additions & 0 deletions src/fsharp/service/FSharpDocument.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.CodeAnalysis

open System
open System.Collections.Generic
open System.Collections.Immutable
open System.IO
open System.IO.MemoryMappedFiles
open System.Xml
open System.Runtime.InteropServices
open System.Threading
open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open FSharp.Compiler
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AbstractIL.ILBinaryReader
open FSharp.Compiler.CheckExpressions
open FSharp.Compiler.CheckDeclarations
open FSharp.Compiler.CompilerConfig
open FSharp.Compiler.CompilerDiagnostics
open FSharp.Compiler.CompilerGlobalState
open FSharp.Compiler.CompilerImports
open FSharp.Compiler.CompilerOptions
open FSharp.Compiler.CreateILModule
open FSharp.Compiler.DependencyManager
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.EditorServices
open FSharp.Compiler.ErrorLogger
open FSharp.Compiler.IO
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.NameResolution
open FSharp.Compiler.ParseAndCheckInputs
open FSharp.Compiler.ScriptClosure
open FSharp.Compiler.Syntax
open FSharp.Compiler.TcGlobals
open FSharp.Compiler.Text
open FSharp.Compiler.Text.Range
open FSharp.Compiler.Xml
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeOps

[<RequireQualifiedAccess>]
type DocumentText =
| OnDisk
| Stream of Stream
| SourceText of ISourceText

interface IDisposable with

member this.Dispose() =
match this with
| Stream stream -> stream.Dispose()
| _ -> ()

[<AbstractClass>]
type FSharpDocument internal () =

abstract FilePath : string

abstract TimeStamp : DateTime

abstract GetText : unit -> DocumentText

type private FSharpDocumentMemoryMappedFile(filePath: string, timeStamp: DateTime, openStream: unit -> Stream) =
inherit FSharpDocument()

override _.FilePath = filePath

override _.TimeStamp = timeStamp

override _.GetText() =
openStream () |> DocumentText.Stream

type private FSharpDocumentByteArray(filePath: string, timeStamp: DateTime, bytes: byte[]) =
inherit FSharpDocument()

override _.FilePath = filePath

override _.TimeStamp = timeStamp

override _.GetText() =
DocumentText.Stream(new MemoryStream(bytes, 0, bytes.Length, false) :> Stream)

type private FSharpDocumentFromFile(filePath: string) =
inherit FSharpDocument()

override _.FilePath = filePath

override _.TimeStamp = FileSystem.GetLastWriteTimeShim(filePath)

override _.GetText() = DocumentText.OnDisk

type private FSharpDocumentCustom(filePath: string, getTimeStamp, getSourceText) =
inherit FSharpDocument()

override _.FilePath = filePath

override _.TimeStamp = getTimeStamp()

override _.GetText() =
DocumentText.SourceText(getSourceText())

type FSharpDocument with

static member Create(filePath, getTimeStamp, getSourceText) =
FSharpDocumentCustom(filePath, getTimeStamp, getSourceText) :> FSharpDocument

static member CreateFromFile(filePath: string) =
FSharpDocumentFromFile(filePath) :> FSharpDocument

static member CreateCopyFromFile(filePath: string) =
let timeStamp = FileSystem.GetLastWriteTimeShim(filePath)

// We want to use mmaped documents only when
// not running on mono, since its MemoryMappedFile implementation throws when "mapName" is not provided (is null), (see: https://github.com/mono/mono/issues/10245)
if runningOnMono then
let bytes = FileSystem.OpenFileForReadShim(filePath, useMemoryMappedFile = false).ReadAllBytes()
FSharpDocumentByteArray(filePath, timeStamp, bytes) :> FSharpDocument
else
let openStream = fun () ->
FileSystem.OpenFileForReadShim(filePath, useMemoryMappedFile = true, shouldShadowCopy = true)
FSharpDocumentMemoryMappedFile(filePath, timeStamp, openStream) :> FSharpDocument

30 changes: 30 additions & 0 deletions src/fsharp/service/FSharpDocument.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.CodeAnalysis

open System
open System.IO
open FSharp.Compiler.Text

[<RequireQualifiedAccess>]
type internal DocumentText =
| OnDisk
| Stream of Stream
| SourceText of ISourceText

interface IDisposable

[<AbstractClass>]
type FSharpDocument =

abstract FilePath : string

abstract TimeStamp : DateTime

abstract internal GetText : unit -> DocumentText

static member internal CreateFromFile : filePath: string -> FSharpDocument

static member CreateCopyFromFile : filePath: string -> FSharpDocument

static member Create : filePath: string * getTimeStamp: (unit -> DateTime) * getSourceText: (unit -> ISourceText) -> FSharpDocument
Loading