Beispiel #1
0
 public static ArgumentSyntax WithRef(this ArgumentSyntax syntax, bool isRef)
 {
     if (isRef)
     {
         return(syntax.WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.RefKeyword)));
     }
     else
     {
         return(syntax.WithRefOrOutKeyword(default(SyntaxToken)));
     }
 }
        public static ArgumentSyntax AddOutKeywordToArgument(ArgumentSyntax argument)
        {
            var newArgument = argument?
                              .WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword))
                              .NormalizeWhitespace();

            return(newArgument);
        }
Beispiel #3
0
        private StatementSyntax ToManagedMethod(string target, ArgumentSyntax source, JSFunctionTypeInfo info)
        {
            List <ArgumentSyntax> arguments = new List <ArgumentSyntax>();

            arguments.Add(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)));
            for (int i = 0; i < info.ArgsTypeInfo.Length; i++)
            {
                var sourceType = info.ArgsTypeInfo[i];
                if (!_isAction && i + 1 == info.ArgsTypeInfo.Length)
                {
                    arguments.Add(ArgToManaged(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
                }
                else
                {
                    arguments.Add(ArgToJS(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
                }
            }

            return(ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                   IdentifierName(target), GetToManagedMethod(Type)))
                                       .WithArgumentList(ArgumentList(SeparatedList(arguments)))));
        }
Beispiel #4
0
 private StatementSyntax ToManagedMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
 {
     return(ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                            IdentifierName(target), GetToManagedMethod(Type)))
                                .WithArgumentList(ArgumentList(SeparatedList(new[] {
         source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
         Argument(ParenthesizedLambdaExpression()
                  .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
                  .WithParameterList(ParameterList(SeparatedList(new[] {
             Parameter(Identifier("__task_result_arg"))
             .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword)))
             .WithType(IdentifierName(Constants.JSMarshalerArgumentGlobal)),
             Parameter(Identifier("__task_result"))
             .WithModifiers(TokenList(Token(SyntaxKind.OutKeyword)))
             .WithType(sourceType)
         })))
                  .WithBlock(Block(SingletonList <StatementSyntax>(ExpressionStatement(
                                                                       InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                   IdentifierName("__task_result_arg"), GetToManagedMethod(_resultMarshalerType)))
                                                                       .WithArgumentList(ArgumentList(SeparatedList(new[] {
             Argument(IdentifierName("__task_result")).WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
         }))))))))
     })))));
 }
Beispiel #5
0
 private StatementSyntax ToManagedMethodVoid(string target, ArgumentSyntax source)
 {
     return(ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                            IdentifierName(target), GetToManagedMethod(Type)))
                                .WithArgumentList(ArgumentList(SingletonSeparatedList(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)))))));
 }
