提交 47181977 编写于 作者: T Tom Meschter

Check the CancellationToken in the DeclarePublicAPI analyzer

Related to issue #610.

The DeclarePublicAPI analyzer loops over the set of AdditionalFiles
looking for one named "PublicAPI.txt", and later loops through all the
lines in that file. If there are a large number of AdditionalFiles, or
the file contains a large number of lines (which is certainly the case
for some of our projects) we may end up doing a lot of work even after
analysis has been cancelled.

This can happen during typing, where we may repeatedly cancel analysis
and start again as the user is typing. We can potentially end up with a
bunch of Tasks doing long-running but unnecessary work, consuming system
resources and making VS less responsive.

The fix here is to be aggressive about checking the CancellationToken
while in these loops.
上级 8b4a0a08
......@@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
......@@ -82,7 +83,7 @@ public override void Initialize(AnalysisContext context)
{
context.RegisterCompilationStartAction(compilationContext =>
{
AdditionalText publicApiAdditionalText = TryGetPublicApiSpec(compilationContext.Options.AdditionalFiles);
AdditionalText publicApiAdditionalText = TryGetPublicApiSpec(compilationContext.Options.AdditionalFiles, compilationContext.CancellationToken);
var publicApiSourceText = publicApiAdditionalText.GetText(compilationContext.CancellationToken);
if (publicApiAdditionalText == null)
......@@ -90,7 +91,7 @@ public override void Initialize(AnalysisContext context)
return;
}
HashSet<string> declaredPublicSymbols = ReadPublicSymbols(publicApiSourceText);
HashSet<string> declaredPublicSymbols = ReadPublicSymbols(publicApiSourceText, compilationContext.CancellationToken);
HashSet<string> examinedPublicTypes = new HashSet<string>();
object lockObj = new object();
......@@ -203,12 +204,14 @@ internal static string GetPublicApiName(ISymbol symbol)
return null;
}
private static HashSet<string> ReadPublicSymbols(SourceText file)
private static HashSet<string> ReadPublicSymbols(SourceText file, CancellationToken cancellationToken)
{
HashSet<string> publicSymbols = new HashSet<string>();
foreach (var line in file.Lines)
{
cancellationToken.ThrowIfCancellationRequested();
var text = line.ToString();
if (!string.IsNullOrWhiteSpace(text))
......@@ -248,10 +251,12 @@ private static bool IsPublicOrPublicProtected(ISymbol symbol)
return false;
}
private static AdditionalText TryGetPublicApiSpec(ImmutableArray<AdditionalText> additionalTexts)
private static AdditionalText TryGetPublicApiSpec(ImmutableArray<AdditionalText> additionalTexts, CancellationToken cancellationToken)
{
foreach (var text in additionalTexts)
{
cancellationToken.ThrowIfCancellationRequested();
if (Path.GetFileName(text.Path).Equals(PublicApiFileName, StringComparison.OrdinalIgnoreCase))
{
return text;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册