You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This tutorial discusses some technical aspects of how to make sure the F# compiler service is
8
+
providing up-to-date results especially when hosted in an IDE. See also [project wide analysis](project.html)
9
+
for information on project analysis.
10
+
11
+
> **NOTE:** The FSharp.Compiler.Service API is subject to change when later versions of the nuget package are published.
12
+
13
+
The logical results of all "Check" routines (``ParseAndCheckFileInProject``, ``GetBackgroundCheckResultsForFileInProject``,
14
+
``TryGetRecentTypeCheckResultsForFile``, ``ParseAndCheckProject``) depend on results reported by the file system,
15
+
especially the ``IFileSystem`` implementation described in the tutorial on [project wide analysis](project.html).
16
+
Logically speaking, these results would be different if file system changes occur. For example,
17
+
referenced DLLs may change on disk, or referenced files may change.
18
+
19
+
The ``FSharpChecker`` component from FSharp.Compiler.Service does _not_ actively "listen"
20
+
to changes in the file system. However ``FSharpChecker`` _does_ repeatedly ask for
21
+
time stamps from the file system which it uses to decide if recomputation is needed.
22
+
FCS doesn’t listen for changes directly - for example, it creates no ``FileWatcher`` object (and the
23
+
``IFileSystem`` API has no ability to create such objects). This is partly for legacy reasons,
24
+
and partly because some hosts forbid the creation of FileWatcher objects.
25
+
26
+
In most cases the repeated timestamp requests are sufficient. If you don't actively
27
+
listen for changes, then ``FSharpChecker`` will still do _approximately_
28
+
the right thing, because it is asking for time stamps repeatedly. However, some updates on the file system
29
+
(such as a DLL appearing after a build, or the user randomly pasting a file into a folder)
30
+
may not actively be noticed by ``FSharpChecker`` until some operation happens to ask for a timestamp.
31
+
By issuing fresh requests, you can ensure that FCS actively reassesses the state of play when
32
+
stays up-to-date when changes are observed.
33
+
34
+
If you want to more actively listen for changes, then you should add watchers for the
35
+
files specified in the ``DependencyFiles`` property of ``FSharpCheckFileResults`` and ``FSharpCheckProjectResults``.
36
+
Here’s what you need to do:
37
+
38
+
* When your client notices an CHANGE event on a DependencyFile, it should schedule a refresh call to perform the ParseAndCheckFileInProject (or other operation) again.
39
+
This will result in fresh FileSystem calls to compute time stamps.
40
+
41
+
* When your client notices an ADD event on a DependencyFile, it should call ``checker.InvalidateConfiguration``
42
+
for all active projects in which the file occurs. This will result in fresh FileSystem calls to compute time
43
+
stamps, and fresh calls to compute whether files exist.
44
+
45
+
* Generally clients don’t listen for DELETE events on files. Although it would be logically more consistent
46
+
to do so, in practice it’s very irritating for a "project clean" to invalidate all intellisense and
47
+
cause lots of red squiggles. Some source control tools also make a change by removing and adding files, which
48
+
is best noticed as a single change event.
49
+
50
+
51
+
52
+
If your host happens to be Visual Studio, then this is one technique you can use:
53
+
* Listeners should be associated with a visual source file buffer
54
+
* Use fragments like this to watch the DependencyFiles:
55
+
56
+
// Get the service
57
+
let vsFileWatch = fls.GetService(typeof<SVsFileChangeEx >) :?> IVsFileChangeEx
58
+
59
+
// Watch the Add and Change events
60
+
let fileChangeFlags =
61
+
uint32 (_VSFILECHANGEFLAGS.VSFILECHG_Add |||
62
+
// _VSFILECHANGEFLAGS.VSFILECHG_Del ||| // don't listen for deletes - if a file (such as a 'Clean'ed project reference) is deleted, just keep using stale info
63
+
_VSFILECHANGEFLAGS.VSFILECHG_Time)
64
+
65
+
// Advise on file changes...
66
+
let cookie = Com.ThrowOnFailure1(vsFileWatch.AdviseFileChange(file, fileChangeFlags, changeEvents))
0 commit comments