Exemple #1
0
        private TypeDeclarationSyntax TransformSpecialMethod(FunctionTransformationResult methodTransform,
                                                             TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult,
                                                             INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, bool onlyMissingMembers)
        {
            // Constructors must not be copied on a partial class (missing members)
            if (methodTransform.AnalyzationResult.Conversion == MethodConversion.Ignore || onlyMissingMembers)
            {
                // We need to add a whitespace trivia to keep directives as they will not have any leading whitespace
                newTypeNode = newTypeNode.RemoveNodeKeepDirectives(methodTransform.Annotation, memberWhitespace,
                                                                   transformResult.EndOfLineTrivia);
                return(newTypeNode);
            }
            var methodNode = newTypeNode.GetAnnotatedNodes(methodTransform.Annotation)
                             .OfType <BaseMethodDeclarationSyntax>()
                             .First();
            var transformedResult = TransformFunction(methodTransform.AnalyzationResult, transformResult, transformResult, namespaceMetadata);
            var transformedNode   = (BaseMethodDeclarationSyntax)transformedResult.Transformed;

            if (transformedNode is ConstructorDeclarationSyntax ctorNode && transformResult.AnalyzationResult.Conversion == TypeConversion.NewType)
            {
                transformedNode = ctorNode.WithIdentifier(Identifier(ctorNode.Identifier.ValueText + "Async").WithTriviaFrom(ctorNode.Identifier));
            }
            newTypeNode = newTypeNode.ReplaceNode(methodNode, transformedNode);
            return(newTypeNode);
        }
Exemple #2
0
        private TypeDeclarationSyntax TransformMethodsAndProperties(TypeDeclarationSyntax newTypeNode,
                                                                    TypeTransformationResult transformResult,
                                                                    INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, bool onlyMissingMembers)
        {
            foreach (var transform in transformResult.TransformedMethods
                     .Cast <AnnotatedNode>()
                     .Concat(transformResult.TransformedProperties)
                     .Concat(transformResult.TransformedSpecialMethods)
                     .Concat(transformResult.TransformedFields)
                     .OrderByDescending(o => o.OriginalStartSpan))
            {
                switch (transform)
                {
                case MethodTransformationResult methodTransform:
                    newTypeNode = TransformMethod(methodTransform, newTypeNode, transformResult, namespaceMetadata, memberWhitespace, onlyMissingMembers);
                    break;

                case PropertyTransformationResult propertyTransform:
                    newTypeNode = TransformProperty(propertyTransform, newTypeNode, transformResult, namespaceMetadata, memberWhitespace, onlyMissingMembers);
                    break;

                case FunctionTransformationResult functionTransform:
                    newTypeNode = TransformSpecialMethod(functionTransform, newTypeNode, transformResult, namespaceMetadata, memberWhitespace, onlyMissingMembers);
                    break;

                case FieldTransformationResult fieldTransform:
                    newTypeNode = TransformField(fieldTransform, newTypeNode, transformResult, namespaceMetadata, memberWhitespace, onlyMissingMembers);
                    break;
                }
            }
            return(newTypeNode);
        }
        public SyntaxNode Transform(IFunctionTransformationResult transformResult, ITypeTransformationMetadata typeMetadata,
                                    INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;

            if (!methodResult.Conversion.HasFlag(MethodConversion.ToAsync))
            {
                return(null);
            }
            var functionNode = transformResult.Transformed;

            if (functionNode.GetFunctionBody() == null)
            {
                return(Update(functionNode, methodResult, namespaceMetadata));
            }
            if (methodResult.SplitTail || methodResult.PreserveReturnType || !methodResult.OmitAsync)
            {
                if (!methodResult.OmitAsync)
                {
                    functionNode = functionNode.AddAsync();
                }
                return(Update(functionNode, methodResult, namespaceMetadata));
            }
            var rewriter = new ReturnTaskFunctionRewriter(transformResult, namespaceMetadata);

            functionNode = rewriter.Visit(functionNode);
            return(Update(functionNode, methodResult, namespaceMetadata));
        }
 private SyntaxNode Update(SyntaxNode functionNode,
                           IFunctionAnalyzationResult methodResult, INamespaceTransformationMetadata namespaceMetadata)
 {
     if (functionNode is LocalFunctionStatementSyntax localFunction)
     {
         return(Update(localFunction, methodResult, namespaceMetadata));
     }
     return(functionNode);
 }
Exemple #5
0
 private T RunReferenceTransformers <T>(T node, IFunctionAnalyzationResult funcResult, IFunctionReferenceAnalyzationResult funcReferenceResult,
                                        INamespaceTransformationMetadata namespaceMetadata)
     where T : SyntaxNode
 {
     foreach (var transformer in _configuration.FunctionReferenceTransformers)
     {
         node = (T)transformer.TransformFunctionReference(node, funcResult, funcReferenceResult, namespaceMetadata) ?? node;
     }
     return(node);
 }
        public TypeDeclarationSyntax Transform(TypeDeclarationSyntax transformedNode, ITypeTransformationResult transformationResult,
                                               INamespaceTransformationMetadata namespaceMetadata, bool missingMembers)
        {
            if (!transformedNode.ContainsDirectives)
            {
                return(transformedNode);
            }

            return((TypeDeclarationSyntax)_triviaRemover.Visit(transformedNode));
        }
Exemple #7
0
        private TypeDeclarationSyntax TransformProperty(PropertyTransformationResult propertyTransform, TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult,
                                                        INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, bool onlyMissingMembers)
        {
            var propertyNode = newTypeNode.GetAnnotatedNodes(propertyTransform.Annotation)
                               .OfType <PropertyDeclarationSyntax>()
                               .First();
            var transformedNode = TransformProperty(propertyNode, !onlyMissingMembers, propertyTransform, transformResult, namespaceMetadata);

            foreach (var transformedAccessor in transformedNode.TransformedAccessors.Where(o => o.Transformed != null))
            {
                foreach (var transformer in _configuration.MethodTransformers)
                {
                    var methodTransformResult = transformer.Transform(transformedAccessor, transformResult, namespaceMetadata);
                    if (methodTransformResult == MethodTransformerResult.Skip)
                    {
                        continue;
                    }
                    transformedAccessor.Transformed = methodTransformResult.TransformedNode ?? transformedAccessor.Transformed;
                    if (methodTransformResult.Fields != null)
                    {
                        if (transformedNode.Fields == null)
                        {
                            transformedNode.Fields = new List <FieldDeclarationSyntax>(1);
                        }
                        transformedNode.Fields.AddRange(methodTransformResult.Fields);
                        // Update member names  for next transformators
                        foreach (var variable in methodTransformResult.Fields.SelectMany(o => o.Declaration.Variables))
                        {
                            transformResult.MemberNames = transformResult.MemberNames.Add(variable.Identifier.Text);
                        }
                    }
                    if (methodTransformResult.Methods != null)
                    {
                        transformedNode.AddMethods(methodTransformResult.Methods);
                        // Update member names for next transformators
                        foreach (var method in methodTransformResult.Methods)
                        {
                            transformResult.MemberNames = transformResult.MemberNames.Add(method.Identifier.Text);
                        }
                    }
                }
                propertyTransform.AddMethod(transformedAccessor.Transformed);
            }
            newTypeNode = newTypeNode.AppendMembers(propertyNode, propertyTransform.Fields, propertyTransform.Methods);
            // We need to remove the property when generating only the missing members
            if (onlyMissingMembers || propertyTransform.AnalyzationResult.Conversion == PropertyConversion.Ignore)
            {
                // We need to add a whitespace trivia to keep directives as they will not have any leading whitespace
                newTypeNode = newTypeNode.RemoveNodeKeepDirectives(propertyTransform.Annotation, memberWhitespace,
                                                                   transformResult.EndOfLineTrivia);
            }
            return(newTypeNode);
        }
