Visual studio 2015 Visual Studio 2015中的GetClassificationSpans没有';我什么也不退

Visual studio 2015 Visual Studio 2015中的GetClassificationSpans没有';我什么也不退,visual-studio-2015,visual-studio-extensions,vspackage,visual-studio-sdk,Visual Studio 2015,Visual Studio Extensions,Vspackage,Visual Studio Sdk,我有一个tagger(ITagger的子类),我试图调用GetClassificationSpans,这样我就可以使用分类查找注释,并使用标记格式化。这在Visual Studio 2013中起作用,但现在在Visual Studio 2015中运行它时,GetClassificationSpans总是返回一个空列表-即使我在调试器中检查了跨度,并且它肯定会传递一个带有注释的跨度 有人知道2015年调用GetClassificationSpans可能会发生什么变化吗 顺便说一句:我通过在标记器提

我有一个tagger(ITagger的子类),我试图调用GetClassificationSpans,这样我就可以使用分类查找注释,并使用标记格式化。这在Visual Studio 2013中起作用,但现在在Visual Studio 2015中运行它时,GetClassificationSpans总是返回一个空列表-即使我在调试器中检查了跨度,并且它肯定会传递一个带有注释的跨度

有人知道2015年调用GetClassificationSpans可能会发生什么变化吗

顺便说一句:我通过在标记器提供程序(ITaggerProvider的子类)中导入IClassiferAggregatorService并将其传递给标记器的构造函数来获得分类器:

[import]
IClassifierAggregatorService aggregator;
然后,我在聚合器上的标记器中使用以下调用,该聚合器是我从提供商处获得的:

IList<ClassificationSpan> lstClassifiers = aggregator.GetClassifier(span.Snapshot.TextBuffer).GetClassificationSpans(span);
IList lstClassifiers=aggregator.GetClassifier(span.Snapshot.TextBuffer).GetClassificationSpans(span);
正如我所说,分类器列表总是空的。与VS2013中运行的代码完全相同。我似乎在网上找不到任何提及VS2015中任何可能导致这种情况的变化的内容


谢谢,好的。在尝试了不同的事情之后,似乎出现了几个问题:

  • 执行顺序必须已更改,以便分类似乎不会在我之前调用GetClassificationSpans的位置之前设置。(在缓冲区级别标记器的构造函数中[而不是在视图级别标记器中])我现在只在处理BufferChanged/LayoutChanged期间调用GetCLassificationSpans。(我现在唯一的问题是,当文件打开时,我似乎没有收到BufferChanged事件。希望这不会太难解决。)
  • 如果我使用传递到提供者的缓冲区引用,在那里设置对IClassizer的引用,并将其传递给我的标记器而不是聚合器(因此我停止在快照范围中使用缓冲区引用),那么效果会更好
  • 通过从以前使用的v12引用更新对SDK DLL的v14的引用,我得到了更好的结果

  • 希望这能帮助遇到相同问题的人。

    因此,一般来说,ITagger API并不要求标记器返回“真实”信息。相反,它是一个API,返回“您当时拥有的任何信息”。如果给您带来麻烦的缓冲区是C#或VB缓冲区,那是因为在VS2015中,我们将Roslyn中的所有内容都移动为异步,因此在重新计算数据之前,对GetClassificationSpans/GetTags的调用可能不会返回任何内容。有一个新的API,IAccurateTagger,它的存在是为了请求标记器提供“真实”数据,尽管这不是您希望在文本缓冲区更改中运行的东西,因为这样会降低性能

    如果您试图在VS2015中查找注释,而让您感到困惑的文件是C#或VB缓冲区,那么最好调用Roslyn API,它可以为您提供所需的直接语法树数据。如果它是一种不同类型的缓冲区,您至少最好调用IAccurateTagger,但由于性能的影响,请尽可能小心地尝试这样做


    (此外,如果您试图构建一个在键入时自动格式化的扩展,那么使用分类标记器将给您带来其他麻烦。VS2013中存在一些错误,您必须解决在标记更改期间调用C时,C会给出过时标记的问题。)

    我遇到了同样的问题,尽管是在不同的上下文中。从我的谷歌搜索中,看起来他们已经改变了分类器,所以它们被懒散地初始化了。。。我猜
    GetClassificationSpans()
    不会强制初始化它们。MSFT仍然认为这是一个bug,所以你可能想投票表决这个问题

    一个潜在的解决方法(如MSFT所建议的)是切换到使用
    TagAggregator
    而不是
    iclassizer
    。因此,不是:

    var service = container.GetService<IClassifierAggregatorService>();
    var classifier = service.GetClassifier(textView.TextBuffer);
    var spans = classifier.GetClassificationSpans(new SnapshotSpan(...));
    
    var service=container.GetService();
    var分类器=service.GetClassifier(textView.TextBuffer);
    var span=classifier.getClassificationspan(新快照span(…);
    
    你可以这样写:

    var service = container.GetService<IViewTagAggregatorFactoryService>();
    var aggregator = service.CreateTagAggregator<IClassificationTag>(textView);
    var tags = aggregator.GetTags(new SnapshotSpan(...)));
    
    var service=container.GetService();
    var aggregator=service.CreateTagAggregator(textView);
    var tags=aggregator.GetTags(新快照范围(…));
    

    这将返回一个
    IMappingTagSpan
    列表,而不是
    ClassificationSpan
    列表,因此使用它们的方式略有不同。但底层数据似乎基本相同——也就是说,您可以得到每个词汇元素的分类和跨度。虽然有一些细微的差别(请参见VS Connect上的说明),但结果对于我的应用程序来说已经足够好了。

    在SDK DLL的不同版本之间移动不应该真的产生影响——一旦在Visual Studio中实际运行,您仍然会调用相同的代码。