@@ -48,7 +48,7 @@ type Location =
4848 Column: int
4949 }
5050
51- type CompletionResponse =
51+ type CompletionResponse =
5252 {
5353 Name: string
5454 Glyph: string
@@ -68,12 +68,12 @@ type FSharpErrorSeverityConverter() =
6868 inherit JsonConverter()
6969
7070 override x.CanConvert ( t : System.Type ) = t = typeof< FSharpErrorSeverity>
71-
71+
7272 override x.WriteJson ( writer , value , serializer ) =
7373 match value :?> FSharpErrorSeverity with
7474 | FSharpErrorSeverity.Error -> serializer.Serialize( writer, " Error" )
7575 | FSharpErrorSeverity.Warning -> serializer.Serialize( writer, " Warning" )
76-
76+
7777 override x.ReadJson ( _reader , _t , _ , _serializer ) =
7878 raise ( System.NotSupportedException())
7979
@@ -135,7 +135,7 @@ module internal CommandInput =
135135 - prints the best guess for the location of fsc and fsi
136136 (or fsharpc and fsharpi on unix)
137137 "
138-
138+
139139 let outputText = @"
140140 Output format
141141 =============
@@ -323,7 +323,7 @@ module internal CompletionUtils =
323323/// Represents current state
324324type internal State =
325325 {
326- Files : Map < string , string [] > //filename -> lines
326+ Files : Map < string , VolatileFile > //filename -> lines * touch date
327327 Projects : Map < string , FSharpProjectFileInfo >
328328 OutputMode : OutputMode
329329 HelpText : Map < String , FSharpToolTipText >
@@ -343,7 +343,7 @@ module internal Main =
343343 }
344344 loop ()
345345 )
346-
346+
347347 member x.WriteLine ( s ) = agent.Post ( Choice1Of2 s)
348348
349349 member x.Quit () = agent.PostAndReply( fun ch -> Choice2Of2 ch)
@@ -367,8 +367,13 @@ module internal Main =
367367 // Main agent that handles IntelliSense requests
368368 let agent = new FSharp.CompilerBinding.LanguageService( fun _ -> ())
369369
370- let rec main ( state : State ) : int =
370+ let mutable currentFiles = Map.empty
371+ let originalFs = Microsoft.FSharp.Compiler.AbstractIL.Internal.Library.Shim.FileSystem
372+ let fs = new FileSystem( originalFs, fun () -> currentFiles)
373+ Microsoft.FSharp.Compiler.AbstractIL.Internal.Library.Shim.FileSystem <- fs
371374
375+ let rec main ( state : State ) : int =
376+ currentFiles <- state.Files
372377 let printMsg = printMsg state
373378
374379 let parsed file =
@@ -379,14 +384,14 @@ module internal Main =
379384 /// Is the specified position consistent with internal state of file?
380385 // Note that both emacs and FSC use 1-based line indexing
381386 let posok file line col =
382- let lines = state.Files.[ file]
387+ let lines = state.Files.[ file]. Lines
383388 let ok = line <= lines.Length && line >= 1 &&
384389 col <= lines.[ line - 1 ]. Length && col >= 0
385390 if not ok then printMsg " ERROR" " Position is out of range"
386391 ok
387392
388393 let getoptions file state =
389- let text = String.concat " \n " state.Files.[ file]
394+ let text = String.concat " \n " state.Files.[ file]. Lines
390395 let project = Map.tryFind file state.Projects
391396 let projFile , args =
392397 match project with
@@ -399,14 +404,16 @@ module internal Main =
399404 // (Map.fold (fun ks k _ -> k::ks) [] state.Files)
400405 // state.OutputMode
401406 match parseCommand( Console.ReadLine()) with
402-
407+
403408 | OutputMode m -> main { state with OutputMode = m }
404409
405410 | Parse( file, kind) ->
406411 // Trigger parse request for a particular file
407412 let lines = readInput [] |> Array.ofList
408413 let file = Path.GetFullPath file
409- let state ' = { state with Files = Map.add file lines state.Files }
414+ let state ' = { state with Files = state.Files |> Map.add file
415+ { Lines = lines
416+ Touched = DateTime.Now } }
410417 let text , projFile , args = getoptions file state'
411418
412419 let task =
@@ -474,7 +481,7 @@ module internal Main =
474481 if parsed file then
475482 let text , projFile , args = getoptions file state
476483 let parseResult = agent.ParseFileInProject( projFile, file, text, args) |> Async.RunSynchronously
477- let decls = parseResult.GetNavigationItems() .Declarations
484+ let decls = parseResult.GetNavigationItems() .Declarations
478485 match state.OutputMode with
479486 | Text ->
480487 let declstrings =
@@ -495,7 +502,7 @@ module internal Main =
495502 match Map.tryFind sym state.HelpText with
496503 | None -> ()
497504 | Some d ->
498-
505+
499506 let tip = TipFormatter.formatTip d
500507 let helptext = Map.add sym tip Map.empty
501508 prAsJson { Kind = " helptext" ; Data = helptext }
@@ -506,7 +513,7 @@ module internal Main =
506513 let file = Path.GetFullPath file
507514 if parsed file && posok file line col then
508515 let text , projFile , args = getoptions file state
509- let lineStr = state.Files.[ file].[ line - 1 ]
516+ let lineStr = state.Files.[ file]. Lines . [ line - 1 ]
510517 // TODO: Deny recent typecheck results under some circumstances (after bracketed expr..)
511518 let timeout = match timeout with Some x -> x | _ -> 20000
512519 let tyResOpt = agent.GetTypedParseResultWithTimeout( projFile, file, text, [||], args, AllowStaleResults.MatchingFileName, timeout)
@@ -537,15 +544,15 @@ module internal Main =
537544 prAsJson { Kind = " helptext" ; Data = helptext }
538545
539546 prAsJson { Kind = " completion"
540- Data = [ for d in decls.Items do
547+ Data = [ for d in decls.Items do
541548 let ( glyph , glyphChar ) = CompletionUtils.getIcon d.Glyph
542549 yield { Name = d.Name; Glyph = glyph; GlyphChar = glyphChar } ] }
543550
544551 let helptext =
545552 Seq.fold ( fun m ( d : FSharpDeclarationListItem ) -> Map.add d.Name d.DescriptionText m) Map.empty decls.Items
546553
547554 main { state with HelpText = helptext }
548- | None ->
555+ | None ->
549556 printMsg " ERROR" " Could not get type information"
550557 main state
551558
@@ -570,20 +577,20 @@ module internal Main =
570577 | Json -> prAsJson { Kind = " tooltip" ; Data = TipFormatter.formatTip tip }
571578
572579 main state
573-
580+
574581 | FindDeclaration ->
575582 let declarations = tyRes.GetDeclarationLocation( line, col, lineStr)
576583 |> Async.RunSynchronously
577584 match declarations with
578585 | FSharpFindDeclResult.DeclNotFound _ -> printMsg " ERROR" " Could not find declaration"
579586 | FSharpFindDeclResult.DeclFound range ->
580-
587+
581588 match state.OutputMode with
582589 | Text -> printAgent.WriteLine( sprintf " DATA: finddecl\n %s :%d :%d \n <<EOF>>" range.FileName range.StartLine range.StartColumn)
583590 | Json ->
584591 let data = { Line = range.StartLine; Column = range.StartColumn; File = range.FileName }
585592 prAsJson { Kind = " finddecl" ; Data = data }
586-
593+
587594 main state
588595
589596 else
0 commit comments