Exemple #8
0
 private TypeDeclarationSyntax RunTypeTransformers(TypeDeclarationSyntax transformedNode, ITypeTransformationResult transfromResult,
                                                   INamespaceTransformationMetadata namespaceMetadata, bool missingMembers)
 {
     if (transformedNode == null)
     {
         return(null);
     }
     foreach (var transformer in _configuration.TypeTransformers)
     {
         transformedNode = transformer.Transform(transformedNode, transfromResult, namespaceMetadata, missingMembers) ?? transformedNode;
     }
     return(transformedNode);
 }
        private TypeDeclarationSyntax TransformMethod(MethodTransformationResult methodTransform, TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult,
                                                      INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, bool onlyMissingMembers)
        {
            if (methodTransform.AnalyzationResult.Conversion == MethodConversion.Ignore || (onlyMissingMembers && !methodTransform.AnalyzationResult.Missing))
            {
                // We need to add a whitespace trivia to keep directives as they will not have any leading whitespace
                newTypeNode = newTypeNode.RemoveNodeKeepDirectives(methodTransform.Annotation, memberWhitespace, transformResult.EndOfLineTrivia);
                return(newTypeNode);
            }
            var methodNode = newTypeNode.GetAnnotatedNodes(methodTransform.Annotation)
                             .OfType <MethodDeclarationSyntax>()
                             .First();
            var transformedNode = TransformMethod(methodNode, !onlyMissingMembers, methodTransform, transformResult, namespaceMetadata);

            if (transformedNode.Transformed != null)
            {
                foreach (var transformer in _configuration.MethodTransformers)
                {
                    var methodTransformResult = transformer.Transform(transformedNode, transformResult, namespaceMetadata);
                    if (methodTransformResult == MethodTransformerResult.Skip)
                    {
                        continue;
                    }
                    transformedNode.Transformed = methodTransformResult.TransformedNode ?? transformedNode.Transformed;
                    if (methodTransformResult.Fields != null)
                    {
                        if (transformedNode.Fields == null)
                        {
                            transformedNode.Fields = new List <FieldDeclarationSyntax>(1);
                        }
                        transformedNode.Fields.AddRange(methodTransformResult.Fields);
                        // Update member names  for next transformators
                        foreach (var variable in methodTransformResult.Fields.SelectMany(o => o.Declaration.Variables))
                        {
                            transformResult.MemberNames = transformResult.MemberNames.Add(variable.Identifier.Text);
                        }
                    }
                    if (methodTransformResult.Methods != null)
                    {
                        transformedNode.AddMethods(methodTransformResult.Methods);
                        // Update member names for next transformators
                        foreach (var method in methodTransformResult.Methods)
                        {
                            transformResult.MemberNames = transformResult.MemberNames.Add(method.Identifier.Text);
                        }
                    }
                }
            }
            newTypeNode = newTypeNode.ReplaceWithMembers(methodNode, methodTransform.Transformed, methodTransform.Fields, methodTransform.Methods);
            return(newTypeNode);
        }
Exemple #10
0
        private TypeDeclarationSyntax TransformField(FieldTransformationResult fieldTransform, TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult,
                                                     INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, bool onlyMissingMembers)
        {
            var fieldNode = newTypeNode.GetAnnotatedNodes(fieldTransform.Annotation)
                            .OfType <BaseFieldDeclarationSyntax>()
                            .First();
            var transformedNode = TransformField(fieldNode, !onlyMissingMembers, fieldTransform, transformResult, namespaceMetadata);

            newTypeNode = transformedNode.Transformed != null
                                ? newTypeNode.ReplaceNode(fieldNode, transformedNode.Transformed)
                                : newTypeNode.RemoveNodeKeepDirectives(transformedNode.Annotation, memberWhitespace, transformResult.EndOfLineTrivia);

            return(newTypeNode);
        }
Exemple #11
0
 private T UpdateTypeAndRunReferenceTransformers <T>(T node, IFunctionAnalyzationResult funcResult, IFunctionReferenceAnalyzationResult funcReferenceResult,
                                                     INamespaceTransformationMetadata namespaceMetadata, Func <INamedTypeSymbol, bool, T> updateTypeFunc)
     where T : SyntaxNode
 {
     // If the async counterpart is from another type e.g. Thread.Sleep -> Task.Delay, we need to change also the type
     if (!funcReferenceResult.AsyncCounterpartSymbol.IsExtensionMethod &&
         !funcReferenceResult.AsyncCounterpartSymbol.OriginalDefinition.ContainingType.Equals(
             funcReferenceResult.ReferenceSymbol.OriginalDefinition.ContainingType))
     {
         var type = funcReferenceResult.AsyncCounterpartSymbol.ContainingType;
         node = updateTypeFunc(type, namespaceMetadata.AnalyzationResult.IsIncluded(type.ContainingNamespace?.ToString()));
     }
     return(RunReferenceTransformers(node, funcResult, funcReferenceResult, namespaceMetadata));
 }
Exemple #12
0
 private SyntaxNode RunFunctionTransformers(
     FunctionTransformationResult functionTransform,
     ITypeTransformationMetadata transformResult,
     INamespaceTransformationMetadata namespaceMetadata)
 {
     if (functionTransform.Transformed == null)
     {
         return(null);
     }
     foreach (var transformer in _configuration.FunctionTransformers)
     {
         functionTransform.Transformed = transformer.Transform(functionTransform, transformResult, namespaceMetadata) ??
                                         functionTransform.Transformed;
     }
     return(functionTransform.Transformed);
 }
Exemple #13
0
 private InvocationExpressionSyntax UpdateTypeAndRunReferenceTransformers(InvocationExpressionSyntax node, IFunctionAnalyzationResult funcResult,
                                                                          IFunctionReferenceAnalyzationResult funcReferenceResult,
                                                                          INamespaceTransformationMetadata namespaceMetadata,
                                                                          Func <MemberAccessExpressionSyntax, INamedTypeSymbol, bool, MemberAccessExpressionSyntax> updateTypeFunc)
 {
     // If the async counterpart is from another type e.g. Thread.Sleep -> Task.Delay, we need to change also the type
     if (!funcReferenceResult.AsyncCounterpartSymbol.IsExtensionMethod &&
         !funcReferenceResult.AsyncCounterpartSymbol.OriginalDefinition.ContainingType.Equals(
             funcReferenceResult.ReferenceSymbol.OriginalDefinition.ContainingType) &&
         node.Expression is MemberAccessExpressionSyntax memberAccess)
     {
         var type = funcReferenceResult.AsyncCounterpartSymbol.ContainingType;
         node = node.WithExpression(updateTypeFunc(memberAccess, type,
                                                   namespaceMetadata.AnalyzationResult.IsIncluded(type.ContainingNamespace?.ToString())));
     }
     return(RunReferenceTransformers(node, funcResult, funcReferenceResult, namespaceMetadata));
 }
Exemple #14
0
        private PropertyTransformationResult TransformProperty(PropertyDeclarationSyntax propertyNode, bool canCopy, PropertyTransformationResult result, ITypeTransformationMetadata typeMetadata,
                                                               INamespaceTransformationMetadata namespaceMetadata)
        {
            var analyzeResult = result.AnalyzationResult;
            var startRootSpan = analyzeResult.Node.SpanStart;

            // Calculate whitespace method trivias
            result.EndOfLineTrivia             = propertyNode.GetEndOfLine();
            result.LeadingWhitespaceTrivia     = propertyNode.GetLeadingWhitespace();
            result.IndentTrivia                = propertyNode.GetIndent(result.LeadingWhitespaceTrivia, typeMetadata.LeadingWhitespaceTrivia);
            result.BodyLeadingWhitespaceTrivia = Whitespace(result.LeadingWhitespaceTrivia.ToFullString() + result.IndentTrivia.ToFullString());

            if (analyzeResult.Conversion == PropertyConversion.Ignore && analyzeResult.GetAccessors().All(o => o.Conversion == MethodConversion.Ignore))
            {
                return(result);
            }

            propertyNode   = propertyNode.WithAdditionalAnnotations(new SyntaxAnnotation(result.Annotation));
            startRootSpan -= propertyNode.SpanStart;

            foreach (var accessorResult in analyzeResult.GetAccessors().Where(o => o.Conversion != MethodConversion.Ignore))
            {
                var spanStart    = accessorResult.Node.SpanStart - startRootSpan;
                var spanLength   = accessorResult.Node.Span.Length;
                var accessorNode = propertyNode.DescendantNodes()
                                   .First(o => o.SpanStart == spanStart && o.Span.Length == spanLength);
                var transformedNode = new AccessorTransformationResult(accessorResult);
                result.TransformedAccessors.Add(transformedNode);
                propertyNode = propertyNode.ReplaceNode(accessorNode, accessorNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));
            }

            if (canCopy && result.AnalyzationResult.Conversion == PropertyConversion.Copy)
            {
                result.Transformed = result.OriginalNode;
            }

            foreach (var accessorResult in result.TransformedAccessors.OrderByDescending(o => o.OriginalStartSpan))
            {
                var accessorNode = propertyNode.GetAnnotatedNodes(accessorResult.Annotation)
                                   .First();
                TransformPropertyAccessor(accessorNode, result, accessorResult, typeMetadata, namespaceMetadata);
            }

            return(result);
        }
Exemple #15
0
        private TypeDeclarationSyntax TransformTypeMembers(INamespaceTransformationMetadata namespaceMetadata,
                                                           bool onlyMissingMembers, TypeTransformationResult transformResult, TypeDeclarationSyntax newTypeNode,
                                                           SyntaxTrivia memberWhitespace, TypeDeclarationSyntax rootTypeNode, TypeDeclarationSyntax typeNode)
        {
            // Replace all rewritten nodes
            foreach (var rewNode in transformResult.TransformedNodes)
            {
                var node = newTypeNode.GetAnnotatedNodes(rewNode.Annotation).First();
                newTypeNode = rewNode.Transformed == null
                                        ? newTypeNode.RemoveNode(node, SyntaxRemoveOptions.KeepUnbalancedDirectives)
                                        : newTypeNode.ReplaceNode(node, rewNode.Transformed);
            }

            newTypeNode = TransformMethodsAndProperties(newTypeNode, transformResult, namespaceMetadata, memberWhitespace, onlyMissingMembers);
            newTypeNode = RunTypeTransformers(newTypeNode, transformResult, namespaceMetadata, onlyMissingMembers);
            transformResult.Transformed = newTypeNode;
            return(rootTypeNode.ReplaceNode(typeNode, newTypeNode));
        }
        public SyntaxNode Transform(IFunctionTransformationResult transformResult, ITypeTransformationMetadata typeMetadata,
                                    INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;
            var functionNode = transformResult.Transformed;

            if (
                !methodResult.Conversion.HasFlag(MethodConversion.ToAsync) ||
                methodResult.OmitAsync ||
                !methodResult.GetMethodOrAccessor().CancellationTokenRequired ||
                functionNode.GetFunctionBody() == null)
            {
                return(null);
            }

            var rewriter = new OperationCanceledExceptionFunctionRewriter(transformResult.EndOfLineTrivia, namespaceMetadata);

            return(rewriter.Visit(functionNode));
        }
        public TypeDeclarationSyntax Transform(TypeDeclarationSyntax transformedNode, ITypeTransformationResult transformationResult,
                                               INamespaceTransformationMetadata namespaceMetadata, bool missingMembers)
        {
            if (!_isEnabledForNewTypes && !_isEnabledForPartialTypes)
            {
                return(null);
            }
            var symbol     = transformationResult.AnalyzationResult.Symbol;
            var conversion = transformationResult.AnalyzationResult.Conversion;

            if (_isEnabledForPartialTypes && (conversion == TypeConversion.Partial || missingMembers))
            {
                var comment = _configuration.AddOrReplacePartialTypeComments?.Invoke(symbol);
                if (!string.IsNullOrEmpty(comment))
                {
                    var commentTrivias = GetOrCreateCommentTrivias(transformationResult, comment);
                    return(transformedNode.WithCommentTrivias(commentTrivias));
                }
                if (_configuration.RemovePartialTypeComments?.Invoke(symbol) == true)
                {
                    return(transformedNode.RemoveCommentTrivias());
                }
            }

            if (_isEnabledForNewTypes && (conversion == TypeConversion.Copy || conversion == TypeConversion.NewType))
            {
                var comment = _configuration.AddOrReplaceNewTypeComments?.Invoke(symbol);
                if (!string.IsNullOrEmpty(comment))
                {
                    var commentTrivias = GetOrCreateCommentTrivias(transformationResult, comment);
                    return(transformedNode.WithCommentTrivias(commentTrivias));
                }
                if (_configuration.RemoveNewTypeComments?.Invoke(symbol) == true)
                {
                    return(transformedNode.RemoveCommentTrivias());
                }
            }
            return(null);
        }
