private async Task <Document> GenerateMappingMethodBody(Document document, BaseMethodDeclarationSyntax methodSyntax, bool useMembersMappers, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var methodSymbol        = semanticModel.GetDeclaredSymbol(methodSyntax, cancellationToken);
            var generator           = SyntaxGenerator.GetGenerator(document);
            var mappingContext      = new MappingContext(methodSyntax, semanticModel);
            var accessibilityHelper = new AccessibilityHelper(methodSymbol.ContainingType);


            if (useMembersMappers)
            {
                foreach (var userDefinedConversion in CustomConversionHelper.FindCustomConversionMethods(methodSymbol))
                {
                    if (userDefinedConversion == methodSymbol || accessibilityHelper.IsSymbolAccessible(userDefinedConversion, methodSymbol.ContainingType) == false)
                    {
                        continue;
                    }

                    mappingContext.CustomConversions.Add(new CustomConversion()
                    {
                        FromType   = new AnnotatedType(userDefinedConversion.Parameters.First().Type),
                        ToType     = new AnnotatedType(userDefinedConversion.ReturnType),
                        Conversion = SyntaxFactory.IdentifierName(userDefinedConversion.Name)
                    });
                }
            }
            var blockSyntax = await MappingImplementorEngine.GenerateMappingBlockAsync(methodSymbol, generator, semanticModel, mappingContext).ConfigureAwait(false);

            return(await document.ReplaceNodes(methodSyntax, methodSyntax.WithOnlyBody(blockSyntax), cancellationToken).ConfigureAwait(false));
        }
        public Task <GenerationResult> GenerateAsync(CSharpSyntaxNode processedNode, AttributeData markerAttribute, TransformationContext context, CancellationToken cancellationToken)
        {
            var syntaxGenerator     = SyntaxGenerator.GetGenerator(context.Document);
            var mappingDeclaration  = (InterfaceDeclarationSyntax)processedNode;
            var interfaceSymbol     = context.SemanticModel.GetDeclaredSymbol(mappingDeclaration);
            var mappingContext      = new MappingContext(interfaceSymbol);
            var accessibilityHelper = new AccessibilityHelper(interfaceSymbol);

            foreach (var x in FindCustomMapperTypes(markerAttribute).SelectMany(CustomConversionHelper.FindCustomConversionMethods))
            {
                if (x.IsStatic && accessibilityHelper.IsSymbolAccessible(x, interfaceSymbol))
                {
                    mappingContext.CustomConversions[(x.Parameters[0].Type, x.ReturnType)] = (ExpressionSyntax)syntaxGenerator.MemberAccessExpression((ExpressionSyntax)syntaxGenerator.IdentifierName(x.ContainingType.ToDisplayString()), x.Name);
示例#3
0
        private async Task <Document> GenerateMappingMethodBody(Document document, BaseMethodDeclarationSyntax methodSyntax, bool useMembersMappers, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            var methodSymbol        = semanticModel.GetDeclaredSymbol(methodSyntax);
            var generator           = SyntaxGenerator.GetGenerator(document);
            var mappingContext      = new MappingContext(methodSyntax, semanticModel);
            var accessibilityHelper = new AccessibilityHelper(methodSymbol.ContainingType);


            if (useMembersMappers)
            {
                foreach (var userDefinedConversion in CustomConversionHelper.FindCustomConversionMethods(methodSymbol))
                {
                    if (userDefinedConversion == methodSymbol || accessibilityHelper.IsSymbolAccessible(userDefinedConversion, methodSymbol.ContainingType) == false)
                    {
                        continue;
                    }

                    mappingContext.CustomConversions[(userDefinedConversion.Parameters.First().Type, userDefinedConversion.ReturnType)] = (ExpressionSyntax)generator.IdentifierName(userDefinedConversion.Name);
        public async Task <GenerationResult> GenerateAsync(CSharpSyntaxNode processedNode, AttributeData markerAttribute, TransformationContext context, CancellationToken cancellationToken)
        {
            var syntaxGenerator     = SyntaxGenerator.GetGenerator(context.Document);
            var mappingDeclaration  = (InterfaceDeclarationSyntax)processedNode;
            var interfaceSymbol     = context.SemanticModel.GetDeclaredSymbol(mappingDeclaration);
            var mappingContext      = new MappingContext(interfaceSymbol);
            var accessibilityHelper = new AccessibilityHelper(interfaceSymbol);

            foreach (var x in FindCustomMapperTypes(markerAttribute).SelectMany(CustomConversionHelper.FindCustomConversionMethods))
            {
                if (x.IsStatic && accessibilityHelper.IsSymbolAccessible(x, interfaceSymbol))
                {
                    mappingContext.CustomConversions.Add(new CustomConversion()
                    {
                        FromType   = new AnnotatedType(x.Parameters[0].Type),
                        ToType     = new AnnotatedType(x.ReturnType),
                        Conversion = (ExpressionSyntax)syntaxGenerator.MemberAccessExpression((ExpressionSyntax)syntaxGenerator.IdentifierName(x.ContainingType.ToDisplayString()), x.Name)
                    });
                }
            }

            var memberDeclarationSyntaxes = mappingDeclaration.Members.Select(async x =>
            {
                if (x is MethodDeclarationSyntax methodDeclaration)
                {
                    var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration);
                    var statements   = ImplementorEngine.CanProvideMappingImplementationFor(methodSymbol) ? await ImplementorEngine.GenerateMappingStatements(methodSymbol, syntaxGenerator, context.SemanticModel, mappingContext).ConfigureAwait(false) :
                                       new List <StatementSyntax>()
                    {
                        GenerateThrowNotSupportedException(context, syntaxGenerator, methodSymbol.Name)
                    };

                    var methodDeclarationSyntax = ((MethodDeclarationSyntax)syntaxGenerator.MethodDeclaration(
                                                       methodDeclaration.Identifier.Text,
                                                       parameters: methodDeclaration.ParameterList.Parameters,
                                                       accessibility: Accessibility.Public,
                                                       modifiers: DeclarationModifiers.Virtual,
                                                       typeParameters: methodDeclaration.TypeParameterList?.Parameters.Select(xx => xx.Identifier.Text),
                                                       returnType: methodDeclaration.ReturnType
                                                       )).WithBody(SyntaxFactory.Block(statements));
                    return(methodDeclarationSyntax);
                }
                return(x);
            });
            var mappingClass = (ClassDeclarationSyntax)syntaxGenerator.ClassDeclaration(
                mappingDeclaration.Identifier.Text.Substring(1),
                accessibility: Accessibility.Public,
                modifiers: DeclarationModifiers.Partial,
                interfaceTypes: new List <SyntaxNode>()
            {
                syntaxGenerator.TypeExpression(interfaceSymbol)
            },
                members: await Task.WhenAll(memberDeclarationSyntaxes));

            var newRoot = WrapInTheSameNamespace(mappingClass, processedNode);
            var usings  = new List <UsingDirectiveSyntax>()
            {
                SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")),
                SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Linq")),
                SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(interfaceSymbol.ContainingNamespace.ToDisplayString()))
            };

            var immutableList = context.SemanticModel.Compilation.GetTypeByMetadataName("System.Collections.Immutable.IImmutableList`1");

            if (immutableList != null)
            {
                usings.Add(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Collections.Immutable")));
            }

            return(new GenerationResult()
            {
                Members = SyntaxFactory.SingletonList(newRoot),
                Usings = new SyntaxList <UsingDirectiveSyntax>(usings)
            });
        }