I have found two ways of proffering a language service on the internet.
The first way involves using a IOleComponentManager
and registering a timer to call my service during idle times.
The second way involves casing my service as an IServiceContainer
and adding a ServiceCreatorCallback
to "proffer the service on demand".
Supposedly the second way is now the "preferred way" of doing things. Unfortunately, when I use this method, OnSynchronizeDropdowns
never gets called on my TypeAndMembersDropdownBars
implementation.
In addition, when my LanguageService
finds errors in the file, it uses ParseRequest.Sink.AddError()
to add errors to the error list. When proffering "On Demand", these errors don't show up in the GUI, even though I see them being added when I debug through the code.
I know that my language service is being registered, because syntax highlighting, "Go to Defintion", and "Find All References" still work.
Here is the code I'm using to "proffer my service on demand":
IServiceContainer serviceContainer = this as IServiceContainer;
ServiceCreatorCallback callback = new ServiceCreatorCallback(CreateLanguageService);
serviceContainer.AddService(typeof(MyLanguageService), callback, true);
Can anyone tell me why some functionality of my LanguageService
does not work when proffering it on demand? Am I missing something, or is that way just not meant for a fully functional language service?
It looks like at least the missing functionality requires using the
IOleComponentManager
method that registers a timer to call the language service during idle periods.Using dotPeek, I found that
OnSynchronizeDropdowns()
gets called fromOnCaretMoved()
for synchronizing the selected item when you click around in the editor.OnCaretMoved()
itself appears to only be called from theLanguageService.OnIdle()
method, which I believe requires the use of the idle timer.After digging some more, I also found that the error list requires that the
ParseRequest.Reason
be set toParseReason.Check
, otherwise it ignores the call. Digging through the code some more, the only place I found that parse reason being used was inSource.OnIdle()
.Update: I believe I have confirmed that registering an idle timer is required for these two pieces of functionality. From MSDN on LanguageService.OnIdle: