From 9fddeaa224e45127f7735249a494fb2621c5446b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20Cimper=C5=A1ek?= Date: Tue, 20 Apr 2021 15:47:51 +0200 Subject: [PATCH] feat: CoreSharp.NHibernate source generator delete: controllers generator fix: sln --- .github/workflows/dotnetcore.yml | 17 +- CoreSharp.Breeze.Tests/BaseDatabaseTest.cs | 8 +- CoreSharp.Breeze.Tests/BreezeDatabaseTest.cs | 2 +- .../CoreSharp.Breeze.Tests.csproj | 4 +- CoreSharp.Common.Tests/BaseTest.cs | 6 +- .../CoreSharp.Common.Tests.csproj | 3 +- .../CoreSharp.Cqrs.AspNetCore.csproj | 2 +- .../CoreSharp.Cqrs.Tests.csproj | 2 +- ...oreSharp.NHibernate.SQLServer.Tests.csproj | 2 +- .../AnalyzersConfig.cs | 41 +++ ...oreSharp.NHibernate.SourceGenerator.csproj | 43 +++ .../NHibernateGenerator.cs | 245 ++++++++++++++++++ .../PropertyOrderAnalyzer.cs | 11 + .../README.md | 42 +++ .../SyntaxNodeExtensions.cs | 59 +++++ .../SyntaxReceiver.cs | 27 ++ .../ValidTypes.cs | 8 + .../VirtualModifierAnalyzer.cs | 11 + .../CoreSharp.Validation.Tests.csproj | 2 +- CoreSharp.sln | 8 +- README.md | 7 +- 21 files changed, 532 insertions(+), 18 deletions(-) create mode 100644 CoreSharp.NHibernate.SourceGenerator/AnalyzersConfig.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/CoreSharp.NHibernate.SourceGenerator.csproj create mode 100644 CoreSharp.NHibernate.SourceGenerator/NHibernateGenerator.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/PropertyOrderAnalyzer.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/README.md create mode 100644 CoreSharp.NHibernate.SourceGenerator/SyntaxNodeExtensions.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/SyntaxReceiver.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/ValidTypes.cs create mode 100644 CoreSharp.NHibernate.SourceGenerator/VirtualModifierAnalyzer.cs diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 616a132..4da1426 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -7,12 +7,27 @@ jobs: runs-on: ubuntu-latest + services: + postgres: + image: postgres:12 + env: + POSTGRES_USER: coresharp + POSTGRES_PASSWORD: coresharp + POSTGRES_DB: coresharp + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v1 - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.100 + dotnet-version: '5.0.x' - name: Test with dotnet run: dotnet test - name: Build with dotnet diff --git a/CoreSharp.Breeze.Tests/BaseDatabaseTest.cs b/CoreSharp.Breeze.Tests/BaseDatabaseTest.cs index 09eb8b0..35eecc9 100644 --- a/CoreSharp.Breeze.Tests/BaseDatabaseTest.cs +++ b/CoreSharp.Breeze.Tests/BaseDatabaseTest.cs @@ -61,10 +61,12 @@ protected virtual Configuration CreateNHibernateConfiguration(Container containe var persistenceModel = GetPersistenceModel(container, config); return Fluently.Configure(config) .Database( - MsSqlConfiguration.MsSql2012.ConnectionString(o => o + PostgreSQLConfiguration.PostgreSQL82.ConnectionString(o => o .Database("coresharp") - .Server("(local)") - .TrustedConnection()) + .Host("localhost") + .Username("coresharp") + .Password("coresharp") + .Port(5432)) ) //.AppendEventListeners(container) .SetDefaultProperties() diff --git a/CoreSharp.Breeze.Tests/BreezeDatabaseTest.cs b/CoreSharp.Breeze.Tests/BreezeDatabaseTest.cs index 96975f2..d3f8864 100644 --- a/CoreSharp.Breeze.Tests/BreezeDatabaseTest.cs +++ b/CoreSharp.Breeze.Tests/BreezeDatabaseTest.cs @@ -97,7 +97,7 @@ protected virtual void FillDatabase(ISession session) { CompositeOrder = compositeOrder, Product = products[(i + j) % 10], - Price = i * j, + Price = (int)(i * j), Quantity = i + j }); } diff --git a/CoreSharp.Breeze.Tests/CoreSharp.Breeze.Tests.csproj b/CoreSharp.Breeze.Tests/CoreSharp.Breeze.Tests.csproj index e565529..dcda5b1 100644 --- a/CoreSharp.Breeze.Tests/CoreSharp.Breeze.Tests.csproj +++ b/CoreSharp.Breeze.Tests/CoreSharp.Breeze.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 latest false @@ -20,6 +20,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/CoreSharp.Common.Tests/BaseTest.cs b/CoreSharp.Common.Tests/BaseTest.cs index 5ccf48a..b109935 100644 --- a/CoreSharp.Common.Tests/BaseTest.cs +++ b/CoreSharp.Common.Tests/BaseTest.cs @@ -1,4 +1,5 @@ -using SimpleInjector; +using CoreSharp.Cqrs.Events; +using SimpleInjector; using SimpleInjector.Lifestyles; using Xunit; @@ -30,7 +31,7 @@ protected virtual void ConfigureContainer(Container container) protected virtual void SetUp() { - + } protected virtual void Cleanup() @@ -39,6 +40,7 @@ protected virtual void Cleanup() private void Configure(Container container) { + var ep = new EventAggregator(container); // TODO: remove container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle(); ConfigureContainer(container); container.RegisterPackages(); diff --git a/CoreSharp.Common.Tests/CoreSharp.Common.Tests.csproj b/CoreSharp.Common.Tests/CoreSharp.Common.Tests.csproj index b389156..aa22e91 100644 --- a/CoreSharp.Common.Tests/CoreSharp.Common.Tests.csproj +++ b/CoreSharp.Common.Tests/CoreSharp.Common.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 false @@ -17,6 +17,7 @@ + diff --git a/CoreSharp.Cqrs.AspNetCore/CoreSharp.Cqrs.AspNetCore.csproj b/CoreSharp.Cqrs.AspNetCore/CoreSharp.Cqrs.AspNetCore.csproj index a8f285b..6e8f54a 100644 --- a/CoreSharp.Cqrs.AspNetCore/CoreSharp.Cqrs.AspNetCore.csproj +++ b/CoreSharp.Cqrs.AspNetCore/CoreSharp.Cqrs.AspNetCore.csproj @@ -1,7 +1,7 @@  - net5.0;netcoreapp3.1;netcoreapp3.0;netstandard2.0 + net5.0;netcoreapp3.1;netstandard2.0 CoreSharp.Cqrs.AspNetCore cime diff --git a/CoreSharp.Cqrs.Tests/CoreSharp.Cqrs.Tests.csproj b/CoreSharp.Cqrs.Tests/CoreSharp.Cqrs.Tests.csproj index 9bfdd24..a05730a 100644 --- a/CoreSharp.Cqrs.Tests/CoreSharp.Cqrs.Tests.csproj +++ b/CoreSharp.Cqrs.Tests/CoreSharp.Cqrs.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 false diff --git a/CoreSharp.NHibernate.SQLServer.Tests/CoreSharp.NHibernate.SQLServer.Tests.csproj b/CoreSharp.NHibernate.SQLServer.Tests/CoreSharp.NHibernate.SQLServer.Tests.csproj index 9d63676..dcc9de2 100644 --- a/CoreSharp.NHibernate.SQLServer.Tests/CoreSharp.NHibernate.SQLServer.Tests.csproj +++ b/CoreSharp.NHibernate.SQLServer.Tests/CoreSharp.NHibernate.SQLServer.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 false diff --git a/CoreSharp.NHibernate.SourceGenerator/AnalyzersConfig.cs b/CoreSharp.NHibernate.SourceGenerator/AnalyzersConfig.cs new file mode 100644 index 0000000..024df60 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/AnalyzersConfig.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml.Serialization; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + [XmlRoot("Analyzers")] + public class AnalyzersConfig + { + private static AnalyzersConfig _instance; + + public VirtualModifierAnalyzer VirtualModifierAnalyzer { get; set; } = new VirtualModifierAnalyzer(); + public PropertyOrderAnalyzer PropertyOrderAnalyzer { get; set; } = new PropertyOrderAnalyzer(); + + [XmlArray("ValidTypes")] + [XmlArrayItem("ValidType")] + public ValidTypes ValidTypes { get; set; } = new ValidTypes() { "CoreSharp.DataAccess.IEntity", "CoreSharp.DataAccess.ICodeList" }; + + public List VirtualModifierAnalyzerValidTypes => new List().Concat(ValidTypes ?? new List()).Concat(VirtualModifierAnalyzer?.ValidTypes ?? new List()).Distinct().ToList(); + public List PropertyOrderAnalyzerValidTypes => new List().Concat(ValidTypes ?? new List()).Concat(PropertyOrderAnalyzer?.ValidTypes ?? new List()).Distinct().ToList(); + + [DebuggerStepThrough] + public static AnalyzersConfig Deserialize(string content) + { + try + { + var xs = new XmlSerializer(typeof(AnalyzersConfig)); + var sr = new StringReader(content); + + return (AnalyzersConfig)xs.Deserialize(sr); + } + catch (Exception) + { + return _instance ?? (_instance = new AnalyzersConfig()); + } + } + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/CoreSharp.NHibernate.SourceGenerator.csproj b/CoreSharp.NHibernate.SourceGenerator/CoreSharp.NHibernate.SourceGenerator.csproj new file mode 100644 index 0000000..3b0743f --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/CoreSharp.NHibernate.SourceGenerator.csproj @@ -0,0 +1,43 @@ + + + + netstandard2.0 + 9 + + CoreSharp.NHibernate.SourceGenerator + + cime + .NET standard NHibernate extensions, convetions + false + Copyright 2021 (c) cime. All rights reserved. + Core# nhibernate dataaccess db + https://github.com/cime/CoreSharp + https://github.com/cime/CoreSharp/blob/master/LICENSE + https://github.com/cime/CoreSharp + enable + 0.1.1 + + + + true + false + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + diff --git a/CoreSharp.NHibernate.SourceGenerator/NHibernateGenerator.cs b/CoreSharp.NHibernate.SourceGenerator/NHibernateGenerator.cs new file mode 100644 index 0000000..d282d32 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/NHibernateGenerator.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Humanizer; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + [Generator] + public class NHibernateGenerator : ISourceGenerator + { + protected static readonly SymbolDisplayFormat SymbolDisplayFormat = new SymbolDisplayFormat(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); + protected IList ValidTypes = new List() { "CoreSharp.DataAccess.IEntity", "CoreSharp.DataAccess.ICodeList" }; + + public void Initialize(GeneratorInitializationContext context) + { +#if DEBUG + if (!Debugger.IsAttached) + { + // Debugger.Launch(); + } +#endif + context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); + } + + public void Execute(GeneratorExecutionContext context) + { + try + { + if (context.SyntaxReceiver is not SyntaxReceiver receiver) + { + return; + } + + var classSymbols = GetClassSymbols(context.Compilation, receiver); + foreach (var classSymbol in classSymbols) + { + var properties = classSymbol.GetMembers().OfType() + .Where(x => !x.ExplicitInterfaceImplementations.Any() && !x.Name.Contains(".")); + var methods = classSymbol.GetMembers().OfType(); + var modified = false; + + foreach (var propertySymbol in properties) + { + var propertyInterfaces = propertySymbol.Type.AllInterfaces; + var namedTypeSymbol = propertySymbol.Type as INamedTypeSymbol; + + if (propertySymbol.SetMethod == null) + { + continue; + } + + if (!(namedTypeSymbol?.IsGenericType == true && + (propertySymbol.Type.Name == "IEnumerable" + || propertySymbol.Type.Name == "ISet" + || propertySymbol.Type.Name == "IList" + || propertySymbol.Type.Name == "HashSet" + || propertySymbol.Type.Name == "List" + || propertyInterfaces.Any(x => + x.Name == "ISet" || x.Name == "IList" || x.Name == "IEnumerable")) + && propertySymbol.Type.Kind != SymbolKind.ArrayType)) + { + continue; + } + + var propertyType = (INamedTypeSymbol)propertySymbol.Type; + + var parentAttribute = propertySymbol.GetAttributes().SingleOrDefault(x => x.AttributeClass.Name == "ParentAttribute"); + var parentPropertyName = parentAttribute?.ConstructorArguments.Single().Value.ToString() ?? classSymbol.Name; + var childType = propertyType.TypeArguments.Single(); + var childTypeName = childType.Name; + var propertyName = propertySymbol.Name; + var propertyNameSingular = propertyName.Singularize(); + var methodNames = new[] { $"Add{propertyNameSingular}", $"Remove{propertyNameSingular}", $"Clear{propertyName}" }; + var notFound = methodNames.Where(x => !methods.Any(m => m.Name == x && + (m.Name == $"Clear{propertyName}" || (m.Parameters.Length == 1 && SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, childType))))).ToList(); + + if (!notFound.Any()) + { + continue; + } + + modified = true; + var addMethod = GenerateAddMethod(notFound, propertyNameSingular, classSymbol, childTypeName, propertySymbol, parentPropertyName); + var removeMethod = GenerateRemoveMethod(notFound, propertyNameSingular, classSymbol, childTypeName, propertySymbol, parentPropertyName); + var clearMethod = GenerateClearMethod(notFound, propertyName, propertySymbol, classSymbol, propertyNameSingular); + + var source = $@"//---------------------- +// +// Generated by NHibernateGenerator +// +//---------------------- +using System; +using System.Linq; +using CoreSharp.NHibernate; +using {childType.ContainingNamespace}; + +namespace {classSymbol.ContainingNamespace} +{{ +public static partial class {classSymbol.Name}Extensions +{{ + {addMethod} + {removeMethod} + {clearMethod} +}} +}} +"; + var desiredFileName = $"{classSymbol.Name}.{propertySymbol.Name}.Methods.cs"; + var sourceText = SourceText.From(source, Encoding.UTF8); // If no encoding specified then SourceText is not debugable + + context.AddSource(desiredFileName, sourceText); + } + + if (modified) + { + var syntax = classSymbol.DeclaringSyntaxReferences + .First().SyntaxTree.GetRoot().FindNode(classSymbol.Locations.First().SourceSpan) as ClassDeclarationSyntax; + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + } + + private static string GenerateClearMethod(List notFound, string propertyName, IPropertySymbol propertySymbol, INamedTypeSymbol classSymbol, string propertyNameSingular) + { + return notFound.Contains($"Clear{propertyName}") ? @$" + public static void Clear{propertySymbol.Name}(this {classSymbol.Name} entity) + {{ + foreach (var item in entity.{propertySymbol.Name}.ToList()) + {{ + entity.Remove{propertyNameSingular}(item); + }} + }} +" : ""; + } + + private static string GenerateRemoveMethod(List notFound, string propertyNameSingular, INamedTypeSymbol classSymbol, string childTypeName, IPropertySymbol propertySymbol, string parentPropertyName) + { + return notFound.Contains($"Remove{propertyNameSingular}") ? @$" + public static void Remove{propertyNameSingular}(this {classSymbol.Name} entity, {childTypeName} item) + {{ + entity.RemoveOneToMany(o => o.{propertySymbol.Name}, item, o => o.{parentPropertyName}); + }} +" : ""; + } + + private static string GenerateAddMethod(List notFound, string propertyNameSingular, INamedTypeSymbol classSymbol, + string childTypeName, IPropertySymbol propertySymbol, string parentPropertyName) + { + var addMethod = notFound.Contains($"Add{propertyNameSingular}") + ? @$" + public static void Add{propertyNameSingular}(this {classSymbol.Name} entity, {childTypeName} item) + {{ + entity.AddOneToMany(o => o.{propertySymbol.Name}, item, o => o.{parentPropertyName}, o => o.Remove{propertyNameSingular}); + }} +" + : ""; + return addMethod; + } + + private static INamedTypeSymbol GetClassSymbol(Compilation compilation, ClassDeclarationSyntax clazz) + { + var model = compilation.GetSemanticModel(clazz.SyntaxTree); + var classSymbol = model.GetDeclaredSymbol(clazz)!; + return classSymbol; + } + + private IList GetClassSymbols(Compilation compilation, SyntaxReceiver receiver) + { + // var classDeclarationSyntaxes = compilation.SyntaxTrees.SelectMany(x => x.GetRoot().DescendantNodes().OfType()).ToList(); + var classSymbols = new List(); + foreach (var clazz in receiver.CandidateClasses) + { + var classSymbol = GetClassSymbol(compilation, clazz); + if (IsValidType(classSymbol) && !classSymbols.Contains(classSymbol)) + { + classSymbols.Add(classSymbol); + } + } + + return classSymbols; + } + + private bool IsValidType(INamedTypeSymbol cls) + { + var interfaces = cls.AllInterfaces.Select(x => x.ToDisplayString(SymbolDisplayFormat)); + + if (interfaces.Any(x => ValidTypes.Contains(x))) + { + return true; + } + + return false; + } + + protected bool IsValidType(SyntaxNodeAnalysisContext nodeContext) + { + var classNode = nodeContext.Node.Parent as ClassDeclarationSyntax; + + if (classNode == null) + { + return false; + } + + var symbol = ModelExtensions.GetDeclaredSymbol(nodeContext.SemanticModel, classNode) as INamedTypeSymbol; + var interfaces = symbol?.AllInterfaces.Select(x => x.ToDisplayString(SymbolDisplayFormat)); + + if (interfaces?.Any(x => ValidTypes.Contains(x)) == true) + { + return true; + } + + return false; + } + + protected bool IsValidType(ClassDeclarationSyntax classSyntax, SemanticModel semanticModel) + { + var classNode = classSyntax; + + if (classNode == null) + { + return false; + } + + var symbol = ModelExtensions.GetDeclaredSymbol(semanticModel, classNode) as INamedTypeSymbol; + var interfaces = symbol?.AllInterfaces.Select(x => x.ToDisplayString(SymbolDisplayFormat)); + + if (interfaces?.Any(x => ValidTypes.Contains(x)) == true) + { + return true; + } + + return false; + } + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/PropertyOrderAnalyzer.cs b/CoreSharp.NHibernate.SourceGenerator/PropertyOrderAnalyzer.cs new file mode 100644 index 0000000..ace622d --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/PropertyOrderAnalyzer.cs @@ -0,0 +1,11 @@ +using System.Xml.Serialization; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + public class PropertyOrderAnalyzer + { + [XmlArray("ValidTypes")] + [XmlArrayItem("ValidType")] + public ValidTypes ValidTypes { get; set; } + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/README.md b/CoreSharp.NHibernate.SourceGenerator/README.md new file mode 100644 index 0000000..7a63368 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/README.md @@ -0,0 +1,42 @@ +CoreSharp NHibernate Source Generator +===================================== + +Extension methods generator for CoreSharp NHibernate entities.\ +This package generates Add/Remove/Clear methods for each collection property. + +Requirements +------------ + +.NET 5 + +Installation +------------ + +Add `CoreSharp.NHibernate.SourceGenerator` reference to csproj: + +```json + + ... + + ... + +``` + +Add `analyzers.config` to root of project: + +```xml + + + + CoreSharp.DataAccess.IEntity + CoreSharp.DataAccess.ICodeList + + + + + + + + + +``` diff --git a/CoreSharp.NHibernate.SourceGenerator/SyntaxNodeExtensions.cs b/CoreSharp.NHibernate.SourceGenerator/SyntaxNodeExtensions.cs new file mode 100644 index 0000000..172bb91 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/SyntaxNodeExtensions.cs @@ -0,0 +1,59 @@ +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + public static class SyntaxNodeExtensions + { + public static bool HasKeyword(this SyntaxNode node, SyntaxKind kind) + { + return node.DescendantTokens().SingleOrDefault(x => x.Kind() == kind) != default(SyntaxToken); + } + + public static bool IsReadonly(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.ReadOnlyKeyword); + } + + public static bool IsAbstract(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.AbstractKeyword); + } + + public static bool IsVirtual(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.VirtualKeyword) || HasKeyword(node, SyntaxKind.OverrideKeyword); + } + + public static bool IsPublic(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.PublicKeyword); + } + + public static bool IsPrivate(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.PrivateKeyword); + } + + public static bool IsStatic(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.StaticKeyword); + } + + public static bool IsPartial(this SyntaxNode node) + { + return HasKeyword(node, SyntaxKind.PartialKeyword); + } + + public static SyntaxToken GetTokenWithKeyword(this SyntaxNode node, SyntaxKind kind) + { + return node.DescendantTokens().FirstOrDefault(x => x.Kind() == kind); + } + + public static string GetIdentifierValue(this SyntaxNode node) + { + return node.ChildTokens().FirstOrDefault(x => x.Kind() == SyntaxKind.IdentifierToken).ValueText; + } + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/SyntaxReceiver.cs b/CoreSharp.NHibernate.SourceGenerator/SyntaxReceiver.cs new file mode 100644 index 0000000..9213878 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/SyntaxReceiver.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +/// +/// Created on demand before each generation pass +/// +namespace CoreSharp.NHibernate.SourceGenerator +{ + internal class SyntaxReceiver : ISyntaxReceiver + { + public IList CandidateClasses { get; } = new List(); + + /// + /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation + /// + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + // any field with at least one attribute is a candidate for property generation + if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax) // && + // classDeclarationSyntax.AttributeLists.Count > 0) + { + CandidateClasses.Add(classDeclarationSyntax); + } + } + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/ValidTypes.cs b/CoreSharp.NHibernate.SourceGenerator/ValidTypes.cs new file mode 100644 index 0000000..2fdb7d1 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/ValidTypes.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + public class ValidTypes : List + { + } +} diff --git a/CoreSharp.NHibernate.SourceGenerator/VirtualModifierAnalyzer.cs b/CoreSharp.NHibernate.SourceGenerator/VirtualModifierAnalyzer.cs new file mode 100644 index 0000000..777bc04 --- /dev/null +++ b/CoreSharp.NHibernate.SourceGenerator/VirtualModifierAnalyzer.cs @@ -0,0 +1,11 @@ +using System.Xml.Serialization; + +namespace CoreSharp.NHibernate.SourceGenerator +{ + public class VirtualModifierAnalyzer + { + [XmlArray("ValidTypes")] + [XmlArrayItem("ValidType")] + public ValidTypes ValidTypes { get; set; } + } +} diff --git a/CoreSharp.Validation.Tests/CoreSharp.Validation.Tests.csproj b/CoreSharp.Validation.Tests/CoreSharp.Validation.Tests.csproj index 79762db..8fd20d8 100644 --- a/CoreSharp.Validation.Tests/CoreSharp.Validation.Tests.csproj +++ b/CoreSharp.Validation.Tests/CoreSharp.Validation.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 false 9.0 diff --git a/CoreSharp.sln b/CoreSharp.sln index 559c040..2c35958 100644 --- a/CoreSharp.sln +++ b/CoreSharp.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29509.3 @@ -95,6 +95,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreSharp.Mvc.Formatters", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{FBF7815A-2F16-43C1-8D21-EF4E6616446A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreSharp.NHibernate.SourceGenerator", "CoreSharp.NHibernate.SourceGenerator\CoreSharp.NHibernate.SourceGenerator.csproj", "{19881C1A-D1CA-40BD-8579-7543C4315902}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -259,6 +261,10 @@ Global {A6D76085-63EF-4B2C-A3D6-B096392E98CC}.Debug|Any CPU.Build.0 = Debug|Any CPU {A6D76085-63EF-4B2C-A3D6-B096392E98CC}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6D76085-63EF-4B2C-A3D6-B096392E98CC}.Release|Any CPU.Build.0 = Release|Any CPU + {19881C1A-D1CA-40BD-8579-7543C4315902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19881C1A-D1CA-40BD-8579-7543C4315902}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19881C1A-D1CA-40BD-8579-7543C4315902}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19881C1A-D1CA-40BD-8579-7543C4315902}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 5da8d03..52126eb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -# CoreSharp # - -## CoreSharp.Breeze +![example workflow](https://github.com/cime/coresharp/actions/workflows/dotnetcore.yml/badge.svg) +[![CodeFactor](https://www.codefactor.io/repository/github/cime/coresharp/badge)](https://www.codefactor.io/repository/github/cime/coresharp) -CoreSharp.Breeze is a customized .NET Standard 2.0 implementation of Breeze server side. +# CoreSharp # ### Installation