diff --git a/src/D2L.CodeStyle.Analyzers/D2L.CodeStyle.Analyzers.csproj b/src/D2L.CodeStyle.Analyzers/D2L.CodeStyle.Analyzers.csproj
index b111776f..b98ce3a9 100644
--- a/src/D2L.CodeStyle.Analyzers/D2L.CodeStyle.Analyzers.csproj
+++ b/src/D2L.CodeStyle.Analyzers/D2L.CodeStyle.Analyzers.csproj
@@ -6,7 +6,7 @@
D2L.CodeStyle.Analyzers
D2L.CodeStyle
D2L.CodeStyle analyzers
- 0.228.0
+ 0.229.0
Apache-2.0
https://github.com/Brightspace/D2L.CodeStyle
D2L
diff --git a/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityAnalyzer.cs b/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityAnalyzer.cs
index f0cbf3fc..684f9555 100644
--- a/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityAnalyzer.cs
+++ b/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityAnalyzer.cs
@@ -37,14 +37,6 @@ public sealed partial class ImmutabilityAnalyzer : DiagnosticAnalyzer {
Diagnostics.PrimaryClassConstructorIntroducesMutability
);
- private readonly ImmutableHashSet m_additionalImmutableTypes;
-
- public ImmutabilityAnalyzer() : this( ImmutableHashSet.Empty ) { }
-
- public ImmutabilityAnalyzer( ImmutableHashSet additionalImmutableTypes ) {
- m_additionalImmutableTypes = additionalImmutableTypes;
- }
-
public override void Initialize( AnalysisContext context ) {
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis( GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics );
@@ -57,7 +49,7 @@ CompilationStartAnalysisContext context
if( !AnnotationsContext.TryCreate( context.Compilation, out AnnotationsContext annotationsContext ) ) {
return;
}
- ImmutabilityContext immutabilityContext = ImmutabilityContext.Create( context.Compilation, annotationsContext, m_additionalImmutableTypes );
+ ImmutabilityContext immutabilityContext = ImmutabilityContext.Create( context.Compilation, annotationsContext );
ImmutableTypeParameterArgumentAnalysis.Register(
context,
diff --git a/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityContext.Factory.cs b/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityContext.Factory.cs
index 06b715e0..0049c966 100644
--- a/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityContext.Factory.cs
+++ b/src/D2L.CodeStyle.Analyzers/Immutability/ImmutabilityContext.Factory.cs
@@ -7,6 +7,8 @@
namespace D2L.CodeStyle.Analyzers.Immutability {
internal partial class ImmutabilityContext {
+ private const string ALL_TYPE_INSTANCES_QUALIFIER = "*";
+
internal static readonly ImmutableArray<(string TypeName, string AssmeblyName)> DefaultExtraTypes = ImmutableArray.Create(
// Framework Container Types (not that the distinction matters)
("System.Collections.Frozen.FrozenDictionary`2", default),
@@ -38,10 +40,10 @@ internal partial class ImmutabilityContext {
("System.Drawing.Imaging.ImageFormat", default),
("System.Drawing.Size", default), // only safe because it's a struct with primitive fields
("System.Guid", default),
- ("System.Index", default),
+ ("System.Index", ALL_TYPE_INSTANCES_QUALIFIER),
("System.Net.IPNetwork", default),
("System.Net.Http.HttpMethod", default),
- ("System.Range", default),
+ ("System.Range", ALL_TYPE_INSTANCES_QUALIFIER),
("System.Reflection.ConstructorInfo", default),
("System.Reflection.FieldInfo", default),
("System.Reflection.MemberInfo", default),
@@ -94,71 +96,54 @@ internal partial class ImmutabilityContext {
internal static ImmutabilityContext Create(
Compilation compilation,
- AnnotationsContext annotationsContext,
- ImmutableHashSet additionalImmutableTypes = default
+ AnnotationsContext annotationsContext
) {
- if( additionalImmutableTypes == default ) {
- additionalImmutableTypes = ImmutableHashSet.Empty;
- }
// Generate a dictionary of types that we have specifically determined
// should be considered Immutable by the Analyzer.
var extraImmutableTypesBuilder = ImmutableDictionary.CreateBuilder( SymbolEqualityComparer.Default );
foreach( ( string typeName, string qualifiedAssembly ) in DefaultExtraTypes ) {
- INamedTypeSymbol type = GetTypeSymbol( compilation, qualifiedAssembly, typeName );
+ ImmutableArray types = GetTypeSymbols( compilation, qualifiedAssembly, typeName );
- if( type == null ) {
+ if( types.IsDefaultOrEmpty ) {
continue;
}
- ImmutableTypeInfo info = ImmutableTypeInfo.CreateWithAllConditionalTypeParameters(
- ImmutableTypeKind.Total,
- type
- );
-
- extraImmutableTypesBuilder.Add( type, info );
- }
-
- foreach( string typeName in additionalImmutableTypes ) {
- INamedTypeSymbol type = GetTypeSymbol( compilation, qualifiedAssembly: default, typeName );
+ foreach( INamedTypeSymbol type in types ) {
- if( type == null ) {
- continue;
- }
+ ImmutableTypeInfo info = ImmutableTypeInfo.CreateWithAllConditionalTypeParameters(
+ ImmutableTypeKind.Total,
+ type
+ );
- if( extraImmutableTypesBuilder.ContainsKey( type ) ) {
- continue;
+ extraImmutableTypesBuilder.Add( type, info );
}
-
- ImmutableTypeInfo info = ImmutableTypeInfo.CreateWithAllConditionalTypeParameters(
- ImmutableTypeKind.Total,
- type
- );
-
- extraImmutableTypesBuilder.Add( type, info );
}
// Generate a set of methods that we have specifically determined
// have a return value which should be considered Immutable by the Analyzer.
var knownImmutableReturnsBuilder = ImmutableHashSet.CreateBuilder( SymbolEqualityComparer.Default );
foreach( ( string typeName, string methodName, string qualifiedAssembly ) in KnownImmutableReturningMethods ) {
- INamedTypeSymbol type = GetTypeSymbol( compilation, qualifiedAssembly, typeName );
+ ImmutableArray types = GetTypeSymbols( compilation, qualifiedAssembly, typeName );
- if( type == null ) {
+ if( types.IsDefaultOrEmpty ) {
continue;
}
- IMethodSymbol[] methodSymbols = type
- .GetMembers( methodName )
- .OfType()
- .Where( m => m.Parameters.Length == 0 )
- .ToArray();
+ foreach( INamedTypeSymbol type in types ) {
- if( methodSymbols.Length != 1 ) {
- continue;
- }
+ IMethodSymbol[] methodSymbols = type
+ .GetMembers( methodName )
+ .OfType()
+ .Where( m => m.Parameters.Length == 0 )
+ .ToArray();
- knownImmutableReturnsBuilder.Add( methodSymbols[0] );
+ if( methodSymbols.Length != 1 ) {
+ continue;
+ }
+
+ knownImmutableReturnsBuilder.Add( methodSymbols[ 0 ] );
+ }
}
return new ImmutabilityContext(
@@ -167,13 +152,13 @@ internal static ImmutabilityContext Create(
knownImmutableReturns: knownImmutableReturnsBuilder.ToImmutable(),
conditionalTypeParamemters: ImmutableHashSet.Empty,
regexInfo: (
- GetTypeSymbol( compilation, default, "System.Text.RegularExpressions.Regex" ),
- GetTypeSymbol( compilation, default, "System.CodeDom.Compiler.GeneratedCodeAttribute" )
+ GetTypeSymbols( compilation, default, "System.Text.RegularExpressions.Regex" ).FirstOrDefault(),
+ GetTypeSymbols( compilation, default, "System.CodeDom.Compiler.GeneratedCodeAttribute" ).FirstOrDefault()
)
);
}
- private static INamedTypeSymbol GetTypeSymbol(
+ private static ImmutableArray GetTypeSymbols(
Compilation compilation,
string qualifiedAssembly,
string typeName
@@ -182,7 +167,7 @@ string typeName
ImmutableArray types = compilation.GetTypesByMetadataName( typeName );
if( types.IsEmpty ) {
- return null;
+ return default;
}
if( qualifiedAssembly == default ) {
@@ -192,16 +177,20 @@ string typeName
);
}
- return types[ 0 ];
+ return types;
+ }
+
+ if( qualifiedAssembly == ALL_TYPE_INSTANCES_QUALIFIER ) {
+ return types;
}
foreach( INamedTypeSymbol type in types ) {
if( type.ContainingAssembly.Name.Equals( qualifiedAssembly, StringComparison.Ordinal ) ) {
- return type;
+ return ImmutableArray.Create( type );
}
}
- return null;
+ return default;
}
}