Beispiel #1
0
            static int FindMissingCommaPosition <TNode>(SeparatedSyntaxList <TNode> nodes, TNode node) where TNode : SyntaxNode
            {
                int index = nodes.IndexOf(node);

                Debug.Assert(index > 0);

                if (index <= 0)
                {
                    return(-1);
                }

                if (nodes.GetSeparator(index - 1).IsMissing)
                {
                    return(nodes[index - 1].Span.End);
                }
                else
                {
                    Debug.Assert(index < nodes.Count - 1);

                    if (index == nodes.Count - 1)
                    {
                        return(-1);
                    }

                    Debug.Assert(nodes.GetSeparator(index).IsMissing);

                    if (!nodes.GetSeparator(index).IsMissing)
                    {
                        return(-1);
                    }

                    return(node.Span.End);
                }
            }
        public void SeparatedSyntaxList_TwoItems_WithTrailingComma()
        {
            var expression1  = SyntaxFacts.ParseExpression("test1");
            var comma1       = SyntaxFacts.ParseToken(",");
            var expression2  = SyntaxFacts.ParseExpression("test2");
            var comma2       = SyntaxFacts.ParseToken(",");
            var nodeOrTokens = new SyntaxNodeOrToken[] { expression1, comma1, expression2, comma2 };
            var list         = new SeparatedSyntaxList <NameExpressionSyntax>(nodeOrTokens);

            Assert.Equal(2, list.Count);
            Assert.Equal(new[] { expression1, expression2 }, list);
            Assert.Equal(new[] { comma1, comma2 }, list.GetSeparators());
            Assert.Equal(comma1, list.GetSeparator(0));
            Assert.Equal(comma2, list.GetSeparator(1));
        }
Beispiel #3
0
        public override SyntaxNode VisitParameterList(ParameterListSyntax node)
        {
            ParameterListSyntax originalNode = node;
            //node = (ParameterListSyntax)base.VisitParameterList(node); can't - see below

            int i = 0;

            foreach (ParameterSyntax parameter in originalNode.Parameters)
            {
                if (RemoveParameter(parameter))
                {
                    node = node.Update(
                        node.OpenParenToken,
                        node.Parameters.RemoveAt(i),
                        node.CloseParenToken);
                    continue;
                }
                // Can't use base.VisitParameterList(node) to inner-process all parameters because some that are destined
                // to be stripped may cause processing errors (e.g. because they contain a generic type reference to a type
                // parameter that is being eliminated). Therefore, do the work ourselves using base.VisitParameter(parameter)
                // on each.
                bool        hasTrailingSeparator = i < node.Parameters.Count - 1;
                bool        hasLeadingSeparator  = i > 0;
                SyntaxToken originalSeparator    = hasTrailingSeparator
                    ? node.Parameters.GetSeparator(i)
                    : (hasLeadingSeparator
                        ? node.Parameters.GetSeparator(i - 1)
                        : SyntaxFactory.MissingToken(SyntaxKind.CommaToken));
                SeparatedSyntaxList <ParameterSyntax> parameters = node.Parameters
                                                                   .RemoveAt(i)
                                                                   .Insert(i, (ParameterSyntax)base.VisitParameter(parameter).WithTriviaFrom(node.Parameters[i]));
                if (hasTrailingSeparator)
                {
                    parameters = parameters.ReplaceSeparator(parameters.GetSeparator(i), originalSeparator);
                }
                else if (hasLeadingSeparator)
                {
                    parameters = parameters.ReplaceSeparator(parameters.GetSeparator(i - 1), originalSeparator);
                }
                node = node.Update(
                    node.OpenParenToken,
                    parameters,
                    node.CloseParenToken);
                i++;
            }

            return(node);
        }
