jiowchern/Regulus.Remote

View on GitHub
Regulus.Remote.Tools.Protocol.Sources/MethodRegulusRemoteValueBlockModifier.cs

Summary

Maintainability
A
3 hrs
Test Coverage
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Regulus.Remote.Tools.Protocol.Sources.Extensions;
using System.Linq;

namespace Regulus.Remote.Tools.Protocol.Sources.BlockModifiers
{
    
    internal class MethodRegulusRemoteValue
    {
        private readonly Compilation _Compilation;

        public MethodRegulusRemoteValue(Compilation compilation)
        {
            this._Compilation = compilation;
        }

        public BlockAndTypes Mod(System.Collections.Generic.IEnumerable<SyntaxNode> nodes)
        {
            var block = nodes.Skip(0).FirstOrDefault() as BlockSyntax;
            var md = nodes.Skip(1).FirstOrDefault() as MethodDeclarationSyntax;
            var cd = nodes.Skip(2).FirstOrDefault() as ClassDeclarationSyntax;
            

            if (Extensions.SyntaxExtensions.AnyNull(block, md,cd))
            {
                return null;
            }
            if (!_Compilation.AllSerializable(md.ParameterList.Parameters.Select(p => p.Type)))
                return null;
            if ((from p in md.ParameterList.Parameters
                 from m in p.Modifiers
                 where m.IsKind(SyntaxKind.OutKeyword)
                 select m).Any())
                return null;

            var interfaceCode = md.ExplicitInterfaceSpecifier.Name.ToFullString();
            var methodCode = md.Identifier.ToFullString();
            var methodCallParamsCode = string.Join(",", from p in md.ParameterList.Parameters select p.Identifier.ToFullString());
            var returnType = md.ReturnType;
            var qn = returnType as QualifiedNameSyntax;

            if (qn == null)
                return null;

            if (qn.Left.ToString() != "Regulus.Remote")
                return null;

            var gn = qn.Right as GenericNameSyntax;
            if (gn == null)
                return null;

            if (gn.Identifier.ToString() != "Value")
                return null;

            return new BlockAndTypes
            {
                Block = SyntaxFactory.Block(SyntaxFactory.ParseStatement(
                                $@"
var returnValue = new {returnType}();
var info = typeof({interfaceCode}).GetMethod(""{methodCode}"");

this._CallMethodEvent(info , new object[] {{{methodCallParamsCode}}} , returnValue);                    
return returnValue;
                                            ")),
                Types = (from p in md.ParameterList.Parameters select p.Type).Union(gn.TypeArgumentList.Arguments)
            };
            
        }
    }
}