Exemple #18
0
        public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult,
                                                 ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
        {
            if (transformResult.AnalyzationResult.OmitAsync)
            {
                return(MethodTransformerResult.Skip);
            }

            var result = _rewriter.VisitMethod(transformResult.Transformed);

            return(result == null
                                ? MethodTransformerResult.Skip
                                : MethodTransformerResult.Update(result));
        }
 private LocalFunctionStatementSyntax Update(LocalFunctionStatementSyntax functionNode,
                                             IFunctionAnalyzationResult analyzeResult, INamespaceTransformationMetadata namespaceMetadata)
 {
     functionNode = functionNode.WithIdentifier(Identifier(analyzeResult.AsyncCounterpartName));
     if (!analyzeResult.PreserveReturnType && analyzeResult.Symbol.MethodKind != MethodKind.PropertySet)
     {
         functionNode = functionNode.ReturnAsTask(namespaceMetadata.TaskConflict);
     }
     return(functionNode);
 }
        private MethodTransformationResult TransformMethod(MethodDeclarationSyntax methodNode, bool canCopy, MethodTransformationResult result, ITypeTransformationMetadata typeMetadata,
                                                           INamespaceTransformationMetadata namespaceMetadata)
        {
            //var result = new MethodTransformationResult(methodResult);
            var methodResult     = result.AnalyzationResult;
            var methodConversion = methodResult.Conversion;

            if (!canCopy)
            {
                methodConversion &= ~MethodConversion.Copy;
            }
            //var methodNode = customNode ?? methodResult.Node;
            var methodBodyNode = methodResult.GetBodyNode();

            // Calculate whitespace method trivias
            result.EndOfLineTrivia             = methodNode.GetEndOfLine();
            result.LeadingWhitespaceTrivia     = methodNode.GetLeadingWhitespace();
            result.IndentTrivia                = methodNode.GetIndent(result.LeadingWhitespaceTrivia, typeMetadata.LeadingWhitespaceTrivia);
            result.BodyLeadingWhitespaceTrivia = Whitespace(result.LeadingWhitespaceTrivia.ToFullString() + result.IndentTrivia.ToFullString());

            if (methodConversion == MethodConversion.Ignore)
            {
                return(result);
            }

            if (methodBodyNode == null)
            {
                if (methodConversion.HasFlag(MethodConversion.ToAsync))
                {
                    result.Transformed = methodNode;
                    if (methodConversion.HasFlag(MethodConversion.Copy))
                    {
                        result.AddMethod(methodResult.Node);
                    }
                    return(result);
                }
                if (methodConversion.HasFlag(MethodConversion.Copy))
                {
                    result.Transformed = methodResult.Node;
                }
                return(result);
            }
            var startMethodSpan = methodResult.Node.Span.Start;

            methodNode       = methodNode.WithAdditionalAnnotations(new SyntaxAnnotation(result.Annotation));
            startMethodSpan -= methodNode.SpanStart;

            // First we need to annotate nodes that will be modified in order to find them later on.
            // We cannot rely on spans after the first modification as they will change
            var typeReferencesAnnotations = new List <string>();

            foreach (var typeReference in methodResult.TypeReferences.Where(o => o.TypeAnalyzationResult.Conversion == TypeConversion.NewType))
            {
                var reference  = typeReference.ReferenceLocation;
                var startSpan  = reference.Location.SourceSpan.Start - startMethodSpan;
                var nameNode   = methodNode.GetSimpleName(startSpan, reference.Location.SourceSpan.Length);
                var annotation = Guid.NewGuid().ToString();
                methodNode = methodNode.ReplaceNode(nameNode, nameNode.WithAdditionalAnnotations(new SyntaxAnnotation(annotation)));
                typeReferencesAnnotations.Add(annotation);
            }

            // For copied methods we need just to replace type references
            if (methodConversion.HasFlag(MethodConversion.Copy))
            {
                var copiedMethod = methodNode;
                // Modify references
                foreach (var refAnnotation in typeReferencesAnnotations)
                {
                    var nameNode = copiedMethod.GetAnnotatedNodes(refAnnotation).OfType <SimpleNameSyntax>().First();
                    copiedMethod = copiedMethod
                                   .ReplaceNode(nameNode, nameNode.WithIdentifier(Identifier(nameNode.Identifier.Value + "Async").WithTriviaFrom(nameNode.Identifier)));
                }
                if (!methodConversion.HasFlag(MethodConversion.ToAsync))
                {
                    result.Transformed = copiedMethod;
                    return(result);
                }
                result.AddMethod(copiedMethod.WithoutAnnotations(result.Annotation));
            }

            foreach (var childFunction in methodResult.ChildFunctions.Where(o => o.Conversion != MethodConversion.Ignore))
            {
                var functionNode   = childFunction.GetNode();
                var functionKind   = functionNode.Kind();
                var typeSpanStart  = functionNode.SpanStart - startMethodSpan;
                var typeSpanLength = functionNode.Span.Length;
                var funcNode       = methodNode.DescendantNodesAndSelf()
                                     .First(o => o.IsKind(functionKind) && o.SpanStart == typeSpanStart && o.Span.Length == typeSpanLength);
                var transformFuncResult = TransformFunction(childFunction, result, typeMetadata, namespaceMetadata);
                result.TransformedFunctions.Add(transformFuncResult);
                methodNode = methodNode.ReplaceNode(funcNode, funcNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformFuncResult.Annotation)));
            }

            foreach (var referenceResult in methodResult.FunctionReferences
                     .Where(o => o.GetConversion() == ReferenceConversion.ToAsync))
            {
                var transfromReference = new FunctionReferenceTransformationResult(referenceResult);
                var isCref             = referenceResult.IsCref;
                var reference          = referenceResult.ReferenceLocation;
                var startSpan          = reference.Location.SourceSpan.Start - startMethodSpan;
                var nameNode           = methodNode.GetSimpleName(startSpan, reference.Location.SourceSpan.Length, isCref);
                methodNode = methodNode.ReplaceNode(nameNode, nameNode.WithAdditionalAnnotations(new SyntaxAnnotation(transfromReference.Annotation)));
                result.TransformedFunctionReferences.Add(transfromReference);

                if (isCref || referenceResult.IsNameOf || !methodResult.OmitAsync)
                {
                    continue;
                }
                // We need to annotate the reference node (InvocationExpression, IdentifierName) in order to know if we need to wrap the node in a Task.FromResult
                var refNode       = referenceResult.ReferenceNode;
                var bodyReference = (IBodyFunctionReferenceAnalyzationResult)referenceResult;
                if (bodyReference.UseAsReturnValue || refNode.IsReturned())
                {
                    startSpan = refNode.SpanStart - startMethodSpan;
                    var referenceNode = methodNode.DescendantNodes().First(o => o.SpanStart == startSpan && o.Span.Length == refNode.Span.Length);
                    methodNode = methodNode.ReplaceNode(referenceNode, referenceNode.WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.TaskReturned)));
                }
            }
            // Before modifying, fixup method body formatting in order to prevent weird formatting when adding additinal code
            methodNode = FixupBodyFormatting(methodNode, result);

            // Modify references
            foreach (var refAnnotation in typeReferencesAnnotations)
            {
                var nameNode = methodNode.GetAnnotatedNodes(refAnnotation).OfType <SimpleNameSyntax>().First();
                methodNode = methodNode
                             .ReplaceNode(nameNode, nameNode.WithIdentifier(Identifier(nameNode.Identifier.Value + "Async").WithTriviaFrom(nameNode.Identifier)));
            }

            foreach (var transformFunction in result.TransformedFunctions)
            {
                var funcNode = methodNode.GetAnnotatedNodes(transformFunction.Annotation).First();
                methodNode = methodNode
                             .ReplaceNode(funcNode, transformFunction.Transformed);
            }

            // We have to order by OriginalStartSpan in order to have consistent formatting when adding awaits
            foreach (var transfromReference in result.TransformedFunctionReferences.OrderByDescending(o => o.OriginalStartSpan))
            {
                methodNode = TransformFunctionReference(methodNode, methodResult, transfromReference, typeMetadata, namespaceMetadata);
            }

            result.Transformed = methodNode;

            return(result);
        }
