Language Service: ParseReason.Check never called after migrating to VS2010
-
24-05-2021 - |
Question
I just migrated my language service from VS2008 to VS2010. Everything works fine except for one important thing: I no longer get LanguageService.ParseSource
invoked for ParseReason.Check
. It do get a single invoke after opening a file. But after editing code, it no longer gets invoked.
Any ideas what could be causing that?
No correct solution
OTHER TIPS
I also migrated a language service from 2008 to 2010. Can you check if you've fallowed all of these steps?
http://msdn.microsoft.com/en-us/library/dd885475.aspx
I didn't have to do anything else, which I verified by diffing the important files in our depot before and after the change.
I don't know if you ever figured your question out, but have you tried making sure that your Source class' LastParseTime is set to 0 when creating it? I seem to recall some issues with Check not happening unless you manually set LastParseTime to 0 when creating your Source object.
Protip: If you use .NET Reflector, you can disassemble all of the base classes for the LanguageService framework and get a pretty good understanding of how it all works under the hood. The classes you'd be interested in live in Microsoft.VisualStudio.Package.LanguageService.10.0.dll, which should be installed in the GAC. I've found this to be unimaginably helpful when trying to figure out why things weren't working in my own Language Service, and being able to step through the source code in the debugger mitigates almost all the pain of working with these frameworks!
When your Source
object is initialized, it starts off with a LastParseTime
of Int32.MaxValue
. The code that causes fires off a ParseRequest
with ParseReason.Check
checks the LastParseTime
value to see if the time since the last change to the text is less than the time it takes to run a parse (or the CodeSenseDelay
setting, whichever is greater).
The code that handles the response from ParseSource
is supposed to set the LastParseTime
, but as far as I can tell, it only does that if the ParseReason
is Check
.
You can get around this issue by setting Source.LastParseTime = 0
when you initialize your Source
. This has the side-effect of setting CompletedFirstParse
to true
, even if the first parse hasn't finished yet.
Another way to fix this issue is to override Source.OnIdle
to fire off the first call to BeginParse()
This is the way I would recommend.
public override void OnIdle(bool periodic)
{
// Once first "Check" parse completes, revert to base implementation
if (this.CompletedFirstParse)
{
base.OnIdle(periodic);
}
// Same as base implementation, except we don't check lastParseTime
else if (!periodic || this.LanguageService == null || this.LanguageService.LastActiveTextView == null || (this.IsCompletorActive) || (!this.IsDirty || this.LanguageService.IsParsing))
{
this.BeginParse();
}
}