diff --git a/Readme.md b/Readme.md index a2a1328..4c124d6 100644 --- a/Readme.md +++ b/Readme.md @@ -19,5 +19,91 @@ Rop.Generators is a free and open source project, licensed under the MIT license Each package is published in nuget +Rop.ControllerGenerator +------------------------ +This generator is designed to automate the creation of controllers for any application. +This is specialy userful for WinForms applications, but can be used in any other type of application. + +- A Controller must be a class that resides in a "Controllers" path in the project, or +alternatively, a class decorated with the attribute `[Controller]` + +- A Controller must have derive from a generic class with the following signature: + `BaseController` where T is the type of the form that the controller will handle. + +- A controler must have a contructor with the following signature: + `public Controller(T form) : base(form)` + where T is the type of the form that the controller will handle. + +In the other hand, the form must be partial and decorated with the attribute `[InsertControllers]` and must have the following line in the constructor: +``` + public Form1() { + [...] + InitControllers(); + [...] + } +``` + +The nuget package Rop.ControllerGenerator.Annotations is required in order to use the attributes. + +Rop.CopyPartialGenerator +------------------------ +This generator is designed to automate the creation of horizontaly derived classes for any application. +There are three types of new classes that can be generated: + +- `[CopyPArtialTo]`A partial class that derives from another partial class (usualy to implements an interface). + This kind of partial class is userful when you need to implement an interface in a class whith exactly the same code. +- `[CopyPartialAsImmutableRecord]` A partial class that derives from another partial class but as Immutable Record. + This kind of partial class is userful when you need to implement a immutable version of a class. +- `[CopyPartialAsEditableClass]` A partial class that derives from another partial class but as an Editable Class. + This kind of partial class is userful when you need to implement a editable version of an immutable class. + +The nuget package Rop.CopyPartialGenerator.Annotations is required in order to use the attributes. + +Rop.DerivedFromGenerator +------------------------ +This generator is designed to allow the creation of derived classes when generic base classes are not allowded. +This is specialy userful for WinForms applications, but can be used in any other type of application. + +- The derived class must be a partial class whit an interface of type `IDerivedFrom` + +The nuget package Rop.DerivedFromGenerator.Annotations is required in order to use the interface. + +Rop.OneOfExtensionsGenerator +------------------------ + +This generator is designed to allow the creation of extension methods based on OneOf methods. +This is specialy userful when you need to create extension methods for each type of a OneOf type. +This avoid to repeating code for each type of the OneOf type. + +- The extension class must be a partial static class decorated with the attribute `[OneOfExtensions]` +- The OneOf Extension methods can be private and prefixed with `_` +- The OneOf Extensio methods must be decorated with the attribute `[SplitOneOf]` + +The nuget package Rop.OneOfExtensionsGenerator.Annotations is required in order to use the attributes. +The nuget package OneOf is required in order to use the OneOf type. + +Rop.ProxyGenerator +------------------------ + +Rop.ProxyGenerator is a source generator package to automatic proxy of interfaces. +It can be used to provide Aspect Oriented Programming to c# via a "proxy". + +-The partial class to be generated must be decorated with the attribute `[ProxyOf(interface,property into the class to be proxied, excluded names to be proxied)]` +-The partial class must have a property of a field with a instance of the interface to be proxied. +-There are a lot of auxiliary attributesd to control the proxy behavior. + +The nuget package Rop.ProxyGenerator.Annotations is required in order to use the attributes. + +Rop.StaticExtensionGenerator +------------------------ + +Rop.StaticExtensionGenerator is a source generator package to automatic static extension methods. +It can be used to provide static extension methods to classes. The current c# languaje does not allow to create static extension methods. + +-The class to contain the static extension must be a generic class where the first generic type is the type class to be extended. +-The class where implement the static extension must be decorated with the attribute `[StaticExtension>()]` + +The nuget package Rop.StaticExtensionGenerator.Annotations is required in order to use the attributes. + ------ (C)2022 Ramón Ordiales Plaza diff --git a/Rop.ControllerGenerator.Annotations/Class1.cs b/Rop.ControllerGenerator.Annotations/Class1.cs deleted file mode 100644 index 21fd2ee..0000000 --- a/Rop.ControllerGenerator.Annotations/Class1.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Rop.ControllerGenerator.Annotations -{ - public class Class1 - { - - } -} diff --git a/Rop.ControllerGenerator.Annotations/ControllerAttribute.cs b/Rop.ControllerGenerator.Annotations/ControllerAttribute.cs new file mode 100644 index 0000000..4effce4 --- /dev/null +++ b/Rop.ControllerGenerator.Annotations/ControllerAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace Rop.ControllerGenerator.Annotations; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] +public class ControllerAttribute : Attribute +{ +} \ No newline at end of file diff --git a/Rop.ControllerGenerator.Annotations/InsertControllersAttribute.cs b/Rop.ControllerGenerator.Annotations/InsertControllersAttribute.cs new file mode 100644 index 0000000..8d731fc --- /dev/null +++ b/Rop.ControllerGenerator.Annotations/InsertControllersAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace Rop.ControllerGenerator.Annotations +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public class InsertControllersAttribute : Attribute + { + } +} + diff --git a/Rop.ControllerGenerator.Annotations/Rop.ControllerGenerator.Annotations.csproj b/Rop.ControllerGenerator.Annotations/Rop.ControllerGenerator.Annotations.csproj index 4de8048..de3c61c 100644 --- a/Rop.ControllerGenerator.Annotations/Rop.ControllerGenerator.Annotations.csproj +++ b/Rop.ControllerGenerator.Annotations/Rop.ControllerGenerator.Annotations.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable diff --git a/Rop.ControllerGenerator/ControllerToInclude.cs b/Rop.ControllerGenerator/ControllerToInclude.cs index 1374c1a..99be919 100644 --- a/Rop.ControllerGenerator/ControllerToInclude.cs +++ b/Rop.ControllerGenerator/ControllerToInclude.cs @@ -1,39 +1,40 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; namespace Rop.Winforms7.ControllerGenerator { public class ControllerToInclude { public string ControllerName { get; } - public string DesiredInstanceName { get; private set; } = ""; - public ClassDeclarationSyntax Cds { get; } - public INamedTypeSymbol NamedTypeSymbol { get; private set; } = null; - public string ControllerFor { get; private set; }=""; - public string ControllerNamesPace { get; private set; } - public ControllerToInclude(ClassDeclarationSyntax cds) + public string DesiredInstanceName { get; } + public INamedTypeSymbol NamedTypeSymbol { get; } + public string ControllerFor { get;} + public string ControllerNamesPace { get; } + + private ControllerToInclude(INamedTypeSymbol namedTypeSymbol, string controllerName, string desiredInstanceName, string controllerFor, string controllerNamesPace) { - ControllerName = cds.Identifier.Text; - Cds=cds; - ControllerNamesPace = cds.SyntaxTree.GetNamespace(); + NamedTypeSymbol = namedTypeSymbol; + ControllerName = controllerName; + DesiredInstanceName = desiredInstanceName; + ControllerFor = controllerFor; + ControllerNamesPace = controllerNamesPace; } - - public bool IsControllerFor(string name, Compilation contextCompilation) + public static ControllerToInclude Factory(ClassDeclarationSyntax controller, Compilation contextCompilation) { - if (NamedTypeSymbol == null) - { - var candidatos=contextCompilation.GetSymbolsWithName(s => s.EndsWith(ControllerName), SymbolFilter.Type); - NamedTypeSymbol = candidatos.FirstOrDefault() as INamedTypeSymbol; - var baseType = NamedTypeSymbol?.BaseType; - if (baseType?.IsGenericType??false) - { - ControllerFor = baseType.TypeArguments[0].Name; - } - DesiredInstanceName = ControllerName.StartsWith(ControllerFor) ? ControllerName.Substring(ControllerFor.Length) : ControllerName; - } - return ControllerFor == name; + var controllerName = controller.Identifier.Text; + var controllerNamesPace = controller.SyntaxTree.GetNamespace(); + if (string.IsNullOrEmpty(controllerNamesPace)) return null; + var namedtypesymbol = contextCompilation.GetSymbolsWithName(s => s.EndsWith(controllerName), SymbolFilter.Type) + .OfType().FirstOrDefault(); + if (namedtypesymbol == null) return null; + var baseType = namedtypesymbol.BaseType; + if (baseType == null) return null; + if (!baseType.IsGenericType) return null; + var controllerFor = baseType.TypeArguments[0].Name; + var desiredInstanceName = controllerName.StartsWith(controllerFor) ? controllerName.Substring(controllerFor.Length) : controllerName; + return new ControllerToInclude(namedtypesymbol, controllerName, desiredInstanceName, controllerFor, controllerNamesPace); } } } \ No newline at end of file diff --git a/Rop.ControllerGenerator/InsertControllerGenerator.cs b/Rop.ControllerGenerator/InsertControllerGenerator.cs index 54edfb0..c4d585e 100644 --- a/Rop.ControllerGenerator/InsertControllerGenerator.cs +++ b/Rop.ControllerGenerator/InsertControllerGenerator.cs @@ -5,7 +5,7 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; namespace Rop.Winforms7.ControllerGenerator { @@ -14,42 +14,29 @@ public class InsertControllerGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { -//#if DEBUG -// if (!Debugger.IsAttached) -// { -// Debugger.Launch(); -// } -//#endif context.RegisterForSyntaxNotifications(() => new ClassesToAugmentReceiver()); } public void Execute(GeneratorExecutionContext context) { var collector = context.SyntaxReceiver as ClassesToAugmentReceiver; - if (collector == null || collector.ClassesToAugment.Count == 0) return; + if (collector == null || collector.ClassesToAugment.Count == 0 || collector.ControllersToInclude.Count==0) return; + var dic=collector.ProcessControllers(context.Compilation); foreach (var classtoaugment in collector.ClassesToAugment) { - generateCode(context, classtoaugment,collector); + generateCode(context, classtoaugment,dic); } collector.Clear(); } - private void generateCode(GeneratorExecutionContext context, PartialClassToAugment classtoaugment,ClassesToAugmentReceiver receiver) + private void generateCode(GeneratorExecutionContext context, PartialClassToAugment classtoaugment,Dictionary> diccontrollers) { var formname=classtoaugment.Identifier; var file = classtoaugment.FileName +".Controllers_.g.cs"; var model = context.Compilation.GetSemanticModel(classtoaugment.Original.SyntaxTree); var classmodel = (INamedTypeSymbol)model.GetDeclaredSymbol(classtoaugment.Original); if (classmodel is null) return; - var finalcontrollers=classtoaugment.GetControllersToInclude(context.Compilation,receiver.ControllersToInclude); + if (!diccontrollers.TryGetValue(formname, out var finalcontrollers)) return; var sb = new StringBuilder(); sb.AppendLine("// Autogenerated code for Controllers"); - if (finalcontrollers.Count == 0) - { - // ERROR NO CONTROLLERS - sb.AppendLines("// ERROR NO CONTROLLERS",$"// Looking for:{classtoaugment.Identifier}"); - var finalerror = sb.ToString(); - context.AddSource(file, finalerror); - return; - } var usings = finalcontrollers.Select(x => x.ControllerNamesPace).Distinct().ToList(); sb.AppendLines(classtoaugment.GetHeader(usings)); foreach (var symbol in finalcontrollers) @@ -71,7 +58,7 @@ private void generateCode(GeneratorExecutionContext context, PartialClassToAugme class ClassesToAugmentReceiver : ISyntaxReceiver { public ConcurrentBag ClassesToAugment { get; private set; } = new ConcurrentBag(); - public ConcurrentBag ControllersToInclude { get; private set; } = new ConcurrentBag(); + public ConcurrentBag ControllersToInclude { get; private set; } = new ConcurrentBag(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { if (!(syntaxNode is ClassDeclarationSyntax cds)) return; @@ -83,13 +70,31 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode) } if (cds.IsDecoratedWith("Controller") || (cds.SyntaxTree.GetNamespace().EndsWith("Controllers"))) { - if ((cds.BaseList?.Types.Count??0) != 0) ControllersToInclude.Add(new ControllerToInclude(cds)); + if ((cds.BaseList?.Types.Count??0) != 0) ControllersToInclude.Add(cds); } } public void Clear() { ClassesToAugment = new ConcurrentBag(); - ControllersToInclude = new ConcurrentBag(); + ControllersToInclude = new ConcurrentBag(); + } + + public Dictionary> ProcessControllers(Compilation contextCompilation) + { + var dic=new Dictionary>(); + foreach (var controller in ControllersToInclude) + { + var cti=ControllerToInclude.Factory(controller,contextCompilation); + if (cti is null) continue; + var name = cti.ControllerFor; + if (!dic.TryGetValue(name, out var lst)) + { + lst=new List(); + dic[name]=lst; + } + lst.Add(cti); + } + return dic; } } } diff --git a/Rop.ControllerGenerator/PartialClassToAugment.cs b/Rop.ControllerGenerator/PartialClassToAugment.cs index cdfbc7b..dab684a 100644 --- a/Rop.ControllerGenerator/PartialClassToAugment.cs +++ b/Rop.ControllerGenerator/PartialClassToAugment.cs @@ -3,69 +3,27 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; +using Rop.GeneratorShared; namespace Rop.Winforms7.ControllerGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public bool IsStatic { get; } - public bool IsGeneric { get; } - public string GenericTypes { get; } - public string Identifier { get; } - public string FileName { get; } - public string Namespace { get; } - public string Modifier { get; } - public IReadOnlyList<(string name, string sentence)> Usings { get; } - public ClassDeclarationSyntax Original { get; } - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) + public PartialClassToAugment(ClassDeclarationSyntax classToAugment) : base(classToAugment) { - Original= classToAugment; - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetUsings().ToList(); - Namespace = classToAugment.SyntaxTree.GetNamespace(); - Modifier = classToAugment.Modifiers.FirstOrDefault().ToString(); - IsStatic = classToAugment.IsStatic(); - IsGeneric = classToAugment.IsGeneric(); - GenericTypes = (IsGeneric) ? classToAugment.TypeParameterList?.ToString()??"" : ""; } public IEnumerable GetHeader(IEnumerable additionalusings) { - yield return "#nullable enable"; - foreach (var u in Usings) + return GetHeader0().Concat(GetHeader1()).Concat(GetNamespace0()).Concat(GetClass0()); + // Local functions + IEnumerable GetHeader1() { - yield return u.sentence; - } - - foreach (var additionalusing in additionalusings) - { - yield return $"using {additionalusing};"; - } - yield return $"namespace {Namespace}"; - yield return "{"; - yield return $"\t{Modifier} {(IsStatic?"static ":"")}partial class {Identifier}{GenericTypes}"; - yield return "\t{"; - } - public IEnumerable GetFooter() - { - yield return "\t}"; - yield return "}"; - } - - public List GetControllersToInclude(Compilation contextCompilation, IEnumerable controllers) - { - var name=this.Identifier; - var res=new List(); - foreach (var c in controllers) - { - if (c.IsControllerFor(name, contextCompilation)) + foreach (var additionalusing in additionalusings) { - res.Add(c); + yield return $"using {additionalusing};"; } } - return res; } } } diff --git a/Rop.ControllerGenerator/Properties/launchSettings.json b/Rop.ControllerGenerator/Properties/launchSettings.json index d7d377a..8b145e3 100644 --- a/Rop.ControllerGenerator/Properties/launchSettings.json +++ b/Rop.ControllerGenerator/Properties/launchSettings.json @@ -5,7 +5,7 @@ }, "DebugComponent": { "commandName": "DebugRoslynComponent", - "targetProject": "..\\test.winforms7\\test.winforms7.csproj" + "targetProject": "..\\tests\test.controllerGenerator\\test.controllergenerator.csproj" } } } \ No newline at end of file diff --git a/Rop.ControllerGenerator/Rop.ControllerGenerator.csproj b/Rop.ControllerGenerator/Rop.ControllerGenerator.csproj index acb8fe5..7bd664c 100644 --- a/Rop.ControllerGenerator/Rop.ControllerGenerator.csproj +++ b/Rop.ControllerGenerator/Rop.ControllerGenerator.csproj @@ -16,6 +16,7 @@ https://api.nuget.org/v3/index.json Readme.md false + true @@ -31,6 +32,6 @@ - + diff --git a/Rop.CopyPartialGenerator/CopyClassToAugment.cs b/Rop.CopyPartialGenerator/CopyClassToAugment.cs index 2afd2dc..d2c14a1 100644 --- a/Rop.CopyPartialGenerator/CopyClassToAugment.cs +++ b/Rop.CopyPartialGenerator/CopyClassToAugment.cs @@ -4,19 +4,14 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; +using Rop.GeneratorShared; namespace Rop.CopyPartialGenerator { - internal enum CopyTypeEnum - { - CopyClass, - CopyImmutable, - CopyEditable - } - public class CopyClassToAugment { - internal CopyTypeEnum AttType { get; } + public CopyTypeEnum AttType { get; } public PartialClassToAugment ClassToAugment { get;} public string NewClassName { get;} public BaseListSyntax BaseList { get; } diff --git a/Rop.CopyPartialGenerator/CopyPartialGenerator.cs b/Rop.CopyPartialGenerator/CopyPartialGenerator.cs index 1cafcd0..c990e94 100644 --- a/Rop.CopyPartialGenerator/CopyPartialGenerator.cs +++ b/Rop.CopyPartialGenerator/CopyPartialGenerator.cs @@ -1,27 +1,17 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; +using System.Collections.Concurrent; +using System.Text; namespace Rop.CopyPartialGenerator { [Generator] public class CopyPartialGenerator : ISourceGenerator { - - public void Initialize(GeneratorInitializationContext context) { - //#if DEBUG - // if (!Debugger.IsAttached) - // { - // Debugger.Launch(); - // } - //#endif context.RegisterForSyntaxNotifications(() => new PartialClassesToCopyReceiver()); - } public void Execute(GeneratorExecutionContext context) @@ -36,7 +26,7 @@ public void Execute(GeneratorExecutionContext context) } private void generateCode(GeneratorExecutionContext context, CopyClassToAugment classtoaugment) { - var file = classtoaugment.ClassToAugment.FileName +".CopyClassTo_"+classtoaugment.NewClassName+".g.cs"; + var file = classtoaugment.ClassToAugment.FileName + ".CopyClassTo_" + classtoaugment.NewClassName + ".g.cs"; var sb = new StringBuilder(); sb.AppendLine("// Autogenerated code for CopyPartialTo"); sb.AppendLines(classtoaugment.NewHeader()); @@ -45,8 +35,8 @@ private void generateCode(GeneratorExecutionContext context, CopyClassToAugment var final = sb.ToString(); context.AddSource(file, final); } - - class PartialClassesToCopyReceiver : ISyntaxReceiver + + private class PartialClassesToCopyReceiver : ISyntaxReceiver { public ConcurrentBag ClassesToAugment { get; private set; } = new ConcurrentBag(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) @@ -54,11 +44,11 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode) // Business logic to decide what we're interested in goes here if (syntaxNode is ClassDeclarationSyntax cds) { - var atts = cds.GetDecoratedManyWith("CopyPartialTo","CopyPartialAsImmutableRecord","CopyPartialAsEditableClass"); - if (atts.Length==0) return; + var atts = cds.GetDecoratedWithAny("CopyPartialTo", "CopyPartialAsImmutableRecord", "CopyPartialAsEditableClass"); + if (atts.Length == 0) return; foreach (var attributeSyntax in atts) { - var ac = new CopyClassToAugment(cds,attributeSyntax); + var ac = new CopyClassToAugment(cds, attributeSyntax); if (ac.NewClassName != null) ClassesToAugment.Add(ac); } } @@ -69,4 +59,4 @@ public void Clear() } } } -} +} \ No newline at end of file diff --git a/Rop.CopyPartialGenerator/CopyTypeEnum.cs b/Rop.CopyPartialGenerator/CopyTypeEnum.cs new file mode 100644 index 0000000..c68a142 --- /dev/null +++ b/Rop.CopyPartialGenerator/CopyTypeEnum.cs @@ -0,0 +1,9 @@ +namespace Rop.CopyPartialGenerator +{ + public enum CopyTypeEnum + { + CopyClass, + CopyImmutable, + CopyEditable + } +} \ No newline at end of file diff --git a/Rop.CopyPartialGenerator/PartialClassToAugment.cs b/Rop.CopyPartialGenerator/PartialClassToAugment.cs index 6499ecc..8ed36ef 100644 --- a/Rop.CopyPartialGenerator/PartialClassToAugment.cs +++ b/Rop.CopyPartialGenerator/PartialClassToAugment.cs @@ -2,43 +2,14 @@ using System.IO; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.GeneratorShared; namespace Rop.CopyPartialGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public bool IsStatic { get; } - public string Identifier { get; } - public string FileName { get; } - public string Namespace { get; } - public IReadOnlyList<(string name, string sentence)> Usings { get; } - public ClassDeclarationSyntax Original { get; } - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) + public PartialClassToAugment(ClassDeclarationSyntax classToAugment):base(classToAugment) { - Original= classToAugment; - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetUsings().ToList(); - Namespace = classToAugment.SyntaxTree.GetNamespace(); - IsStatic = classToAugment.IsStatic(); - } - public virtual IEnumerable GetHeader() - { - foreach (var u in Usings) - { - yield return u.sentence; - } - - yield return $"namespace {Namespace}"; - yield return "{"; - yield return $"\tpublic {(IsStatic?"static ":"")}partial class {Identifier}"; - yield return "\t{"; - } - public IEnumerable GetFooter() - { - yield return "\t}"; - yield return "}"; } } } diff --git a/Rop.CopyPartialGenerator/Rop.CopyPartialGenerator.csproj b/Rop.CopyPartialGenerator/Rop.CopyPartialGenerator.csproj index d0cb10a..aa6d773 100644 --- a/Rop.CopyPartialGenerator/Rop.CopyPartialGenerator.csproj +++ b/Rop.CopyPartialGenerator/Rop.CopyPartialGenerator.csproj @@ -1,4 +1,4 @@ - + Rop.CopyPartialGenerator Rop.CopyPartialGenerator @@ -32,4 +32,5 @@ + diff --git a/Rop.CopyPartialGenerator/SyntaxHelper.cs b/Rop.CopyPartialGenerator/SyntaxHelper.cs deleted file mode 100644 index d89fd5b..0000000 --- a/Rop.CopyPartialGenerator/SyntaxHelper.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Rop.CopyPartialGenerator -{ - public static class SyntaxHelper - { - public static string GetDecoratedWith(this AttributeSyntax att, params string[] attnames) - { - var name = att.Name.ToString(); - return attnames.FirstOrDefault(a => a.Equals(name))??""; - } - public static bool IsDecoratedWith(this AttributeSyntax att, params string[] attnames) - { - return GetDecoratedWith(att, attnames)!=""; - } - - /// - /// Class is decorated with some attribute - /// - public static bool IsDecoratedWith(this TypeDeclarationSyntax item, params string[] attnames) - { - return item.AttributeLists.SelectMany(a => a.Attributes).Any(a =>a.IsDecoratedWith(attnames)); - } - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, params string[] attnames) - { - return item.AttributeLists.SelectMany(a => a.Attributes).Any(a => a.IsDecoratedWith(attnames)); - } - /// - /// Get decorated attribute for a class - /// - public static AttributeSyntax GetDecoratedWith(this TypeDeclarationSyntax item, string attname) - { - return item.AttributeLists.SelectMany(a => a.Attributes).FirstOrDefault(a => a.IsDecoratedWith(attname)); - } - public static AttributeSyntax[] GetDecoratedManyWith(this TypeDeclarationSyntax item,params string[] attnames) - { - return item.AttributeLists.SelectMany(a => a.Attributes).Where(a =>a.IsDecoratedWith(attnames)).ToArray(); - } - - /// - /// Get decorated attribute for a member - /// - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, string attname) - { - return item.AttributeLists.SelectMany(a => a.Attributes).FirstOrDefault(a => a.IsDecoratedWith(attname)); - } - /// - /// Childs of type T - /// - public static IEnumerable ChildNodesOfType(this SyntaxNode node) - { - return node.ChildNodes().OfType(); - } - public static IEnumerable ChildNodesOfType(this SyntaxNode node,params Type[] types) - { - return node.ChildNodes().Where(n => types.Any(t=>IsSameOrSubclass(t,n.GetType()))); - } - public static bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant) - { - return potentialDescendant.IsSubclassOf(potentialBase) - || potentialDescendant == potentialBase; - } - - public static bool IsStatic(this ClassDeclarationSyntax cds) - { - return cds.Modifiers.Any(SyntaxKind.StaticKeyword); - } - - public static string ToStringValue(this ExpressionSyntax expression) - { - switch (expression) - { - case TypeOfExpressionSyntax tof: - return tof.Type.ToString(); - case InvocationExpressionSyntax inv: - var a = inv.ArgumentList.Arguments.FirstOrDefault() as ArgumentSyntax; - IdentifierNameSyntax i=null; - if (a?.Expression is MemberAccessExpressionSyntax b) - i = b?.ChildNodes().Last() as IdentifierNameSyntax; - else if (a?.Expression is IdentifierNameSyntax ai) - i = ai; - return i?.Identifier.ToString() ?? ""; - case ArrayCreationExpressionSyntax arr: - var arrv = arr.Initializer.Expressions.Select(c => c.ToStringValue()); - return string.Join(",", arrv); - default: - var v= expression.ToString(); - if (v.StartsWith("\"")) v = v.Substring(1); - if (v.EndsWith("\"")) v = v.Substring(0,v.Length-1); - return v; - } - } - public static IEnumerable ToStringValues(this AttributeArgumentListSyntax argumentlist) - { - foreach (var arg in argumentlist.Arguments) - { - yield return arg.Expression.ToStringValue(); - } - } - - public static IEnumerable<(string, string)> GetUsings(this SyntaxTree syntaxTree) - { - var r = syntaxTree.GetRoot(); - return r.ChildNodesOfType().Select(u => (u.Name.ToString(), u.ToString())).ToList(); - } - public static string GetNamespace(this SyntaxTree syntaxTree){ - var r = syntaxTree.GetRoot(); - return r.ChildNodesOfType().FirstOrDefault()?.Name.ToString(); - } - - - /// - /// Appendlines to a stringbuilder - /// - public static void AppendLines(this StringBuilder sb, params string[] lines) - { - AppendLines(sb, lines as IEnumerable); - } - public static void AppendLines(this StringBuilder sb, IEnumerable lines) - { - foreach (var line in lines) - { - sb.AppendLine(line); - } - } - - } -} diff --git a/Rop.DerivedFrom.Annotations/Class1.cs b/Rop.DerivedFrom.Annotations/Class1.cs deleted file mode 100644 index 7cebdc8..0000000 --- a/Rop.DerivedFrom.Annotations/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Rop.DerivedFrom.Annotations -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/Rop.DerivedFrom.Annotations/IDerivedFrom.cs b/Rop.DerivedFrom.Annotations/IDerivedFrom.cs new file mode 100644 index 0000000..fa9b093 --- /dev/null +++ b/Rop.DerivedFrom.Annotations/IDerivedFrom.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rop.DerivedFrom.Annotations +{ + public interface IDerivedFrom + { + } +} diff --git a/Rop.DerivedFromGenerator/DerivedFromGenerator.cs b/Rop.DerivedFromGenerator/DerivedFromGenerator.cs index 9bafb03..65181a0 100644 --- a/Rop.DerivedFromGenerator/DerivedFromGenerator.cs +++ b/Rop.DerivedFromGenerator/DerivedFromGenerator.cs @@ -3,7 +3,8 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; + namespace Rop.Winforms7.DerivedFromGenerator { @@ -12,12 +13,7 @@ public class DerivedFromGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { -//#if DEBUG -// if (!Debugger.IsAttached) -// { -// Debugger.Launch(); -// } -//#endif + context.RegisterForSyntaxNotifications(() => new ClassesToAugmentReceiver()); } public void Execute(GeneratorExecutionContext context) @@ -42,8 +38,7 @@ private void generateCode(GeneratorExecutionContext context, ProxyPartialClassTo var sb = new StringBuilder(); sb.AppendLine("// Autogenerated code for "+basename); sb.AppendLines(classtoaugment.GetHeader()); - sb.AppendLines($"\tpublic abstract class {newname}:{basename}{{}}"); - sb.AppendLines($"\tpublic partial class {formname}:{newname}{{}}"); + sb.AppendLines(classtoaugment.GetClassNew(formname, newname, basename)); sb.AppendLines(classtoaugment.GetFooter()); var final = sb.ToString(); context.AddSource(file, final); diff --git a/Rop.DerivedFromGenerator/PartialClassToAugment.cs b/Rop.DerivedFromGenerator/PartialClassToAugment.cs index 32c08d1..9efeea5 100644 --- a/Rop.DerivedFromGenerator/PartialClassToAugment.cs +++ b/Rop.DerivedFromGenerator/PartialClassToAugment.cs @@ -4,67 +4,40 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; +using Rop.GeneratorShared; + namespace Rop.Winforms7.DerivedFromGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public bool IsStatic { get; } - public bool IsGeneric { get; } - public string GenericTypes { get; } - public string Identifier { get; } - public string FileName { get; } - public string Namespace { get; } - public string Modifier { get; } - public IReadOnlyList<(string name, string sentence)> Usings { get; } - public ClassDeclarationSyntax Original { get; } - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) + public PartialClassToAugment(ClassDeclarationSyntax classToAugment) : base(classToAugment) { - Original= classToAugment; - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetUsings().ToList(); - Namespace = classToAugment.SyntaxTree.GetNamespace(); - Modifier = classToAugment.Modifiers.FirstOrDefault().ToString(); - IsStatic = classToAugment.IsStatic(); - IsGeneric = classToAugment.IsGeneric(); - GenericTypes = (IsGeneric) ? classToAugment.TypeParameterList?.ToString()??"" : ""; } - public IEnumerable GetHeader() => GetHeader(Array.Empty()); - public IEnumerable GetHeader(IEnumerable additionalusings) + public IEnumerable GetClassNew(string formname,string newname,string basename) { - yield return "#nullable enable"; - foreach (var u in Usings) - { - yield return u.sentence; - } + yield return $"\tpublic abstract class {newname}:{basename}{{}}"; + yield return $"\tpublic partial class {formname}:{newname}{{}}"; + } - foreach (var additionalusing in additionalusings) + public new IEnumerable GetHeader() => this.GetHeader(Array.Empty()); + public IEnumerable GetHeader(IEnumerable additionalusings) + { + return GetHeader0().Concat(GetHeader1()).Concat(GetNamespace0()); + // Local functions + IEnumerable GetHeader1() { - yield return $"using {additionalusing};"; + foreach (var additionalusing in additionalusings) + { + yield return $"using {additionalusing};"; + } } - yield return $"namespace {Namespace}"; - yield return "{"; } - public IEnumerable GetFooter() + public override IEnumerable GetFooter() { yield return "}"; } } - - public class ProxyPartialClassToAugment - { - public PartialClassToAugment Original { get; } - public TypeSyntax BaseToFlat { get; } - - public ProxyPartialClassToAugment(PartialClassToAugment original, TypeSyntax baseToFlat) - { - Original = original; - BaseToFlat = baseToFlat; - } - } - } diff --git a/Rop.DerivedFromGenerator/ProxyPartialClassToAugment.cs b/Rop.DerivedFromGenerator/ProxyPartialClassToAugment.cs new file mode 100644 index 0000000..0612beb --- /dev/null +++ b/Rop.DerivedFromGenerator/ProxyPartialClassToAugment.cs @@ -0,0 +1,16 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Rop.Winforms7.DerivedFromGenerator +{ + public class ProxyPartialClassToAugment + { + public PartialClassToAugment Original { get; } + public TypeSyntax BaseToFlat { get; } + + public ProxyPartialClassToAugment(PartialClassToAugment original, TypeSyntax baseToFlat) + { + Original = original; + BaseToFlat = baseToFlat; + } + } +} \ No newline at end of file diff --git a/Rop.DerivedFromGenerator/Rop.DerivedFromGenerator.csproj b/Rop.DerivedFromGenerator/Rop.DerivedFromGenerator.csproj index 6c38b11..4a27ffe 100644 --- a/Rop.DerivedFromGenerator/Rop.DerivedFromGenerator.csproj +++ b/Rop.DerivedFromGenerator/Rop.DerivedFromGenerator.csproj @@ -32,6 +32,6 @@ - + diff --git a/Rop.Generators.Shared/BasePartialClassToAugment.cs b/Rop.Generators.Shared/BasePartialClassToAugment.cs new file mode 100644 index 0000000..ac3e6a6 --- /dev/null +++ b/Rop.Generators.Shared/BasePartialClassToAugment.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; + +namespace Rop.GeneratorShared +{ + public abstract class BasePartialClassToAugment + { + public bool IsStatic { get; } + public bool IsGeneric { get; } + public string GenericTypes { get; } + public string Identifier { get; } + public string FileName { get; } + public string Namespace { get; } + public string Modifier { get; } + public IReadOnlyList<(string name, string sentence)> Usings { get; } + public ClassDeclarationSyntax Original { get; } + + protected BasePartialClassToAugment(ClassDeclarationSyntax classToAugment) + { + Original= classToAugment; + Identifier = classToAugment.Identifier.ToString(); + var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); + FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; + Usings = classToAugment.SyntaxTree.GetUsings().ToList(); + Namespace = classToAugment.SyntaxTree.GetNamespace(); + Modifier = classToAugment.Modifiers.FirstOrDefault().ToString(); + IsStatic = classToAugment.IsStatic(); + IsGeneric = classToAugment.IsGeneric(); + GenericTypes = (IsGeneric) ? classToAugment.TypeParameterList?.ToString()??"" : ""; + } + + protected virtual IEnumerable GetHeader0() + { + yield return "#nullable enable"; + foreach (var u in Usings) + { + yield return u.sentence; + } + } + protected virtual IEnumerable GetNamespace0() + { + yield return $"namespace {Namespace}"; + yield return "{"; + } + + protected virtual IEnumerable GetClass0() + { + yield return $"\t{Modifier} {(IsStatic?"static ":"")}partial class {Identifier}{GenericTypes}"; + yield return "\t{"; + } + protected virtual IEnumerable GetHeader() + { + return GetHeader0().Concat(GetNamespace0()).Concat(GetClass0()); + } + public virtual IEnumerable GetFooter() + { + yield return "\t}"; + yield return "}"; + } + } +} diff --git a/Rop.Generators.Shared/Rop.Generators.Shared.projitems b/Rop.Generators.Shared/Rop.Generators.Shared.projitems index 95aa317..28ba484 100644 --- a/Rop.Generators.Shared/Rop.Generators.Shared.projitems +++ b/Rop.Generators.Shared/Rop.Generators.Shared.projitems @@ -9,6 +9,7 @@ Rop.GeneratorShared + diff --git a/Rop.Generators.Shared/SyntaxHelperAtts.cs b/Rop.Generators.Shared/SyntaxHelperAtts.cs index 4d00b5c..67ea6d1 100644 --- a/Rop.Generators.Shared/SyntaxHelperAtts.cs +++ b/Rop.Generators.Shared/SyntaxHelperAtts.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Rop.Generators.Shared { @@ -15,7 +15,7 @@ public static partial class SyntaxHelperAtts /// /// Member is decorated with some attribute /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname,params string[] attname2) => IsDecoratedWith(item, attname2.Prepend(attname),out _); + public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname, params string[] attname2) => IsDecoratedWith(item, attname2.Prepend(attname), out _); /// /// Member is decorated with some attribute @@ -26,7 +26,7 @@ public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string att /// /// Member is decorated with some attribute /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname,out AttributeSyntax decorated) + public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname, out AttributeSyntax decorated) { decorated = GetDecoratedWith(item, attname); return decorated != null; @@ -35,7 +35,7 @@ public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string att /// /// Member is decorated with some attribute /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item,IEnumerable attnames,out AttributeSyntax decorated) + public static bool IsDecoratedWith(this MemberDeclarationSyntax item, IEnumerable attnames, out AttributeSyntax decorated) { decorated = GetDecoratedWith(item, attnames); return decorated != null; @@ -46,7 +46,7 @@ public static bool IsDecoratedWith(this MemberDeclarationSyntax item,IEnumerable /// /// /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item,ImmutableHashSet attnames,out AttributeSyntax decorated) + public static bool IsDecoratedWith(this MemberDeclarationSyntax item, ImmutableHashSet attnames, out AttributeSyntax decorated) { decorated = GetDecoratedWith(item, attnames); return decorated != null; @@ -66,32 +66,43 @@ public static AttributeSyntax[] GetDecoratedWithSome(this MemberDeclarationSynta { return GetAttributes(item).Where(a => a.Name.ToString().Equals(attname)).ToArray(); } + public static string IsDecoratedWithAny(this AttributeSyntax att, params string[] attnames) + { + var name = att.Name.ToString(); + return attnames.FirstOrDefault(a => a.Equals(name)) ?? ""; + } + + public static AttributeSyntax[] GetDecoratedWithAny(this MemberDeclarationSyntax item, params string[] attnames) + { + return GetAttributes(item).Where(a => a.IsDecoratedWithAny(attnames) != "").ToArray(); + } + /// /// Get many decorated attributes for a class /// public static AttributeSyntax[] GetDecoratedWithSomeGeneric(this MemberDeclarationSyntax item, string attname) { - var genattname=attname+"<"; + var genattname = attname + "<"; return GetAttributes(item).Where(a => a.Name.ToString().StartsWith(genattname)).ToArray(); } /// /// Get decorated attribute for a class /// - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item,IEnumerable attname) + public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, IEnumerable attname) { var lst = attname.ToImmutableHashSet(); return GetDecoratedWith(item, lst); } - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item,ImmutableHashSet attnames) + public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, ImmutableHashSet attnames) { - return GetAttributes(item).FirstOrDefault(a =>a.Name.ToString().InList(attnames)); + return GetAttributes(item).FirstOrDefault(a => a.Name.ToString().InList(attnames)); } - - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, string attname,params string[] attname2) + + public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, string attname, params string[] attname2) { var lst = attname2.Prepend(attname); - return GetDecoratedWith(item,lst); + return GetDecoratedWith(item, lst); } } } \ No newline at end of file diff --git a/Rop.Generators.sln b/Rop.Generators.sln index c05d442..e7585fc 100644 --- a/Rop.Generators.sln +++ b/Rop.Generators.sln @@ -32,7 +32,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.OneOfExtensionGenerato EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.DerivedFrom", "Test\Test.DerivedFrom\Test.DerivedFrom.csproj", "{3823745B-AED0-402E-AE0B-2277E3A24A34}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.StaticExtension", "Test\Test.StaticExtension\Test.StaticExtension.csproj", "{1323FB30-4474-488B-AC84-E22ED4887040}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.StaticExtensions", "Test\Test.StaticExtension\Test.StaticExtensions.csproj", "{1323FB30-4474-488B-AC84-E22ED4887040}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.ControllerGenerator", "Rop.ControllerGenerator\Rop.ControllerGenerator.csproj", "{59CBDAF7-857A-47D6-AE57-0D069F5D925F}" EndProject @@ -40,11 +40,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.DerivedFromGenerator", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.StaticExtensionGenerator", "Rop.StaticExtensionGenerator\Rop.StaticExtensionGenerator.csproj", "{5A2BDD1D-9A9B-42BF-B00C-4104CEB957F6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rop.ControllerGenerator.Annotations", "Rop.ControllerGenerator.Annotations\Rop.ControllerGenerator.Annotations.csproj", "{97A781B7-95A8-4A1C-BBD2-2463A9BEB5AA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.ControllerGenerator.Annotations", "Rop.ControllerGenerator.Annotations\Rop.ControllerGenerator.Annotations.csproj", "{97A781B7-95A8-4A1C-BBD2-2463A9BEB5AA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rop.DerivedFrom.Annotations", "Rop.DerivedFrom.Annotations\Rop.DerivedFrom.Annotations.csproj", "{6A90600D-4829-4453-BEB5-6FEBAC9D049F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.DerivedFrom.Annotations", "Rop.DerivedFrom.Annotations\Rop.DerivedFrom.Annotations.csproj", "{6A90600D-4829-4453-BEB5-6FEBAC9D049F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rop.StaticExtension.Annotations", "Rop.StaticExtension.Annotations\Rop.StaticExtension.Annotations.csproj", "{20C84D28-B7D0-41E5-BD4E-759F7D11CCA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rop.StaticExtension.Annotations", "Rop.StaticExtension.Annotations\Rop.StaticExtension.Annotations.csproj", "{20C84D28-B7D0-41E5-BD4E-759F7D11CCA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.ControllerGenerator", "Test\Test.ControllerGenerator\Test.ControllerGenerator.csproj", "{7EBAA8C5-695E-40CB-885B-B907929C7702}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -120,6 +122,10 @@ Global {20C84D28-B7D0-41E5-BD4E-759F7D11CCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {20C84D28-B7D0-41E5-BD4E-759F7D11CCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {20C84D28-B7D0-41E5-BD4E-759F7D11CCA2}.Release|Any CPU.Build.0 = Release|Any CPU + {7EBAA8C5-695E-40CB-885B-B907929C7702}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EBAA8C5-695E-40CB-885B-B907929C7702}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EBAA8C5-695E-40CB-885B-B907929C7702}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EBAA8C5-695E-40CB-885B-B907929C7702}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -130,11 +136,18 @@ Global {8D959B4E-8953-4FCA-A5C7-E3F6206EC47A} = {F10EFED0-5CB0-40A6-849D-ADD8A497A930} {3823745B-AED0-402E-AE0B-2277E3A24A34} = {F10EFED0-5CB0-40A6-849D-ADD8A497A930} {1323FB30-4474-488B-AC84-E22ED4887040} = {F10EFED0-5CB0-40A6-849D-ADD8A497A930} + {7EBAA8C5-695E-40CB-885B-B907929C7702} = {F10EFED0-5CB0-40A6-849D-ADD8A497A930} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28136F61-670C-48E3-872A-9242018602A1} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{10ed2d2d-6d3d-4570-b78c-f61b52328596}*SharedItemsImports = 5 + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{568ee803-f01b-4f45-ba81-70642128a797}*SharedItemsImports = 5 + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{59cbdaf7-857a-47d6-ae57-0d069f5d925f}*SharedItemsImports = 5 + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{5a2bdd1d-9a9b-42bf-b00c-4104ceb957f6}*SharedItemsImports = 5 + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{86231b22-cb3a-4de0-af41-c26710435cc9}*SharedItemsImports = 5 + Rop.Generators.Shared\Rop.Generators.Shared.projitems*{8f79abde-e5ad-421d-be65-0042f27b104b}*SharedItemsImports = 5 Rop.Generators.Shared\Rop.Generators.Shared.projitems*{b6fa2a36-63eb-4074-b174-3e85b96e4265}*SharedItemsImports = 13 EndGlobalSection EndGlobal diff --git a/Rop.OneOfExtensionGenerator/ExtensionClassWithOneOfToAugment.cs b/Rop.OneOfExtensionGenerator/ExtensionClassWithOneOfToAugment.cs index 29df3a1..30efa1f 100644 --- a/Rop.OneOfExtensionGenerator/ExtensionClassWithOneOfToAugment.cs +++ b/Rop.OneOfExtensionGenerator/ExtensionClassWithOneOfToAugment.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; namespace Rop.OneOfExtensionGenerator { diff --git a/Rop.OneOfExtensionGenerator/OneOfExtensionGenerator.cs b/Rop.OneOfExtensionGenerator/OneOfExtensionGenerator.cs index f5e65ff..a55b302 100644 --- a/Rop.OneOfExtensionGenerator/OneOfExtensionGenerator.cs +++ b/Rop.OneOfExtensionGenerator/OneOfExtensionGenerator.cs @@ -2,6 +2,7 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; namespace Rop.OneOfExtensionGenerator { diff --git a/Rop.OneOfExtensionGenerator/PartialClassToAugment.cs b/Rop.OneOfExtensionGenerator/PartialClassToAugment.cs index 828dc32..b501d7c 100644 --- a/Rop.OneOfExtensionGenerator/PartialClassToAugment.cs +++ b/Rop.OneOfExtensionGenerator/PartialClassToAugment.cs @@ -2,45 +2,15 @@ using System.IO; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.GeneratorShared; namespace Rop.OneOfExtensionGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public string Identifier { get; set; } - public string FileName { get; set; } - public string Namespace { get; set; } - public List<(string name, string sentence)> Usings { get; set; } - - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) - { - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetRoot().ChildNodes() - .OfType() - .Select(u => (u.Name.ToString(), u.ToString())).ToList(); - Namespace = classToAugment.SyntaxTree.GetRoot().ChildNodes().OfType() - .First().Name.ToString(); - } - - public IEnumerable GetHeader() - { - foreach (var u in Usings) - { - yield return u.sentence; - } - - yield return $"namespace {Namespace}"; - yield return "{"; - yield return $"\tpublic static partial class {Identifier}"; - yield return "\t{"; - } - - public IEnumerable GetFooter() + public PartialClassToAugment(ClassDeclarationSyntax classToAugment) : base(classToAugment) { - yield return "\t}"; - yield return "}"; } + public new IEnumerable GetHeader()=>base.GetHeader(); } } diff --git a/Rop.OneOfExtensionGenerator/Rop.OneOfExtensionGenerator.csproj b/Rop.OneOfExtensionGenerator/Rop.OneOfExtensionGenerator.csproj index 83151ab..b03c382 100644 --- a/Rop.OneOfExtensionGenerator/Rop.OneOfExtensionGenerator.csproj +++ b/Rop.OneOfExtensionGenerator/Rop.OneOfExtensionGenerator.csproj @@ -33,5 +33,6 @@ + diff --git a/Rop.OneOfExtensionGenerator/SyntaxHelper.cs b/Rop.OneOfExtensionGenerator/SyntaxHelper.cs index 3bea82e..da1d757 100644 --- a/Rop.OneOfExtensionGenerator/SyntaxHelper.cs +++ b/Rop.OneOfExtensionGenerator/SyntaxHelper.cs @@ -5,27 +5,27 @@ namespace Rop.OneOfExtensionGenerator { - public static class SyntaxHelper - { - public static bool IsDecoratedWith(this TypeDeclarationSyntax item, string attname) - { - return item.AttributeLists.SelectMany(a => a.Attributes).Any(a => a.Name.ToString().Equals(attname)); - } - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname) - { - return item.AttributeLists.SelectMany(a => a.Attributes).Any(a => a.Name.ToString().Equals(attname)); - } + //public static class SyntaxHelper + //{ + // public static bool IsDecoratedWith(this TypeDeclarationSyntax item, string attname) + // { + // return item.AttributeLists.SelectMany(a => a.Attributes).Any(a => a.Name.ToString().Equals(attname)); + // } + // public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname) + // { + // return item.AttributeLists.SelectMany(a => a.Attributes).Any(a => a.Name.ToString().Equals(attname)); + // } - public static void AppendLines(this StringBuilder sb, params string[] lines) - { - AppendLines(sb, lines as IEnumerable); - } - public static void AppendLines(this StringBuilder sb, IEnumerable lines) - { - foreach (var line in lines) - { - sb.AppendLine(line); - } - } - } + // public static void AppendLines(this StringBuilder sb, params string[] lines) + // { + // AppendLines(sb, lines as IEnumerable); + // } + // public static void AppendLines(this StringBuilder sb, IEnumerable lines) + // { + // foreach (var line in lines) + // { + // sb.AppendLine(line); + // } + // } + //} } diff --git a/Rop.ProxyGenerator/IncludesAtts.cs b/Rop.ProxyGenerator/IncludesAtts.cs new file mode 100644 index 0000000..950f685 --- /dev/null +++ b/Rop.ProxyGenerator/IncludesAtts.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Rop.Generators.Shared; + +namespace Rop.ProxyGenerator +{ + public class IncludesAtts + { + public List AttsToInclude { get; } = new List(); + public IncludesAtts(ISymbol namedTypeSymbol) + { + var nextatts = namedTypeSymbol.GetAttributes().SkipWhile(a => SymbolHelperAtts.GetShortName(a) != "IncludeNextAttributes") + .ToList(); + if (nextatts.Any()) + { + AttsToInclude.AddRange(nextatts.Skip(1).Select(a=>a.ToString())); + } + } + + public void Render(StringBuilder sb, int tabs) + { + foreach (var att in AttsToInclude) + { + sb.AppendLines(tabs,$"[{att}]"); + } + } + public bool IsEmpty => AttsToInclude.Count == 0; + } +} \ No newline at end of file diff --git a/Rop.ProxyGenerator/PartialClassToAugment.cs b/Rop.ProxyGenerator/PartialClassToAugment.cs index 0a8d106..8b7bdfc 100644 --- a/Rop.ProxyGenerator/PartialClassToAugment.cs +++ b/Rop.ProxyGenerator/PartialClassToAugment.cs @@ -3,33 +3,16 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; +using Rop.GeneratorShared; namespace Rop.ProxyGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public bool IsStatic { get; } - public bool IsGeneric { get; } - public string GenericTypes { get; } - public string Identifier { get; } - public string FileName { get; } - public string Namespace { get; } - public string Modifier { get; } public bool DisableNullable { get; } - public IReadOnlyList<(string name, string sentence)> Usings { get; } - public ClassDeclarationSyntax Original { get; } - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) + public PartialClassToAugment(ClassDeclarationSyntax classToAugment):base(classToAugment) { - Original= classToAugment; - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetUsings().ToList(); - Namespace = classToAugment.SyntaxTree.GetNamespace(); - Modifier = classToAugment.Modifiers.FirstOrDefault().ToString(); - IsStatic = classToAugment.IsStatic(); - IsGeneric = classToAugment.IsGeneric(); - GenericTypes = (IsGeneric) ? classToAugment.TypeParameterList?.ToString()??"" : ""; var attr=classToAugment.GetDecoratedWith("ProxyOfDisableNullable"); if (attr!=null) { @@ -57,10 +40,5 @@ public IEnumerable GetHeader(INamedTypeSymbol interfacetoinclude) yield return $"\t{Modifier} {(IsStatic?"static ":"")}partial class {Identifier}{GenericTypes}"; yield return "\t{"; } - public IEnumerable GetFooter() - { - yield return "\t}"; - yield return "}"; - } } } diff --git a/Rop.ProxyGenerator/ProxyClassToAugment.cs b/Rop.ProxyGenerator/ProxyClassToAugment.cs index 849b779..6294d3e 100644 --- a/Rop.ProxyGenerator/ProxyClassToAugment.cs +++ b/Rop.ProxyGenerator/ProxyClassToAugment.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; namespace Rop.ProxyGenerator { diff --git a/Rop.ProxyGenerator/ProxyGenerator.cs b/Rop.ProxyGenerator/ProxyGenerator.cs index a824182..5197bc7 100644 --- a/Rop.ProxyGenerator/ProxyGenerator.cs +++ b/Rop.ProxyGenerator/ProxyGenerator.cs @@ -1,11 +1,11 @@ using System.Collections.Concurrent; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Rop.Generators.Shared; namespace Rop.ProxyGenerator { @@ -23,12 +23,6 @@ public class ProxyGenerator : ISourceGenerator public void Initialize(GeneratorInitializationContext context) { -//#if DEBUG -// if (!Debugger.IsAttached) -// { -// Debugger.Launch(); -// } -//#endif context.RegisterForSyntaxNotifications(() => new ProxyClassesToAugmentReceiver()); } @@ -280,27 +274,4 @@ public void Clear() } } } - - public class IncludesAtts - { - public List AttsToInclude { get; } = new List(); - public IncludesAtts(ISymbol namedTypeSymbol) - { - var nextatts = namedTypeSymbol.GetAttributes().SkipWhile(a => a.GetShortName() != "IncludeNextAttributes") - .ToList(); - if (nextatts.Any()) - { - AttsToInclude.AddRange(nextatts.Skip(1).Select(a=>a.ToString())); - } - } - - public void Render(StringBuilder sb, int tabs) - { - foreach (var att in AttsToInclude) - { - sb.AppendLines(tabs,$"[{att}]"); - } - } - public bool IsEmpty => AttsToInclude.Count == 0; - } } diff --git a/Rop.ProxyGenerator/Rop.ProxyGenerator.csproj b/Rop.ProxyGenerator/Rop.ProxyGenerator.csproj index d700150..6bf3894 100644 --- a/Rop.ProxyGenerator/Rop.ProxyGenerator.csproj +++ b/Rop.ProxyGenerator/Rop.ProxyGenerator.csproj @@ -32,4 +32,5 @@ + diff --git a/Rop.ProxyGenerator/SymbolHelperAtts.cs b/Rop.ProxyGenerator/SymbolHelperAtts.cs deleted file mode 100644 index 4604b1a..0000000 --- a/Rop.ProxyGenerator/SymbolHelperAtts.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Rop.ProxyGenerator -{ - public static partial class SymbolHelperAtts - { - public static string GetShortName(this AttributeData adata) - { - var n=adata?.AttributeClass?.Name ?? ""; - if (n.EndsWith("Attribute")) - n = n.Substring(0, n.Length - "Attribute".Length); - return n; - } - - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this ISymbol item, string attname,params string[] attname2) => IsDecoratedWith(item, attname2.Prepend(attname),out _); - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this ISymbol item, string attname) => - IsDecoratedWith(item, attname, out _); - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this ISymbol item, string attname,out AttributeData decorated) - { - decorated = GetDecoratedWith(item, attname); - return decorated != null; - } - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this ISymbol item,IEnumerable attnames,out AttributeData decorated) - { - decorated = GetDecoratedWith(item, attnames); - return decorated != null; - } - /// - /// Member is decorated with some attributes - /// - /// - /// - /// - public static bool IsDecoratedWith(this ISymbol item,ImmutableHashSet attnames,out AttributeData decorated) - { - decorated = GetDecoratedWith(item, attnames); - return decorated != null; - } - - /// - /// Get decorated attribute for a class - /// - public static AttributeData GetDecoratedWith(this ISymbol item, string attname) - { - return item.GetAttributes().FirstOrDefault(a => a.GetShortName().Equals(attname)); - } - /// - /// Get decorated attribute for a class - /// - public static AttributeData GetDecoratedWith(this ISymbol item,IEnumerable attname) - { - var lst = attname.ToImmutableHashSet(); - return GetDecoratedWith(item, lst); - } - public static AttributeData GetDecoratedWith(this ISymbol item,ImmutableHashSet attnames) - { - return item.GetAttributes().FirstOrDefault(a =>a.GetShortName().InList(attnames)); - } - - public static AttributeData GetDecoratedWith(this ISymbol item, string attname,params string[] attname2) - { - var lst = attname2.Prepend(attname); - return GetDecoratedWith(item,lst); - } - - public static string GetParametersDefinition(this IMethodSymbol meth) - { - var pars = new List(); - foreach (var p in meth.Parameters) - { - var ps =$"{p.Type} {p.MetadataName}"; - switch (p.RefKind) - { - case RefKind.In: ps = "in " + ps; - break; - case RefKind.Out: ps = "out " + ps; - break; - case RefKind.Ref: ps = "ref " + ps; - break; - } - pars.Add(ps); - } - var j = string.Join(",",pars); - return j; - } - public static string GetParametersSignature(this IMethodSymbol meth) - { - var pars = meth.Parameters.Select(p => $"{p.OriginalDefinition}"); - var pdef = string.Join(",",pars); - return pdef; - } - - public static string GetParametersNames(this IMethodSymbol meth) - { - var pars = new List(); - foreach (var p in meth.Parameters) - { - var ps = p.MetadataName; - switch (p.RefKind) - { - case RefKind.In: ps = "in " + ps; - break; - case RefKind.Out: ps = "out " + ps; - break; - case RefKind.Ref: ps = "ref " + ps; - break; - } - pars.Add(ps); - } - var j = string.Join(",",pars); - return j; - } - - public static string ToSignature(this ISymbol s) - { - switch (s) - { - case IMethodSymbol m: - - return $"{m.Name}({m.GetParametersSignature()})"; - default: - return s.Name; - } - } - } -} \ No newline at end of file diff --git a/Rop.ProxyGenerator/SyntaxHelper.cs b/Rop.ProxyGenerator/SyntaxHelper.cs deleted file mode 100644 index f81af67..0000000 --- a/Rop.ProxyGenerator/SyntaxHelper.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Rop.ProxyGenerator -{ - public static partial class SyntaxHelper - { - /// - /// Childs of type T - /// - public static IEnumerable ChildNodesOfType(this SyntaxNode node) => node.ChildNodes().OfType(); - - public static IEnumerable ChildNodesOfType(this SyntaxNode node,params Type[] types) - { - return node.ChildNodes().Where(n => types.Any(t=>IsSameOrSubclass(t,n.GetType()))); - } - public static bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant) - { - return potentialDescendant.IsSubclassOf(potentialBase) || potentialDescendant == potentialBase; - } - - public static bool IsStatic(this ClassDeclarationSyntax cds) - { - return cds.Modifiers.Any(SyntaxKind.StaticKeyword); - } - public static bool IsGeneric(this ClassDeclarationSyntax cds) - { - return cds.TypeParameterList?.Parameters.Count > 0; - } - - public static TypeName GetInterfaceImplementation(this ClassDeclarationSyntax cds, TypeName originalinterface) - { - if (!originalinterface.IsGeneric) return originalinterface; - foreach (var basetype in cds.BaseList.Types) - { - var n = basetype.ToString(); - } - return originalinterface; - } - - public static string ToStringValue(this ExpressionSyntax expression) - { - switch (expression) - { - case TypeOfExpressionSyntax tof: - return tof.Type.ToString(); - case InvocationExpressionSyntax inv: - var a = inv.ArgumentList.Arguments.FirstOrDefault() as ArgumentSyntax; - IdentifierNameSyntax i=null; - if (a?.Expression is IdentifierNameSyntax aasi) - { - i = aasi; - } - else - { - var b = a?.Expression as MemberAccessExpressionSyntax; - i = b?.ChildNodes().Last() as IdentifierNameSyntax; - } - return i?.Identifier.ToString() ?? ""; - case ArrayCreationExpressionSyntax arr: - var arrv = arr.Initializer.Expressions.Select(c => c.ToStringValue()); - return string.Join(",", arrv); - default: - var v= expression.ToString(); - if (v.StartsWith("\"")) v = v.Substring(1); - if (v.EndsWith("\"")) v = v.Substring(0,v.Length-1); - return v; - } - } - public static IEnumerable ToStringValues(this AttributeArgumentListSyntax argumentlist) - { - foreach (var arg in argumentlist.Arguments) - { - yield return arg.Expression.ToStringValue(); - } - } - - public static IEnumerable<(string, string)> GetUsings(this SyntaxTree syntaxTree) - { - var r = syntaxTree.GetRoot(); - return r.ChildNodesOfType().Select(u => (u.Name.ToString(), u.ToString())).ToList(); - } - public static string GetNamespace(this SyntaxTree syntaxTree){ - var r = syntaxTree.GetRoot(); - return r.ChildNodesOfType().FirstOrDefault()?.Name.ToString(); - } - - public static IEnumerable GetOrderedMembers(this INamedTypeSymbol typeSymbol,bool inherited) - { - var morder = new OrderedNames(); - var dic=new Dictionary(); - _getOrderedMembers(typeSymbol,inherited,morder,dic); - //var mnames = morder.ToImmutableHashSet(); - //var dic=typeSymbol.GetMembers().Where(mm => mm.Name.InList(mnames)).ToDictionary(mm=>mm.Name); - foreach (var m in dic.Values) - { - yield return m; - } - } - - private class OrderedName - { - public string Name { get; set; } - public int Order { get; set; } = 999999; - } - - private class OrderedNames - { - private readonly Dictionary _dic=new Dictionary(); - - public void Add(string name) - { - if (_dic.ContainsKey(name)) return; - _dic[name] = new OrderedName() { Name = name, Order = _dic.Count }; - } - - public void AddRange(IEnumerable name) - { - foreach (var n in name) - { - Add(n); - } - } - - public OrderedName Get(string name) - { - if (!_dic.TryGetValue(name, out var res)) return null; - return res; - } - public bool Contains(string name) => _dic.ContainsKey(name); - } - - private class OrderedMember - { - public OrderedMember(ISymbol m, OrderedName order) - { - this.Member = m; - this.Order = order.Order; - Name = m.Name; - Signature = m.ToSignature(); - } - - public string Name { get; } - public string Signature { get; } - public ISymbol Member { get; } - public int Order { get; set; } = 999999; - } private static void _getOrderedMembers(this INamedTypeSymbol typeSymbol, bool inherited,OrderedNames morder,Dictionary dic) - { - if (inherited) - { - var sub = typeSymbol.Interfaces; - foreach (var s in sub) - { - _getOrderedMembers(s,true, morder,dic); - } - } - var singlemorder = typeSymbol.MemberNames; - morder.AddRange(singlemorder); - var lstmembers = new List(); - foreach (var m in typeSymbol.GetMembers()) - { - if (!(m is IEventSymbol || m is IPropertySymbol || m is IMethodSymbol)) continue; - var order = morder.Get(m.Name); - if (order == null) continue; - lstmembers.Add(new OrderedMember(m,order)); - } - lstmembers = lstmembers.OrderBy(m => m.Order).ToList(); - foreach (var m in lstmembers) - { - dic[m.Signature] = m.Member; - } - } - } -} diff --git a/Rop.ProxyGenerator/SyntaxHelperAtts.cs b/Rop.ProxyGenerator/SyntaxHelperAtts.cs deleted file mode 100644 index f62d7ca..0000000 --- a/Rop.ProxyGenerator/SyntaxHelperAtts.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Rop.ProxyGenerator -{ - public static partial class SyntaxHelperAtts - { - /// - /// Get Attributes from AttributeLists - /// - public static IEnumerable GetAttributes(this MemberDeclarationSyntax item) => item.AttributeLists.SelectMany(a => a.Attributes); - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname,params string[] attname2) => IsDecoratedWith(item, attname2.Prepend(attname),out _); - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname) => - IsDecoratedWith(item, attname, out _); - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item, string attname,out AttributeSyntax decorated) - { - decorated = GetDecoratedWith(item, attname); - return decorated != null; - } - - /// - /// Member is decorated with some attribute - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item,IEnumerable attnames,out AttributeSyntax decorated) - { - decorated = GetDecoratedWith(item, attnames); - return decorated != null; - } - /// - /// Member is decorated with some attributes - /// - /// - /// - /// - public static bool IsDecoratedWith(this MemberDeclarationSyntax item,ImmutableHashSet attnames,out AttributeSyntax decorated) - { - decorated = GetDecoratedWith(item, attnames); - return decorated != null; - } - - /// - /// Get decorated attribute for a class - /// - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, string attname) - { - return GetAttributes(item).FirstOrDefault(a => a.Name.ToString().Equals(attname)); - } - /// - /// Get many decorated attributes for a class - /// - public static AttributeSyntax[] GetDecoratedWithSome(this MemberDeclarationSyntax item, string attname) - { - return GetAttributes(item).Where(a => a.Name.ToString().Equals(attname)).ToArray(); - } - - /// - /// Get decorated attribute for a class - /// - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item,IEnumerable attname) - { - var lst = attname.ToImmutableHashSet(); - return GetDecoratedWith(item, lst); - } - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item,ImmutableHashSet attnames) - { - return GetAttributes(item).FirstOrDefault(a =>a.Name.ToString().InList(attnames)); - } - - public static AttributeSyntax GetDecoratedWith(this MemberDeclarationSyntax item, string attname,params string[] attname2) - { - var lst = attname2.Prepend(attname); - return GetDecoratedWith(item,lst); - } - } -} \ No newline at end of file diff --git a/Rop.ProxyGenerator/TextHelper.cs b/Rop.ProxyGenerator/TextHelper.cs deleted file mode 100644 index 1c88dde..0000000 --- a/Rop.ProxyGenerator/TextHelper.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Text; - -namespace Rop.ProxyGenerator -{ - public static class TextHelper - { - - /// - /// Appendlines to a stringbuilder - /// - public static void AppendLines(this StringBuilder sb, params string[] lines) - { - AppendLines(sb, lines as IEnumerable); - } - public static void AppendLines(this StringBuilder sb, IEnumerable lines) - { - foreach (var line in lines) - { - sb.AppendLine(line); - } - } - /// - /// Appendlines to a stringbuilder - /// - public static void AppendLines(this StringBuilder sb,int tabs, params string[] lines) - { - AppendLines(sb,tabs, lines as IEnumerable); - } - public static void AppendLines(this StringBuilder sb,int tabs, IEnumerable lines) - { - var t = new string('\t', tabs); - foreach (var line in lines) - { - sb.Append(t); - sb.AppendLine(line); - } - } - public static void AppendTab(this StringBuilder sb,int tabs,string cad) - { - var t = new string('\t', tabs); - sb.Append(t); - sb.Append(cad); - } - public static bool InList(this string cad, ImmutableHashSet list) => list.Contains(cad); - public static bool InList(this string cad, IEnumerable list) => list.Contains(cad); - } -} \ No newline at end of file diff --git a/Rop.ProxyGenerator/TypeName.cs b/Rop.ProxyGenerator/TypeName.cs deleted file mode 100644 index 699b89d..0000000 --- a/Rop.ProxyGenerator/TypeName.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace Rop.ProxyGenerator -{ - public struct TypeName - { - public readonly string Name; - public readonly string FullName; - public readonly bool IsGeneric; - public readonly TypeName[] GenericNames; - - public TypeName(string tname) - { - if (string.IsNullOrEmpty(tname)) throw new ArgumentException("Type name is empty"); - if (!tname.Contains('<')) - { - Name = tname; - FullName=tname; - IsGeneric = false; - GenericNames = Array.Empty(); - } - else - { - FullName = tname; - IsGeneric = true; - var p1 = tname.IndexOf("<"); - var p2=tname.LastIndexOf('>'); - var inner=tname.Substring(p1+1,p2-p1-1); - Name = tname.Substring(0, p1); - var sp = inner.Split(','); - var all=sp.Select(x =>new TypeName(x.Trim())).ToArray(); - GenericNames = all; - } - } - - public string ReplaceGeneric(params string[] generics) - { - if (GenericNames.Length != generics.Length) throw new ArgumentException("Number of generics mismatch"); - if (!IsGeneric) return FullName; - var j = string.Join(",", generics); - return $"{Name}<{j}>"; - } - public bool Equals(INamedTypeSymbol interf) - { - if (interf?.Name != Name) return false; - var ts = interf.TypeArguments.Select(a => a.ToString()).ToList(); - if (GenericNames.Length!=ts.Count) return false; - for (var f = 0; f < GenericNames.Length; f++) - { - var a = ts[f]; - var b = GenericNames[f].FullName; - if (a.Equals(b)) continue; - var p = a.LastIndexOf('.'); - if (p != -1) - { - a = a.Substring(p + 1); - } - if (!a.Equals(b)) return false; - } - return true; - } - } -} \ No newline at end of file diff --git a/Rop.StaticExtension.Annotations/StaticExtensionAttribute.cs b/Rop.StaticExtension.Annotations/StaticExtensionAttribute.cs new file mode 100644 index 0000000..9a43b4f --- /dev/null +++ b/Rop.StaticExtension.Annotations/StaticExtensionAttribute.cs @@ -0,0 +1,9 @@ +namespace Rop.StaticExtension.Annotations; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] +public class StaticExtensionAttribute:Attribute +{ + public StaticExtensionAttribute() + { + } +} \ No newline at end of file diff --git a/Rop.StaticExtensionGenerator/ExtensionToInclude.cs b/Rop.StaticExtensionGenerator/ExtensionToInclude.cs index 7356369..57cac72 100644 --- a/Rop.StaticExtensionGenerator/ExtensionToInclude.cs +++ b/Rop.StaticExtensionGenerator/ExtensionToInclude.cs @@ -1,7 +1,7 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; namespace Rop.Winforms7.StaticExtensionGenerator { diff --git a/Rop.StaticExtensionGenerator/PartialClassToAugment.cs b/Rop.StaticExtensionGenerator/PartialClassToAugment.cs index 7634a57..454f75f 100644 --- a/Rop.StaticExtensionGenerator/PartialClassToAugment.cs +++ b/Rop.StaticExtensionGenerator/PartialClassToAugment.cs @@ -3,33 +3,15 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; +using Rop.GeneratorShared; namespace Rop.Winforms7.StaticExtensionGenerator { - public class PartialClassToAugment + public class PartialClassToAugment:BasePartialClassToAugment { - public bool IsStatic { get; } - public bool IsGeneric { get; } - public string GenericTypes { get; } - public string Identifier { get; } - public string FileName { get; } - public string Namespace { get; } - public string Modifier { get; } - public IReadOnlyList<(string name, string sentence)> Usings { get; } - public ClassDeclarationSyntax Original { get; } - public PartialClassToAugment(ClassDeclarationSyntax classToAugment) + public PartialClassToAugment(ClassDeclarationSyntax classToAugment) : base(classToAugment) { - Original= classToAugment; - Identifier = classToAugment.Identifier.ToString(); - var stfp = Path.GetFileNameWithoutExtension(classToAugment.SyntaxTree.FilePath); - FileName = (string.IsNullOrEmpty(stfp)) ? Identifier : stfp; - Usings = classToAugment.SyntaxTree.GetUsings().ToList(); - Namespace = classToAugment.SyntaxTree.GetNamespace(); - Modifier = classToAugment.Modifiers.FirstOrDefault().ToString(); - IsStatic = classToAugment.IsStatic(); - IsGeneric = classToAugment.IsGeneric(); - GenericTypes = (IsGeneric) ? classToAugment.TypeParameterList?.ToString()??"" : ""; } public IEnumerable GetHeader(IEnumerable additionalusings) { @@ -38,7 +20,6 @@ public IEnumerable GetHeader(IEnumerable additionalusings) { yield return u.sentence; } - foreach (var additionalusing in additionalusings) { yield return $"using {additionalusing};"; @@ -48,11 +29,6 @@ public IEnumerable GetHeader(IEnumerable additionalusings) yield return $"\t{Modifier} {(IsStatic?"static ":"")}partial class {Identifier}{GenericTypes}"; yield return "\t{"; } - public IEnumerable GetFooter() - { - yield return "\t}"; - yield return "}"; - } } public class ProxyPartialClassToAugment diff --git a/Rop.StaticExtensionGenerator/Rop.StaticExtensionGenerator.csproj b/Rop.StaticExtensionGenerator/Rop.StaticExtensionGenerator.csproj index ca2bf4b..7da86ef 100644 --- a/Rop.StaticExtensionGenerator/Rop.StaticExtensionGenerator.csproj +++ b/Rop.StaticExtensionGenerator/Rop.StaticExtensionGenerator.csproj @@ -33,6 +33,7 @@ - + + diff --git a/Rop.StaticExtensionGenerator/StaticExtensionGenerator.cs b/Rop.StaticExtensionGenerator/StaticExtensionGenerator.cs index 8d309f8..9f5ca40 100644 --- a/Rop.StaticExtensionGenerator/StaticExtensionGenerator.cs +++ b/Rop.StaticExtensionGenerator/StaticExtensionGenerator.cs @@ -3,7 +3,7 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Rop.GeneratorHelper; +using Rop.Generators.Shared; namespace Rop.Winforms7.StaticExtensionGenerator { @@ -12,12 +12,6 @@ public class StaticExtensionGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { -//#if DEBUG -// if (!Debugger.IsAttached) -// { -// Debugger.Launch(); -// } -//#endif context.RegisterForSyntaxNotifications(() => new ClassesToAugmentReceiver()); } public void Execute(GeneratorExecutionContext context) diff --git a/Test/Test.ControllerGenerator/Controllers/BaseController.cs b/Test/Test.ControllerGenerator/Controllers/BaseController.cs new file mode 100644 index 0000000..16457e0 --- /dev/null +++ b/Test/Test.ControllerGenerator/Controllers/BaseController.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Test.ControllerGenerator.Controllers +{ + public abstract class BaseController where T: Form + { + public T ParentForm { get; } + protected BaseController(T parentForm) + { + ParentForm = parentForm; + } + } +} diff --git a/Test/Test.ControllerGenerator/Controllers/Form1MainController.cs b/Test/Test.ControllerGenerator/Controllers/Form1MainController.cs new file mode 100644 index 0000000..2855608 --- /dev/null +++ b/Test/Test.ControllerGenerator/Controllers/Form1MainController.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Test.ControllerGenerator.Controllers +{ + public class Form1MainController:BaseController + { + public string Test=> "I'm a main controller"; + public Form1MainController(Form1 form1):base(form1) + { + } + } +} diff --git a/Test/Test.ControllerGenerator/ExternalController.cs b/Test/Test.ControllerGenerator/ExternalController.cs new file mode 100644 index 0000000..85953c6 --- /dev/null +++ b/Test/Test.ControllerGenerator/ExternalController.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Rop.ControllerGenerator.Annotations; +using Test.ControllerGenerator.Controllers; + +namespace Test.ControllerGenerator +{ + [Controller] + public class ExternalController:BaseController + { + public string Test => "I'm an external controller"; + public ExternalController(Form1 form) : base(form) + { + } + } +} diff --git a/Test/Test.ControllerGenerator/Form.cs b/Test/Test.ControllerGenerator/Form.cs new file mode 100644 index 0000000..037535a --- /dev/null +++ b/Test/Test.ControllerGenerator/Form.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Test.ControllerGenerator +{ + public class Form + { + } +} diff --git a/Test/Test.ControllerGenerator/Form1.cs b/Test/Test.ControllerGenerator/Form1.cs new file mode 100644 index 0000000..b362ae0 --- /dev/null +++ b/Test/Test.ControllerGenerator/Form1.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Rop.ControllerGenerator.Annotations; + +namespace Test.ControllerGenerator +{ + [InsertControllers] + public partial class Form1:Form + { + + public Form1() + { + InitControllers(); + Console.WriteLine(MainController!.Test); + Console.WriteLine(ExternalController!.Test); + } + } +} diff --git a/Test/Test.ControllerGenerator/Program.cs b/Test/Test.ControllerGenerator/Program.cs new file mode 100644 index 0000000..b4e455c --- /dev/null +++ b/Test/Test.ControllerGenerator/Program.cs @@ -0,0 +1,6 @@ +// See https://aka.ms/new-console-template for more information + +using Test.ControllerGenerator; + +Console.WriteLine("Hello, World!"); +var f=new Form1(); \ No newline at end of file diff --git a/Test/Test.ControllerGenerator/Test.ControllerGenerator.csproj b/Test/Test.ControllerGenerator/Test.ControllerGenerator.csproj new file mode 100644 index 0000000..3cc70ed --- /dev/null +++ b/Test/Test.ControllerGenerator/Test.ControllerGenerator.csproj @@ -0,0 +1,15 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + diff --git a/Test/Test.CopyPartialGenerator/Test.CopyPartialGenerator.csproj b/Test/Test.CopyPartialGenerator/Test.CopyPartialGenerator.csproj index fe67d12..4dc1c7a 100644 --- a/Test/Test.CopyPartialGenerator/Test.CopyPartialGenerator.csproj +++ b/Test/Test.CopyPartialGenerator/Test.CopyPartialGenerator.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 diff --git a/Test/Test.DerivedFrom/Program.cs b/Test/Test.DerivedFrom/Program.cs index 018383f..5303e31 100644 --- a/Test/Test.DerivedFrom/Program.cs +++ b/Test/Test.DerivedFrom/Program.cs @@ -1,4 +1,6 @@ -namespace Test.Derived; +using Rop.DerivedFrom.Annotations; + +namespace Test.Derived; internal class Program { @@ -18,10 +20,6 @@ public A SoyDeBaseForm() } } -public interface IDerivedFrom -{ -} - public partial class Form1 : IDerivedFrom> { public void Hola() diff --git a/Test/Test.DerivedFrom/Test.DerivedFrom.csproj b/Test/Test.DerivedFrom/Test.DerivedFrom.csproj index 19e885c..15cc5b2 100644 --- a/Test/Test.DerivedFrom/Test.DerivedFrom.csproj +++ b/Test/Test.DerivedFrom/Test.DerivedFrom.csproj @@ -8,7 +8,8 @@ - + + diff --git a/Test/Test.OneOfExtensionGenerator/Test.OneOfExtensionGenerator.csproj b/Test/Test.OneOfExtensionGenerator/Test.OneOfExtensionGenerator.csproj index 20de312..2ca6ee7 100644 --- a/Test/Test.OneOfExtensionGenerator/Test.OneOfExtensionGenerator.csproj +++ b/Test/Test.OneOfExtensionGenerator/Test.OneOfExtensionGenerator.csproj @@ -11,7 +11,7 @@ $(BaseIntermediateOutputPath)\GeneratedFiles - + diff --git a/Test/Test.StaticExtension/BaseForm.cs b/Test/Test.StaticExtension/BaseForm.cs new file mode 100644 index 0000000..c3e0af2 --- /dev/null +++ b/Test/Test.StaticExtension/BaseForm.cs @@ -0,0 +1,10 @@ +namespace Test.StaticExtensions; + +public class BaseForm +{ + public B ItemB { get; set; } + public A SoyDeBaseForm() + { + return default; + } +} \ No newline at end of file diff --git a/Test/Test.StaticExtension/Form1.cs b/Test/Test.StaticExtension/Form1.cs new file mode 100644 index 0000000..276fae4 --- /dev/null +++ b/Test/Test.StaticExtension/Form1.cs @@ -0,0 +1,14 @@ +namespace Test.StaticExtensions; +using Rop.StaticExtension.Annotations; + +[StaticExtension>()] +public partial class Form1 : BaseForm +{ + public void Hola() + { + var x = SoyDeBaseForm(); + Console.WriteLine(x.ToString()); + } + + public static int Execute2(bool b)=>MyStaticExtension.Execute(b); +} \ No newline at end of file diff --git a/Test/Test.StaticExtension/MyStaticExtension.cs b/Test/Test.StaticExtension/MyStaticExtension.cs new file mode 100644 index 0000000..8b45c29 --- /dev/null +++ b/Test/Test.StaticExtension/MyStaticExtension.cs @@ -0,0 +1,11 @@ +namespace Test.StaticExtensions; + +public class MyStaticExtension where T : BaseForm,new() +{ + public static A Execute(B b) + { + var t= new T(); + t.ItemB= b; + return t.SoyDeBaseForm(); + } +} \ No newline at end of file diff --git a/Test/Test.StaticExtension/Program.cs b/Test/Test.StaticExtension/Program.cs index 23a814b..58c689a 100644 --- a/Test/Test.StaticExtension/Program.cs +++ b/Test/Test.StaticExtension/Program.cs @@ -1,6 +1,6 @@ -using Rop.Winforms7.Annotations; + -namespace Test.StaticExtension; +namespace Test.StaticExtensions; internal class Program @@ -10,36 +10,4 @@ private static void Main(string[] args) Console.WriteLine("Hello, World!"); Form1.Execute(true); } -} - -public class BaseForm -{ - public B ItemB { get; set; } - public A SoyDeBaseForm() - { - return default; - } -} - -public class MyStaticExtension where T : BaseForm,new() -{ - public static A Execute(B b) - { - var t= new T(); - t.ItemB= b; - return t.SoyDeBaseForm(); - } -} - - -[StaticExtension>] -public partial class Form1 : BaseForm -{ - public void Hola() - { - var x = SoyDeBaseForm(); - Console.WriteLine(x.ToString()); - } - - public static int Execute2(bool b)=>MyStaticExtension.Execute(b); } \ No newline at end of file diff --git a/Test/Test.StaticExtension/Test.StaticExtension.csproj b/Test/Test.StaticExtension/Test.StaticExtension.csproj deleted file mode 100644 index 673fae0..0000000 --- a/Test/Test.StaticExtension/Test.StaticExtension.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net7.0 - enable - enable - - - - - - - - diff --git a/Test/Test.StaticExtension/Test.StaticExtensions.csproj b/Test/Test.StaticExtension/Test.StaticExtensions.csproj new file mode 100644 index 0000000..1a5f3ab --- /dev/null +++ b/Test/Test.StaticExtension/Test.StaticExtensions.csproj @@ -0,0 +1,15 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + +