So I'm trying to create my own visual studio language plugin for a DSL. My question is, I've implemented LanguageService
and override GetScanner. Through debugging I see that it actually returns the IScanner
implementation, but it never calls ScanTokenAndProvideInfoAboutIt
.
All of this loading happens after opening a file with an extension my language package is tied to, which leads me to believe that it's actually trying to use my plugin for it.
I'm a bit lost here, the process of creating visual studio plugins looks intuitive on the surface, but seems cursed under the covers.
internal class ValLanguageScanner : IScanner
{
private IVsTextBuffer m_buffer;
string m_source;
public ValLanguageScanner(IVsTextBuffer buffer)
{
// Breakpoint gets hit here(to to creation in GetScanner method)
m_buffer = buffer;
}
bool IScanner.ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo, ref int state)
{
// Breakpoint never gets hit here
var foundToken = false;
return foundToken;
}
void IScanner.SetSource(string source, int offset)
{
m_source = source.Substring(offset);
}
}
public class ValLanguageService : LanguageService
{
private const string _name = "Val";
private LanguagePreferences m_preferences;
private ValLanguageScanner m_scanner;
public override LanguagePreferences GetLanguagePreferences()
{
if (m_preferences == null)
{
m_preferences = new LanguagePreferences(this.Site,typeof(ValLanguageService).GUID,this.Name);
m_preferences.Init();
}
return m_preferences;
}
public override IScanner GetScanner(IVsTextLines buffer)
{
if (m_scanner == null)
{
m_scanner = new ValLanguageScanner(buffer);
}
return m_scanner;
}
public override AuthoringScope ParseSource(ParseRequest req)
{
return new ValLanguageAuthoringScope();
}
public override string GetFormatFilterList()
{
return "Val(*.val)|*.val";
}
public override string Name
{
get { return _name; }
}
}
[PackageRegistration(UseManagedResourcesOnly = true)]
[ProvideServiceAttribute(typeof(ValLanguageService),
ServiceName = "Val Language Service")]
[ProvideLanguageExtensionAttribute(typeof(ValLanguageService),
".val")]
[ProvideLanguageExtensionAttribute(typeof(ValLanguageService),
".vallist")]
[InstalledProductRegistration("#110", "#112", "1.0")]
public class ValLanguagePackage : Package, IOleComponent
{
private uint m_componentID;
public ValLanguagePackage()
{
Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
protected override void Initialize()
{
base.Initialize(); // required
// Proffer the service.
IServiceContainer serviceContainer = this as IServiceContainer;
ValLanguageService langService = new ValLanguageService();
langService.SetSite(this);
serviceContainer.AddService(typeof(ValLanguageService),
langService,
true);
// Register a timer to call our language service during
// idle periods.
IOleComponentManager mgr = GetService(typeof(SOleComponentManager))
as IOleComponentManager;
if (m_componentID == 0 && mgr != null)
{
OLECRINFO[] crinfo = new OLECRINFO[1];
crinfo[0].cbSize = (uint)Marshal.SizeOf(typeof(OLECRINFO));
crinfo[0].grfcrf = (uint)_OLECRF.olecrfNeedIdleTime |
(uint)_OLECRF.olecrfNeedPeriodicIdleTime;
crinfo[0].grfcadvf = (uint)_OLECADVF.olecadvfModal |
(uint)_OLECADVF.olecadvfRedrawOff |
(uint)_OLECADVF.olecadvfWarningsOff;
crinfo[0].uIdleTimeInterval = 1000;
int hr = mgr.FRegisterComponent(this, crinfo, out m_componentID);
}
}
protected override void Dispose(bool disposing)
{
if (m_componentID != 0)
{
Debug.WriteLine("OMG DISPOSING");
IOleComponentManager mgr = GetService(typeof(SOleComponentManager))
as IOleComponentManager;
if (mgr != null)
{
int hr = mgr.FRevokeComponent(m_componentID);
}
m_componentID = 0;
}
Debug.WriteLine("OMG DISPOSING BASE");
base.Dispose(disposing);
Debug.WriteLine("OMG DISPOSED");
}
#region IOleComponent Members
public int FDoIdle(uint grfidlef)
{
bool bPeriodic = (grfidlef & (uint)_OLEIDLEF.oleidlefPeriodic) != 0;
// Use typeof(TestLanguageService) because we need to
// reference the GUID for our language service.
LanguageService service = GetService(typeof(ValLanguageService))
as LanguageService;
if (service != null)
{
service.OnIdle(bPeriodic);
}
return 0;
}
public int FContinueMessageLoop(uint uReason,
IntPtr pvLoopData,
MSG[] pMsgPeeked)
{
return 1;
}
public int FPreTranslateMessage(MSG[] pMsg)
{
return 0;
}
public int FQueryTerminate(int fPromptUser)
{
return 1;
}
public int FReserved1(uint dwReserved,
uint message,
IntPtr wParam,
IntPtr lParam)
{
return 1;
}
public IntPtr HwndGetWindow(uint dwWhich, uint dwReserved)
{
return IntPtr.Zero;
}
public void OnActivationChange(IOleComponent pic,
int fSameComponent,
OLECRINFO[] pcrinfo,
int fHostIsActivating,
OLECHOSTINFO[] pchostinfo,
uint dwReserved)
{
}
public void OnAppActivate(int fActive, uint dwOtherThreadID)
{
}
public void OnEnterState(uint uStateID, int fEnter)
{
}
public void OnLoseActivation()
{
}
public void Terminate()
{
}
#endregion
}