【发布时间】:2012-04-01 10:00:54
【问题描述】:
我刚刚将语言服务从 VS2008 迁移到 VS2010。一切正常,除了一件重要的事情:我不再为ParseReason.Check 调用LanguageService.ParseSource。打开文件后,它确实会获得一次调用。但是在编辑代码后,它不再被调用。
有什么可能导致这种情况的想法吗?
【问题讨论】:
标签: visual-studio-2010 vs-extensibility languageservice
我刚刚将语言服务从 VS2008 迁移到 VS2010。一切正常,除了一件重要的事情:我不再为ParseReason.Check 调用LanguageService.ParseSource。打开文件后,它确实会获得一次调用。但是在编辑代码后,它不再被调用。
有什么可能导致这种情况的想法吗?
【问题讨论】:
标签: visual-studio-2010 vs-extensibility languageservice
我还从 2008 年迁移到 2010 年的语言服务。您能检查一下您是否已完成所有这些步骤吗?
http://msdn.microsoft.com/en-us/library/dd885475.aspx
我不需要做任何其他事情,我通过在更改前后对比我们仓库中的重要文件来验证这一点。
【讨论】:
我不知道您是否曾经弄清楚您的问题,但是您是否尝试过确保在创建 Source 类的 LastParseTime 时将其设置为 0?我似乎记得 Check 不会发生的一些问题,除非您在创建 Source 对象时手动将 LastParseTime 设置为 0。
Protip:如果您使用 .NET Reflector,您可以反汇编 LanguageService 框架的所有基类,并很好地理解它们是如何工作的。您感兴趣的类位于 Microsoft.VisualStudio.Package.LanguageService.10.0.dll 中,应该安装在 GAC 中。当我试图弄清楚为什么事情在我自己的语言服务中不起作用时,我发现这非常有用,并且能够在调试器中单步调试源代码几乎减轻了使用这些框架的所有痛苦!
【讨论】:
当您的Source 对象被初始化时,它以LastParseTime 的Int32.MaxValue 开始。导致使用ParseReason.Check 触发ParseRequest 的代码检查LastParseTime 值以查看自上次更改文本以来的时间是否小于运行解析所需的时间(或CodeSenseDelay 设置,以较大者为准)。
处理来自ParseSource 的响应的代码应该设置LastParseTime,但据我所知,只有当ParseReason 是Check 时才会这样做。
您可以通过在初始化Source 时设置Source.LastParseTime = 0 来解决此问题。这具有将CompletedFirstParse 设置为true 的副作用,即使第一次解析尚未完成。
解决此问题的另一种方法是覆盖Source.OnIdle 以触发对BeginParse() 的第一次调用这是我推荐的方法。
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();
}
}
【讨论】: