Skip to content

Commit

Permalink
Updated how types are discovered
Browse files Browse the repository at this point in the history
  • Loading branch information
david-driscoll committed Apr 17, 2024
1 parent 60e8d15 commit 3373ae3
Show file tree
Hide file tree
Showing 256 changed files with 447 additions and 173 deletions.
92 changes: 65 additions & 27 deletions src/Conventions.Analyzers/AssemblyProviderConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Rocket.Surgery.Conventions.Analyzers.Support.AssemblyProviders;
using Rocket.Surgery.Conventions.Support;
using Compilation = Microsoft.CodeAnalysis.Compilation;

namespace Rocket.Surgery.Conventions;

Expand Down Expand Up @@ -200,12 +201,14 @@ private static GetTypesFilterData LoadTypeFilterData(CompiledAssemblyFilter asse
WithAttributeFilterDescriptor descriptor => new(
true,
descriptor.Attribute.ContainingAssembly.MetadataName,
Helpers.GetFullMetadataName(descriptor.Attribute)
Helpers.GetFullMetadataName(descriptor.Attribute),
descriptor.Attribute.IsUnboundGenericType
),
WithoutAttributeFilterDescriptor descriptor => new WithAttributeData(
false,
descriptor.Attribute.ContainingAssembly.MetadataName,
Helpers.GetFullMetadataName(descriptor.Attribute)
Helpers.GetFullMetadataName(descriptor.Attribute),
descriptor.Attribute.IsUnboundGenericType
),
_ => null!,
}
Expand Down Expand Up @@ -237,12 +240,14 @@ private static GetTypesFilterData LoadTypeFilterData(CompiledAssemblyFilter asse
AssignableToTypeFilterDescriptor descriptor => new(
true,
descriptor.Type.ContainingAssembly.MetadataName,
Helpers.GetFullMetadataName(descriptor.Type)
Helpers.GetFullMetadataName(descriptor.Type),
descriptor.Type.IsUnboundGenericType
),
NotAssignableToTypeFilterDescriptor descriptor => new AssignableToTypeData(
false,
descriptor.Type.ContainingAssembly.MetadataName,
Helpers.GetFullMetadataName(descriptor.Type)
Helpers.GetFullMetadataName(descriptor.Type),
descriptor.Type.IsUnboundGenericType
),
_ => null!,
}
Expand All @@ -260,7 +265,9 @@ private static GetTypesFilterData LoadTypeFilterData(CompiledAssemblyFilter asse
AssignableToAnyTypeFilterDescriptor descriptor => new(
true,
descriptor
.Types.Select(z => new AnyTypeData(z.ContainingAssembly.MetadataName, Helpers.GetFullMetadataName(z)))
.Types.Select(
z => new AnyTypeData(z.ContainingAssembly.MetadataName, Helpers.GetFullMetadataName(z), z.IsUnboundGenericType)
)
.OrderBy(z => z.Assembly)
.ThenBy(z => z.Type)
.ToImmutableArray()
Expand All @@ -269,7 +276,7 @@ private static GetTypesFilterData LoadTypeFilterData(CompiledAssemblyFilter asse
false,
descriptor
.Types
.Select(z => new AnyTypeData(z.ContainingAssembly.MetadataName, Helpers.GetFullMetadataName(z)))
.Select(z => new AnyTypeData(z.ContainingAssembly.MetadataName, Helpers.GetFullMetadataName(z), z.IsUnboundGenericType))
.OrderBy(z => z.Assembly)
.ThenBy(z => z.Type)
.ToImmutableArray()
Expand Down Expand Up @@ -322,17 +329,31 @@ ImmutableDictionary<string, IAssemblySymbol> assemblySymbols
)
{
var descriptors = ImmutableArray.CreateBuilder<ITypeFilterDescriptor>();
foreach (var item in data.NamespaceFilters) descriptors.Add(new NamespaceFilterDescriptor(item.Filter, item.Namespaces.ToImmutableHashSet()));
foreach (var item in data.NameFilters) descriptors.Add(new NameFilterDescriptor(item.Filter, item.Names.ToImmutableHashSet()));
foreach (var item in data.TypeKindFilters) descriptors.Add(new TypeKindFilterDescriptor(item.Include, item.TypeKinds.ToImmutableHashSet()));
foreach (var item in data.TypeInfoFilters) descriptors.Add(new TypeInfoFilterDescriptor(item.Include, item.TypeInfos.ToImmutableHashSet()));
foreach (var item in data.NamespaceFilters)
{
descriptors.Add(new NamespaceFilterDescriptor(item.Filter, item.Namespaces.ToImmutableHashSet()));
}

foreach (var item in data.NameFilters)
{
descriptors.Add(new NameFilterDescriptor(item.Filter, item.Names.ToImmutableHashSet()));
}

foreach (var item in data.TypeKindFilters)
{
descriptors.Add(new TypeKindFilterDescriptor(item.Include, item.TypeKinds.ToImmutableHashSet()));
}

foreach (var item in data.TypeInfoFilters)
{
descriptors.Add(new TypeInfoFilterDescriptor(item.Include, item.TypeInfos.ToImmutableHashSet()));
}

foreach (var item in data.WithAttributeFilters)
{
foreach (var a in compilation.GetTypesByMetadataName(item.Attribute))
{
descriptors.Add(item.Include ? new WithAttributeFilterDescriptor(a) : new WithoutAttributeFilterDescriptor(a));
}
if (findType(assemblySymbols, compilation, item.Assembly, item.Attribute) is not {} type) continue;
if (item.UnboundGenericType) type = type.ConstructUnboundGenericType();
descriptors.Add(item.Include ? new WithAttributeFilterDescriptor(type) : new WithoutAttributeFilterDescriptor(type));
}

foreach (var item in data.WithAttributeStringFilters)
Expand All @@ -344,21 +365,19 @@ ImmutableDictionary<string, IAssemblySymbol> assemblySymbols

foreach (var item in data.AssignableToTypeFilters)
{
foreach (var a in compilation.GetTypesByMetadataName(item.Type))
{
descriptors.Add(item.Include ? new AssignableToTypeFilterDescriptor(a) : new NotAssignableToTypeFilterDescriptor(a));
}
if (findType(assemblySymbols, compilation, item.Assembly, item.Type) is not {} type) continue;
if (item.UnboundGenericType) type = type.ConstructUnboundGenericType();
descriptors.Add(item.Include ? new AssignableToTypeFilterDescriptor(type) : new NotAssignableToTypeFilterDescriptor(type));
}

foreach (var item in data.AssignableToAnyTypeFilters)
{
var filters = ImmutableHashSet.CreateBuilder<INamedTypeSymbol>(SymbolEqualityComparer.Default);
foreach (var type in item.Types)
foreach (var typeData in item.Types)
{
foreach (var a in compilation.GetTypesByMetadataName(type.Type))
{
filters.Add(a);
}
if (findType(assemblySymbols, compilation, typeData.Assembly, typeData.Type) is not {} type) continue;
if (typeData.UnboundGenericType) type = type.ConstructUnboundGenericType();
filters.Add(type);
}

descriptors.Add(
Expand All @@ -369,6 +388,19 @@ ImmutableDictionary<string, IAssemblySymbol> assemblySymbols
}

return new(data.Filter, descriptors.ToImmutable());

static INamedTypeSymbol? findType(ImmutableDictionary<string, IAssemblySymbol> assemblySymbols, Compilation compilation, string assemblyName, string typeName)
{
if (CompiledAssemblyFilter._coreAssemblies.Contains(assemblyName)) return compilation.GetTypeByMetadataName(typeName);

if (!assemblySymbols.TryGetValue(assemblyName, out var assembly)
|| FindTypeVisitor.FindType(compilation, assembly, typeName) is not { } type)
{
return null;
}

return type;
}
}

[JsonSourceGenerationOptions]
Expand Down Expand Up @@ -452,7 +484,9 @@ internal record WithAttributeData
[property: JsonPropertyName("a")]
string Assembly,
[property: JsonPropertyName("b")]
string Attribute);
string Attribute,
[property: JsonPropertyName("u")]
bool UnboundGenericType);

internal record WithAttributeStringData
(
Expand All @@ -468,7 +502,9 @@ internal record AssignableToTypeData
[property: JsonPropertyName("a")]
string Assembly,
[property: JsonPropertyName("t")]
string Type);
string Type,
[property: JsonPropertyName("u")]
bool UnboundGenericType);