Exemple #21
0
        private RootTypeTransformationResult TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata, bool onlyMissingMembers)
        {
            var rootTypeNode        = rootTypeResult.Node;
            var startRootTypeSpan   = rootTypeNode.SpanStart;
            var rootTransformResult = new RootTypeTransformationResult(rootTypeResult)
            {
                MemberNames = rootTypeResult.Symbol.MemberNames.ToImmutableHashSet()
            };

            // We do this here because we want that the root node has span start equal to 0
            rootTypeNode       = rootTypeNode.WithAdditionalAnnotations(new SyntaxAnnotation(rootTransformResult.Annotation));
            startRootTypeSpan -= rootTypeNode.SpanStart;

            // Before any modification we need to annotate nodes that will be transformed in order to find them later on.
            // We cannot rely on spans as they changes each time the node is modified.
            // We need to annotate also the ignored types to be later removed
            foreach (var typeResult in rootTypeResult.GetSelfAndDescendantsTypes())
            {
                var typeSpanStart  = typeResult.Node.SpanStart - startRootTypeSpan;
                var typeSpanLength = typeResult.Node.Span.Length;
                var typeNode       = rootTypeNode.DescendantNodesAndSelf().OfType <TypeDeclarationSyntax>()
                                     .First(o => o.SpanStart == typeSpanStart && o.Span.Length == typeSpanLength);
                var leadingWhitespace = typeNode.GetLeadingWhitespace();
                TypeTransformationResult transformResult;
                if (typeNode == rootTypeNode)
                {
                    transformResult = rootTransformResult;
                    transformResult.IndentTrivia = typeNode.GetIndent(leadingWhitespace, namespaceMetadata.LeadingWhitespaceTrivia);
                }
                else
                {
                    transformResult = new TypeTransformationResult(typeResult)
                    {
                        MemberNames  = typeResult.Symbol.MemberNames.ToImmutableHashSet(),
                        IndentTrivia = typeNode.GetIndent(leadingWhitespace)
                    };
                    rootTypeNode = rootTypeNode.ReplaceNode(typeNode, typeNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformResult.Annotation)));
                    rootTransformResult.DescendantTransformedTypes.Add(transformResult);
                }
                transformResult.LeadingWhitespaceTrivia = leadingWhitespace;
                transformResult.EndOfLineTrivia         = typeNode.GetEndOfLine();

                if (typeResult.Conversion == TypeConversion.Ignore)
                {
                    continue;                     // The ignored type shall be only annotated
                }

                // TypeReferences can be changes only if we create a new type
                if (typeResult.Conversion == TypeConversion.NewType || typeResult.Conversion == TypeConversion.Copy)
                {
                    foreach (var typeReference in typeResult.TypeReferences.Where(o => o.TypeAnalyzationResult.Conversion == TypeConversion.NewType))
                    {
                        var reference       = typeReference.ReferenceLocation;
                        var refSpanStart    = reference.Location.SourceSpan.Start - startRootTypeSpan;
                        var refSpanLength   = reference.Location.SourceSpan.Length;
                        var nameNode        = rootTypeNode.GetSimpleName(refSpanStart, refSpanLength, typeReference.IsCref);
                        var transformedNode = new TransformationResult(nameNode)
                        {
                            Transformed = nameNode.WithIdentifier(Identifier(nameNode.Identifier.ValueText + "Async").WithTriviaFrom(nameNode.Identifier))
                        };
                        transformResult.TransformedNodes.Add(transformedNode);
                        rootTypeNode = rootTypeNode.ReplaceNode(nameNode, nameNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));
                    }
                }

                foreach (var fieldResult in typeResult.Fields)
                {
                    var fieldSpanStart  = fieldResult.Node.SpanStart - startRootTypeSpan;
                    var fieldSpanLength = fieldResult.Node.Span.Length;
                    var fieldNode       = rootTypeNode.DescendantNodes()
                                          .OfType <BaseFieldDeclarationSyntax>()
                                          .First(o => o.SpanStart == fieldSpanStart && o.Span.Length == fieldSpanLength);
                    var transformedNode = new FieldTransformationResult(fieldResult);
                    transformResult.TransformedFields.Add(transformedNode);
                    rootTypeNode = rootTypeNode.ReplaceNode(fieldNode, fieldNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));
                }

                // Annotate and save an empty method transformation result
                foreach (var methodResult in typeResult.Methods /*.Where(o => o.Conversion != MethodConversion.Ignore)*/)
                {
                    var methodSpanStart  = methodResult.Node.SpanStart - startRootTypeSpan;
                    var methodSpanLength = methodResult.Node.Span.Length;
                    var methodNode       = rootTypeNode.DescendantNodes()
                                           .OfType <MethodDeclarationSyntax>()
                                           .First(o => o.SpanStart == methodSpanStart && o.Span.Length == methodSpanLength);
                    // Only create the transformation result for the method and transform the method later as the method may change
                    // (a directive may be added to the method when removing type members)
                    var transformedNode = new MethodTransformationResult(methodResult);
                    transformResult.TransformedMethods.Add(transformedNode);
                    rootTypeNode = rootTypeNode.ReplaceNode(methodNode, methodNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));

                    // Annotate all locks inside the method before the transformations begins as will be easier to transform them if needed
                    foreach (var lockData in methodResult.Locks)
                    {
                        var lockSpanStart  = lockData.Node.SpanStart - startRootTypeSpan;
                        var lockSpanLength = lockData.Node.Span.Length;
                        var lockNode       = rootTypeNode.DescendantNodes()
                                             .OfType <LockStatementSyntax>()
                                             .First(o => o.SpanStart == lockSpanStart && o.Span.Length == lockSpanLength);
                        var lockTransformedNode = new LockTransformationResult(lockData);
                        transformedNode.TransformedLocks.Add(lockTransformedNode);
                        rootTypeNode = rootTypeNode.ReplaceNode(lockNode,
                                                                lockNode.WithAdditionalAnnotations(new SyntaxAnnotation(lockTransformedNode.Annotation)));
                    }
                }

                foreach (var methodResult in typeResult.SpecialMethods)
                {
                    var methodSpanStart  = methodResult.GetNode().SpanStart - startRootTypeSpan;
                    var methodSpanLength = methodResult.GetNode().Span.Length;
                    var methodNode       = rootTypeNode.DescendantNodes()
                                           .OfType <BaseMethodDeclarationSyntax>()
                                           .First(o => o.SpanStart == methodSpanStart && o.Span.Length == methodSpanLength);
                    var transformedNode = new FunctionTransformationResult(methodResult);
                    transformResult.TransformedSpecialMethods.Add(transformedNode);
                    rootTypeNode = rootTypeNode.ReplaceNode(methodNode, methodNode.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));
                }


                foreach (var propertyResult in typeResult.Properties)
                {
                    var spanStart  = propertyResult.Node.SpanStart - startRootTypeSpan;
                    var spanLength = propertyResult.Node.Span.Length;
                    var node       = rootTypeNode.DescendantNodes()
                                     .OfType <PropertyDeclarationSyntax>()
                                     .First(o => o.SpanStart == spanStart && o.Span.Length == spanLength);
                    var transformedNode = new PropertyTransformationResult(propertyResult);
                    transformResult.TransformedProperties.Add(transformedNode);
                    rootTypeNode = rootTypeNode.ReplaceNode(node, node.WithAdditionalAnnotations(new SyntaxAnnotation(transformedNode.Annotation)));
                }
            }
            // Save the orignal node that was only annotated
            var originalAnnotatedNode = rootTypeNode;

            // Now we can start transforming the type. Start from the bottom in order to preserve replaced nested types
            foreach (var transformResult in rootTransformResult.GetSelfAndDescendantTransformedTypes().OrderByDescending(o => o.OriginalNode.SpanStart))
            {
                var typeResult = transformResult.AnalyzationResult;

                // Add partial keyword on the original node if not present
                if ((typeResult.Conversion == TypeConversion.Partial || onlyMissingMembers) && !typeResult.IsPartial)
                {
                    if (rootTransformResult.OriginalModified == null)
                    {
                        rootTransformResult.OriginalModified = originalAnnotatedNode;
                    }
                    var typeNode = rootTransformResult.OriginalModified.GetAnnotatedNodes(transformResult.Annotation).OfType <TypeDeclarationSyntax>().First();
                    rootTransformResult.OriginalModified = rootTransformResult.OriginalModified.ReplaceNode(typeNode, typeNode.AddPartial());
                }
                if (typeResult.Conversion == TypeConversion.Ignore ||
                    (
                        onlyMissingMembers &&
                        !typeResult.GetSelfAndDescendantsTypes().SelectMany(o => o.MethodsAndAccessors).Any(o => o.Missing)
                    ))
                {
                    rootTypeNode = rootTypeNode.RemoveNodeKeepDirectives(transformResult.Annotation, transformResult.LeadingWhitespaceTrivia,
                                                                         transformResult.EndOfLineTrivia);
                    continue;
                }

                var memberWhitespace = Whitespace(transformResult.LeadingWhitespaceTrivia.ToFullString() + transformResult.IndentTrivia.ToFullString());

                if (typeResult.Conversion == TypeConversion.Partial || onlyMissingMembers)
                {
                    // First we need to remove ignored method
                    var typeNode = rootTypeNode.GetAnnotatedNodes(transformResult.Annotation).OfType <TypeDeclarationSyntax>().First();
                    // We need to remove the attributes as they cannot be defined in both partial classes
                    var newTypeNode = typeNode.AddPartial().WithoutAttributes();

                    // We need to remove all other members that are not methods, properties or types
                    newTypeNode = newTypeNode.RemoveMembersKeepDirectives(o =>
                                                                          !(o is BaseMethodDeclarationSyntax ||
                                                                            o is TypeDeclarationSyntax ||
                                                                            o is PropertyDeclarationSyntax ||
                                                                            o is BaseFieldDeclarationSyntax), memberWhitespace,
                                                                          transformResult.EndOfLineTrivia);

                    rootTypeNode = TransformTypeMembers(namespaceMetadata, onlyMissingMembers, transformResult, newTypeNode,
                                                        memberWhitespace, rootTypeNode, typeNode);
                }
                // If the root type has to be a new type then all nested types have to be new types
                else if (typeResult.Conversion == TypeConversion.NewType || typeResult.Conversion == TypeConversion.Copy)
                {
                    var typeNode        = rootTypeNode.GetAnnotatedNodes(transformResult.Annotation).OfType <TypeDeclarationSyntax>().First();
                    var identifierToken = typeNode.ChildTokens().First(o => o.IsKind(SyntaxKind.IdentifierToken));
                    var newTypeNode     = typeResult.Conversion == TypeConversion.NewType
                                                ? typeNode.ReplaceToken(identifierToken, Identifier(identifierToken.ValueText + "Async").WithTriviaFrom(identifierToken))
                                                : typeNode;

                    rootTypeNode = TransformTypeMembers(namespaceMetadata, onlyMissingMembers, transformResult, newTypeNode,
                                                        memberWhitespace, rootTypeNode, typeNode);
                }
            }

            rootTransformResult.Transformed = rootTypeNode;
            return(rootTransformResult);
        }
        /// <summary>
        /// The method with SplitTail needs to be splitted into two methods
        /// </summary>
        public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult,
                                                 ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;

            if (!methodResult.SplitTail)
            {
                return(MethodTransformerResult.Skip);
            }

            var methodNode = transformResult.Transformed;
            // Tail method body shall contain all statements after preconditions
            var skipStatements = methodResult.Preconditions.Count;

            // If a cancellation guard was generated we need to skip also that
            if (_analyzeConfiguration.UseCancellationTokens && _analyzeConfiguration.CancellationTokens.Guards && methodResult.CancellationTokenRequired)
            {
                skipStatements++;
            }
            var tailMethodBody = methodNode.Body
                                 .WithStatements(new SyntaxList <StatementSyntax>()
                                                 .AddRange(methodNode.Body.Statements.Skip(skipStatements)));
            // Main method shall contain only preconditions and a call to the tail method
            var bodyStatements = new SyntaxList <StatementSyntax>()
                                 .AddRange(methodNode.Body.Statements.Take(skipStatements));
            ParameterListSyntax tailCallParameterList;
            // TODO: handle name collisions
            var tailIdentifier = Identifier("Internal" + methodNode.Identifier.Value);             // The transformed method has already the Async postfix
            MethodDeclarationSyntax      tailMethod   = null;
            LocalFunctionStatementSyntax tailFunction = null;

            if (_configuration.LocalFunctions)
            {
                tailFunction = LocalFunctionStatement(
                    methodNode.ReturnType.WithoutLeadingTrivia(),
                    tailIdentifier)
                               .WithParameterList(ParameterList()
                                                  .WithCloseParenToken(Token(TriviaList(), SyntaxKind.CloseParenToken, TriviaList(transformResult.EndOfLineTrivia))))
                               .AddAsync()
                               .WithLeadingTrivia(transformResult.LeadingWhitespaceTrivia)
                               .WithBody(tailMethodBody)
                               .AppendIndent(transformResult.IndentTrivia.ToFullString());
                // We do not need any parameter for the local function as we already have the parameters from the parent method
                tailCallParameterList = ParameterList();
            }
            else
            {
                var tailMethodModifiers = TokenList(
                    Token(TriviaList(transformResult.EndOfLineTrivia, transformResult.LeadingWhitespaceTrivia), SyntaxKind.PrivateKeyword, TriviaList(Space)));
                if (methodNode.Modifiers.Any(o => o.IsKind(SyntaxKind.StaticKeyword)))
                {
                    tailMethodModifiers = tailMethodModifiers.Add(Token(TriviaList(), SyntaxKind.StaticKeyword, TriviaList(Space)));
                }
                tailMethod = methodNode
                             .WithReturnType(methodNode.ReturnType.WithLeadingTrivia())            // Remove lead trivia in case the return type is the first node (eg. void Method())
                             .WithIdentifier(tailIdentifier)
                             .WithModifiers(tailMethodModifiers)
                             .AddAsync()
                             .WithBody(tailMethodBody);
                // Tail call shall contain the cancellation token parameter
                tailCallParameterList = methodNode.ParameterList;
            }

            var tailCall = ReturnStatement(
                Token(TriviaList(transformResult.BodyLeadingWhitespaceTrivia), SyntaxKind.ReturnKeyword, TriviaList(Space)),
                IdentifierName(tailIdentifier).Invoke(tailCallParameterList),
                Token(TriviaList(), SyntaxKind.SemicolonToken, TriviaList(transformResult.EndOfLineTrivia))
                );

            bodyStatements = bodyStatements.Add(tailCall);
            // Append local function at the end for easier reading
            if (tailFunction != null)
            {
                bodyStatements = bodyStatements.Add(tailFunction);
            }
            methodNode = methodNode.WithBody(methodNode.Body
                                             .WithStatements(bodyStatements));

            var result = MethodTransformerResult.Update(methodNode);

            if (tailMethod != null)
            {
                result.AddMethod(tailMethod);
            }
            return(result);
        }
