diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs
index ff0b17281..9e2470720 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs
@@ -6,7 +6,8 @@
namespace StyleCop.Analyzers.Helpers
{
using System;
- using System.Collections.Concurrent;
+ using System.Collections.Generic;
+ using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
@@ -23,18 +24,17 @@ internal static class SyntaxTreeHelpers
/// This allows many analyzers that run on every token in the file to avoid checking
/// the same state in the document repeatedly.
///
- private static Tuple, ConcurrentDictionary> usingAliasCache
- = Tuple.Create(new WeakReference(null), default(ConcurrentDictionary));
+ private static Tuple, IReadOnlyDictionary> usingAliasCache
+ = Tuple.Create(new WeakReference(null), default(IReadOnlyDictionary));
- public static ConcurrentDictionary GetOrCreateUsingAliasCache(this Compilation compilation)
+ public static IReadOnlyDictionary GetOrCreateUsingAliasCache(this Compilation compilation)
{
var cache = usingAliasCache;
Compilation cachedCompilation;
if (!cache.Item1.TryGetTarget(out cachedCompilation) || cachedCompilation != compilation)
{
- var containsGlobalUsingAlias = ContainsGlobalUsingAliasNoCache(compilation);
- var replacementDictionary = containsGlobalUsingAlias ? null : new ConcurrentDictionary();
+ var replacementDictionary = CreateDictionary(compilation);
var replacementCache = Tuple.Create(new WeakReference(compilation), replacementDictionary);
while (true)
@@ -75,7 +75,7 @@ public static bool IsWhitespaceOnly(this SyntaxTree tree, CancellationToken canc
&& TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1;
}
- internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictionary cache)
+ internal static bool ContainsUsingAlias(this SyntaxTree tree, IReadOnlyDictionary cache)
{
if (tree == null)
{
@@ -88,35 +88,39 @@ internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictiona
return true;
}
- bool result;
- if (cache.TryGetValue(tree, out result))
+ if (cache.TryGetValue(tree, out var result))
{
return result;
}
- bool generated = ContainsUsingAliasNoCache(tree);
- cache.TryAdd(tree, generated);
- return generated;
+ Debug.Assert(false, "This should not happen. Syntax tree could not be found in cache!");
+ return false;
}
- private static bool ContainsUsingAliasNoCache(SyntaxTree tree)
+ private static IReadOnlyDictionary CreateDictionary(Compilation compilation)
{
- var nodes = tree.GetRoot().DescendantNodes(node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration));
+ var result = new Dictionary();
- return nodes.OfType().Any(x => x.Alias != null);
- }
+ foreach (var tree in compilation.SyntaxTrees)
+ {
+ CheckUsingAliases(tree, out var containsUsingAlias, out var containsGlobalUsingAlias);
+ if (containsGlobalUsingAlias)
+ {
+ return null;
+ }
- private static bool ContainsGlobalUsingAliasNoCache(Compilation compilation)
- {
- return compilation.SyntaxTrees.Any(ContainsGlobalUsingAliasNoCache);
+ result.Add(tree, containsUsingAlias);
+ }
+
+ return result;
}
- private static bool ContainsGlobalUsingAliasNoCache(SyntaxTree tree)
+ private static void CheckUsingAliases(SyntaxTree tree, out bool containsUsingAlias, out bool containsGlobalUsingAlias)
{
- var nodes = tree.GetRoot().DescendantNodes(node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration));
-
- var relevantNodes = nodes.OfType().ToArray();
- return relevantNodes.Any(x => x.Alias != null && !x.GlobalKeyword().IsKind(SyntaxKind.None));
+ var usingNodes = tree.GetRoot().DescendantNodes(node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration) || node.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration)).OfType();
+ var usingAliasNodes = usingNodes.Where(x => x.Alias != null).ToList();
+ containsUsingAlias = usingAliasNodes.Any();
+ containsGlobalUsingAlias = usingAliasNodes.Any(x => !x.GlobalKeyword().IsKind(SyntaxKind.None));
}
}
}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1404CodeAnalysisSuppressionMustHaveJustification.cs b/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1404CodeAnalysisSuppressionMustHaveJustification.cs
index 10b7e65d2..b0d1d8d5d 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1404CodeAnalysisSuppressionMustHaveJustification.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1404CodeAnalysisSuppressionMustHaveJustification.cs
@@ -6,7 +6,7 @@
namespace StyleCop.Analyzers.MaintainabilityRules
{
using System;
- using System.Collections.Concurrent;
+ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
@@ -78,7 +78,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
///
private sealed class AnalyzerInstance
{
- private readonly ConcurrentDictionary usingAliasCache;
+ private readonly IReadOnlyDictionary usingAliasCache;
///
/// A lazily-initialized reference to within the context of a
@@ -86,7 +86,7 @@ private sealed class AnalyzerInstance
///
private INamedTypeSymbol suppressMessageAttribute;
- public AnalyzerInstance(ConcurrentDictionary usingAliasCache)
+ public AnalyzerInstance(IReadOnlyDictionary usingAliasCache)
{
this.usingAliasCache = usingAliasCache;
}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1121UseBuiltInTypeAlias.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1121UseBuiltInTypeAlias.cs
index 8f86c7322..6c820eddd 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1121UseBuiltInTypeAlias.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1121UseBuiltInTypeAlias.cs
@@ -6,7 +6,7 @@
namespace StyleCop.Analyzers.ReadabilityRules
{
using System;
- using System.Collections.Concurrent;
+ using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -159,9 +159,9 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
private sealed class Analyzer
{
- private readonly ConcurrentDictionary usingAliasCache;
+ private readonly IReadOnlyDictionary usingAliasCache;
- public Analyzer(ConcurrentDictionary usingAliasCache)
+ public Analyzer(IReadOnlyDictionary usingAliasCache)
{
this.usingAliasCache = usingAliasCache;
}