internal record AssignableToAnyTypeData
(
Expand All @@ -482,7 +518,9 @@ internal record AnyTypeData
[property: JsonPropertyName("a")]
string Assembly,
[property: JsonPropertyName("t")]
string Type);
string Type,
[property: JsonPropertyName("u")]
bool UnboundGenericType);


internal record NamespaceFilterData
Expand Down Expand Up @@ -512,4 +550,4 @@ internal record TypeInfoFilterData
bool Include,
[property: JsonPropertyName("t")]
ImmutableArray<TypeInfoFilter> TypeInfos);
}
}
6 changes: 2 additions & 4 deletions src/Conventions.Analyzers/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ public static string GetFullMetadataName(ISymbol? s)
return string.Empty;
}

var sb =s is INamedTypeSymbol { Arity: > 0, IsUnboundGenericType: true } namedTypeSymbol
? new StringBuilder(namedTypeSymbol.Name + ("<" + (string.Concat(Enumerable.Range(0,3).Select(z => ","))) + ">"))
:new StringBuilder(s.MetadataName);
var sb = new StringBuilder(s.MetadataName);
var last = s;

s = s.ContainingSymbol;
Expand All @@ -36,7 +34,7 @@ public static string GetFullMetadataName(ISymbol? s)
sb.Insert(0, '.');
}

sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
//sb.Insert(0, s.MetadataName);
s = s.ContainingSymbol;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public bool IsMatch(Compilation compilation, TSymbol targetType)
internal record CompiledAssemblyFilter
(ImmutableArray<IAssemblyDescriptor> AssemblyDescriptors) : ICompiledTypeFilter<IAssemblySymbol>
{
private static readonly HashSet<string> _coreAssemblies =
internal static readonly HashSet<string> _coreAssemblies =
[
"mscorlib",
"netstandard",
Expand Down Expand Up @@ -155,4 +155,4 @@ static bool TypeInfoFilterFunc(TypeInfoFilter typeFilter, INamedTypeSymbol type)
};
}
}
}
}
9 changes: 5 additions & 4 deletions test/Analyzers.Tests/GetTypesTestsData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ public class GetTypesTestsData
public static IEnumerable<object[]> GetTypesData()
{
// ReSharper disable RedundantNameQualifier
yield return TestMethod(z => z
.FromAssemblyDependenciesOf<IValidator>()
.GetTypes(x => x.NotInfoOf(TypeInfoFilter.Abstract).AssignableTo(typeof(AbstractValidator<>))));
yield break;
yield return TestMethod(
z => z
.FromAssemblyDependenciesOf<IValidator>()
.GetTypes(x => x.NotInfoOf(TypeInfoFilter.Abstract).AssignableTo(typeof(AbstractValidator<>)))
);

yield return TestMethod(z => z.FromAssemblyOf<IConvention>().GetTypes(x => x.StartsWith("IService")));
yield return TestMethod(z => z.FromAssemblyOf<IConvention>().GetTypes(x => x.StartsWith("S").EndsWith("Convention")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<in-memory assembly>,
<in-memory assembly>,
AutoMapper.dll,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ IEnumerable<Assembly> IAssemblyProvider.GetAssemblies(Action<IAssemblyProviderAs
break;
// FilePath: Input2.cs Member: Register
case "Input2.cs":
yield return typeof(global::FluentValidation.AbstractValidator<>).Assembly;
yield return typeof(global::Microsoft.Extensions.Configuration.ConfigurationDebugViewContext).Assembly;
yield return typeof(global::Microsoft.Extensions.DependencyInjection.ActivatorUtilities).Assembly;
yield return typeof(global::Microsoft.Extensions.Configuration.RocketSurgeryLoggingExtensions).Assembly;
Expand All @@ -53,4 +54,4 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand All @@ -19,4 +20,4 @@
System.Private.CoreLib.dll,
System.Runtime.dll
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return typeof(global::Rocket.Surgery.Conventions.Configuration.ConfigurationAsyncConvention);
yield return typeof(global::Rocket.Surgery.Conventions.Configuration.ConfigurationConvention);
yield return typeof(global::Rocket.Surgery.Conventions.DependencyInjection.ServiceAsyncConvention);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return RocketSurgeryConventionsAbstractions.GetType("EnumPolyfill");
yield return typeof(global::Microsoft.Extensions.Configuration.RocketSurgeryLoggingExtensions);
yield return RocketSurgeryConventions.GetType("Microsoft.Extensions.DependencyInjection.LoggingBuilder");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return typeof(global::Rocket.Surgery.Conventions.Configuration.IConfigurationAsyncConvention);
yield return typeof(global::Rocket.Surgery.Conventions.Configuration.IConfigurationConvention);
yield return typeof(global::Rocket.Surgery.Conventions.DependencyInjection.IServiceAsyncConvention);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return RocketSurgeryConventionsAbstractions.GetType("EnumPolyfill");
yield return RocketSurgeryConventionsAbstractions.GetType("Polyfill");
yield return RocketSurgeryConventionsAbstractions.GetType("RegexPolyfill");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return RocketSurgeryConventionsAbstractions.GetType("Rocket.Surgery.Conventions.ConventionDependency");
yield return RocketSurgeryConventionsAbstractions.GetType("Rocket.Surgery.Conventions.ConventionOrDelegate");
yield return typeof(global::Rocket.Surgery.Conventions.DependencyDirection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return typeof(global::Rocket.Surgery.Conventions.DependencyInjection.ServiceAsyncConvention);
yield return typeof(global::Rocket.Surgery.Conventions.DependencyInjection.ServiceConvention);
yield return typeof(global::Rocket.Surgery.Conventions.Setup.SetupAsyncConvention);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IEnumerable<Type> IAssemblyProvider.GetTypes(Func<ITypeProviderAssemblySelector,
switch (lineNumber)
{
// FilePath: Input1.cs Member: Register
case 17:
case 18:
yield return typeof(global::Microsoft.Extensions.Configuration.ConfigurationDebugViewContext);
yield return typeof(global::Microsoft.Extensions.Configuration.ConfigurationExtensions);
yield return typeof(global::Microsoft.Extensions.Configuration.ConfigurationKeyNameAttribute);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<in-memory assembly>,
<in-memory assembly>,
<in-memory assembly>,
FluentValidation.dll,
Microsoft.Extensions.Configuration.Abstractions.dll,
Microsoft.Extensions.DependencyInjection.Abstractions.dll,
mscorlib.dll,
Expand Down
Loading

0 comments on commit 3373ae3

Please sign in to comment.