Exemple #23
0
 public OperationCanceledExceptionFunctionRewriter(SyntaxTrivia eolTrivia, INamespaceTransformationMetadata namespaceMetadata)
 {
     _eolTrivia         = eolTrivia;
     _namespaceMetadata = namespaceMetadata;
 }
        private MethodTransformerResult Update(MethodDeclarationSyntax methodNode,
                                               IMethodOrAccessorAnalyzationResult methodResult, INamespaceTransformationMetadata namespaceMetadata)
        {
            methodNode = methodNode.WithIdentifier(Identifier(methodResult.AsyncCounterpartName));

            // Remove the new modifier
            if (methodNode.Modifiers.Any(o => o.IsKind(SyntaxKind.NewKeyword)))
            {
                var newMofidier = methodNode.Modifiers.First(o => o.IsKind(SyntaxKind.NewKeyword));
                if (methodNode.GetFirstToken(true).IsKind(SyntaxKind.NewKeyword))
                {
                    methodNode = methodNode
                                 .WithModifiers(TokenList(methodNode.Modifiers.Where(o => !o.IsKind(SyntaxKind.NewKeyword))))
                                 .WithLeadingTrivia(newMofidier.LeadingTrivia);
                }
                else
                {
                    var nextToken = newMofidier.GetNextToken(true);
                    methodNode = methodNode
                                 .ReplaceToken(nextToken, nextToken.WithLeadingTrivia(newMofidier.LeadingTrivia))
                                 .WithModifiers(TokenList(methodNode.Modifiers.Where(o => !o.IsKind(SyntaxKind.NewKeyword))));
                }
            }

            if (!methodResult.PreserveReturnType && methodResult.Symbol.MethodKind != MethodKind.PropertySet)
            {
                methodNode = methodNode.ReturnAsTask(namespaceMetadata.TaskConflict);
            }
            return(MethodTransformerResult.Update(methodNode));
        }
Exemple #25
0
        public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult,
                                                 ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;

            if (!methodResult.CancellationTokenRequired)
            {
                return(MethodTransformerResult.Skip);
            }
            var originalNode = methodResult.GetNode();
            var cancellationTokenParamName = "cancellationToken";             // TODO: handle variable collision for token
            var generationOptions          = methodResult.MethodCancellationToken.GetValueOrDefault();
            var methodNode = transformResult.Transformed;

            methodNode = methodNode
                         .AddCancellationTokenParameter(cancellationTokenParamName,
                                                        generationOptions.HasFlag(MethodCancellationToken.Optional),
                                                        transformResult.LeadingWhitespaceTrivia,
                                                        transformResult.EndOfLineTrivia);

            var methodBody = methodNode.Body;

            if (_configuration.Guards && methodBody != null && !methodResult.Faulted)
            {
                var startGuard = methodResult.OmitAsync
                                        ? GetSyncGuard(methodResult, cancellationTokenParamName, transformResult.BodyLeadingWhitespaceTrivia,
                                                       transformResult.EndOfLineTrivia, transformResult.IndentTrivia)
                                        : GetAsyncGuard(cancellationTokenParamName, transformResult.BodyLeadingWhitespaceTrivia,
                                                        transformResult.EndOfLineTrivia);

                methodNode = methodNode.WithBody(
                    methodBody.WithStatements(
                        methodBody.Statements.Insert(methodResult.Preconditions.Count, startGuard))
                    );
                // We need to get all statements that have at least one async invocation without a cancellation token argument, to prepend an extra guard
                var statements = new Dictionary <int, string>();
                foreach (var functionReference in transformResult.TransformedFunctionReferences)
                {
                    if (!(functionReference.AnalyzationResult is IBodyFunctionReferenceAnalyzationResult bodyFunctionReference))
                    {
                        continue;
                    }
                    if (bodyFunctionReference.GetConversion() != ReferenceConversion.ToAsync || bodyFunctionReference.PassCancellationToken)
                    {
                        continue;
                    }
                    var statement = methodNode
                                    .GetAnnotatedNodes(functionReference.Annotation)
                                    .First().Ancestors().OfType <StatementSyntax>().First();
                    if (statements.ContainsKey(statement.SpanStart))
                    {
                        continue;
                    }
                    var annotation = Guid.NewGuid().ToString();
                    methodNode = methodNode
                                 .ReplaceNode(statement, statement.WithAdditionalAnnotations(new SyntaxAnnotation(annotation)));
                    statements.Add(statement.SpanStart, annotation);
                }
                // For each statement we need to find the index where is located in the block.
                // TODO: Add support when the parent is not a block syntax
                foreach (var pair in statements)
                {
                    var statement   = methodNode.GetAnnotatedNodes(pair.Value).OfType <StatementSyntax>().First();
                    var parentBlock = statement.Parent as BlockSyntax;
                    if (parentBlock == null)
                    {
                        continue;                         // Currently not supported
                    }
                    var index          = parentBlock.Statements.IndexOf(statement);
                    var newParentBlock = parentBlock
                                         .WithStatements(parentBlock.Statements
                                                         .Insert(index, GetAsyncGuard(cancellationTokenParamName, statement.GetLeadingWhitespace(), transformResult.EndOfLineTrivia)));
                    methodNode = methodNode
                                 .ReplaceNode(parentBlock, newParentBlock);
                }
            }

            var originalMethodNode = originalNode as MethodDeclarationSyntax;

            // Add an additional overload if specified
            if (originalMethodNode == null ||
                (
                    !generationOptions.HasFlag(MethodCancellationToken.ForwardNone) &&
                    !generationOptions.HasFlag(MethodCancellationToken.SealedForwardNone)
                ))
            {
                return(MethodTransformerResult.Update(methodNode));
            }
            var overloadNode = originalMethodNode
                               .ReturnAsTask(namespaceMetadata.TaskConflict)
                               .WithTriviaFrom(transformResult.Transformed)  // We want to have the sumamry of the transformed node but not the parameter list
                               .WithoutAnnotations(transformResult.Annotation)
                               .WithIdentifier(Identifier(methodNode.Identifier.ValueText));

            // We can have abstract methods that don't have a body
            if (methodResult.Symbol.IsAbstract)
            {
                // Add the trailing trivia from the semicolon to close paren
                overloadNode = overloadNode
                               .WithParameterList(
                    overloadNode.ParameterList
                    .WithCloseParenToken(
                        overloadNode.ParameterList.CloseParenToken.WithTrailingTrivia(overloadNode.SemicolonToken.TrailingTrivia))
                    )
                               .WithSemicolonToken(default(SyntaxToken));
                methodBody = Block()
                             .WithOpenBraceToken(
                    Token(TriviaList(transformResult.LeadingWhitespaceTrivia), SyntaxKind.OpenBraceToken,
                          TriviaList(transformResult.EndOfLineTrivia)))
                             .WithCloseBraceToken(
                    Token(TriviaList(transformResult.LeadingWhitespaceTrivia), SyntaxKind.CloseBraceToken,
                          TriviaList(transformResult.EndOfLineTrivia)));
            }

            var tokenArg = Argument(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    IdentifierName("CancellationToken"),
                    IdentifierName("None")));

            overloadNode = overloadNode
                           .WithBody(methodBody
                                     .WithStatements(
                                         SingletonList <StatementSyntax>(
                                             ReturnStatement(originalMethodNode.ForwardCall(methodResult.Symbol, methodNode.Identifier.ValueText, tokenArg))
                                             .WithReturnKeyword(
                                                 Token(TriviaList(transformResult.BodyLeadingWhitespaceTrivia), SyntaxKind.ReturnKeyword, TriviaList(Space))
                                                 )
                                             .WithSemicolonToken(Token(TriviaList(), SyntaxKind.SemicolonToken, TriviaList(transformResult.EndOfLineTrivia)))
                                             )
                                         ));
            if (generationOptions.HasFlag(MethodCancellationToken.SealedForwardNone))
            {
                if (methodResult.Symbol.IsVirtual)
                {
                    // For virtual methods we need to remove the virtual keyword
                    overloadNode = overloadNode
                                   .WithModifiers(TokenList(originalMethodNode.Modifiers.Where(o => !o.IsKind(SyntaxKind.VirtualKeyword))));
                }
                else if (methodResult.Symbol.OverriddenMethod != null)
                {
                    // For overrides we need to add the sealed keyword
                    overloadNode = overloadNode
                                   .WithModifiers(originalMethodNode.Modifiers.Add(Token(TriviaList(), SyntaxKind.SealedKeyword, TriviaList(Space))));
                }
                else if (methodResult.Symbol.IsAbstract)
                {
                    // For abstract we need to remove the abstract keyword
                    overloadNode = overloadNode
                                   .WithModifiers(TokenList(originalMethodNode.Modifiers.Where(o => !o.IsKind(SyntaxKind.AbstractKeyword))));
                }
            }
            // We need to remove all directives
            while (overloadNode.ContainsDirectives)
            {
                overloadNode = overloadNode.RemoveNode(overloadNode.GetFirstDirective(), SyntaxRemoveOptions.KeepNoTrivia);
            }

            return(MethodTransformerResult.Update(methodNode)
                   .AddMethod(overloadNode));
        }
