Skip to content

Commit

Permalink
fix: don't choke on unconstructed generics. Don't treat their type pa…
Browse files Browse the repository at this point in the history
…rameters like type arguments.
  • Loading branch information
ascott18 committed Jul 24, 2024
1 parent de01ab1 commit 9a9f5b4
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 9 deletions.
13 changes: 13 additions & 0 deletions playground/Coalesce.Web.Vue2/src/metadata.g.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions playground/Coalesce.Web.Vue2/src/models.g.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.HasValue<AbstractImpl>("impl");
}
}


public class TestBehaviors<T, TContext> : StandardBehaviors<T, TContext>
where T : class
where TContext : DbContext
{
public TestBehaviors(CrudContext<TContext> context) : base(context)
{
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using IntelliTect.Coalesce.Tests.TargetClasses.TestDbContext;
using IntelliTect.Coalesce.Tests.Util;
using IntelliTect.Coalesce.TypeDefinition;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
Expand Down Expand Up @@ -250,5 +251,15 @@ public void EnumValues_IsCorrect(ClassViewModelData data)
}
);
}

[Theory]
[ClassViewModelData(typeof(TestBehaviors<,>))]
public void UnconstructedGeneric(ClassViewModelData data)
{
var type = data.TypeViewModel;
Assert.True(type.IsGeneric);
Assert.Equal(type, type.PureType);
Assert.Null(type.FirstTypeArgument);
}
}
}
14 changes: 10 additions & 4 deletions src/IntelliTect.Coalesce.Tests/Util/ReflectionRepositoryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static ReflectionRepositoryFactory()
public static readonly IReadOnlyCollection<SyntaxTree> ModelSyntaxTrees = GetModelSyntaxTrees();

internal static readonly CSharpCompilation Compilation = GetCompilation(new SyntaxTree[0]);
internal static readonly IEnumerable<ITypeSymbol> Symbols = GetAllSymbols();
internal static readonly List<ITypeSymbol> Symbols = GetAllSymbols();

public static readonly ReflectionRepository Symbol = MakeFromSymbols();
public static readonly ReflectionRepository Reflection = MakeFromReflection();
Expand All @@ -34,14 +34,20 @@ public static ReflectionRepository MakeFromSymbols()
{
var rr = new ReflectionRepository();
rr.DiscoverCoalescedTypes(Symbols
.Where(s =>
.Where(s =>
// For classes inside the TargetClasses namespace, only include those from
// the symbol discovery assembly, not the copies that were included from the
// assembly metadata of this very test assembly (IntelliTect.Coalesce.Tests),
// as the versions derived from assembly metadata behave slightly differently
// and are also just otherwise redundant.
!s.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Contains("IntelliTect.Coalesce.Tests.TargetClasses") ||
(s is IArrayTypeSymbol ats ? ats.ElementType : s).ContainingAssembly.MetadataName == SymbolDiscoveryAssemblyName
s.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) is string fqn &&
(
(
!fqn.Contains("IntelliTect.Coalesce.Tests.TargetClasses") //&&
// !fqn.StartsWith("System.")
) ||
(s is IArrayTypeSymbol ats ? ats.ElementType : s).ContainingAssembly?.MetadataName == SymbolDiscoveryAssemblyName
)
)
.Select(s => new SymbolTypeViewModel(rr, s))
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ internal SymbolTypeViewModel(ReflectionRepository? reflectionRepository, ITypeSy
{
Symbol = symbol;

FirstTypeArgument = IsGeneric
? SymbolTypeViewModel.GetOrCreate(reflectionRepository, NamedSymbol.TypeArguments.First())
: null;
if (IsGeneric)
{
var typeArg = NamedSymbol.TypeArguments.First();
if (typeArg.Kind is not SymbolKind.ErrorType and not SymbolKind.TypeParameter)
{
FirstTypeArgument = GetOrCreate(reflectionRepository, typeArg);
}
}

ArrayType = IsArray
? SymbolTypeViewModel.GetOrCreate(reflectionRepository, ((IArrayTypeSymbol)Symbol).ElementType)
Expand Down
4 changes: 2 additions & 2 deletions src/IntelliTect.Coalesce/TypeDefinition/TypeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ internal TypeViewModel(ReflectionRepository? reflectionRepository) : this()
/// </summary>
public abstract bool IsReferenceType { get; }

public bool IsNullableValueType => !IsReferenceType && IsA(typeof(Nullable<>));
public bool IsNullableValueType => !IsReferenceType && IsA(typeof(Nullable<>)) && FirstTypeArgument is not null;

public abstract bool IsClass { get; }

Expand Down Expand Up @@ -334,7 +334,7 @@ public TypeViewModel PureType
)?[0]
?? FirstTypeArgument!;
}
if (IsReferenceOrNullableValue)
if (IsReferenceOrNullableValue && FirstTypeArgument is not null)
{
return FirstTypeArgument!;
}
Expand Down

0 comments on commit 9a9f5b4

Please sign in to comment.