예제 #1
0
            private static void ProcessNodeMembers(TreeTextSpan.Builder builder, SyntaxList <MemberDeclarationSyntax> members)
            {
                foreach (var namespaceDeclaration in members.OfType <NamespaceDeclarationSyntax>())
                {
                    var childBuilder = builder.AddChild(namespaceDeclaration.FullSpan.Start);
                    childBuilder.SetEnd(namespaceDeclaration.FullSpan.End);

                    ProcessNodeMembers(childBuilder, namespaceDeclaration.Members);
                }
            }
예제 #2
0
        private static int CountNamespaces(SyntaxList <MemberDeclarationSyntax> members)
        {
            var result = 0;

            foreach (var namespaceDeclaration in members.OfType <NamespaceDeclarationSyntax>())
            {
                result += 1 + CountNamespaces(namespaceDeclaration.Members);
            }

            return(result);
        }
예제 #3
0
 /// <summary>
 /// Retourne les conditions sur les paramètres dans une listes d'expressions.
 /// </summary>
 /// <param name="expressions">Liste d'expressions.</param>
 /// <param name="paramètres">Les paramètres du constructeur.</param>
 /// <param name="modèleSémantique">Modèle sémantique.</param>
 /// <returns>La liste d'assignations.</returns>
 public static IEnumerable <IfStatementSyntax> TrouveConditionsParametres(SyntaxList <StatementSyntax> expressions, ParameterListSyntax paramètres, SemanticModel modèleSémantique) =>
 expressions
 .OfType <IfStatementSyntax>()
 .Where(e =>
        (e.Condition
         ?.DescendantNodes()?.OfType <IdentifierNameSyntax>()
         ?.Any(identifiant => modèleSémantique.GetSymbolInfo(identifiant).Symbol?.Kind == SymbolKind.Parameter)
         ?? false) &&
        (e.Statement
         ?.DescendantNodes()?.OfType <IdentifierNameSyntax>()
         ?.All(identifiant => modèleSémantique.GetSymbolInfo(identifiant).Symbol?.Kind != SymbolKind.Field)
         ?? false));
예제 #4
0
        ExpressionSyntax CollectCondition(ExpressionSyntax expressionSyntax, SyntaxList <SwitchLabelSyntax> labels)
        {
            //default
            if (labels.Count == 0 || labels.OfType <DefaultSwitchLabelSyntax>().Any())
            {
                return(null);
            }

            var conditionList =
                labels
                .OfType <CaseSwitchLabelSyntax>()
                .Select(l => SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, expressionSyntax, l.Value)).ToList();

            //attempt to add parentheses
            //TODO: port InsertParentheses in-full rather than a make-do (but I didn't think I had the time to do a full-port)
            for (int i = 0; i < conditionList.Count; ++i)
            {
                var cond = conditionList[i];
                if (NeedsParentheses((cond.Right)))
                {
                    conditionList[i] = cond.WithRight(SyntaxFactory.ParenthesizedExpression(cond.Right));
                }
            }

            if (conditionList.Count == 1)
            {
                return(conditionList.First());
            }

            //combine case labels
            BinaryExpressionSyntax condition = conditionList[0];

            for (int i = 1; i < conditionList.Count; ++i)
            {
                condition = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, condition, conditionList[i]);
            }
            return(condition);
        }
예제 #5
0
        private static MemberDeclarationSyntax LastField(
            SyntaxList <MemberDeclarationSyntax> members,
            FieldDeclarationSyntax fieldDeclaration
            )
        {
            var lastConst = members
                            .OfType <FieldDeclarationSyntax>()
                            .Where(f => f.Modifiers.Any(SyntaxKind.ConstKeyword))
                            .LastOrDefault();

            // Place a const after the last existing const.  If we don't have a last const
            // we'll just place the const before the first member in the type.
            if (fieldDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword))
            {
                return(lastConst);
            }

            var lastReadOnly = members
                               .OfType <FieldDeclarationSyntax>()
                               .Where(f => f.Modifiers.Any(SyntaxKind.ReadOnlyKeyword))
                               .LastOrDefault();

            var lastNormal = members
                             .OfType <FieldDeclarationSyntax>()
                             .Where(
                f =>
                !f.Modifiers.Any(SyntaxKind.ReadOnlyKeyword) &&
                !f.Modifiers.Any(SyntaxKind.ConstKeyword)
                )
                             .LastOrDefault();

            // Place a readonly field after the last readonly field if we have one.  Otherwise
            // after the last field/const.
            return(fieldDeclaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)
              ? lastReadOnly ?? lastConst ?? lastNormal
              : lastNormal ?? lastReadOnly ?? lastConst);
        }
 private static Dictionary <string, string> FetchQuestsVariables(SyntaxList <StatementSyntax> statements)
 {
     return(statements
            .OfType <LocalDeclarationStatementSyntax>()
            .Where(
                decl =>
                decl.Declaration.Variables.Count == 1 &&
                decl.Declaration.Variables[0].Initializer.Value is ObjectCreationExpressionSyntax
                )
            .ToDictionary(
                decl => decl.Declaration.Variables[0].Identifier.ValueText,
                decl => (decl.Declaration.Variables[0].Initializer.Value as ObjectCreationExpressionSyntax).Type.ToString()
                )
            );
 }
예제 #7
0
        private static SyntaxList <XmlNodeSyntax> RemoveMalformattedStandardText(SyntaxList <XmlNodeSyntax> content, string preText, string postText, ref string trailingString)
        {
            var regex = new Regex(@"^\s*" + Regex.Escape(preText) + "[^ ]+" + Regex.Escape(postText));
            var item  = content.OfType <XmlTextSyntax>().FirstOrDefault();

            if (item == null)
            {
                return(content);
            }

            int index = -1;

            foreach (var token in item.TextTokens)
            {
                index++;

                if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken))
                {
                    continue;
                }
                else if (token.IsKind(SyntaxKind.XmlTextLiteralToken))
                {
                    string value = token.ValueText.Trim(null);

                    Match match = regex.Match(value);

                    if (!match.Success)
                    {
                        return(content);
                    }
                    else if (match.Length == value.Length)
                    {
                        // Remove the token
                        var tokens = item.TextTokens;

                        while (index >= 0)
                        {
                            tokens = tokens.RemoveAt(0);
                            index--;
                        }

                        var newContent = item.WithTextTokens(tokens);

                        return(content.Replace(item, newContent));
                    }
                    else
                    {
                        // Remove the tokens before
                        var tokens = item.TextTokens;

                        while (index >= 0)
                        {
                            tokens = tokens.RemoveAt(0);
                            index--;
                        }

                        trailingString = value.Substring(match.Length);

                        var newContent = item.WithTextTokens(tokens);

                        return(content.Replace(item, newContent));
                    }
                }
                else
                {
                    return(content);
                }
            }

            return(content);
        }
예제 #8
0
 public static SourceItem[] CreateNestedItems(SyntaxList <MemberDeclarationSyntax> members, SemanticModel semanticModel) =>
 members.OfType <TypeDeclarationSyntax>()
 .Select(d => TryCreateItem(d, semanticModel))
 .Where(i => i != null)
 .ToArray() !;
예제 #9
0
        private static Task <Document> RefactorAsync(
            Document document,
            XmlElementSyntax xmlElement,
            CancellationToken cancellationToken)
        {
            SyntaxList <XmlNodeSyntax> nodes = xmlElement.Content;

            (TextSpan span1, TextSpan span2, List <TextSpan> spans) = AddParagraphToDocumentationCommentAnalyzer.FindFixableSpan(nodes, stopOnFirstMatch: false, cancellationToken: cancellationToken);

            var textChanges = new List <TextChange>();

            string newLine = nodes
                             .OfType <XmlTextSyntax>()
                             .SelectMany(f => f.TextTokens)
                             .First(f => f.IsKind(SyntaxKind.XmlTextLiteralNewLineToken))
                             .ValueText;

            string indentation = SyntaxTriviaAnalysis.DetermineIndentation(xmlElement, cancellationToken).ToString();

            string s = $"{newLine}{indentation}/// ";

            int prevEnd = -1;

            foreach (TextSpan span in spans)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (prevEnd != -1)
                {
                    textChanges.Add(TextSpan.FromBounds(prevEnd, span.Start), s);
                }

                SyntaxToken token    = xmlElement.FindToken(span.Start);
                SyntaxToken endToken = xmlElement.FindToken(span.End - 1);

                bool isMultiline = xmlElement.SyntaxTree.IsMultiLineSpan(span, cancellationToken);

                var text = "<para>";

                if (isMultiline)
                {
                    text += s;
                }

                int start  = token.SpanStart;
                int length = 0;

                if (token.IsKind(SyntaxKind.XmlTextLiteralToken) &&
                    token.ValueText[0] == ' ')
                {
                    if (prevEnd == -1)
                    {
                        start++;
                    }
                    else
                    {
                        length++;
                    }
                }

                textChanges.Add(new TextSpan(start, length), text);

                text = "";

                if (isMultiline)
                {
                    text += s;
                }

                text += "</para>";

                textChanges.Add(new TextSpan(span.End, 0), text);

                prevEnd = endToken.Span.End;
            }

            cancellationToken.ThrowIfCancellationRequested();

            return(document.WithTextChangesAsync(textChanges, cancellationToken));
        }
