public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var unit           = root as CompilationUnitSyntax;
            var removingUsings = new List <UsingDirectiveSyntax>();

            foreach (var u in unit.Usings)
            {
                try
                {
                    if (u.StaticKeyword.RawKind == (int)SyntaxKind.StaticKeyword)
                    {
                        removingUsings.Add(u);
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(u, e);
                }
            }

            return(root.RemoveNodes(removingUsings, SyntaxRemoveOptions.KeepDirectives));
        }
Exemple #2
0
 public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
 {
     root = InsertVariables(root, model);
     return(ReplacePatterns(root, model));
 }
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var assignments   = root.DescendantNodes().OfType <AssignmentExpressionSyntax>();
            var updatedBlocks = new Dictionary <BlockSyntax, List <StatementSyntax> >();
            var locals        = new List <LocalDeclarationStatementSyntax>();

            foreach (var assignment in assignments)
            {
                try
                {
                    if (assignment.Left is IdentifierNameSyntax identifier)
                    {
                        var local = assignment.GetParent <LocalDeclarationStatementSyntax>();
                        if (local != null && locals.Contains(local))
                        {
                            continue;
                        }
                        locals.Add(local);

                        var name = identifier.Identifier.ValueText;

                        if (local != null && local.Declaration.Variables.Any(v => v.Identifier.ValueText == name))
                        {
                            var block = local.Ancestors().OfType <BlockSyntax>().First();

                            var statements = updatedBlocks.ContainsKey(block) ? updatedBlocks[block] : block.Statements.ToList();
                            var index      = statements.IndexOf(local);

                            foreach (var variable in local.Declaration.Variables)
                            {
                                var newLocal = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(local.Declaration.Type.WithoutTrivia(), SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(variable.Identifier.ValueText)))).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));

                                if (local.Declaration.Variables.First().Equals(variable))
                                {
                                    newLocal = newLocal.WithLeadingTrivia(local.GetLeadingTrivia());
                                }

                                statements.Insert(index++, newLocal);

                                if (variable.Initializer != null)
                                {
                                    var equals = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(variable.Identifier.ValueText), variable.Initializer.Value.WithoutTrivia())).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));
                                    if (local.Declaration.Variables.Last().Equals(variable))
                                    {
                                        equals = equals.WithTrailingTrivia(local.GetTrailingTrivia());
                                    }

                                    statements.Insert(index++, equals);
                                }
                            }

                            statements.Remove(local);

                            updatedBlocks[block] = statements;
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(assignment, e);
                }
            }

            if (updatedBlocks.Count > 0)
            {
                root = root.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => b1.WithStatements(SyntaxFactory.List(updatedBlocks[b1])));
            }

            return(root);
        }
Exemple #4
0
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater, SharpSixRewriter rewriter)
        {
            var discards = root
                           .DescendantNodes()
                           .OfType <DiscardDesignationSyntax>();

            var outVars = root
                          .DescendantNodes()
                          .OfType <ArgumentSyntax>()
                          .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword);

            var outDiscardVars = root
                                 .DescendantNodes()
                                 .OfType <ArgumentSyntax>()
                                 .Where(arg => {
                if (arg.Expression is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER)
                {
                    var si = model.GetSymbolInfo(arg.Expression);
                    return(si.Symbol == null || si.Symbol is IDiscardSymbol);
                }

                return(false);
            });

            var discardAssigments = root
                                    .DescendantNodes()
                                    .OfType <AssignmentExpressionSyntax>()
                                    .Where(assignment => {
                if (assignment.Left is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER)
                {
                    var si = model.GetSymbolInfo(assignment.Left);
                    return(si.Symbol == null || si.Symbol is IDiscardSymbol);
                }

                return(false);
            });

            var updatedMembers = new Dictionary <MemberAccessExpressionSyntax, string>();

            foreach (var memberAccess in root.DescendantNodes().OfType <MemberAccessExpressionSyntax>())
            {
                try
                {
                    var symbol = model.GetSymbolInfo(memberAccess).Symbol;

                    if (symbol != null && symbol is IFieldSymbol && symbol.ContainingType.IsTupleType)
                    {
                        var field      = symbol as IFieldSymbol;
                        var tupleField = field.CorrespondingTupleField;
                        updatedMembers[memberAccess] = tupleField.Name;
                    }
                }
                catch (Exception E)
                {
                    Console.WriteLine(E);
                }
            }

            var updatedStatements  = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >();
            var updatedDiscards    = new Dictionary <DiscardDesignationSyntax, string>();
            var updatedDiscardVars = new Dictionary <ArgumentSyntax, string>();

            var tempIndex = 0;

            foreach (var discard in discards)
            {
                try
                {
                    var noLocal     = false;
                    var parentTuple = discard.GetParent <TupleExpressionSyntax>();
                    if (parentTuple != null && parentTuple.Parent is AssignmentExpressionSyntax ae && ae.Left == parentTuple)
                    {
                        noLocal = true;
                    }

                    var typeInfo        = model.GetTypeInfo(discard.Parent);
                    var beforeStatement = discard.Ancestors().OfType <StatementSyntax>().FirstOrDefault();

                    if (beforeStatement != null)
                    {
                        if (typeInfo.Type != null)
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            if (!noLocal)
                            {
                                var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discard.Parent.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                  SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance))
                                                                                                                                                                                                                  ));

                                var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));
                                locals.Add(local);

                                updatedStatements[beforeStatement] = locals;
                            }

                            updatedDiscards[discard] = instance;
                        }
                        else if (discard.Parent is DeclarationPatternSyntax && !(discard.Parent.Parent is IsPatternExpressionSyntax))
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            updatedDiscards[discard] = instance;
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(discard, e);
                }
            }

            foreach (var discardVar in outDiscardVars)
            {
                try
                {
                    var typeInfo = model.GetTypeInfo(discardVar.Expression);

                    if (typeInfo.Type != null)
                    {
                        var beforeStatement = discardVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                        if (beforeStatement != null)
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                            var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discardVar.Expression.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                     SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance))
                                                                                                                                                                                                                     ));

                            var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));
                            locals.Add(local);

                            updatedStatements[beforeStatement] = locals;
                            updatedDiscardVars[discardVar]     = instance;
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(discardVar, e);
                }
            }

            foreach (var outVar in outVars)
            {
                try
                {
                    if (((DeclarationExpressionSyntax)outVar.Expression).Designation.Kind() == SyntaxKind.DiscardDesignation)
                    {
                        continue;
                    }

                    var typeInfo = model.GetTypeInfo(outVar.Expression);

                    if (typeInfo.Type != null)
                    {
                        var beforeStatement = outVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                        if (beforeStatement != null)
                        {
                            if (outVar.Expression is DeclarationExpressionSyntax de)
                            {
                                if (de.Designation is SingleVariableDesignationSyntax designation)
                                {
                                    var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                    var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, outVar.Expression.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                         SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                                                                                                                         ));

                                    locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                    updatedStatements[beforeStatement] = locals;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(outVar, e);
                }
            }

            var annotatedStatemnts   = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >();
            var annotatedDiscards    = new Dictionary <SyntaxAnnotation, string>();
            var annotatedDiscardVars = new Dictionary <SyntaxAnnotation, string>();
            var annotatedAssigments  = new List <SyntaxAnnotation>();
            var annotatedMembers     = new Dictionary <SyntaxAnnotation, string>();

            var keys = updatedStatements.Keys.Cast <SyntaxNode>()
                       .Concat(updatedDiscards.Keys.Cast <SyntaxNode>())
                       .Concat(updatedDiscardVars.Keys.Cast <SyntaxNode>())
                       .Concat(discardAssigments)
                       .Concat(updatedMembers.Keys.Cast <SyntaxNode>());

            root = root.ReplaceNodes(keys, (n1, n2) =>
            {
                var annotation = new SyntaxAnnotation();

                if (n1 is AssignmentExpressionSyntax)
                {
                    annotatedAssigments.Add(annotation);
                }
                else if (n1 is DiscardDesignationSyntax)
                {
                    annotatedDiscards[annotation] = updatedDiscards[(DiscardDesignationSyntax)n1];
                }
                else if (n1 is ArgumentSyntax)
                {
                    annotatedDiscardVars[annotation] = updatedDiscardVars[(ArgumentSyntax)n1];
                }
                else if (n1 is MemberAccessExpressionSyntax)
                {
                    annotatedMembers[annotation] = updatedMembers[(MemberAccessExpressionSyntax)n1];
                }
                else
                {
                    annotatedStatemnts[annotation] = updatedStatements[(StatementSyntax)n1];
                }

                n2 = n2.WithAdditionalAnnotations(annotation);
                return(n2);
            });

            foreach (var annotation in annotatedDiscards.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var name          = annotatedDiscards[annotation];

                root = root.ReplaceNode(annotatedNode, SyntaxFactory.SingleVariableDesignation(SyntaxFactory.Identifier(name)).NormalizeWhitespace());
            }

            foreach (var annotation in annotatedDiscardVars.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var name          = annotatedDiscardVars[annotation];

                root = root.ReplaceNode(annotatedNode, ((ArgumentSyntax)annotatedNode).WithExpression(SyntaxFactory.IdentifierName(name)));
            }

            foreach (var annotation in annotatedAssigments)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                root = root.ReplaceNode(annotatedNode, ((AssignmentExpressionSyntax)annotatedNode).WithLeft(SyntaxFactory.IdentifierName("H5.Script.Discard")));
            }

            outVars = root
                      .DescendantNodes()
                      .OfType <ArgumentSyntax>()
                      .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword);

            root = root.ReplaceNodes(outVars, (n1, n2) =>
            {
                if (!(((DeclarationExpressionSyntax)n2.Expression).Designation is SingleVariableDesignationSyntax designation))
                {
                    return(n2);
                }

                return(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(designation.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).NormalizeWhitespace());
            });
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var localFns       = root.DescendantNodes().OfType <LocalFunctionStatementSyntax>();
            var updatedBlocks  = new Dictionary <SyntaxNode, List <StatementSyntax> >();
            var initForBlocks  = new Dictionary <SyntaxNode, List <StatementSyntax> >();
            var updatedClasses = new Dictionary <TypeDeclarationSyntax, List <DelegateDeclarationSyntax> >();

            foreach (var fn in localFns)
            {
                try
                {
                    var parentNode      = fn.Parent;
                    var usage           = GetFirstUsageLocalFunc(model, fn, parentNode);
                    var beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode);

                    if (beforeStatement is LocalFunctionStatementSyntax beforeFn)
                    {
                        List <SyntaxNode> ignore = new List <SyntaxNode>();
                        var usageFn           = usage;
                        var beforeStatementFn = beforeStatement;
                        while (beforeStatementFn != null && beforeStatementFn is LocalFunctionStatementSyntax)
                        {
                            ignore.Add(usageFn);
                            usageFn           = GetFirstUsageLocalFunc(model, fn, parentNode, ignore);
                            beforeStatementFn = usageFn?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode);
                        }

                        usage           = GetFirstUsageLocalFunc(model, beforeFn, parentNode);
                        beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode);

                        if (beforeStatementFn != null && (beforeStatement == null || beforeStatementFn.SpanStart < beforeStatement.SpanStart))
                        {
                            beforeStatement = beforeStatementFn;
                        }
                    }

                    var customDelegate = false;

                    if (fn.TypeParameterList != null && fn.TypeParameterList.Parameters.Count > 0)
                    {
                        customDelegate = true;
                    }
                    else
                    {
                        foreach (var prm in fn.ParameterList.Parameters)
                        {
                            if (prm.Default != null)
                            {
                                customDelegate = true;
                                break;
                            }

                            foreach (var modifier in prm.Modifiers)
                            {
                                var kind = modifier.Kind();
                                if (kind == SyntaxKind.RefKeyword ||
                                    kind == SyntaxKind.OutKeyword ||
                                    kind == SyntaxKind.ParamsKeyword)
                                {
                                    customDelegate = true;
                                    break;
                                }
                            }

                            if (customDelegate)
                            {
                                break;
                            }
                        }
                    }

                    var returnType = fn.ReturnType.WithoutLeadingTrivia().WithoutTrailingTrivia();
                    var isVoid     = returnType is PredefinedTypeSyntax ptsInstance && ptsInstance.Keyword.Kind() == SyntaxKind.VoidKeyword;

                    TypeSyntax varType;

                    if (customDelegate)
                    {
                        var typeDecl  = parentNode.Ancestors().OfType <TypeDeclarationSyntax>().FirstOrDefault();
                        var delegates = updatedClasses.ContainsKey(typeDecl) ? updatedClasses[typeDecl] : new List <DelegateDeclarationSyntax>();
                        var name      = $"___{fn.Identifier.ValueText}_Delegate_{delegates.Count}";
                        var delDecl   = SyntaxFactory.DelegateDeclaration(returnType, SyntaxFactory.Identifier(name))
                                        .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)))
                                        .WithParameterList(fn.ParameterList).NormalizeWhitespace();
                        delegates.Add(delDecl);
                        updatedClasses[typeDecl] = delegates;

                        varType = SyntaxFactory.IdentifierName(name);
                    }
                    else if (isVoid)
                    {
                        if (fn.ParameterList.Parameters.Count == 0)
                        {
                            varType = SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Action"));
                        }
                        else
                        {
                            varType = SyntaxFactory.QualifiedName
                                      (
                                SyntaxFactory.IdentifierName("System"),
                                SyntaxFactory.GenericName("Action").WithTypeArgumentList
                                (
                                    SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(fn.ParameterList.Parameters.Select(p => p.Type)))
                                )
                                      );
                        }
                    }
                    else
                    {
                        if (fn.ParameterList.Parameters.Count == 0)
                        {
                            varType = SyntaxFactory.QualifiedName(
                                SyntaxFactory.IdentifierName("System"),
                                SyntaxFactory.GenericName("Func").WithTypeArgumentList(
                                    SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(returnType))
                                    )
                                );
                        }
                        else
                        {
                            varType = SyntaxFactory.QualifiedName
                                      (
                                SyntaxFactory.IdentifierName("System"),
                                SyntaxFactory.GenericName("Func").WithTypeArgumentList
                                (
                                    SyntaxFactory.TypeArgumentList(
                                        SyntaxFactory.SeparatedList(
                                            fn.ParameterList.Parameters.Select(p => p.Type).Concat(
                                                new TypeSyntax[] { returnType }
                                                )
                                            )
                                        )
                                )
                                      );
                        }
                    }

                    List <ParameterSyntax> prms = new List <ParameterSyntax>();

                    if (customDelegate)
                    {
                        foreach (var prm in fn.ParameterList.Parameters)
                        {
                            var newPrm = prm.WithDefault(null);
                            var idx    = newPrm.Modifiers.IndexOf(SyntaxKind.ParamsKeyword);

                            if (idx > -1)
                            {
                                newPrm = newPrm.WithModifiers(newPrm.Modifiers.RemoveAt(idx));
                            }

                            prms.Add(newPrm);
                        }
                    }
                    else
                    {
                        foreach (var prm in fn.ParameterList.Parameters)
                        {
                            prms.Add(SyntaxFactory.Parameter(prm.Identifier));
                        }
                    }

                    var initVar = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).WithVariables(
                                                                              SyntaxFactory.SingletonSeparatedList(
                                                                                  SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fn.Identifier.ValueText)).WithInitializer
                                                                                  (
                                                                                      SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression))
                                                                                  )
                                                                                  )
                                                                              )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE));

                    var lambda = SyntaxFactory.ParenthesizedLambdaExpression(fn.Body ?? (CSharpSyntaxNode)fn.ExpressionBody.Expression).WithParameterList(
                        SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(prms))
                        );

                    if (fn.Modifiers.Any(SyntaxKind.AsyncKeyword))
                    {
                        lambda = lambda.WithAsyncKeyword(SyntaxFactory.Token(SyntaxKind.AsyncKeyword));
                    }

                    var assignment = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                                                          SyntaxFactory.IdentifierName(fn.Identifier.ValueText),
                                                                                                          lambda
                                                                                                          )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE));

                    List <StatementSyntax> statements = null;

                    if (updatedBlocks.ContainsKey(parentNode))
                    {
                        statements = updatedBlocks[parentNode];
                    }
                    else
                    {
                        if (parentNode is BlockSyntax bs)
                        {
                            statements = bs.Statements.ToList();
                        }
                        else if (parentNode is SwitchSectionSyntax sss)
                        {
                            statements = sss.Statements.ToList();
                        }
                    }

                    var fnIdx = statements.IndexOf(fn);
                    statements.Insert(beforeStatement != null ? statements.IndexOf(beforeStatement) : Math.Max(0, fnIdx), assignment);
                    updatedBlocks[parentNode] = statements;

                    statements = initForBlocks.ContainsKey(parentNode) ? initForBlocks[parentNode] : new List <StatementSyntax>();
                    statements.Insert(0, initVar);
                    initForBlocks[parentNode] = statements;
                }
                catch (Exception e)
                {
                    throw new ReplacerException(fn, e);
                }
            }

            foreach (var key in initForBlocks.Keys)
            {
                updatedBlocks[key] = initForBlocks[key].Concat(updatedBlocks[key]).ToList();
            }

            if (updatedClasses.Count > 0)
            {
                root = root.ReplaceNodes(updatedClasses.Keys, (t1, t2) =>
                {
                    var members = updatedClasses[t1].ToArray();

                    t1 = t1.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => {
                        SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1])));
                        return(result);
                    });

                    if (t1 is ClassDeclarationSyntax cls)
                    {
                        return(cls.AddMembers(members));
                    }

                    if (t2 is StructDeclarationSyntax structDecl)
                    {
                        return(structDecl.AddMembers(members));
                    }

                    return(t1);
                });
            }
            else if (updatedBlocks.Count > 0)
            {
                root = root.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => {
                    SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1])));
                    return(result);
                });
            }

            root = root.RemoveNodes(root.DescendantNodes().OfType <LocalFunctionStatementSyntax>(), SyntaxRemoveOptions.KeepTrailingTrivia | SyntaxRemoveOptions.KeepLeadingTrivia);

            return(root);
        }
Exemple #6
0
        public SyntaxNode InsertVariables(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var tuples = root
                         .DescendantNodes()
                         .OfType <TupleExpressionSyntax>()
                         .Where(e => e.Parent is AssignmentExpressionSyntax ae && ae.Left == e || e.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e);

            var updatedStatements = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >();

            foreach (var tuple in tuples)
            {
                try
                {
                    var beforeStatement = tuple.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    if (beforeStatement != null)
                    {
                        foreach (var arg in tuple.Arguments)
                        {
                            if (arg.Expression is DeclarationExpressionSyntax de)
                            {
                                if (de.Designation is SingleVariableDesignationSyntax designation)
                                {
                                    var locals   = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                    var typeInfo = model.GetTypeInfo(de).Type;
                                    var varDecl  = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo, model, arg.Expression.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                  SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                                                                                                                  ));

                                    locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                    updatedStatements[beforeStatement] = locals;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(tuple, e);
                }
            }

            var parenthesized = root
                                .DescendantNodes()
                                .OfType <ParenthesizedVariableDesignationSyntax>()
                                .Where(e => e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is AssignmentExpressionSyntax ae && ae.Left == e.Parent ||
                                       e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e.Parent);

            foreach (var p in parenthesized)
            {
                try
                {
                    var beforeStatement = p.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    var declaration     = (DeclarationExpressionSyntax)p.Parent;
                    if (beforeStatement != null)
                    {
                        var typeInfo            = model.GetTypeInfo(declaration).Type;
                        List <TypeSyntax> types = new List <TypeSyntax>();
                        if (typeInfo.IsTupleType)
                        {
                            var elements = ((INamedTypeSymbol)typeInfo).TupleElements;
                            foreach (var el in elements)
                            {
                                types.Add(SyntaxHelper.GenerateTypeSyntax(el.Type, model, declaration.GetLocation().SourceSpan.Start, rewriter));
                            }
                        }
                        else
                        {
                            continue;
                        }

                        int idx = 0;
                        foreach (var v in p.Variables)
                        {
                            if (v is SingleVariableDesignationSyntax designation)
                            {
                                var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();

                                var varDecl = SyntaxFactory.VariableDeclaration(types[idx++]).WithVariables(SyntaxFactory.SingletonSeparatedList(
                                                                                                                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                ));

                                locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                updatedStatements[beforeStatement] = locals;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(p, e);
                }
            }

            var annotated = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >();

            root = root.ReplaceNodes(updatedStatements.Keys, (n1, n2) =>
            {
                var annotation        = new SyntaxAnnotation();
                annotated[annotation] = updatedStatements[n1];

                n2 = n2.WithAdditionalAnnotations(annotation);
                return(n2);
            });

            foreach (var annotation in annotated.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var varStatements = annotated[annotation];

                if (annotatedNode is ForEachVariableStatementSyntax fe)
                {
                    varStatements[varStatements.Count - 1] = varStatements.Last().WithAdditionalAnnotations(new SyntaxAnnotation("last_variable"));
                    var list = new List <StatementSyntax>(varStatements);

                    if (fe.Statement is BlockSyntax b)
                    {
                        list.AddRange(b.Statements);
                    }
                    else
                    {
                        list.Add(fe.Statement);
                    }

                    root = root.ReplaceNode(annotatedNode, fe.WithStatement(SyntaxFactory.Block(list)).NormalizeWhitespace());
                }
                else if (annotatedNode.Parent is BlockSyntax || !(annotatedNode is StatementSyntax))
                {
                    root = root.InsertNodesBefore(annotatedNode, varStatements);
                }
                else
                {
                    var list = new List <StatementSyntax>(varStatements);
                    list.Add((StatementSyntax)annotatedNode);
                    root = root.ReplaceNode(annotatedNode, SyntaxFactory.Block(list).NormalizeWhitespace());
                }
            }

            return(root);
        }
Exemple #7
0
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater, SharpSixRewriter rewriter)
        {
            root = InsertVariables(root, model, rewriter);
            var tuple = updater(root);

            root  = tuple.Item1.GetRoot();
            model = tuple.Item2;

            root  = ReplaceDeconstructions(root, model);
            tuple = updater(root);
            root  = tuple.Item1.GetRoot();
            model = tuple.Item2;

            root = ReplaceForeachDeconstructions(root, model);

            return(root);
        }
Exemple #8
0
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter)
        {
            var switches = root.DescendantNodes().OfType <SwitchStatementSyntax>().Where(sw => {
                return(sw.Sections.Any(s => s.Labels.Any(l => l is CasePatternSwitchLabelSyntax || l is CaseSwitchLabelSyntax csl && csl.Value is CastExpressionSyntax ce && ce.Expression.Kind() == SyntaxKind.DefaultLiteralExpression)));
            });

            var tempKey = 0;

            root = root.ReplaceNodes(switches, (s1, sw) =>
            {
                try
                {
                    var ifNodes = new List <IfStatementSyntax>();
                    BlockSyntax defaultBlock = null;
                    var isComplex            = IsExpressionComplexEnoughToGetATemporaryVariable.IsComplex(model, s1.Expression);
                    var switchExpression     = sw.Expression;
                    StatementSyntax switchConditionVariable = null;

                    var iType          = model.GetTypeInfo(s1.Expression).Type;
                    var expressionType = SyntaxFactory.ParseTypeName(iType.ToMinimalDisplayString(model, s1.Expression.GetLocation().SourceSpan.Start));

                    if (isComplex)
                    {
                        var key              = tempKey++;
                        var keyArg           = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("case_pattern" + key));
                        var methodIdentifier = SyntaxFactory.IdentifierName("global::H5.Script.ToTemp");

                        var toTemp = SyntaxFactory.InvocationExpression(methodIdentifier,
                                                                        SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(keyArg), SyntaxFactory.Argument(switchExpression) })));

                        switchConditionVariable = SyntaxFactory.ExpressionStatement(toTemp).NormalizeWhitespace();

                        var parentMethodIdentifier = SyntaxFactory.GenericName(SyntaxFactory.Identifier("global::H5.Script.FromTemp"),
                                                                               SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(new[] { expressionType })));
                        switchExpression = SyntaxFactory.InvocationExpression(parentMethodIdentifier,
                                                                              SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(keyArg) })));
                    }

                    foreach (var section in sw.Sections)
                    {
                        // This should catch most (if not all) unhandled yet natively supported syntax usage
                        try
                        {
                            var tuple     = CollectCondition(switchExpression, section.Labels, expressionType);
                            var condition = tuple.Item1;
                            var variables = tuple.Item2;
                            var whens     = tuple.Item3;

                            var body     = SyntaxFactory.Block();
                            var whenBody = SyntaxFactory.Block();

                            foreach (var variable in variables)
                            {
                                body = body.WithStatements(body.Statements.Add(SyntaxFactory.LocalDeclarationStatement(variable)));
                            }

                            foreach (var statement in section.Statements)
                            {
                                if (whens.Count > 0)
                                {
                                    whenBody = whenBody.WithStatements(whenBody.Statements.Add(statement));
                                }
                                else
                                {
                                    body = body.WithStatements(body.Statements.Add(statement));
                                }
                            }

                            if (whens.Count > 0)
                            {
                                ExpressionSyntax whenCondition = whens[0];
                                for (int i = 1; i < whens.Count; ++i)
                                {
                                    whenCondition = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, whenCondition, whens[i]);
                                }

                                body = body.WithStatements(body.Statements.Add(SyntaxFactory.IfStatement(whenCondition, whenBody)));
                            }

                            if (condition == null)
                            {
                                defaultBlock = body
                                               .WithLeadingTrivia(section.GetLeadingTrivia())
                                               .WithTrailingTrivia(section.GetTrailingTrivia());
                                break;
                            }

                            ifNodes.Add(SyntaxFactory.IfStatement(condition, body).WithLeadingTrivia(section.GetLeadingTrivia()));
                        }
                        catch (Exception e)
                        {
                            throw new ReplacerException(section, e);
                        }
                    }

                    var doBlock = SyntaxFactory.Block();
                    if (switchConditionVariable != null)
                    {
                        doBlock = doBlock.WithStatements(doBlock.Statements.Add(switchConditionVariable));
                    }

                    doBlock = doBlock.WithStatements(doBlock.Statements.AddRange(ifNodes));

                    if (defaultBlock != null)
                    {
                        doBlock = doBlock.WithStatements(doBlock.Statements.Add(defaultBlock));
                    }

                    var doStatement = SyntaxFactory.DoStatement(doBlock, SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression));

                    doStatement = doStatement.WithLeadingTrivia(sw.GetLeadingTrivia().Concat(doStatement.GetLeadingTrivia())).WithTrailingTrivia(sw.GetTrailingTrivia());
                    return(doStatement.NormalizeWhitespace());
                }
                catch (Exception e)
                {
                    throw new ReplacerException(sw, e);
                }
            });

            return(root);
        }
Exemple #9
0
 public static GenericNameSyntax GenerateGenericName(SyntaxToken name, IEnumerable <ITypeSymbol> types, SemanticModel model, int pos, SharpSixRewriter rewriter)
 {
     return(SyntaxFactory.GenericName(name, SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(types.Select((type) => GenerateTypeSyntax(type, model, pos, rewriter))))));
 }
Exemple #10
0
        public static TypeSyntax GenerateTypeSyntax(ITypeSymbol type, SemanticModel model, int pos, SharpSixRewriter rewriter)
        {
            if (type.IsTupleType)
            {
                var elements = ((INamedTypeSymbol)type).TupleElements;
                var types    = new List <TypeSyntax>();
                foreach (var el in elements)
                {
                    types.Add(GenerateTypeSyntax(el.Type, model, pos, rewriter));
                }

                return(SyntaxFactory.GenericName(SyntaxFactory.Identifier("System.ValueTuple"), SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(types))));
            }

            var typeName = type.FullyQualifiedName(false);

            if (rewriter.usingStaticNames.Any(n => typeName.StartsWith(n + '.')))
            {
                return(SyntaxFactory.ParseTypeName(type.ToDisplayString()));
            }
            else if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
            {
                var elements = namedType.TypeArguments;
                var types    = new List <TypeSyntax>();
                foreach (var el in elements)
                {
                    types.Add(GenerateTypeSyntax(el, model, pos, rewriter));
                }

                if (type.OriginalDefinition != null && type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
                {
                    return(SyntaxFactory.IdentifierName(type.ToMinimalDisplayString(
                                                            model,
                                                            pos,
                                                            new SymbolDisplayFormat(
                                                                genericsOptions: SymbolDisplayGenericsOptions.None
                                                                )
                                                            )));
                }

                if (types.Count > 0)
                {
                    string gtypeName;
                    if (type.ContainingType != null)
                    {
                        var parent = GenerateTypeSyntax(type.ContainingType, model, pos, rewriter);
                        var name   = type.Name;
                        gtypeName = SyntaxFactory.QualifiedName((NameSyntax)parent, SyntaxFactory.IdentifierName(name)).ToString();
                    }
                    else
                    {
                        gtypeName = type.ToMinimalDisplayString(
                            model,
                            pos,
                            new SymbolDisplayFormat(
                                genericsOptions: SymbolDisplayGenericsOptions.None
                                )
                            );
                    }

                    if (model != null)
                    {
                        var ai = model.GetSpeculativeAliasInfo(pos, SyntaxFactory.IdentifierName(gtypeName), SpeculativeBindingOption.BindAsTypeOrNamespace);

                        if (ai != null && ai.Name == gtypeName)
                        {
                            return(SyntaxFactory.ParseTypeName(gtypeName));
                        }
                    }

                    return(SyntaxFactory.GenericName(
                               SyntaxFactory.Identifier(gtypeName),
                               SyntaxFactory.TypeArgumentList(
                                   SyntaxFactory.SeparatedList(types)
                                   )
                               ));
                }
            }

            if (type.ContainingType != null && type.Kind != SymbolKind.TypeParameter)
            {
                var parent = GenerateTypeSyntax(type.ContainingType, model, pos, rewriter);
                var name   = type.Name;
                return(SyntaxFactory.QualifiedName((NameSyntax)parent, SyntaxFactory.IdentifierName(name)));
            }

            return(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(model, pos)));
        }