Beispiel #4
0
        private static void AnalyzeEnumMembers(SyntaxNodeAnalysisContext context, SeparatedSyntaxList <EnumMemberDeclarationSyntax> members)
        {
            int count          = members.Count;
            int separatorCount = members.SeparatorCount;

            for (int i = 0; i < count; i++)
            {
                EnumMemberDeclarationSyntax enumMember = members[i];

                if (AnalyzeLeading(context, enumMember))
                {
                    continue;
                }

                TrailingAnalysis?analysis = AnalyzeTrailing(enumMember);

                if (analysis == null &&
                    (separatorCount == count || i < count - 1))
                {
                    analysis = AnalyzeTrailing(members.GetSeparator(i));
                }

                ReportDiagnostic(context, analysis);
            }
        }
        public static bool IsApplicableSpan(InitializerExpressionSyntax initializer, TextSpan span)
        {
            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            if (!expressions.Any())
            {
                return(true);
            }

            if (span.IsEmpty)
            {
                if (expressions.Count == expressions.SeparatorCount &&
                    TextSpan.FromBounds(expressions.GetSeparator(expressions.Count - 1).Span.End, initializer.CloseBraceToken.SpanStart).Contains(span))
                {
                    return(true);
                }

                TextSpan span2 = TextSpan.FromBounds(expressions.Last().Span.End, initializer.CloseBraceToken.SpanStart);

                if (span2.Length > 0)
                {
                    span2 = new TextSpan(span2.Start + 1, span2.Length - 1);

                    if (span2.Contains(span))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #6
0
        private Doc PrintSeparatedSyntaxList <T>(
            SeparatedSyntaxList <T> list,
            Func <T, Doc> printFunc,
            Doc afterSeparator)
            where T : SyntaxNode
        {
            var parts = new Parts();

            for (var x = 0; x < list.Count; x++)
            {
                parts.Push(printFunc(list[x]));
                // TODO 1 this keeps trailing commas, that should probably be an option, for let's keep what appears to make finding "bad" code formats easier
                if (x < list.SeparatorCount)
                {
                    parts.Push(
                        this.PrintSyntaxToken(
                            list.GetSeparator(x),
                            afterSeparator
                            )
                        );
                }
            }

            return(parts.Count == 0 ? Doc.Null : Concat(parts));
        }
        private static bool AreSeparatedWithEmptyLine(SeparatedSyntaxList <EnumMemberDeclarationSyntax> members)
        {
            int count = members.Count;

            if (members.SeparatorCount < count - 1)
            {
                return(false);
            }

            for (int i = 1; i < count; i++)
            {
                if (!members[i].GetLeadingTrivia().Any(SyntaxKind.EndOfLineTrivia))
                {
                    return(false);
                }
            }

            for (int i = 0; i < count - 1; i++)
            {
                if (!members.GetSeparator(i).TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia))
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #8
0
        private static Task <Document> WrapAndIndentEachNodeInListAsync <TNode>(
            Document document,
            SeparatedSyntaxList <TNode> nodes,
            CancellationToken cancellationToken) where TNode : SyntaxNode
        {
            return(document.WithTextChangesAsync(GetTextChanges().Where(f => f != default), cancellationToken));

            IEnumerable <TextChange> GetTextChanges()
            {
                string newText = SyntaxTriviaAnalysis.GetEndOfLine(nodes[0]).ToString() + GetIndentation();

                yield return(GetTextChange(nodes[0].GetFirstToken().GetPreviousToken(), nodes[0]));

                for (int i = 1; i < nodes.Count; i++)
                {
                    yield return(GetTextChange(nodes.GetSeparator(i - 1), nodes[i]));
                }

                TextChange GetTextChange(SyntaxToken token, SyntaxNode node)
                {
                    TextSpan span = TextSpan.FromBounds(token.Span.End, node.SpanStart);

                    return((node.SyntaxTree.IsSingleLineSpan(span))
                        ? new TextChange(span, newText)
                        : default);
        private static void AnalyzeInitializerExpression(SyntaxNodeAnalysisContext context)
        {
            var initializer = (InitializerExpressionSyntax)context.Node;

            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            ExpressionSyntax expression = expressions.SingleOrDefault(shouldThrow: false);

            if (expression == null)
            {
                return;
            }

            if (initializer.SpanContainsDirectives())
            {
                return;
            }

            if (initializer.IsSingleLine(includeExteriorTrivia: false))
            {
                return;
            }

            if (!expression.IsSingleLine())
            {
                return;
            }

            if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(expression))
            {
                return;
            }

            if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(initializer.OpenBraceToken))
            {
                return;
            }

            if (!initializer.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            if (expressions.SeparatorCount == 1 &&
                !SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(expressions.GetSeparator(0)))
            {
                return;
            }

            if (!initializer.OpenBraceToken.GetPreviousToken().TrailingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.RemoveNewlinesFromInitializerWithSingleLineExpression, initializer);
        }
Beispiel #10
0
        public override SyntaxNode VisitVariableDeclaration(VariableDeclarationSyntax node)
        {
            node = (VariableDeclarationSyntax)base.VisitVariableDeclaration(node);

            TypeSyntax type = node.Type;
            SeparatedSyntaxList <VariableDeclaratorSyntax> declarations = node.Variables;

            List <VariableDeclaratorSyntax> listOfVariables = new List <VariableDeclaratorSyntax>();

            List <SyntaxToken> listOfSeperators = new List <SyntaxToken>();

            if (transformKind == TransformKind.DefaultInitAllVars)
            {
                foreach (VariableDeclaratorSyntax decl in declarations)
                {
                    if (decl.Initializer == null)
                    {
                        TypeSyntax newType = type;

                        if (newType.HasLeadingTrivia)
                        {
                            newType = newType.WithLeadingTrivia(new SyntaxTriviaList());
                        }

                        if (newType.HasTrailingTrivia)
                        {
                            newType = newType.WithLeadingTrivia(new SyntaxTriviaList());
                        }

                        SyntaxTrivia            whiteSpaceTrivia = SyntaxFactory.Whitespace(" ");
                        DefaultExpressionSyntax defaultExpr      = SyntaxFactory.DefaultExpression(newType);
                        EqualsValueClauseSyntax equalsClause     = SyntaxFactory.EqualsValueClause(SyntaxFactory.Token(SyntaxFactory.TriviaList(whiteSpaceTrivia), SyntaxKind.EqualsToken, SyntaxFactory.TriviaList(whiteSpaceTrivia)), defaultExpr);

                        VariableDeclaratorSyntax newDecl = SyntaxFactory.VariableDeclarator(decl.Identifier, decl.ArgumentList, equalsClause);
                        listOfVariables.Add(newDecl);
                    }
                    else
                    {
                        listOfVariables.Add(decl);
                    }
                }

                for (int i = 0; i < declarations.SeparatorCount; i++)
                {
                    SyntaxToken seperator = declarations.GetSeparator(i);
                    listOfSeperators.Add(SyntaxFactory.Token(seperator.LeadingTrivia, seperator.Kind(), seperator.TrailingTrivia));
                }

                SeparatedSyntaxList <VariableDeclaratorSyntax> seperatedSyntaxList = SyntaxFactory.SeparatedList(listOfVariables, listOfSeperators);

                return(SyntaxFactory.VariableDeclaration(type, seperatedSyntaxList));
            }

            return(node);
        }
Beispiel #11
0
        private static List <SyntaxToken> GetSeparators <T>(SeparatedSyntaxList <T> arguments, int numSeparatorsToSkip = 0) where T : SyntaxNode
        {
            var separators = new List <SyntaxToken>();

            for (int i = 0; i < arguments.SeparatorCount - numSeparatorsToSkip; i++)
            {
                separators.Add(arguments.GetSeparator(i));
            }

            return(separators);
        }
        public void SeparatedSyntaxList_OneItem()
        {
            var expression   = SyntaxFacts.ParseExpression("test");
            var nodeOrTokens = new SyntaxNodeOrToken[] { expression };
            var list         = new SeparatedSyntaxList <NameExpressionSyntax>(nodeOrTokens);

            Assert.Equal(1, list.Count);
            Assert.Equal(expression, Assert.Single(list));
            Assert.Empty(list.GetSeparators());
            Assert.Equal(null, list.GetSeparator(0));
        }
        public void SeparatedSyntaxList_OneItem_WithTrailingComma()
        {
            var expression   = SyntaxFacts.ParseExpression("test");
            var comma        = SyntaxFacts.ParseToken(",");
            var nodeOrTokens = new SyntaxNodeOrToken[] { expression, comma };
            var list         = new SeparatedSyntaxList <NameExpressionSyntax>(nodeOrTokens);

            Assert.Equal(1, list.Count);
            Assert.Equal(expression, Assert.Single(list));
            Assert.Equal(new[] { comma }, list.GetSeparators());
            Assert.Equal(comma, list.GetSeparator(0));
        }
Beispiel #14
0
        private static int GetItemIndexByPosition<TNode>(SeparatedSyntaxList<TNode> list, int position)
            where TNode : SyntaxNode
        {
            for (var i = list.SeparatorCount - 1; i >= 0; i--)
            {
                if (position > list.GetSeparator(i).SpanStart)
                {
                    return i + 1;
                }
            }

            return 0;
        }
        private TypeArgumentListSyntax ParameterToArgumentListSyntax(TypeParameterListSyntax typeParameters)
        {
            var list = new SeparatedSyntaxList <TypeSyntax>();

            list = list.AddRange(typeParameters.Parameters.Select(p => SyntaxFactory.ParseName(p.ToString()).WithTriviaFrom(p)));

            for (int i = 0; i < list.SeparatorCount; i++)
            {
                var separator = list.GetSeparator(i);
                // Make sure the parameter list looks nice
                list = list.ReplaceSeparator(separator, separator.WithTrailingTrivia(SyntaxFactory.Whitespace(" ")));
            }

            return(SyntaxFactory.TypeArgumentList(list));
        }
Beispiel #16
0
        private static TypeArgumentListSyntax ParameterToArgumentListSyntax(TypeParameterListSyntax typeParameters)
        {
            var list = new SeparatedSyntaxList <TypeSyntax>();

            list = list.AddRange(typeParameters.Parameters.Select(p => SyntaxFactory.ParseName(p.ToString()).WithTriviaFrom(p)));

            for (int i = 0; i < list.SeparatorCount; i++)
            {
                var separator = list.GetSeparator(i);
                // Make sure the parameter list looks nice
                // Cannot use ReplaceSeparator due to dotnet/roslyn#2630: https://github.com/dotnet/roslyn/issues/2630
                list = SyntaxFactory.SeparatedList <TypeSyntax>(list.GetWithSeparators().Replace(separator, separator.WithTrailingTrivia(SyntaxFactory.Space)));
            }

            return(SyntaxFactory.TypeArgumentList(list));
        }
        private static async Task <Document> SortEnumMembersAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            SpecialType enumSpecialType = semanticModel.GetDeclaredSymbol(enumDeclaration).EnumUnderlyingType.SpecialType;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> newMembers = members
                                                                           .OrderBy(f => GetConstantValue(f, semanticModel, cancellationToken), EnumValueComparer.GetInstance(enumSpecialType))
                                                                           .ToSeparatedSyntaxList();

            if (AreSeparatedWithEmptyLine(members))
            {
                for (int i = 0; i < newMembers.Count; i++)
                {
                    newMembers = newMembers.ReplaceAt(i, newMembers[i].TrimLeadingTrivia());
                }

                for (int i = 0; i < newMembers.Count - 1; i++)
                {
                    SyntaxToken separator = newMembers.GetSeparator(i);

                    newMembers = newMembers.ReplaceSeparator(
                        separator,
                        separator.TrimTrailingTrivia().AppendToTrailingTrivia(new SyntaxTrivia[] { NewLine(), NewLine() }));
                }
            }

            if (newMembers.SeparatorCount == members.SeparatorCount - 1)
            {
                SyntaxNodeOrTokenList newMembersWithSeparators = newMembers.GetWithSeparators();

                newMembersWithSeparators = newMembersWithSeparators.Add(CommaToken());

                newMembers = newMembersWithSeparators.ToSeparatedSyntaxList <EnumMemberDeclarationSyntax>();
            }

            MemberDeclarationSyntax newNode = enumDeclaration
                                              .WithMembers(newMembers)
                                              .WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(enumDeclaration, newNode, cancellationToken).ConfigureAwait(false));
        }
Beispiel #18
0
        public static SelectionResult Create <TNode>(SeparatedSyntaxList <TNode> list, TextSpan span) where TNode : SyntaxNode
        {
            SeparatedSyntaxList <TNode> .Enumerator en = list.GetEnumerator();

            if (en.MoveNext())
            {
                int i = 0;

                while (span.Start >= en.Current.FullSpan.End &&
                       en.MoveNext())
                {
                    i++;
                }

                if (span.Start >= en.Current.FullSpan.Start &&
                    span.Start <= en.Current.SpanStart)
                {
                    int j = i;

                    while (span.End > GetLastIndex(en.Current, j) &&
                           en.MoveNext())
                    {
                        j++;
                    }

                    if (span.End >= en.Current.Span.End &&
                        span.End <= GetLastIndex(en.Current, j))
                    {
                        return(new SelectionResult(i, j));
                    }
                }
            }

            return(Fail);

            int GetLastIndex(TNode node, int i)
            {
                if (i < list.Count - 1 ||
                    list.Count == list.SeparatorCount)
                {
                    return(list.GetSeparator(i).FullSpan.End);
                }

                return(node.FullSpan.End);
            }
        }
            /// <summary>
            /// Given the cursor position, find which argument is active.
            /// This will be useful to later find which parameter should be highlighted.
            /// </summary>
            private static int TryGetArgumentIndex(SeparatedSyntaxList <ArgumentSyntax> arguments, int position)
            {
                if (arguments.Count == 0)
                {
                    return(-1);
                }

                for (var i = 0; i < arguments.Count - 1; i++)
                {
                    // `$$,` points to the argument before the separator
                    // but `,$$` points to the argument following the separator
                    if (position <= arguments.GetSeparator(i).Span.Start)
                    {
                        return(i);
                    }
                }

                return(arguments.Count - 1);
            }
Beispiel #20
0
        private static void AnalyzeInitializerExpression(SyntaxNodeAnalysisContext context)
        {
            var initializer = (InitializerExpressionSyntax)context.Node;

            SeparatedSyntaxList<ExpressionSyntax> expressions = initializer.Expressions;

            if (!expressions.Any())
                return;

            int count = expressions.Count;

            if (count != expressions.SeparatorCount)
                return;

            SyntaxToken token = expressions.GetSeparator(count - 1);

            Debug.Assert(!token.IsMissing);

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantCommaInInitializer, token);
        }
        private static Tuple <List <T>, List <SyntaxToken> > GetNodesAndSeparators <T>(this SeparatedSyntaxList <T> separatedList) where T : SyntaxNode
        {
            Debug.Assert(separatedList.Count == separatedList.SeparatorCount ||
                         separatedList.Count == separatedList.SeparatorCount + 1);

            var nodes      = new List <T>(separatedList.Count);
            var separators = new List <SyntaxToken>(separatedList.SeparatorCount);

            for (int i = 0; i < separatedList.Count; i++)
            {
                nodes.Add(separatedList[i]);

                if (i < separatedList.SeparatorCount)
                {
                    separators.Add(separatedList.GetSeparator(i));
                }
            }

            return(Tuple.Create(nodes, separators));
        }
        private static void AnalyzeDeclaration<TMember>(
            SyntaxNodeAnalysisContext context,
            SeparatedSyntaxList<TMember> members,
            SyntaxToken openBrace,
            SyntaxToken closeBrace) where TMember : MemberDeclarationSyntax
        {
            if (members.Any())
            {
                AnalyzeStart(context, members[0], openBrace);

                int count = members.SeparatorCount;

                SyntaxNodeOrToken nodeOrToken = (count == members.Count)
                    ? members.GetSeparator(count - 1)
                    : members.Last();

                AnalyzeEnd(context, nodeOrToken, closeBrace);
            }
            else
            {
                AnalyzeEmptyBraces(context, openBrace, closeBrace);
            }
        }
 private static void DetectMultiLineArgumentList <T>(SeparatedSyntaxList <T> arguments, out bool multiline, out int indent) where T : SyntaxNode
 {
     multiline = false;
     indent    = 0;
     for (int j = 0; j < arguments.Count - 1; j++)
     {
         foreach (SyntaxTrivia trivia in arguments.GetSeparator(j).TrailingTrivia)
         {
             if (trivia.IsKind(SyntaxKind.EndOfLineTrivia))
             {
                 multiline = true;
             }
             else if (trivia.IsKind(SyntaxKind.WhitespaceTrivia))
             {
                 int length = trivia.ToString().Length;
                 if (length >= 4) // kind of a hack
                 {
                     indent = Math.Max(indent, length);
                 }
             }
         }
     }
 }
        private static void Analyze <TNode>(
            SyntaxNodeAnalysisContext context,
            SyntaxNodeOrToken openNodeOrToken,
            SeparatedSyntaxList <TNode> nodes) where TNode : SyntaxNode
        {
            TNode first = nodes.FirstOrDefault();

            if (first == null)
            {
                return;
            }

            TextSpan span = nodes.GetSpan(includeExteriorTrivia: false);

            if (span.IsSingleLine(first.SyntaxTree))
            {
                SyntaxTriviaList trailing = openNodeOrToken.GetTrailingTrivia();

                if (!IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                {
                    return;
                }

                int indentationLength = GetIncreasedIndentationLength(openNodeOrToken.Parent);

                if (indentationLength == 0)
                {
                    return;
                }

                if (ShouldFixIndentation(first.GetLeadingTrivia(), indentationLength))
                {
                    ReportDiagnostic();
                }
            }
            else
            {
                TextLineCollection lines = null;

                IndentationAnalysis indentationAnalysis = IndentationAnalysis.Create(openNodeOrToken.Parent);

                int indentationLength = indentationAnalysis.IncreasedIndentationLength;

                if (indentationLength == 0)
                {
                    return;
                }

                for (int i = nodes.Count - 1; i >= 0; i--)
                {
                    SyntaxTriviaList trailing = (i == 0)
                        ? openNodeOrToken.GetTrailingTrivia()
                        : nodes.GetSeparator(i - 1).TrailingTrivia;

                    if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                    {
                        if (ShouldFixIndentation(nodes[i].GetLeadingTrivia(), indentationLength))
                        {
                            ReportDiagnostic();
                            break;
                        }
                    }
                    else
                    {
                        if (nodes.Count > 1 &&
                            ShouldWrapAndIndent(context.Node, i))
                        {
                            ReportDiagnostic();
                            break;
                        }

                        if (nodes.Count == 1 &&
                            first.IsKind(SyntaxKind.Argument))
                        {
                            var argument = (ArgumentSyntax)(SyntaxNode)first;

                            LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= first.SyntaxTree.GetText().Lines);

                            if (lambdaBlock.Block != null)
                            {
                                SyntaxToken      token   = lambdaBlock.Token;
                                SyntaxTriviaList leading = token.LeadingTrivia;

                                if (leading.Any())
                                {
                                    SyntaxTrivia trivia = leading.Last();

                                    if (trivia.IsWhitespaceTrivia() &&
                                        trivia.SpanStart == lambdaBlock.LineStartIndex &&
                                        trivia.Span.Length != indentationAnalysis.IndentationLength)
                                    {
                                        ReportDiagnostic();
                                        break;
                                    }
                                }
                                else if (lambdaBlock.LineStartIndex == token.SpanStart)
                                {
                                    ReportDiagnostic();
                                    break;
                                }

                                return;
                            }
                        }

                        if (lines == null)
                        {
                            lines = first.SyntaxTree.GetText().Lines;
                        }

                        int lineIndex = lines.IndexOf(span.Start);
                        if (lineIndex < lines.Count - 1)
                        {
                            int lineStartIndex = lines[lineIndex + 1].Start;

                            if (first.Span.Contains(lineStartIndex))
                            {
                                SyntaxToken token = first.FindToken(lineStartIndex);

                                if (!token.IsKind(SyntaxKind.None))
                                {
                                    SyntaxTriviaList leading = token.LeadingTrivia;

                                    if (leading.Any())
                                    {
                                        if (leading.FullSpan.Contains(lineStartIndex))
                                        {
                                            SyntaxTrivia trivia = leading.Last();

                                            if (trivia.IsWhitespaceTrivia() &&
                                                trivia.SpanStart == lineStartIndex &&
                                                trivia.Span.Length != indentationLength)
                                            {
                                                ReportDiagnostic();
                                                break;
                                            }
                                        }
                                    }
                                    else if (lineStartIndex == token.SpanStart)
                                    {
                                        ReportDiagnostic();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticDescriptors.FixFormattingOfList,
                    Location.Create(first.SyntaxTree, nodes.Span),
                    GetTitle());
            }
        private static void AnalyzePragmaWarningDirectiveTrivia(SyntaxNodeAnalysisContext context)
        {
            var directive = (PragmaWarningDirectiveTriviaSyntax)context.Node;

            SeparatedSyntaxList <ExpressionSyntax> errorCodes = directive.ErrorCodes;

            int codeCount = errorCodes.Count;

            if (codeCount == 0)
            {
                return;
            }

            if (codeCount == errorCodes.SeparatorCount)
            {
                if (!errorCodes.GetSeparator(codeCount - 1).TrailingTrivia.IsEmptyOrWhitespace())
                {
                    return;
                }
            }
            else if (!errorCodes.Last().GetTrailingTrivia().IsEmptyOrWhitespace())
            {
                return;
            }

            if (IsSuppressingThisAnalyzer(errorCodes))
            {
                return;
            }

            SyntaxTrivia trivia = directive.ParentTrivia;

            if (!trivia.TryGetContainingList(out SyntaxTriviaList list))
            {
                return;
            }

            int count = list.Count;

            if (count == 1)
            {
                return;
            }

            int index = list.IndexOf(trivia);

            if (index == count - 1)
            {
                return;
            }

            int i = index - 1;

            while (i >= 0 &&
                   list[i].IsWhitespaceOrEndOfLineTrivia())
            {
                i--;
            }

            if (i >= 0)
            {
                SyntaxTrivia directiveTrivia = list[i];

                if (directiveTrivia.IsKind(SyntaxKind.PragmaWarningDirectiveTrivia))
                {
                    var previousDirective = (PragmaWarningDirectiveTriviaSyntax)directiveTrivia.GetStructure();

                    if (!IsSuppressingThisAnalyzer(previousDirective.ErrorCodes))
                    {
                        return;
                    }
                }
            }

            i = index + 1;

            while (i < count &&
                   list[i].IsWhitespaceOrEndOfLineTrivia())
            {
                i++;
            }

            if (i == count)
            {
                return;
            }

            if (!list[i].IsKind(SyntaxKind.PragmaWarningDirectiveTrivia))
            {
                return;
            }

            if (list[i].GetStructure() is not PragmaWarningDirectiveTriviaSyntax nextDirective)
            {
                return;
            }

            SyntaxToken disableOrRestoreKeyword = directive.DisableOrRestoreKeyword;

            SyntaxKind keywordKind = disableOrRestoreKeyword.Kind();

            if (keywordKind != nextDirective.DisableOrRestoreKeyword.Kind())
            {
                return;
            }

            if (keywordKind == SyntaxKind.DisableKeyword &&
                IsSuppressingThisAnalyzer(nextDirective.ErrorCodes))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.MergePreprocessorDirectives, directive);
        }
Beispiel #26
0
        internal static List <TextChange> GetFixListChanges <TNode>(
            SyntaxNode containingNode,
            SyntaxNodeOrToken openNodeOrToken,
            IReadOnlyList <TNode> nodes,
            ListFixMode fixMode = ListFixMode.Fix,
            CancellationToken cancellationToken = default) where TNode : SyntaxNode
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(containingNode, cancellationToken);

            string increasedIndentation = indentationAnalysis.GetIncreasedIndentation();

            bool isSingleLine;
            SeparatedSyntaxList <TNode> separatedList = default;

            if (nodes is SyntaxList <TNode> list)
            {
                isSingleLine = list.IsSingleLine(includeExteriorTrivia: false, cancellationToken: cancellationToken);
            }
            else
            {
                separatedList = (SeparatedSyntaxList <TNode>)nodes;

                isSingleLine = separatedList.IsSingleLine(
                    includeExteriorTrivia: false,
                    cancellationToken: cancellationToken);
            }

            if (isSingleLine &&
                fixMode == ListFixMode.Fix)
            {
                TNode node = nodes[0];

                SyntaxTriviaList leading = node.GetLeadingTrivia();

                TextSpan span = (leading.Any() && leading.Last().IsWhitespaceTrivia())
                    ? leading.Last().Span
                    : new TextSpan(node.SpanStart, 0);

                return(new List <TextChange>()
                {
                    new TextChange(span, increasedIndentation)
                });
            }

            var textChanges              = new List <TextChange>();
            TextLineCollection lines     = null;
            string             endOfLine = DetermineEndOfLine(containingNode).ToString();

            for (int i = 0; i < nodes.Count; i++)
            {
                SyntaxToken token;
                if (i == 0)
                {
                    token = (openNodeOrToken.IsNode)
                        ? openNodeOrToken.AsNode().GetLastToken()
                        : openNodeOrToken.AsToken();
                }
                else
                {
                    token = (list == default)
                        ? separatedList.GetSeparator(i - 1)
                        : list[i - 1].GetLastToken();
                }

                SyntaxTriviaList trailing = token.TrailingTrivia;
                TNode            node     = nodes[i];
                var indentationAdded      = false;

                if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                {
                    SyntaxTrivia last = node.GetLeadingTrivia().LastOrDefault();

                    if (last.IsWhitespaceTrivia())
                    {
                        if (last.Span.Length == increasedIndentation.Length)
                        {
                            continue;
                        }

                        textChanges.Add(last.Span, increasedIndentation);
                    }
                    else
                    {
                        textChanges.Add(new TextSpan(node.SpanStart, 0), increasedIndentation);
                    }

                    indentationAdded = true;
                }
                else
                {
                    if (nodes.Count == 1 &&
                        node is ArgumentSyntax argument)
                    {
                        LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= argument.SyntaxTree.GetText().Lines);

                        if (lambdaBlock.Block != null)
                        {
                            increasedIndentation = indentationAnalysis.Indentation.ToString();
                        }
                    }

                    if ((nodes.Count > 1 || fixMode == ListFixMode.Wrap) &&
                        ShouldWrapAndIndent(containingNode, i))
                    {
                        textChanges.Add(
                            (trailing.Any() && trailing.Last().IsWhitespaceTrivia())
                                ? trailing.Last().Span
                                : new TextSpan(token.FullSpan.End, 0),
                            endOfLine);

                        textChanges.Add(new TextSpan(node.FullSpan.Start, 0), increasedIndentation);

                        indentationAdded = true;
                    }
                }

                ImmutableArray <IndentationInfo> indentations = FindIndentations(node, node.Span).ToImmutableArray();

                if (!indentations.Any())
                {
                    continue;
                }

                LambdaBlock lambdaBlock2 = GetLambdaBlock(node, lines ??= node.SyntaxTree.GetText().Lines);

                bool isLambdaBlockWithOpenBraceAtEndOfLine = lambdaBlock2.Token == indentations.Last().Token;

                int baseIndentationLength = (isLambdaBlockWithOpenBraceAtEndOfLine)
                    ? indentations.Last().Span.Length
                    : indentations[0].Span.Length;

                for (int j = indentations.Length - 1; j >= 0; j--)
                {
                    IndentationInfo indentationInfo = indentations[j];

                    if (indentationAdded &&
                        node is ArgumentSyntax argument &&
                        (argument.Expression as AnonymousFunctionExpressionSyntax)?.Block != null)
                    {
                        indentationAdded = false;
                    }

                    string replacement = increasedIndentation;

                    if (indentationAdded)
                    {
                        replacement += indentationAnalysis.GetSingleIndentation();
                    }

                    if ((j > 0 || isLambdaBlockWithOpenBraceAtEndOfLine) &&
                        indentationInfo.Span.Length > baseIndentationLength)
                    {
                        replacement += indentationInfo.ToString().Substring(baseIndentationLength);
                    }

                    if (indentationInfo.Span.Length != replacement.Length)
                    {
                        textChanges.Add(indentationInfo.Span, replacement);
                    }
                }
            }

            FormattingVerifier.VerifyChangedSpansAreWhitespace(containingNode, textChanges);

            return(textChanges);
        }
Beispiel #27
0
        private string GetSeparator(int idx)
        {
            var separator = separatedSyntaxList.GetSeparator(idx);

            return($"{Helper.GetNewLineIfExist(separator.LeadingTrivia)}{separator.ToString()}{Helper.GetNewLineIfExist(separator.TrailingTrivia)}");
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsEnabled(CodeFixIdentifiers.AddMissingComma))
            {
                return;
            }

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

            ExpressionSyntax expression = root.FindNode(context.Span).FirstAncestorOrSelf <ExpressionSyntax>();

            if (expression == null)
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.SyntaxErrorCharExpected:
                {
                    if (!Settings.IsEnabled(CodeFixIdentifiers.AddMissingComma))
                    {
                        break;
                    }

                    if (!expression.IsParentKind(SyntaxKind.ArrayInitializerExpression))
                    {
                        break;
                    }

                    var initializer = (InitializerExpressionSyntax)expression.Parent;

                    SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

                    int index = expressions.IndexOf(expression);

                    Debug.Assert(index > 0);

                    if (index <= 0)
                    {
                        break;
                    }

                    int newCommaIndex = expression.Span.End;

                    if (expressions.GetSeparator(index - 1).IsMissing)
                    {
                        newCommaIndex = expressions[index - 1].Span.End;
                    }
                    else
                    {
                        Debug.Assert(index < expressions.Count - 1);

                        if (index == expressions.Count - 1)
                        {
                            break;
                        }

                        Debug.Assert(expressions.GetSeparator(index).IsMissing);

                        if (!expressions.GetSeparator(index).IsMissing)
                        {
                            break;
                        }

                        newCommaIndex = expression.Span.End;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add missing comma",
                        cancellationToken =>
                        {
                            var textChange = new TextChange(new TextSpan(newCommaIndex, 0), ",");
                            return(context.Document.WithTextChangeAsync(textChange, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        private static TypeArgumentListSyntax ParameterToArgumentListSyntax(TypeParameterListSyntax typeParameters)
        {
            var list = new SeparatedSyntaxList<TypeSyntax>();
            list = list.AddRange(typeParameters.Parameters.Select(p => SyntaxFactory.ParseName(p.ToString()).WithTriviaFrom(p)));

            for (int i = 0; i < list.SeparatorCount; i++)
            {
                // Make sure the parameter list looks nice
                var separator = list.GetSeparator(i);
                list = list.ReplaceSeparator(separator, separator.WithTrailingTrivia(SyntaxFactory.Space));
            }

            return SyntaxFactory.TypeArgumentList(list);
        }
        private static Task <Document> FormatInitializerOnSingleLineAsync(
            Document document,
            InitializerExpressionSyntax initializer,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            SyntaxToken trailingComma = initializer.Expressions.GetTrailingSeparator();

            if (trailingComma == default)
            {
                return(SyntaxFormatter.ToSingleLineAsync(document, initializer, cancellationToken));
            }

            SyntaxNode parent = initializer.Parent;

            initializer = initializer
                          .ReplaceWhitespace(SyntaxFactory.ElasticMarker, TextSpan.FromBounds(initializer.FullSpan.Start, initializer.Span.End))
                          .WithFormatterAnnotation();

            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            expressions = expressions.ReplaceAt(0, expressions.First().WithTrailingTrivia(SyntaxFactory.Space));

            expressions = expressions.ReplaceSeparator(expressions.GetSeparator(0), SyntaxFactory.MissingToken(SyntaxKind.CommaToken));

            initializer = initializer.WithExpressions(expressions);

            SyntaxNode newParent = GetNewParent();

            return(document.ReplaceNodeAsync(parent, newParent, cancellationToken));

            SyntaxNode GetNewParent()
            {
                switch (parent)
                {
                case ObjectCreationExpressionSyntax objectCreation:
                {
                    objectCreation = objectCreation.WithInitializer(initializer);

                    ArgumentListSyntax argumentList = objectCreation.ArgumentList;

                    if (argumentList != null)
                    {
                        return(objectCreation.WithArgumentList(argumentList.WithoutTrailingTrivia()));
                    }
                    else
                    {
                        return(objectCreation.WithType(objectCreation.Type.WithoutTrailingTrivia()));
                    }
                }

                case ArrayCreationExpressionSyntax arrayCreation:
                {
                    return(arrayCreation
                           .WithInitializer(initializer)
                           .WithType(arrayCreation.Type.WithoutTrailingTrivia()));
                }

                case ImplicitArrayCreationExpressionSyntax implicitArrayCreation:
                {
                    return(implicitArrayCreation
                           .WithInitializer(initializer)
                           .WithCloseBracketToken(implicitArrayCreation.CloseBracketToken.WithoutTrailingTrivia()));
                }
                }

                throw new InvalidOperationException();
            }
        }
        private static void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context)
        {
            var enumDeclaration = (EnumDeclarationSyntax)context.Node;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            int count = members.Count;

            if (count <= 1)
            {
                return;
            }

            SyntaxTree                  tree = enumDeclaration.SyntaxTree;
            CancellationToken           cancellationToken = context.CancellationToken;
            EnumMemberDeclarationSyntax member;
            bool?isSingleLine;
            bool?isPreviousSingleLine = null;

            for (int i = 1; i < count; i++, isPreviousSingleLine = isSingleLine)
            {
                member       = members[i];
                isSingleLine = null;
                SyntaxToken      commaToken     = members.GetSeparator(i - 1);
                SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia;

                if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                {
                    continue;
                }

                SyntaxTriviaList leadingTrivia = member.GetLeadingTrivia();

                (bool emptyOrWhitespaceTrivia, bool documentationComment, bool emptyLine) = AnalyzeLeadingTrivia(leadingTrivia);

                if (documentationComment)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarationAndDocumentationComment, trailingTrivia.Last());
                    continue;
                }

                if (!emptyOrWhitespaceTrivia &&
                    !emptyLine)
                {
                    continue;
                }

                if ((isSingleLine ?? (isSingleLine = tree.IsSingleLineSpan(member.Span, cancellationToken)).Value) &&
                    (isPreviousSingleLine ?? tree.IsSingleLineSpan(members[i - 1].Span, cancellationToken)))
                {
                    if (emptyLine)
                    {
                        ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineDeclarationsOfSameKind, leadingTrivia[0]);
                    }
                    else if (emptyOrWhitespaceTrivia)
                    {
                        ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarations, trailingTrivia.Last());
                    }
                }
                else if (emptyOrWhitespaceTrivia)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trailingTrivia.Last());
                }
            }
        }