예제 #10
0
        Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> > CollectCondition(ExpressionSyntax expressionSyntax, SyntaxList <SwitchLabelSyntax> labels, TypeSyntax keyType)
        {
            var conditionList = new List <ExpressionSyntax>();
            var variables     = new List <VariableDeclarationSyntax>();
            var whens         = new List <ExpressionSyntax>();

            if (labels.Count == 0 || labels.OfType <DefaultSwitchLabelSyntax>().Any())
            {
                return(new Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> >(null, variables, whens));
            }

            var patternsCount = labels.Count(l => l is CasePatternSwitchLabelSyntax);

            foreach (var item in labels)
            {
                try
                {
                    if (item is CaseSwitchLabelSyntax)
                    {
                        var label = (CaseSwitchLabelSyntax)item;

                        if (label.Value is CastExpressionSyntax ce && ce.Expression.Kind() == SyntaxKind.DefaultLiteralExpression)
                        {
                            conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression,
                                                                             SyntaxFactory.BinaryExpression(SyntaxKind.IsExpression, expressionSyntax, ce.Type),
                                                                             //SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, expressionSyntax, SyntaxFactory.DefaultExpression(ce.Type))
                                                                             SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(
                                                                                                                    SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                    SyntaxFactory.IdentifierName("System.Object"),
                                                                                                                    SyntaxFactory.IdentifierName("Equals")), SyntaxFactory.ArgumentList(
                                                                                                                    SyntaxFactory.SeparatedList <ArgumentSyntax>(
                                                                                                                        new SyntaxNodeOrToken[] {
                                SyntaxFactory.Argument(expressionSyntax),
                                SyntaxFactory.Token(SyntaxKind.CommaToken),
                                SyntaxFactory.Argument(
                                    SyntaxFactory.DefaultExpression(ce.Type)
                                    )
                            })))
                                                                             ));
                        }
                        else
                        {
                            conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, expressionSyntax, label.Value));
                        }
                    }
                    else if (item is CasePatternSwitchLabelSyntax)
                    {
                        var    label   = (CasePatternSwitchLabelSyntax)item;
                        string varName = null;
                        if (label.Pattern is DeclarationPatternSyntax)
                        {
                            var declarationPattern = (DeclarationPatternSyntax)label.Pattern;
                            var designation        = declarationPattern.Designation as SingleVariableDesignationSyntax;

                            if (designation != null)
                            {
                                var declarationType = declarationPattern.Type;

                                if (declarationType.IsVar)
                                {
                                    declarationType = keyType;
                                }

                                var varDecl = SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var")).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                       SyntaxFactory.VariableDeclarator(
                                                                                                                                           SyntaxFactory.Identifier(designation.Identifier.ValueText)
                                                                                                                                           ).WithInitializer(SyntaxFactory.EqualsValueClause(patternsCount > 1 ? (ExpressionSyntax)SyntaxFactory.BinaryExpression(SyntaxKind.AsExpression, expressionSyntax, declarationType) : SyntaxFactory.CastExpression(declarationType, expressionSyntax)))
                                                                                                                                       )).WithTrailingTrivia(SyntaxFactory.Whitespace("\n")).NormalizeWhitespace();
                                varName = designation.Identifier.ValueText;
                                variables.Add(varDecl);

                                conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.IsExpression, expressionSyntax, declarationType));
                            }
                        }
                        else if (label.Pattern is ConstantPatternSyntax)
                        {
                            var constPattern = (ConstantPatternSyntax)label.Pattern;
                            conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, expressionSyntax, constPattern.Expression));
                        }

                        if (label.WhenClause != null)
                        {
                            var c = label.WhenClause.Condition;
                            if (patternsCount > 1 && NeedsParentheses(c))
                            {
                                c = SyntaxFactory.ParenthesizedExpression(c);
                            }

                            if (varName != null && patternsCount > 1)
                            {
                                whens.Add(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, SyntaxFactory.IdentifierName(varName), SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), c));
                            }
                            else
                            {
                                whens.Add(c);
                            }
                        }
                    }
                }