Exemple #26
0
 public SyntaxNode Transform(IFunctionTransformationResult transformResult,
                             ITypeTransformationMetadata typeMetadata,
                             INamespaceTransformationMetadata namespaceMetadata)
 {
     return(transformResult.AnalyzationResult.OmitAsync ? null : _rewriter.VisitFunction(transformResult.Transformed));
 }
        public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult,
                                                 ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;

            if (!methodResult.Conversion.HasFlag(MethodConversion.ToAsync))
            {
                return(MethodTransformerResult.Skip);
            }
            var methodNode = transformResult.Transformed;

            if (methodNode.GetFunctionBody() == null)
            {
                return(Update(methodNode, methodResult, namespaceMetadata));
            }
            if (methodResult.SplitTail || methodResult.PreserveReturnType || !methodResult.OmitAsync)
            {
                if (!methodResult.OmitAsync)
                {
                    methodNode = methodNode.AddAsync();
                }
                return(Update(methodNode, methodResult, namespaceMetadata));
            }
            var rewriter = new ReturnTaskFunctionRewriter(transformResult, namespaceMetadata);

            methodNode = (MethodDeclarationSyntax)rewriter.VisitMethodDeclaration(methodNode);
            return(Update(methodNode, methodResult, namespaceMetadata));
        }
Exemple #28
0
 private MethodTransformerResult Update(MethodDeclarationSyntax methodNode,
                                        IMethodOrAccessorAnalyzationResult methodResult, INamespaceTransformationMetadata namespaceMetadata)
 {
     methodNode = methodNode.WithIdentifier(Identifier(methodResult.AsyncCounterpartName));
     if (!methodResult.PreserveReturnType && methodResult.Symbol.MethodKind != MethodKind.PropertySet)
     {
         methodNode = methodNode.ReturnAsTask(namespaceMetadata.TaskConflict);
     }
     return(MethodTransformerResult.Update(methodNode));
 }
Exemple #29
0
 public ReturnTaskFunctionRewriter(IFunctionTransformationResult transformResult, INamespaceTransformationMetadata namespaceMetadata)
 {
     _transformResult   = transformResult;
     _methodResult      = transformResult.AnalyzationResult;
     _namespaceMetadata = namespaceMetadata;
 }
Exemple #30
0
        private RootTypeTransformationResult TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata)
        {
            var anyMissingMembers = rootTypeResult.Conversion != TypeConversion.Partial && rootTypeResult.GetSelfAndDescendantsTypes()
                                    .Any(o => o.MethodsAndAccessors.Any(m => m.Missing));
            var result = TransformType(rootTypeResult, namespaceMetadata, false);

            if (anyMissingMembers)
            {
                result.Partial = TransformType(rootTypeResult, namespaceMetadata, true);
                var transformedNode = result.Partial.Transformed;
                // We need to remove all directives
                while (transformedNode.ContainsDirectives)
                {
                    transformedNode = transformedNode.RemoveNode(transformedNode.GetFirstDirective(), SyntaxRemoveOptions.KeepNoTrivia);
                }
                result.Partial.Transformed = transformedNode;
                result.OriginalModified    = result.Partial.OriginalModified;
            }
            return(result);
        }