Beispiel #6
0
        public CodeActionEdit GetEdit(CancellationToken cancellationToken)
        {
            SyntaxNode     root  = (SyntaxNode)this.document.GetSyntaxRoot(cancellationToken);
            ISemanticModel model = this.document.GetSemanticModel(cancellationToken);

            ISymbol typeSymbol = model.GetDeclaredSymbol(this.typeDeclaration, cancellationToken);

            string typeName   = typeSymbol.Name;
            string methodName = String.Format("Create{0}", typeName);

            // Note: typeSyntax will already contain template parameters, same as class definition
            TypeSyntax typeSyntax = Syntax.ParseTypeName(typeSymbol.ToMinimalDisplayString(this.ctorDeclaration.GetLocation(), model));

            // Filter out access modifiers
            var accessModifiers = this.ctorDeclaration.Modifiers.Where(IsAccessModifier);

            // Define modifiers, access modifier same as in constructor + static keyword
            SyntaxTokenList modifiers = Syntax.TokenList(accessModifiers)
                                        .Add(Syntax.Token(SyntaxKind.StaticKeyword));

            // Forward parameters to arguments, from ctor declaration to ctor call
            SeparatedSyntaxList <ArgumentSyntax> arguments = Syntax.SeparatedList <ArgumentSyntax>();

            foreach (ParameterSyntax parameter in this.ctorDeclaration.ParameterList.Parameters)
            {
                ArgumentSyntax argument = Syntax.Argument(Syntax.IdentifierName(parameter.Identifier));

                // Perfect forwarding
                // If parameter if `ref' or `out', it must be forwarded with same keyword
                if (parameter.Modifiers.Any(SyntaxKind.OutKeyword))
                {
                    argument = argument.WithRefOrOutKeyword(Syntax.Token(SyntaxKind.OutKeyword));
                }
                else if (parameter.Modifiers.Any(SyntaxKind.RefKeyword))
                {
                    argument = argument.WithRefOrOutKeyword(Syntax.Token(SyntaxKind.RefKeyword));
                }
                arguments = arguments.Add(argument);
            }

            // If class is a parametrized type (template), factory method should also handle those parameters
            // TODO:
            // class A<T,U> { public A(){} } -> class A<T,U> { private A(){} public static A<V,Z> CreateA<V,Z>(){...} }

            // Create object creation expression
            ObjectCreationExpressionSyntax objectCreationExpression = Syntax.ObjectCreationExpression(typeSyntax)
                                                                      .WithArgumentList(Syntax.ArgumentList(arguments));

            // Create simple factory method, return new TYPE(ARGUMENTS);
            BlockSyntax methodBody = Syntax.Block(Syntax.List <StatementSyntax>(Syntax.ReturnStatement(objectCreationExpression)));

            // Define factory method
            MethodDeclarationSyntax factoryMethod = Syntax.MethodDeclaration(typeSyntax, methodName)
                                                    .WithBody(methodBody)
                                                    .WithModifiers(modifiers)
                                                    .WithParameterList(this.ctorDeclaration.ParameterList)
                                                    .WithLeadingTrivia(Syntax.ElasticCarriageReturnLineFeed)
                                                    .WithAdditionalAnnotations(CodeAnnotations.Formatting);

            ReplaceConstructorWithFactoryMethodRewriter visitor = new ReplaceConstructorWithFactoryMethodRewriter(model, typeSymbol, cancellationToken, methodName, factoryMethod, ctorDeclaration, this.typeDeclaration);

            SyntaxNode newRoot = visitor.Visit(root);

            return(new CodeActionEdit(document.UpdateSyntaxRoot(newRoot)));
        }
 public static ArgumentSyntax WithOutKeyword(this ArgumentSyntax argument)
 {
     return(argument.WithRefOrOutKeyword(OutKeyword.ToToken()));
 }
 protected virtual ArgumentSyntax ToManagedMethodRefOrOut(ArgumentSyntax argument)
 {
     return(argument.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)));
 }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyCodeFixEnabled(
                    CodeFixIdentifiers.AddOutModifierToArgument,
                    CodeFixIdentifiers.RemoveRefModifier,
                    CodeFixIdentifiers.CreateSingletonArray))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            ArgumentSyntax argument = root
                                      .FindNode(context.Span, getInnermostNodeForTie: true)?
                                      .FirstAncestorOrSelf <ArgumentSyntax>();

            Debug.Assert(argument != null, $"{nameof(argument)} is null");

            if (argument == null)
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.ArgumentMustBePassedWithOutKeyword:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddOutModifierToArgument))
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add 'out' modifier",
                        cancellationToken =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(CSharpFactory.OutKeyword())
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, context.CancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    break;
                }

                case CompilerDiagnosticIdentifiers.ArgumentMayNotBePassedWithRefKeyword:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveRefModifier))
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove 'ref' modifier",
                        cancellationToken =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(default(SyntaxToken))
                                                         .PrependToLeadingTrivia(argument.RefOrOutKeyword.GetLeadingAndTrailingTrivia())
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, context.CancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotConvertArgumentType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddOutModifierToArgument))
                    {
                        return;
                    }

                    ExpressionSyntax expression = argument.Expression;

                    if (expression?.IsMissing == false)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression);

                        if (typeSymbol?.IsErrorType() == false)
                        {
                            foreach (ITypeSymbol typeSymbol2 in DetermineParameterTypeHelper.DetermineParameterTypes(argument, semanticModel, context.CancellationToken))
                            {
                                if (!typeSymbol.Equals(typeSymbol2) &&
                                    typeSymbol2.IsArrayType())
                                {
                                    var arrayType = (IArrayTypeSymbol)typeSymbol2;

                                    if (semanticModel.IsImplicitConversion(expression, arrayType.ElementType))
                                    {
                                        CodeAction codeAction = CodeAction.Create(
                                            "Create singleton array",
                                            cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken),
                                            GetEquivalenceKey(diagnostic));

                                        context.RegisterCodeFix(codeAction, diagnostic);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    break;
                }
                }
            }
        }