예제 #11
0
        private T TransformFunctionReference <T>(T node, IFunctionAnalyzationResult funcResult, FunctionReferenceTransformationResult transfromReference,
                                                 ITypeTransformationMetadata typeMetadata,
                                                 INamespaceTransformationMetadata namespaceMetadata)
            where T : SyntaxNode
        {
            var nameNode                = node.GetAnnotatedNodes(transfromReference.Annotation).OfType <SimpleNameSyntax>().First();
            var funReferenceResult      = transfromReference.AnalyzationResult;
            var bodyFuncReferenceResult = funReferenceResult as IBodyFunctionReferenceAnalyzationResult;
            var newNameNode             = nameNode
                                          .WithIdentifier(Identifier(funReferenceResult.AsyncCounterpartName))
                                          .WithTriviaFrom(nameNode);

            transfromReference.Transformed = newNameNode;

            var cancellationTokenParamName = funcResult.GetMethodOrAccessor().CancellationTokenRequired ? "cancellationToken" : null;             // TODO: remove

            // If we have a cref change the name to the async counterpart and add/update arguments
            if (bodyFuncReferenceResult == null)
            {
                if (funReferenceResult.IsCref)
                {
                    var crefNode  = (NameMemberCrefSyntax)nameNode.Parent;
                    var paramList = new List <CrefParameterSyntax>();
                    // If the cref has already the parameters set then use them
                    if (crefNode.Parameters != null)
                    {
                        paramList.AddRange(crefNode.Parameters.Parameters);
                        // If the external async counterpart has a cancellation token, add it
                        if (funReferenceResult.AsyncCounterpartFunction == null &&
                            funReferenceResult.ReferenceSymbol.Parameters.Length <
                            funReferenceResult.AsyncCounterpartSymbol.Parameters.Length)
                        {
                            paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken))));
                        }
                    }
                    else
                    {
                        // We have to add the parameters to avoid ambiguity
                        var asyncSymbol = funReferenceResult.AsyncCounterpartSymbol;
                        paramList.AddRange(asyncSymbol.Parameters
                                           .Select(o => CrefParameter(o.Type
                                                                      .CreateTypeSyntax(true, namespaceMetadata.AnalyzationResult.IsIncluded(o.Type.ContainingNamespace?.ToString())))));
                    }

                    // If the async counterpart is internal and a token is required add a token parameter
                    if (funReferenceResult.AsyncCounterpartFunction?.GetMethodOrAccessor()?.CancellationTokenRequired == true)
                    {
                        paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken))));
                    }

                    node = node.ReplaceNestedNodes(
                        crefNode.Parent as QualifiedCrefSyntax,
                        crefNode,
                        crefNode
                        .ReplaceNode(nameNode, newNameNode)
                        .WithParameters(CrefParameterList(SeparatedList(paramList))),
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                          (type, fullName) => rootNode.WithContainer(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(rootNode.Container))),
                        childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata)
                        );
                }
                else if (funReferenceResult.IsNameOf)
                {
                    node = node.ReplaceNestedNodes(
                        nameNode.Parent as MemberAccessExpressionSyntax,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                          (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))),
                        childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata)
                        );
                }
                return(node);
            }
            // If we have a method passed as an argument we need to check if we have to wrap it inside a function
            if (bodyFuncReferenceResult.AsyncDelegateArgument != null)
            {
                if (bodyFuncReferenceResult.WrapInsideFunction)
                {
                    // TODO: move to analyze step
                    var  argumentNode  = nameNode.Ancestors().OfType <ArgumentSyntax>().First();
                    var  delReturnType = (INamedTypeSymbol)bodyFuncReferenceResult.AsyncDelegateArgument.ReturnType;
                    var  returnType    = bodyFuncReferenceResult.AsyncCounterpartSymbol.ReturnType;
                    bool returnTypeMismatch;
                    if (bodyFuncReferenceResult.ReferenceFunction != null)
                    {
                        var refMethod = bodyFuncReferenceResult.ReferenceFunction as IMethodAnalyzationResult;
                        if (refMethod != null && refMethod.PreserveReturnType)
                        {
                            returnTypeMismatch = !delReturnType.Equals(returnType);   // TODO Generics
                        }
                        else if (delReturnType.IsGenericType)                         // Generic Task
                        {
                            returnTypeMismatch = delReturnType.TypeArguments.First().IsAwaitRequired(returnType);
                        }
                        else
                        {
                            returnTypeMismatch = delReturnType.IsAwaitRequired(returnType);
                        }
                    }
                    else
                    {
                        returnTypeMismatch = !delReturnType.Equals(returnType);                         // TODO Generics
                    }

                    var newArgumentExpression = argumentNode.Expression
                                                .ReplaceNestedNodes(
                        nameNode.Parent as MemberAccessExpressionSyntax,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                          (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))),
                        childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata)
                        )
                                                .WrapInsideFunction(bodyFuncReferenceResult.AsyncDelegateArgument, returnTypeMismatch,
                                                                    namespaceMetadata.TaskConflict,
                                                                    invocation => invocation.AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult));
                    node = node
                           .ReplaceNode(argumentNode.Expression, newArgumentExpression);
                }
                else
                {
                    node = node.ReplaceNestedNodes(
                        nameNode.Parent as MemberAccessExpressionSyntax,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                          (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))),
                        childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata)
                        );
                }
                return(node);
            }

            InvocationExpressionSyntax invokeNode = null;
            var isAccessor = bodyFuncReferenceResult.ReferenceSymbol.IsAccessor();

            if (!isAccessor && funReferenceResult.ReferenceNode.IsKind(SyntaxKind.InvocationExpression))
            {
                invokeNode = nameNode.Ancestors().OfType <InvocationExpressionSyntax>().First();
            }

            if (!bodyFuncReferenceResult.AwaitInvocation)
            {
                // An arrow method does not have a statement
                var statement = nameNode.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                var newNode   = (SyntaxNode)statement ?? node;

                if (invokeNode != null)
                {
                    newNode = newNode.ReplaceNestedNodes(
                        invokeNode,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode
                                                                          .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult),
                                                                          funcResult, funReferenceResult, namespaceMetadata,
                                                                          (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression)))
                        );
                }
                else if (isAccessor)
                {
                    newNode = ConvertAccessor(newNode, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult,
                                              invNode => UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                                               (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))));
                }
                else
                {
                    newNode = newNode.ReplaceNestedNodes(
                        nameNode.Parent as MemberAccessExpressionSyntax,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                          (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))),
                        childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata)
                        );
                }

                if (statement != null && !statement.IsKind(SyntaxKind.LocalFunctionStatement))
                {
                    if (bodyFuncReferenceResult.UseAsReturnValue)
                    {
                        newNode = ((StatementSyntax)newNode).ToReturnStatement();
                    }
                    node = node
                           .ReplaceNode(statement, newNode);
                }
                else
                {
                    node = (T)newNode;
                }
            }
            else
            {
                // We need to annotate the invocation node because of the AddAwait method as it needs the parent node
                var invokeAnnotation = Guid.NewGuid().ToString();
                if (isAccessor)
                {
                    node = ConvertAccessor(node, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult, invNode =>
                                           UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata,
                                                                                 (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression)))
                                           .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation))
                                           );
                }
                else
                {
                    node = node.ReplaceNestedNodes(
                        invokeNode,
                        nameNode,
                        newNameNode,
                        rootNode => UpdateTypeAndRunReferenceTransformers(rootNode
                                                                          .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult),
                                                                          funcResult, funReferenceResult, namespaceMetadata,
                                                                          (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression)))
                        .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation))
                        );
                }

                invokeNode = node.GetAnnotatedNodes(invokeAnnotation).OfType <InvocationExpressionSyntax>().First();

                var conditionalAccessNode = invokeNode.Ancestors()
                                            .TakeWhile(o => !(o is StatementSyntax))
                                            .OfType <ConditionalAccessExpressionSyntax>()
                                            .FirstOrDefault();
                if (conditionalAccessNode != null)                 // ?. syntax
                {
                    var statement = (StatementSyntax)invokeNode.Ancestors().FirstOrDefault(o => o is StatementSyntax);
                    var block     = statement?.Parent as BlockSyntax;
                    if (statement == null || block == null)
                    {
                        // TODO: convert arrow method/property/function to a normal one
                        // TODO: convert to block if there is no block
                        node = node.ReplaceNode(conditionalAccessNode,
                                                conditionalAccessNode.AddAwait(_configuration.ConfigureAwaitArgument));
                    }
                    else
                    {
                        var fnName = nameNode.Identifier.ValueText;
                        // TODO: handle name collisions
                        var variableName             = $"{char.ToLowerInvariant(fnName[0])}{fnName.Substring(1)}Task";
                        var leadingTrivia            = statement.GetLeadingTrivia();
                        var newConditionalAccessNode = ConditionalAccessExpression(
                            conditionalAccessNode.Expression,
                            invokeNode)
                                                       .WithTriviaFrom(conditionalAccessNode);
                        var localVar = LocalDeclarationStatement(
                            VariableDeclaration(
                                IdentifierName(Identifier(leadingTrivia, "var", TriviaList(Space))),
                                SingletonSeparatedList(
                                    VariableDeclarator(
                                        Identifier(TriviaList(), variableName, TriviaList(Space)))
                                    .WithInitializer(
                                        EqualsValueClause(newConditionalAccessNode.WithoutTrivia())
                                        .WithEqualsToken(Token(TriviaList(), SyntaxKind.EqualsToken, TriviaList(Space)))
                                        )
                                    )))
                                       .WithSemicolonToken(Token(TriviaList(), SyntaxKind.SemicolonToken, TriviaList(typeMetadata.EndOfLineTrivia)));
                        var index = block.Statements.IndexOf(statement);

                        var lastReturnNode = block.DescendantNodes()
                                             .Where(o => o.SpanStart >= statement.SpanStart)
                                             .OfType <ReturnStatementSyntax>()
                                             .LastOrDefault();

                        var variableAnnotation = Guid.NewGuid().ToString();
                        var newBlock           = block.ReplaceNode(conditionalAccessNode,
                                                                   conditionalAccessNode.WhenNotNull.ReplaceNode(invokeNode,
                                                                                                                 IdentifierName(variableName)
                                                                                                                 .WithAdditionalAnnotations(new SyntaxAnnotation(variableAnnotation))
                                                                                                                 .WithLeadingTrivia(conditionalAccessNode.GetLeadingTrivia())
                                                                                                                 .WithTrailingTrivia(conditionalAccessNode.GetTrailingTrivia())
                                                                                                                 ));

                        var variable = newBlock.GetAnnotatedNodes(variableAnnotation).OfType <IdentifierNameSyntax>().First();
                        newBlock = newBlock.ReplaceNode(variable, variable.AddAwait(_configuration.ConfigureAwaitArgument));

                        var ifBlock = Block()
                                      .WithOpenBraceToken(
                            Token(TriviaList(leadingTrivia), SyntaxKind.OpenBraceToken, TriviaList(typeMetadata.EndOfLineTrivia)))
                                      .WithCloseBraceToken(
                            Token(TriviaList(leadingTrivia), SyntaxKind.CloseBraceToken, TriviaList(typeMetadata.EndOfLineTrivia)))
                                      .WithStatements(new SyntaxList <StatementSyntax>()
                                                      .AddRange(newBlock.AppendIndent(typeMetadata.IndentTrivia.ToFullString()).Statements.Skip(index)));

                        var ifStatement = IfStatement(
                            BinaryExpression(
                                SyntaxKind.NotEqualsExpression,
                                IdentifierName(Identifier(TriviaList(), variableName, TriviaList(Space))),
                                LiteralExpression(SyntaxKind.NullLiteralExpression))
                            .WithOperatorToken(
                                Token(TriviaList(), SyntaxKind.ExclamationEqualsToken, TriviaList(Space))),
                            ifBlock
                            )
                                          .WithIfKeyword(
                            Token(TriviaList(leadingTrivia), SyntaxKind.IfKeyword, TriviaList(Space)))
                                          .WithCloseParenToken(
                            Token(TriviaList(), SyntaxKind.CloseParenToken, TriviaList(typeMetadata.EndOfLineTrivia)));

                        var statements = new SyntaxList <StatementSyntax>()
                                         .AddRange(newBlock.Statements.Take(index))
                                         .Add(localVar)
                                         .Add(ifStatement);
                        if (lastReturnNode?.Expression != null)
                        {
                            // Check if the variable is defined otherwise return default return type value
                            if (lastReturnNode.Expression is IdentifierNameSyntax idNode &&
                                statements.OfType <VariableDeclaratorSyntax>().All(o => o.Identifier.ToString() != idNode.Identifier.ValueText))
                            {
                                lastReturnNode = lastReturnNode.WithExpression(DefaultExpression(funcResult.GetNode().GetReturnType().WithoutTrivia()));
                            }
                            statements = statements.Add(lastReturnNode);
                        }
                        node = node.ReplaceNode(block, newBlock.WithStatements(statements));
                    }
                }
                else
                {
                    node = node.ReplaceNode(invokeNode, invokeNode.AddAwait(_configuration.ConfigureAwaitArgument));
                }
            }
            return(node);
        }
