AArnott / CodeGeneration.Roslyn

Assists in performing Roslyn-based code generation during a build.
Microsoft Public License
408 stars 60 forks source link

Fork with new experimental functional that allow full source code modification in compiler pipeline #159

Closed GoldyD closed 4 years ago

GoldyD commented 4 years ago

Hello All!

I create fork this project with new functional that allow full code modification in compiler pipeline - add new piece of code, replace existing code to new one, remove existing code. Added capability to ordered transform one piece code with many generators defined on it. AOP Welcome :)

Sample OrderedGeneratorsSolution solution added in samples folder.

Example of usage:

    [TryCatchOrdered(ExecutionOrder = 1)]
    [DuplicateWithSuffixByNameOrdered("t", ExecutionOrder = 2)]    
    [RemoveOrdered(ExecutionOrder = 3)]
    public partial class Foo
    {
        [DuplicateWithSuffixByNameOrdered("t", ExecutionOrder = 1)]
        public object `Prop1;

        [DuplicateWithSuffixByNameOrdered("k", ExecutionOrder = 1)]
        public int? Prop2;

        public void Test()
        {
            var aa = 1;
            var dd = 3;
            var bb = 0;
            var cc = aa / bb;
        }
    }

Each attribute has ExecutionOrder property for order transform current node Also added capability to transform fields or properties.

After transformation current piece of code will be replaced to:

    [TryCatchOrdered(ExecutionOrder = 1)]
    [DuplicateWithSuffixByNameOrdered("t", ExecutionOrder = 2)]
    [RemoveOrdered(ExecutionOrder = 3)]
    public partial class Foot
    {
        [DuplicateWithSuffixByNameOrdered("t", ExecutionOrder = 1)]
        public object Prop1;
        [DuplicateWithSuffixByNameOrdered("t", ExecutionOrder = 1)]
        public object Prop1t;
        [DuplicateWithSuffixByNameOrdered("k", ExecutionOrder = 1)]
        public int? Prop2;
        [DuplicateWithSuffixByNameOrdered("k", ExecutionOrder = 1)]
        public int? Prop2k;
        public void Test()
        {
            try
            {
                var aa = 1;
                var dd = 3;
                var bb = 0;
                var cc = aa / bb;
            }
            catch (Exception ex)
            {
            }
        }
    }

Transformations: 1) All methods wrapped to try catch block (in future generator may transformed for write all methods exceptions in log) 2) Created new copy of class Foo (after step 1) - Foot 3) Old class Foo will be removed

For create you own generation attribute - inherit this from OrderedCodeGenerationAttribute. For access full code transformation capability in generator - inherit this from IRichCodeGenerator, in GenerateRichAsync method assign RichGenerationResult.Members to list of ChangeMember, each member can do one of tree modification AddMember, ReplaceMember, RemoveMember.

Not done yet:

Fork at: GoldyD

weltkante commented 4 years ago

Just out of curiosity, how well does this integrate with VS?

One major point why rewriting is not allowed is that it will break a lot of the convenience tools in programming with VS and reduces it to a mere text editor. You might want to clearly advertise if you don't have a plan how to solve these problems (they are hard).

GoldyD commented 4 years ago

My fork has same restriction as source project that can only generate new code. In VS generation running in background, when base code class that has generator attributes will be changed and saved to disk.

AArnott commented 4 years ago

I don't think I'd ever go for this because the line numbers reported in exceptions, crashes, etc would not line up with source code. You're welcome to continue the effort of course, but please do so on your own forum.