예제 #12
0
 private MemberDeclarationSyntax[] ImplementMethods(SyntaxList <MemberDeclarationSyntax> syntaxList)
 {
     return(syntaxList.OfType <MethodDeclarationSyntax>()
            .Select(x => this.ImplementMethod(x))
            .ToArray());
 }
예제 #13
0
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                var filePath = args[0];

                var code = File.ReadAllText(filePath);

                SyntaxTree tree = CSharpSyntaxTree.ParseText(code);

                var root = (CompilationUnitSyntax)tree.GetRoot();

                var members = root.Members;

                var helloWorldDeclaration = (NamespaceDeclarationSyntax)members[0];

                var classDeclaration = (ClassDeclarationSyntax)helloWorldDeclaration.Members[0];

                SyntaxList <MemberDeclarationSyntax> classMembers = classDeclaration.Members;

                var propertyList = new List <MemberDeclaration>();

                var meaningfulMembers = classMembers
                                        .OfType <PropertyDeclarationSyntax>()
                                        .Where(member => !HasMemberJsonIgnoreAttribute(member))
                                        .ToList();

                foreach (var propertySyntax in meaningfulMembers)
                {
                    var member = new MemberDeclaration();
                    member.Name = propertySyntax.Identifier.Text.ToCamelCase();

                    if (propertySyntax.Type is GenericNameSyntax)
                    {
                        member.Type = BuildPropertyTypeFromGenericNameSyntax(propertySyntax.Type as GenericNameSyntax);
                    }
                    else if (propertySyntax.Type is NullableTypeSyntax)
                    {
                        member.Type = BuildPropertyTypeFromNullableTypeSyntax(propertySyntax.Type as NullableTypeSyntax);
                    }
                    else
                    {
                        member.Type = BuildPropertyTypeFromStandardSyntax(propertySyntax.Type);
                    }

                    propertyList.Add(member);
                }
                //foreach (var memeber in propertyList)
                //{
                //    Console.WriteLine($"{memeber.Name}, Type: {memeber?.Type?.Name}, {memeber?.Type?.IsArray}");
                //}
                var modelDeclaration = new ModelDeclaration(Path.GetFileNameWithoutExtension(filePath), propertyList);
                Console.Write(JsonConvert.SerializeObject(modelDeclaration,
                                                          new JsonSerializerSettings
                {
                    DefaultValueHandling = DefaultValueHandling.Ignore,
                    ContractResolver     = new CamelCasePropertyNamesContractResolver(),
                    Formatting           = Formatting.Indented
                }));
            }
        }
 public static ImmutableArray <PropertyDeclarationSyntax> GetRecordProperties(this SyntaxList <MemberDeclarationSyntax> members)
 {
     return(members.OfType <PropertyDeclarationSyntax>()
            .Where(propSyntax => propSyntax.IsRecordViable())
            .ToImmutableArray());
 }
예제 #15
0
        Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> > CollectCondition(ExpressionSyntax expressionSyntax, SyntaxList <SwitchLabelSyntax> labels, TypeSyntax keyType)
        {
            var conditionList = new List <ExpressionSyntax>();
            var variables     = new List <VariableDeclarationSyntax>();
            var whens         = new List <ExpressionSyntax>();

            if (labels.Count == 0 || labels.OfType <DefaultSwitchLabelSyntax>().Any())
            {
                return(new Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> >(null, variables, whens));
            }

            var patternsCount = labels.Count(l => l is CasePatternSwitchLabelSyntax);

            foreach (var item in labels)
            {
                if (item is CaseSwitchLabelSyntax)
                {
                    var label = (CaseSwitchLabelSyntax)item;
                    conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, expressionSyntax, label.Value));
                }
                else if (item is CasePatternSwitchLabelSyntax)
                {
                    var    label   = (CasePatternSwitchLabelSyntax)item;
                    string varName = null;
                    if (label.Pattern is DeclarationPatternSyntax)
                    {
                        var declarationPattern = (DeclarationPatternSyntax)label.Pattern;
                        var designation        = declarationPattern.Designation as SingleVariableDesignationSyntax;

                        if (designation != null)
                        {
                            var declarationType = declarationPattern.Type;

                            if (declarationType.IsVar)
                            {
                                declarationType = keyType;
                            }

                            var varDecl = SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var")).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                   SyntaxFactory.VariableDeclarator(
                                                                                                                                       SyntaxFactory.Identifier(designation.Identifier.ValueText)
                                                                                                                                       ).WithInitializer(SyntaxFactory.EqualsValueClause(patternsCount > 1 ? (ExpressionSyntax)SyntaxFactory.BinaryExpression(SyntaxKind.AsExpression, expressionSyntax, declarationType) : SyntaxFactory.CastExpression(declarationType, expressionSyntax)))
                                                                                                                                   )).WithTrailingTrivia(SyntaxFactory.Whitespace("\n")).NormalizeWhitespace();
                            varName = designation.Identifier.ValueText;
                            variables.Add(varDecl);

                            conditionList.Add(SyntaxFactory.BinaryExpression(SyntaxKind.IsExpression, expressionSyntax, declarationType));
                        }
                    }

                    if (label.WhenClause != null)
                    {
                        var c = label.WhenClause.Condition;
                        if (patternsCount > 1 && NeedsParentheses(c))
                        {
                            c = SyntaxFactory.ParenthesizedExpression(c);
                        }

                        if (varName != null && patternsCount > 1)
                        {
                            whens.Add(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, SyntaxFactory.IdentifierName(varName), SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), c));
                        }
                        else
                        {
                            whens.Add(c);
                        }
                    }
                }
            }

            for (int i = 0; i < conditionList.Count; ++i)
            {
                var cond = conditionList[i];
                var be   = cond as BinaryExpressionSyntax;

                if (be != null)
                {
                    if (NeedsParentheses(be.Right))
                    {
                        conditionList[i] = be.WithRight(SyntaxFactory.ParenthesizedExpression(be.Right));
                    }
                }
                else
                {
                    if (NeedsParentheses(cond))
                    {
                        conditionList[i] = SyntaxFactory.ParenthesizedExpression(cond);
                    }
                }
            }

            if (conditionList.Count == 1)
            {
                return(new Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> >(conditionList.First(), variables, whens));
            }

            ExpressionSyntax condition = conditionList[0];

            for (int i = 1; i < conditionList.Count; ++i)
            {
                condition = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, condition, conditionList[i]);
            }
            return(new Tuple <ExpressionSyntax, List <VariableDeclarationSyntax>, List <ExpressionSyntax> >(condition, variables, whens));
        }