private static void HandleSyntaxTreeAxtion(SyntaxTreeAnalysisContext context)
        {
            var root = context.Tree.GetRoot(context.CancellationToken);

            var fileHeader = FileHeaderHelpers.ParseFileHeader(root);
            if (fileHeader.IsMissing || fileHeader.IsMalformed)
            {
                // this will be handled by SA1633
                return;
            }

            var copyrightElement = fileHeader.GetElement("copyright");
            if (copyrightElement == null)
            {
                // this will be handled by SA1634
                return;
            }

            var companyAttribute = copyrightElement.Attribute("company");
            if (string.IsNullOrWhiteSpace(companyAttribute?.Value))
            {
                var location = fileHeader.GetElementLocation(context.Tree, copyrightElement);
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
            }
        }
        private static void HandleOpenBracketToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            bool firstInLine = token.IsFirstInLine();
            bool precededBySpace = true;
            bool ignorePrecedingSpaceProblem = false;

            if (!firstInLine)
            {
                precededBySpace = token.IsPrecededByWhitespace(context.CancellationToken);

                // ignore if handled by SA1026
                ignorePrecedingSpaceProblem = precededBySpace && token.GetPreviousToken().IsKind(SyntaxKind.NewKeyword);
            }

            bool followedBySpace = token.IsFollowedByWhitespace();
            bool lastInLine = token.IsLastInLine();

            if (!firstInLine && precededBySpace && !ignorePrecedingSpaceProblem && !IsPartOfIndexInitializer(token))
            {
                // Opening square bracket must {not be preceded} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemovePreceding, "not be preceded"));
            }

            if (!lastInLine && followedBySpace)
            {
                // Opening square bracket must {not be followed} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveFollowing, "not be followed"));
            }
        }
        private static void AnalyzeOpenBrace(SyntaxTreeAnalysisContext context, SyntaxToken openBrace)
        {
            var prevToken = openBrace.GetPreviousToken();
            var triviaList = TriviaHelper.MergeTriviaLists(prevToken.TrailingTrivia, openBrace.LeadingTrivia);

            var done = false;
            var eolCount = 0;
            for (var i = triviaList.Count - 1; !done && (i >= 0); i--)
            {
                switch (triviaList[i].Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    break;
                case SyntaxKind.EndOfLineTrivia:
                    eolCount++;
                    break;
                default:
                    if (triviaList[i].IsDirective)
                    {
                        // These have a built-in end of line
                        eolCount++;
                    }

                    done = true;
                    break;
                }
            }

            if (eolCount < 2)
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, openBrace.GetLocation()));
        }
        private static void HandleSingleLineComment(SyntaxTreeAnalysisContext context, SyntaxTrivia singleLineComment)
        {
            int index = 0;

            // PERF: Explicitly cast to IReadOnlyList so we only box once.
            IReadOnlyList<SyntaxTrivia> list = TriviaHelper.GetContainingTriviaList(singleLineComment, out index);
            var firstNonWhiteSpace = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(list);

            // When we encounter a block of single line comments, we only want to raise this diagnostic
            // on the first or last line.  This ensures that whitespace in code commented out using
            // the Comment Selection option in Visual Studio will not raise the diagnostic for every
            // blank line in the code which is commented out.
            bool isFirst = index == firstNonWhiteSpace;
            if (!isFirst)
            {
                // This is -2 because we need to go back past the end of line trivia as well.
                var lastNonWhiteSpace = TriviaHelper.IndexOfTrailingWhitespace(list) - 2;
                if (index != lastNonWhiteSpace)
                {
                    return;
                }
            }

            if (IsNullOrWhiteSpace(singleLineComment.ToString(), 2))
            {
                var diagnostic = Diagnostic.Create(Descriptor, singleLineComment.GetLocation());
                context.ReportDiagnostic(diagnostic);
            }
        }
        private static void HandleOpenBracketToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            bool firstInLine = token.IsFirstInLine();
            bool precededBySpace = true;
            bool ignorePrecedingSpaceProblem = false;

            if (!firstInLine)
            {
                precededBySpace = token.IsPrecededByWhitespace();

                // ignore if handled by SA1026
                ignorePrecedingSpaceProblem = precededBySpace && token.GetPreviousToken().IsKind(SyntaxKind.NewKeyword);
            }

            bool followedBySpace = token.IsFollowedByWhitespace();
            bool lastInLine = token.IsLastInLine();

            if (!firstInLine && precededBySpace && !ignorePrecedingSpaceProblem && !lastInLine && followedBySpace)
            {
                // Opening square bracket must {neither preceded nor followed} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), "neither preceded nor followed"));
            }
            else if (!firstInLine && precededBySpace && !ignorePrecedingSpaceProblem)
            {
                // Opening square bracket must {not be preceded} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), "not be preceded"));
            }
            else if (!lastInLine && followedBySpace)
            {
                // Opening square bracket must {not be followed} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), "not be followed"));
            }
        }
        private static void HandleOpenBracketToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            if (!token.Parent.IsKind(SyntaxKind.AttributeList))
            {
                return;
            }

            if (token.IsLastInLine())
            {
                return;
            }

            if (!token.HasTrailingTrivia)
            {
                return;
            }

            if (!token.TrailingTrivia[0].IsKind(SyntaxKind.WhitespaceTrivia))
            {
                return;
            }

            // Opening attribute brackets must not be followed by a space.
            context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingCodeFixProvider.RemoveFollowing));
        }
        private static void HandleCloseBracketToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            if (!token.Parent.IsKind(SyntaxKind.AttributeList))
            {
                return;
            }

            if (token.IsFirstInLine())
            {
                return;
            }

            SyntaxToken precedingToken = token.GetPreviousToken();
            if (!precedingToken.HasTrailingTrivia)
            {
                return;
            }

            if (!precedingToken.TrailingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia))
            {
                return;
            }

            // Closing attribute brackets must not be preceded by a space.
            context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveImmediatePreceding));
        }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);

            var descentNodes = syntaxRoot.DescendantNodes(descendIntoChildren: node => node != null && !node.IsKind(SyntaxKind.ClassDeclaration));

            string foundClassName = null;
            bool isPartialClass = false;

            foreach (var node in descentNodes)
            {
                if (node.IsKind(SyntaxKind.ClassDeclaration))
                {
                    ClassDeclarationSyntax classDeclaration = node as ClassDeclarationSyntax;
                    if (foundClassName != null)
                    {
                        if (isPartialClass && foundClassName == classDeclaration.Identifier.Text)
                        {
                            continue;
                        }

                        var location = NamedTypeHelpers.GetNameOrIdentifierLocation(node);
                        if (location != null)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
                        }
                    }
                    else
                    {
                        foundClassName = classDeclaration.Identifier.Text;
                        isPartialClass = classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword);
                    }
                }
            }
        }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
            {
                // Handling of empty documents is now the responsibility of the analyzers
                return;
            }

            var firstToken = context.Tree.GetRoot().GetFirstToken(includeZeroWidth: true);

            if (firstToken.HasLeadingTrivia)
            {
                var leadingTrivia = firstToken.LeadingTrivia;

                var firstNonBlankLineTriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(leadingTrivia);
                switch (firstNonBlankLineTriviaIndex)
                {
                case 0:
                    // no blank lines
                    break;

                case -1:
                    // only blank lines
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, leadingTrivia.Span)));
                    break;

                default:
                    var textSpan = TextSpan.FromBounds(leadingTrivia[0].Span.Start, leadingTrivia[firstNonBlankLineTriviaIndex].Span.Start);
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, textSpan)));
                    break;
                }
            }
        }
        // If you want a full implementation of this analyzer with system tests and a code fix, go to
        // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1120CommentsMustContainText.cs
        private void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);

            foreach (var node in root.DescendantTrivia())
            {
                switch (node.Kind())
                {
                    case SyntaxKind.SingleLineCommentTrivia:
                        // Remove the leading // from the comment
                        var commentText = node.ToString().Substring(2);
                        int index = 0;

                        var list = TriviaHelper.GetContainingTriviaList(node, out index);
                        bool isFirst = IsFirstComment(list, index);
                        bool isLast = IsLastComment(list, index);

                        if (string.IsNullOrWhiteSpace(commentText) && (isFirst || isLast))
                        {
                            var diagnostic = Diagnostic.Create(Rule, node.GetLocation());
                            context.ReportDiagnostic(diagnostic);
                        }

                        break;
                }
            }
        }
        private static void HandleSyntaxTreeAxtion(SyntaxTreeAnalysisContext context)
        {
            var root = context.Tree.GetRoot(context.CancellationToken);

            var fileHeader = FileHeaderHelpers.ParseFileHeader(root);
            if (fileHeader.IsMissing || fileHeader.IsMalformed)
            {
                // this will be handled by SA1633
                return;
            }

            var copyrightElement = fileHeader.GetElement("copyright");
            if (copyrightElement == null)
            {
                // this will be handled by SA1634
                return;
            }

            var fileAttribute = copyrightElement.Attribute("file");
            if (fileAttribute == null)
            {
                // this will be handled by SA1637
                return;
            }

            var fileName = Path.GetFileName(context.Tree.FilePath);

            if (!fileAttribute.Value.Equals(fileName, StringComparison.Ordinal))
            {
                var location = fileHeader.GetElementLocation(context.Tree, copyrightElement);
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
            }
        }
Exemplo n.º 12
0
        private static void CheckTrivias(IEnumerable<SyntaxTrivia> trivias, SyntaxTreeAnalysisContext context)
        {
            var shouldReport = true;
            foreach (var trivia in trivias)
            {
                // comment start is checked because of  https://github.com/dotnet/roslyn/issues/10003

                if (!trivia.ToFullString().TrimStart().StartsWith("/**", StringComparison.Ordinal) &&
                    trivia.IsKind(SyntaxKind.MultiLineCommentTrivia))
                {
                    CheckMultilineComment(context, trivia);
                    shouldReport = true;
                    continue;
                }

                if (!trivia.ToFullString().TrimStart().StartsWith("///", StringComparison.Ordinal) &&
                    trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) &&
                    shouldReport)
                {
                    var triviaContent = GetTriviaContent(trivia);
                    if (!IsCode(triviaContent))
                    {
                        continue;
                    }

                    context.ReportDiagnostic(Diagnostic.Create(Rule, trivia.GetLocation()));
                    shouldReport = false;
                }
            }
        }
 private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     if (context.Tree.Options.DocumentationMode != DocumentationMode.Diagnose)
     {
         context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Tree.GetLocation(new TextSpan(0, 0))));
     }
 }
 public void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     if (context.Tree.Options.DocumentationMode == DocumentationMode.None)
     {
         Volatile.Write(ref this.documentationAnalysisDisabled, true);
     }
 }
        private static void HandleLessThanToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            switch (token.Parent.Kind())
            {
            case SyntaxKind.TypeArgumentList:
            case SyntaxKind.TypeParameterList:
                break;

            default:
                // not a generic bracket
                return;
            }

            bool firstInLine = token.IsFirstInLine();
            bool precededBySpace = firstInLine || token.IsPrecededByWhitespace();
            bool followedBySpace = token.IsFollowedByWhitespace();

            if (!firstInLine && precededBySpace)
            {
                // Opening generic brackets must not be {preceded} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), "preceded"));
            }

            if (followedBySpace)
            {
                // Opening generic brackets must not be {followed} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), "followed"));
            }
        }
        private static void HandleOpenBraceToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            bool followedBySpace = token.IsFollowedByWhitespace();

            if (token.Parent is InterpolationSyntax)
            {
                if (followedBySpace)
                {
                    // Opening curly bracket must{} be {followed} by a space.
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), " not", "followed"));
                }

                return;
            }

            bool precededBySpace = token.IsFirstInLine() || token.IsPrecededByWhitespace();

            if (!precededBySpace)
            {
                // Opening curly bracket must{} be {preceded} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), string.Empty, "preceded"));
            }

            if (!token.IsLastInLine() && !followedBySpace)
            {
                // Opening curly bracket must{} be {followed} by a space.
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), string.Empty, "followed"));
            }
        }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var firstToken = context.Tree.GetRoot().GetFirstToken(includeZeroWidth: true);

            if (firstToken.HasLeadingTrivia)
            {
                var leadingTrivia = firstToken.LeadingTrivia;

                var firstNonBlankLineTriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(leadingTrivia);
                switch (firstNonBlankLineTriviaIndex)
                {
                case 0:
                    // no blank lines
                    break;

                case -1:
                    // only blank lines
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, leadingTrivia.Span)));
                    break;

                default:
                    var textSpan = TextSpan.FromBounds(leadingTrivia[0].Span.Start, leadingTrivia[firstNonBlankLineTriviaIndex].Span.Start);
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, textSpan)));
                    break;
                }
            }
        }
            public static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings)
            {
                var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);

                var firstTypeDeclaration = GetFirstTypeDeclaration(syntaxRoot);
                if (firstTypeDeclaration == null)
                {
                    return;
                }

                if (firstTypeDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword))
                {
                    return;
                }

                string suffix;
                var fileName = FileNameHelpers.GetFileNameAndSuffix(context.Tree.FilePath, out suffix);
                var expectedFileName = FileNameHelpers.GetConventionalFileName(firstTypeDeclaration, settings.DocumentationRules.FileNamingConvention);

                if (string.Compare(fileName, expectedFileName, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    if (settings.DocumentationRules.FileNamingConvention == FileNamingConvention.StyleCop
                        && string.Compare(fileName, FileNameHelpers.GetSimpleFileName(firstTypeDeclaration), StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        return;
                    }

                    var properties = ImmutableDictionary.Create<string, string>()
                        .Add(ExpectedFileNameKey, expectedFileName + suffix);

                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, firstTypeDeclaration.Identifier.GetLocation(), properties));
                }
            }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);

            var descentNodes = syntaxRoot.DescendantNodes(descendIntoChildren: node => node != null && !node.IsKind(SyntaxKind.ClassDeclaration));

            bool foundNode = false;

            foreach (var node in descentNodes)
            {
                if (node.IsKind(SyntaxKind.NamespaceDeclaration))
                {
                    if (foundNode)
                    {
                        var location = NamedTypeHelpers.GetNameOrIdentifierLocation(node);
                        if (location != null)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, location));
                        }
                    }
                    else
                    {
                        foundNode = true;
                    }
                }
            }
        }
        private static void AnalyzeTree(SyntaxTreeAnalysisContext context)
        {
            var tree = context.Tree;
            var emptyStrings = tree.GetRoot().DescendantTokens()
                .Where(x => x.RawKind == (int)SyntaxKind.StringLiteralToken
                       && string.IsNullOrEmpty(x.ValueText)).ToList();

            foreach (var s in emptyStrings)
            {
                // Skip if it is inside method parameter definition or as case switch or a attribute argument.
                if (s.Parent.Parent.Parent.IsKind(SyntaxKind.Parameter) ||
                    s.Parent.Parent.IsKind(SyntaxKind.CaseSwitchLabel) ||
                    s.Parent.Parent.IsKind(SyntaxKind.AttributeArgument))
                {
                    continue;
                }

                FieldDeclarationSyntax fieldSyntax = s.Parent.Parent.Parent.Parent.Parent as FieldDeclarationSyntax;
                if (fieldSyntax != null && fieldSyntax.DescendantTokens().Any(x => x.IsKind(SyntaxKind.ConstKeyword)))
                {
                    continue;
                }

                var line = s.SyntaxTree.GetLineSpan(s.FullSpan);
                var diagnostic = Diagnostic.Create(Rule, s.GetLocation());

                context.ReportDiagnostic(diagnostic);
            }
        }
 private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);
     foreach (var token in root.DescendantTokens().Where(t => t.IsKind(SyntaxKind.OpenParenToken)))
     {
         HandleOpenParenToken(context, token);
     }
 }
 private void AnalyzeType(SyntaxTreeAnalysisContext context, TypeDeclarationSyntax typeDeclaration)
 {
     var numberOfFields = typeDeclaration.Members.Count(member => member is FieldDeclarationSyntax);
     if (numberOfFields > MaximumNumberOfFields)
     {
         context.ReportDiagnostic(Diagnostic.Create(Rule, typeDeclaration.Identifier.GetLocation(), typeDeclaration.Identifier.Text, numberOfFields));
     }
 }
        private void HandleDotToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            this.HandleMemberAccessSymbol(context, token);
        }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            byte[] preamble = context.Tree.Encoding.GetPreamble();

            if (!IsUtf8Preamble(preamble))
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, TextSpan.FromBounds(0, 0))));
            }
        }
 private async void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     var root = await context.Tree.GetRootAsync();
     var typeDeclarations = root.DescendantNodesAndSelf().OfType<TypeDeclarationSyntax>();
     foreach (var typeDeclaration in typeDeclarations)
     {
         AnalyzeType(context, typeDeclaration);
     }
 }
        private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var diagnostics = RenameTrackingTaggerProvider.GetDiagnosticsAsync(context.Tree, DiagnosticDescriptor, context.CancellationToken).WaitAndGetResult(context.CancellationToken);

            foreach (var diagnostic in diagnostics)
            {
                context.ReportDiagnostic(diagnostic);
            }
        }
        private static void HandleIncrementDecrementToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            switch (token.Parent.Kind())
            {
            case SyntaxKind.PreIncrementExpression:
            case SyntaxKind.PreDecrementExpression:
                if (token.HasTrailingTrivia)
                {
                    string symbolName;
                    if (token.IsKind(SyntaxKind.MinusMinusToken))
                    {
                        symbolName = "Decrement";
                    }
                    else
                    {
                        symbolName = "Increment";
                    }

                    // {Increment|Decrement} symbol '{++|--}' must not be {followed} by a space.
                    var properties = TokenSpacingProperties.RemoveFollowing;
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties, symbolName, token.Text, "followed"));
                }

                break;

            case SyntaxKind.PostIncrementExpression:
            case SyntaxKind.PostDecrementExpression:
                SyntaxToken previousToken = token.GetPreviousToken();
                if (!previousToken.IsMissing && previousToken.HasTrailingTrivia)
                {
                    string symbolName;
                    if (token.IsKind(SyntaxKind.MinusMinusToken))
                    {
                        symbolName = "Decrement";
                    }
                    else
                    {
                        symbolName = "Increment";
                    }

                    // {Increment|Decrement} symbol '{++|--}' must not be {preceded} by a space.
                    var properties = TokenSpacingProperties.RemovePreceding;
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties, symbolName, token.Text, "preceded"));
                }

                break;

            default:
                return;
            }
        }
        private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia)
        {
            if (trivia.ToFullString().IndexOf('\t') < 0)
            {
                return;
            }

            // Tabs must not be used.
            context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation()));
        }
Exemplo n.º 29
0
 private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     // Find source files with documentation comment diagnostics turned off.
     if (context.Tree.Options.DocumentationMode != DocumentationMode.Diagnose)
     {
         // For all such files, produce a diagnostic.
         var diagnostic = Diagnostic.Create(Rule, Location.None, Path.GetFileName(context.Tree.FilePath));
         context.ReportDiagnostic(diagnostic);
     }
 }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            byte[] preamble = context.Tree.Encoding.GetPreamble();

            if (!IsUtf8Preamble(preamble))
            {
                ImmutableDictionary<string, string> properties = ImmutableDictionary<string, string>.Empty.SetItem(EncodingProperty, context.Tree.Encoding?.WebName ?? "<null>");
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, TextSpan.FromBounds(0, 0)), properties));
            }
        }
Exemplo n.º 31
0
        private static void HandleOpenParenToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            if (token.IsLastInLine())
            {
                // ignore open parenthesis when last on line.
                return;
            }

            var prevToken         = token.GetPreviousToken();
            var leadingTriviaList = TriviaHelper.MergeTriviaLists(prevToken.TrailingTrivia, token.LeadingTrivia);

            var isFirstOnLine = false;

            if (prevToken.GetLineSpan().EndLinePosition.Line < token.GetLineSpan().StartLinePosition.Line)
            {
                var done = false;
                for (var i = leadingTriviaList.Count - 1; !done && (i >= 0); i--)
                {
                    switch (leadingTriviaList[i].Kind())
                    {
                    case SyntaxKind.WhitespaceTrivia:
                        break;

                    case SyntaxKind.EndOfLineTrivia:
                        isFirstOnLine = true;
                        done          = true;
                        break;

                    default:
                        done = true;
                        break;
                    }
                }
            }

            bool haveLeadingSpace;
            bool partOfUnaryExpression;
            bool startOfIndexer;

            var prevTokenIsOpenParen = prevToken.IsKind(SyntaxKind.OpenParenToken);

            switch (token.Parent.Kind())
            {
            case SyntaxKind.IfStatement:
            case SyntaxKind.DoStatement:
            case SyntaxKind.WhileStatement:
            case SyntaxKind.ForStatement:
            case SyntaxKind.ForEachStatement:
            case SyntaxKind.SwitchStatement:
            case SyntaxKind.FixedStatement:
            case SyntaxKind.LockStatement:
            case SyntaxKind.UsingStatement:
            case SyntaxKind.CatchDeclaration:
            case SyntaxKind.CatchFilterClause:
                haveLeadingSpace = true;
                break;

            case SyntaxKind.ArgumentList:
            case SyntaxKind.AttributeArgumentList:
            case SyntaxKind.CheckedExpression:
            case SyntaxKind.UncheckedExpression:
            case SyntaxKind.ConstructorConstraint:
            case SyntaxKind.DefaultExpression:
            case SyntaxKind.SizeOfExpression:
            case SyntaxKind.TypeOfExpression:
                haveLeadingSpace = false;
                break;

            case SyntaxKind.ParenthesizedExpression:
                partOfUnaryExpression = prevToken.Parent is PrefixUnaryExpressionSyntax;
                startOfIndexer        = prevToken.IsKind(SyntaxKind.OpenBracketToken);
                var partOfCastExpression = prevToken.IsKind(SyntaxKind.CloseParenToken) && prevToken.Parent.IsKind(SyntaxKind.CastExpression);

                haveLeadingSpace = !partOfUnaryExpression && !startOfIndexer && !partOfCastExpression;
                break;

            case SyntaxKind.CastExpression:
                partOfUnaryExpression = prevToken.Parent is PrefixUnaryExpressionSyntax;
                startOfIndexer        = prevToken.IsKind(SyntaxKind.OpenBracketToken);
                var consecutiveCast     = prevToken.IsKind(SyntaxKind.CloseParenToken) && prevToken.Parent.IsKind(SyntaxKind.CastExpression);
                var partOfInterpolation = prevToken.IsKind(SyntaxKind.OpenBraceToken) && prevToken.Parent.IsKind(SyntaxKind.Interpolation);

                haveLeadingSpace = !partOfUnaryExpression && !startOfIndexer && !consecutiveCast && !partOfInterpolation;
                break;

            case SyntaxKind.ParameterList:
                var partOfLambdaExpression = token.Parent.Parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression);
                haveLeadingSpace = partOfLambdaExpression;
                break;

            default:
                haveLeadingSpace = false;
                break;
            }

            // Ignore spacing before if another opening parenthesis is before this.
            // That way the first opening parenthesis will report any spacing errors.
            if (!prevTokenIsOpenParen)
            {
                var hasLeadingComment = (leadingTriviaList.Count > 0) && leadingTriviaList.Last().IsKind(SyntaxKind.MultiLineCommentTrivia);
                var hasLeadingSpace   = (leadingTriviaList.Count > 0) && leadingTriviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia);

                if (!isFirstOnLine && !hasLeadingComment && (haveLeadingSpace != hasLeadingSpace))
                {
                    var properties = ImmutableDictionary.Create <string, string>()
                                     .Add(LocationKey, LocationPreceding)
                                     .Add(ActionKey, haveLeadingSpace ? ActionInsert : ActionRemove);

                    context.ReportDiagnostic(Diagnostic.Create(haveLeadingSpace ? DescriptorPreceded : DescriptorNotPreceded, token.GetLocation(), properties.ToImmutableDictionary()));
                }
            }

            if (token.IsFollowedByWhitespace())
            {
                var properties = ImmutableDictionary.Create <string, string>()
                                 .Add(LocationKey, LocationFollowing)
                                 .Add(ActionKey, ActionRemove);

                context.ReportDiagnostic(Diagnostic.Create(DescriptorNotFollowed, token.GetLocation(), properties.ToImmutableDictionary()));
            }
        }
Exemplo n.º 32
0
        private static void HandleCloseParenToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            bool precededBySpace = token.IsFirstInLine() || token.IsPrecededByWhitespace(context.CancellationToken);
            bool followedBySpace = token.IsFollowedByWhitespace();
            bool lastInLine      = token.IsLastInLine();
            bool precedesStickyCharacter;
            bool allowEndOfLine = false;

            bool suppressFollowingSpaceError = false;

            SyntaxToken nextToken = token.GetNextToken();

            switch (nextToken.Kind())
            {
            case SyntaxKind.OpenParenToken:
            case SyntaxKind.CloseParenToken:
            case SyntaxKind.OpenBracketToken:
            case SyntaxKind.CloseBracketToken:
            case SyntaxKind.SemicolonToken:
            case SyntaxKind.CommaToken:
            case SyntaxKind.DoubleQuoteToken:
                precedesStickyCharacter = true;
                break;

            case SyntaxKind.GreaterThanToken:
                precedesStickyCharacter = nextToken.Parent.IsKind(SyntaxKind.TypeArgumentList);
                break;

            case SyntaxKind.QuestionToken:
                if (nextToken.Parent.IsKind(SyntaxKind.ConditionalAccessExpression))
                {
                    // allow a space for this case, but only if the ')' character is the last on the line
                    allowEndOfLine          = true;
                    precedesStickyCharacter = true;
                }
                else
                {
                    precedesStickyCharacter = false;
                }

                break;

            case SyntaxKind.PlusToken:
                precedesStickyCharacter = nextToken.Parent.IsKind(SyntaxKind.UnaryPlusExpression);

                // this will be reported as SA1022
                suppressFollowingSpaceError = precedesStickyCharacter;
                break;

            case SyntaxKind.MinusToken:
                precedesStickyCharacter = nextToken.Parent.IsKind(SyntaxKind.UnaryMinusExpression);

                // this will be reported as SA1021
                suppressFollowingSpaceError = precedesStickyCharacter;
                break;

            case SyntaxKind.DotToken:
            case SyntaxKind.MinusGreaterThanToken:
                // allow a space for these cases, but only if the ')' character is the last on the line
                allowEndOfLine          = true;
                precedesStickyCharacter = true;
                break;

            case SyntaxKind.ColonToken:
                bool requireSpace =
                    nextToken.Parent.IsKind(SyntaxKind.ConditionalExpression) ||
                    nextToken.Parent.IsKind(SyntaxKind.BaseConstructorInitializer) ||
                    nextToken.Parent.IsKind(SyntaxKind.ThisConstructorInitializer);
                precedesStickyCharacter = !requireSpace;
                break;

            case SyntaxKind.PlusPlusToken:
            case SyntaxKind.MinusMinusToken:
                precedesStickyCharacter     = true;
                suppressFollowingSpaceError = false;
                break;

            case SyntaxKind.CloseBraceToken:
                precedesStickyCharacter = nextToken.Parent is InterpolationSyntax;
                break;

            default:
                precedesStickyCharacter = false;
                break;
            }

            switch (token.Parent.Kind())
            {
            case SyntaxKind.CastExpression:
                precedesStickyCharacter = true;
                break;

            default:
                break;
            }

            foreach (var trivia in token.TrailingTrivia)
            {
                if (trivia.IsKind(SyntaxKind.EndOfLineTrivia))
                {
                    break;
                }
                else if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) ||
                         trivia.IsKind(SyntaxKind.MultiLineCommentTrivia))
                {
                    lastInLine = false;
                    precedesStickyCharacter = false;
                    break;
                }
            }

            if (precededBySpace)
            {
                // Closing parenthesis should{ not} be {preceded} by a space.
                var properties = token.IsFirstInLine()
                    ? TokenSpacingProperties.RemovePreceding
                    : TokenSpacingProperties.RemoveImmediatePreceding;
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties, " not", "preceded"));
            }

            if (!suppressFollowingSpaceError)
            {
                if (!precedesStickyCharacter && !followedBySpace && !lastInLine)
                {
                    // Closing parenthesis should{} be {followed} by a space.
                    var properties = TokenSpacingProperties.InsertFollowing;
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties, string.Empty, "followed"));
                }
                else if (precedesStickyCharacter && followedBySpace && (!lastInLine || !allowEndOfLine))
                {
                    // Closing parenthesis should{ not} be {followed} by a space.
                    var properties = TokenSpacingProperties.RemoveFollowing;
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties, " not", "followed"));
                }
            }
        }
Exemplo n.º 33
0
 protected abstract void Recurse(
     SyntaxTreeAnalysisContext context,
     Dictionary <int, int> preferredOrder,
     ReportDiagnostic severity,
     SyntaxNode root);
        /// <summary>
        /// Scans an entire document for lines with trailing whitespace.
        /// </summary>
        /// <param name="context">The context that provides the document to scan.</param>
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var root = context.Tree.GetRoot(context.CancellationToken);
            var text = context.Tree.GetText(context.CancellationToken);

            SyntaxTrivia previousTrivia = default(SyntaxTrivia);

            foreach (var trivia in root.DescendantTrivia(descendIntoTrivia: true))
            {
                switch (trivia.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    if (previousTrivia.Span.End < trivia.SpanStart)
                    {
                        // Some token appeared between the previous trivia and the end of the line.
                        break;
                    }

                    if (previousTrivia.IsKind(SyntaxKind.WhitespaceTrivia))
                    {
                        // Report warning for whitespace token followed by the end of a line
                        context.ReportDiagnostic(Diagnostic.Create(Descriptor, previousTrivia.GetLocation()));
                    }
                    else if (previousTrivia.IsKind(SyntaxKind.PreprocessingMessageTrivia))
                    {
                        TextSpan trailinMessageWhitespace = FindTrailingWhitespace(text, previousTrivia.Span);
                        if (!trailinMessageWhitespace.IsEmpty)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, trailinMessageWhitespace)));
                        }
                    }

                    break;

                case SyntaxKind.SingleLineCommentTrivia:
                    TextSpan trailingWhitespace = FindTrailingWhitespace(text, trivia.Span);
                    if (!trailingWhitespace.IsEmpty)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, trailingWhitespace)));
                    }

                    break;

                case SyntaxKind.MultiLineCommentTrivia:
                    var line = text.Lines.GetLineFromPosition(trivia.Span.Start);
                    while (line.End <= trivia.Span.End)
                    {
                        trailingWhitespace = FindTrailingWhitespace(text, line.Span);
                        if (!trailingWhitespace.IsEmpty)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, trailingWhitespace)));
                        }

                        if (line.EndIncludingLineBreak == text.Length)
                        {
                            // We've reached the end of the document.
                            break;
                        }

                        line = text.Lines.GetLineFromPosition(line.EndIncludingLineBreak + 1);
                    }

                    break;

                case SyntaxKind.SingleLineDocumentationCommentTrivia:
                case SyntaxKind.MultiLineDocumentationCommentTrivia:
                    SyntaxToken previousToken = default(SyntaxToken);
                    foreach (var token in trivia.GetStructure().DescendantTokens(descendIntoTrivia: true))
                    {
                        if (token.IsKind(SyntaxKind.XmlTextLiteralNewLineToken) &&
                            previousToken.IsKind(SyntaxKind.XmlTextLiteralToken) &&
                            previousToken.Span.End == token.SpanStart)
                        {
                            trailingWhitespace = FindTrailingWhitespace(text, previousToken.Span);
                            if (!trailingWhitespace.IsEmpty)
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, trailingWhitespace)));
                            }
                        }

                        previousToken = token;
                    }

                    break;

                default:
                    break;
                }

                previousTrivia = trivia;
            }

            if (previousTrivia.IsKind(SyntaxKind.WhitespaceTrivia) && previousTrivia.Span.End == previousTrivia.SyntaxTree.Length)
            {
                // Report whitespace at the end of the last line in the document
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, previousTrivia.GetLocation()));
            }
        }
Exemplo n.º 35
0
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);

            foreach (var token in root.DescendantTokens())
            {
                switch (token.Kind())
                {
                case SyntaxKind.AwaitKeyword:
                case SyntaxKind.CaseKeyword:
                case SyntaxKind.CatchKeyword:
                case SyntaxKind.FixedKeyword:
                case SyntaxKind.ForKeyword:
                case SyntaxKind.ForEachKeyword:
                case SyntaxKind.FromKeyword:
                case SyntaxKind.GroupKeyword:
                case SyntaxKind.IfKeyword:
                case SyntaxKind.InKeyword:
                case SyntaxKind.IntoKeyword:
                case SyntaxKind.JoinKeyword:
                case SyntaxKind.LetKeyword:
                case SyntaxKind.LockKeyword:
                case SyntaxKind.OrderByKeyword:
                case SyntaxKind.OutKeyword:
                case SyntaxKind.RefKeyword:
                case SyntaxKind.SelectKeyword:
                case SyntaxKind.SwitchKeyword:
                case SyntaxKind.UsingKeyword:
                case SyntaxKind.WhereKeyword:
                case SyntaxKind.WhileKeyword:
                case SyntaxKind.YieldKeyword:
                    HandleRequiredSpaceToken(ref context, token);
                    break;

                case SyntaxKind.CheckedKeyword:
                case SyntaxKind.UncheckedKeyword:
                    if (token.GetNextToken().IsKind(SyntaxKind.OpenBraceToken))
                    {
                        HandleRequiredSpaceToken(ref context, token);
                    }
                    else
                    {
                        HandleDisallowedSpaceToken(ref context, token);
                    }

                    break;

                case SyntaxKind.DefaultKeyword:
                    if (token.Parent.IsKind(SyntaxKindEx.DefaultLiteralExpression))
                    {
                        // Ignore spacing around a default literal expression for now
                        break;
                    }

                    HandleDisallowedSpaceToken(ref context, token);
                    break;

                case SyntaxKind.NameOfKeyword:
                case SyntaxKind.SizeOfKeyword:
                case SyntaxKind.TypeOfKeyword:
                    HandleDisallowedSpaceToken(ref context, token);
                    break;

                case SyntaxKind.NewKeyword:
                case SyntaxKind.StackAllocKeyword:
                    HandleNewOrStackAllocKeywordToken(ref context, token);
                    break;

                case SyntaxKind.ReturnKeyword:
                    HandleReturnKeywordToken(ref context, token);
                    break;

                case SyntaxKind.ThrowKeyword:
                    HandleThrowKeywordToken(ref context, token);
                    break;

                default:
                    break;
                }
            }
        }
Exemplo n.º 36
0
        private static void HandleOpenParenToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            var prevToken = token.GetPreviousToken();

            // Don't check leading spaces when preceded by a keyword that is already handled by SA1000
            bool precededByKeyword;

            switch (prevToken.Kind())
            {
            case SyntaxKind.AwaitKeyword:
            case SyntaxKind.CaseKeyword:
            case SyntaxKind.CatchKeyword:
            case SyntaxKind.CheckedKeyword:
            case SyntaxKind.DefaultKeyword:
            case SyntaxKind.FixedKeyword:
            case SyntaxKind.ForKeyword:
            case SyntaxKind.ForEachKeyword:
            case SyntaxKind.FromKeyword:
            case SyntaxKind.GroupKeyword:
            case SyntaxKind.IfKeyword:
            case SyntaxKind.InKeyword:
            case SyntaxKind.IntoKeyword:
            case SyntaxKind.JoinKeyword:
            case SyntaxKind.LetKeyword:
            case SyntaxKind.LockKeyword:
            case SyntaxKind.NameOfKeyword:
            case SyntaxKind.NewKeyword:
            case SyntaxKind.OrderByKeyword:
            case SyntaxKind.ReturnKeyword:
            case SyntaxKind.SelectKeyword:
            case SyntaxKind.SizeOfKeyword:
            case SyntaxKind.StackAllocKeyword:
            case SyntaxKind.SwitchKeyword:
            case SyntaxKind.ThrowKeyword:
            case SyntaxKind.TypeOfKeyword:
            case SyntaxKind.UncheckedKeyword:
            case SyntaxKind.UsingKeyword:
            case SyntaxKind.WhereKeyword:
            case SyntaxKind.WhileKeyword:
            case SyntaxKind.YieldKeyword:
                precededByKeyword = true;
                break;

            default:
                precededByKeyword = false;
                break;
            }

            var leadingTriviaList = TriviaHelper.MergeTriviaLists(prevToken.TrailingTrivia, token.LeadingTrivia);

            var isFirstOnLine = false;

            if (prevToken.GetLineSpan().EndLinePosition.Line < token.GetLineSpan().StartLinePosition.Line)
            {
                var done = false;
                for (var i = leadingTriviaList.Count - 1; !done && (i >= 0); i--)
                {
                    switch (leadingTriviaList[i].Kind())
                    {
                    case SyntaxKind.WhitespaceTrivia:
                        break;

                    case SyntaxKind.EndOfLineTrivia:
                        isFirstOnLine = true;
                        done          = true;
                        break;

                    default:
                        done = true;
                        break;
                    }
                }
            }

            bool haveLeadingSpace;
            bool partOfUnaryExpression;
            bool startOfIndexer;

            var prevTokenIsOpenParen = prevToken.IsKind(SyntaxKind.OpenParenToken);

            switch (token.Parent.Kind())
            {
            case SyntaxKind.IfStatement:
            case SyntaxKind.DoStatement:
            case SyntaxKind.WhileStatement:
            case SyntaxKind.ForStatement:
            case SyntaxKind.ForEachStatement:
            case SyntaxKind.SwitchStatement:
            case SyntaxKind.FixedStatement:
            case SyntaxKind.LockStatement:
            case SyntaxKind.UsingStatement:
            case SyntaxKind.CatchDeclaration:
            case SyntaxKind.CatchFilterClause:
                haveLeadingSpace = true;
                break;

            case SyntaxKindEx.PositionalPatternClause:
                haveLeadingSpace = prevToken.IsKind(SyntaxKind.IsKeyword) ||
                                   prevToken.IsKind(SyntaxKindEx.OrKeyword) ||
                                   prevToken.IsKind(SyntaxKindEx.AndKeyword) ||
                                   prevToken.IsKind(SyntaxKindEx.NotKeyword) ||
                                   prevToken.IsKind(SyntaxKind.CommaToken);
                break;

            case SyntaxKindEx.ParenthesizedPattern:
                var partOfCastExpression = prevToken.IsKind(SyntaxKind.CloseParenToken) && prevToken.Parent.IsKind(SyntaxKind.CastExpression);
                haveLeadingSpace = !partOfCastExpression;
                break;

            case SyntaxKind.ArgumentList:
            case SyntaxKind.AttributeArgumentList:
            case SyntaxKind.CheckedExpression:
            case SyntaxKind.UncheckedExpression:
            case SyntaxKind.ConstructorConstraint:
            case SyntaxKind.DefaultExpression:
            case SyntaxKind.SizeOfExpression:
            case SyntaxKind.TypeOfExpression:
            default:
                haveLeadingSpace = false;
                break;

            case SyntaxKindEx.ParenthesizedVariableDesignation:
                haveLeadingSpace = true;
                break;

            case SyntaxKind.ParenthesizedExpression:
            case SyntaxKindEx.TupleExpression:
                if (prevToken.Parent.IsKind(SyntaxKind.Interpolation) ||
                    token.Parent.Parent.IsKind(SyntaxKindEx.RangeExpression))
                {
                    haveLeadingSpace = false;
                    break;
                }

                partOfUnaryExpression = prevToken.Parent is PrefixUnaryExpressionSyntax;
                startOfIndexer        = prevToken.IsKind(SyntaxKind.OpenBracketToken);
                partOfCastExpression  = prevToken.IsKind(SyntaxKind.CloseParenToken) && prevToken.Parent.IsKind(SyntaxKind.CastExpression);

                haveLeadingSpace = !partOfUnaryExpression && !startOfIndexer && !partOfCastExpression;
                break;

            case SyntaxKind.CastExpression:
                partOfUnaryExpression = prevToken.Parent is PrefixUnaryExpressionSyntax;
                startOfIndexer        = prevToken.IsKind(SyntaxKind.OpenBracketToken);
                var consecutiveCast     = prevToken.IsKind(SyntaxKind.CloseParenToken) && prevToken.Parent.IsKind(SyntaxKind.CastExpression);
                var partOfInterpolation = prevToken.IsKind(SyntaxKind.OpenBraceToken) && prevToken.Parent.IsKind(SyntaxKind.Interpolation);
                var partOfRange         = prevToken.IsKind(SyntaxKindEx.DotDotToken);

                haveLeadingSpace = !partOfUnaryExpression && !startOfIndexer && !consecutiveCast && !partOfInterpolation && !partOfRange;
                break;

            case SyntaxKind.ParameterList:
                var partOfLambdaExpression = token.Parent.Parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression);
                haveLeadingSpace = partOfLambdaExpression;
                break;

            case SyntaxKindEx.TupleType:
                // Comma covers tuple types in parameters and nested within other tuple types.
                // 'out', 'ref', 'in', 'params' parameters are covered by IsKeywordKind.
                // Attributes of parameters are covered by checking the previous token's parent.
                // Return types are handled by a helper.
                haveLeadingSpace = prevToken.IsKind(SyntaxKind.CommaToken) ||
                                   SyntaxFacts.IsKeywordKind(prevToken.Kind()) ||
                                   prevToken.Parent.IsKind(SyntaxKind.AttributeList) ||
                                   ((TypeSyntax)token.Parent).GetContainingNotEnclosingType().IsReturnType();
                break;
            }

            // Ignore spacing before if another opening parenthesis is before this.
            // That way the first opening parenthesis will report any spacing errors.
            if (!prevTokenIsOpenParen && !precededByKeyword)
            {
                var hasLeadingComment = (leadingTriviaList.Count > 0) && leadingTriviaList.Last().IsKind(SyntaxKind.MultiLineCommentTrivia);
                var hasLeadingSpace   = (leadingTriviaList.Count > 0) && leadingTriviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia);

                if (!isFirstOnLine && !hasLeadingComment && (haveLeadingSpace != hasLeadingSpace))
                {
                    if (haveLeadingSpace)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(DescriptorPreceded, token.GetLocation(), TokenSpacingProperties.InsertPreceding));
                    }
                    else
                    {
                        context.ReportDiagnostic(Diagnostic.Create(DescriptorNotPreceded, token.GetLocation(), TokenSpacingProperties.RemovePreceding));
                    }
                }
            }

            if (token.IsFollowedByWhitespace())
            {
                context.ReportDiagnostic(Diagnostic.Create(DescriptorNotFollowed, token.GetLocation(), TokenSpacingProperties.RemoveFollowingPreserveLayout));
            }
        }
Exemplo n.º 37
0
 private void Analyze(SyntaxTreeAnalysisContext context)
 => context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, TextSpan.FromBounds(1000, 2000))));
Exemplo n.º 38
0
 public void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     context.ReportDiagnostic(Diagnostic.Create(s_syntaxDiagnosticDescriptor, context.Tree.GetRoot().GetFirstToken().GetLocation()));
 }
Exemplo n.º 39
0
 public BracesVisitor(SyntaxTreeAnalysisContext context)
     : base(SyntaxWalkerDepth.Token)
 {
     this.context = context;
 }
        private void ProcessMemberDeclaration(
            SyntaxTreeAnalysisContext context,
            CodeStyleOption2 <AccessibilityModifiersRequired> option, MemberDeclarationSyntax member)
        {
            if (member.IsKind(SyntaxKind.NamespaceDeclaration, out NamespaceDeclarationSyntax namespaceDeclaration))
            {
                ProcessMembers(context, option, namespaceDeclaration.Members);
            }

            // If we have a class or struct, recurse inwards.
            if (member.IsKind(SyntaxKind.ClassDeclaration, out TypeDeclarationSyntax typeDeclaration) ||
                member.IsKind(SyntaxKind.StructDeclaration, out typeDeclaration))
            {
                ProcessMembers(context, option, typeDeclaration.Members);
            }

#if false
            // Add this once we have the language version for C# that supports accessibility
            // modifiers on interface methods.
            if (option.Value == AccessibilityModifiersRequired.Always &&
                member.IsKind(SyntaxKind.InterfaceDeclaration, out typeDeclaration))
            {
                // Only recurse into an interface if the user wants accessibility modifiers on
                ProcessTypeDeclaration(context, generator, option, typeDeclaration);
            }
#endif

            // Have to have a name to report the issue on.
            var name = member.GetNameToken();
            if (name.Kind() == SyntaxKind.None)
            {
                return;
            }

            // Certain members never have accessibility. Don't bother reporting on them.
            if (!SyntaxFacts.CanHaveAccessibility(member))
            {
                return;
            }

            // This analyzer bases all of its decisions on the accessibility
            var accessibility = SyntaxFacts.GetAccessibility(member);

            // Omit will flag any accessibility values that exist and are default
            // The other options will remove or ignore accessibility
            var isOmit = option.Value == AccessibilityModifiersRequired.OmitIfDefault;

            if (isOmit)
            {
                if (accessibility == Accessibility.NotApplicable)
                {
                    return;
                }

                var parentKind = member.Parent.Kind();
                switch (parentKind)
                {
                // Check for default modifiers in namespace and outside of namespace
                case SyntaxKind.CompilationUnit:
                case SyntaxKind.NamespaceDeclaration:
                {
                    // Default is internal
                    if (accessibility != Accessibility.Internal)
                    {
                        return;
                    }
                }
                break;

                case SyntaxKind.ClassDeclaration:
                case SyntaxKind.StructDeclaration:
                {
                    // Inside a type, default is private
                    if (accessibility != Accessibility.Private)
                    {
                        return;
                    }
                }
                break;

                default:
                    return;     // Unknown parent kind, don't do anything
                }
            }
            else
            {
                // Mode is always, so we have to flag missing modifiers
                if (accessibility != Accessibility.NotApplicable)
                {
                    return;
                }
            }

            // Have an issue to flag, either add or remove. Report issue to user.
            var additionalLocations = ImmutableArray.Create(member.GetLocation());
            context.ReportDiagnostic(DiagnosticHelper.Create(
                                         Descriptor,
                                         name.GetLocation(),
                                         option.Notification.Severity,
                                         additionalLocations: additionalLocations,
                                         properties: null));
        }
 protected override void ProcessCompilationUnit(
     SyntaxTreeAnalysisContext context,
     CodeStyleOption2 <AccessibilityModifiersRequired> option, CompilationUnitSyntax compilationUnit)
 {
     ProcessMembers(context, option, compilationUnit.Members);
 }
 public static void ReportDiagnosticWhenActive(this SyntaxTreeAnalysisContext context, Diagnostic diagnostic) =>
 ReportDiagnostic(new ReportingContext(context, diagnostic));
 // Actions/SyntaxTree
 private static void OnSyntaxTree(SyntaxTreeAnalysisContext context)
 {
 }
Exemplo n.º 44
0
        private static void HandleCloseBracketToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            // attribute brackets are handled separately
            if (token.Parent.IsKind(SyntaxKind.AttributeList))
            {
                return;
            }

            bool firstInLine     = token.IsFirstInLine();
            bool precededBySpace = firstInLine || token.IsPrecededByWhitespace();
            bool followedBySpace = token.IsFollowedByWhitespace();
            bool lastInLine      = token.IsLastInLine();
            bool precedesSpecialCharacter;

            // Tests for this rule have a lot of exclusions which are supposed to be caught by other rules
            bool suppressFollowingSpaceError = true;

            if (!lastInLine)
            {
                SyntaxToken nextToken = token.GetNextToken();
                switch (nextToken.Kind())
                {
                case SyntaxKind.CloseBracketToken:
                case SyntaxKind.OpenParenToken:
                case SyntaxKind.CommaToken:
                case SyntaxKind.SemicolonToken:
                // TODO: "certain types of operator symbols"
                case SyntaxKind.DotToken:
                case SyntaxKind.OpenBracketToken:
                case SyntaxKind.CloseParenToken:
                    precedesSpecialCharacter = true;
                    break;

                case SyntaxKind.PlusPlusToken:
                case SyntaxKind.MinusMinusToken:
                    precedesSpecialCharacter    = true;
                    suppressFollowingSpaceError = false;
                    break;

                case SyntaxKind.GreaterThanToken:
                    precedesSpecialCharacter = nextToken.Parent.IsKind(SyntaxKind.TypeArgumentList);
                    break;

                case SyntaxKind.QuestionToken:
                    precedesSpecialCharacter = nextToken.Parent.IsKind(SyntaxKind.ConditionalAccessExpression);
                    break;

                case SyntaxKind.CloseBraceToken:
                    precedesSpecialCharacter = nextToken.Parent is InterpolationSyntax;
                    break;

                default:
                    precedesSpecialCharacter = false;
                    break;
                }
            }
            else
            {
                precedesSpecialCharacter = false;
            }

            if (!firstInLine && precededBySpace)
            {
                // Closing square bracket must{ not} be {preceded} by a space.
                var properties = new Dictionary <string, string>
                {
                    [OpenCloseSpacingCodeFixProvider.LocationKey] = OpenCloseSpacingCodeFixProvider.LocationPreceding,
                    [OpenCloseSpacingCodeFixProvider.ActionKey]   = OpenCloseSpacingCodeFixProvider.ActionRemove
                };
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties.ToImmutableDictionary(), " not", "preceded"));
            }

            if (!lastInLine)
            {
                if (!precedesSpecialCharacter && !followedBySpace)
                {
                    // Closing square bracket must{} be {followed} by a space.
                    var properties = new Dictionary <string, string>
                    {
                        [OpenCloseSpacingCodeFixProvider.LocationKey] = OpenCloseSpacingCodeFixProvider.LocationFollowing,
                        [OpenCloseSpacingCodeFixProvider.ActionKey]   = OpenCloseSpacingCodeFixProvider.ActionInsert
                    };
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties.ToImmutableDictionary(), string.Empty, "followed"));
                }
                else if (precedesSpecialCharacter && followedBySpace && !suppressFollowingSpaceError)
                {
                    // Closing square brackets must {not} be {followed} by a space
                    var properties = new Dictionary <string, string>
                    {
                        [OpenCloseSpacingCodeFixProvider.LocationKey] = OpenCloseSpacingCodeFixProvider.LocationFollowing,
                        [OpenCloseSpacingCodeFixProvider.ActionKey]   = OpenCloseSpacingCodeFixProvider.ActionRemove
                    };
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), properties.ToImmutableDictionary(), " not", "followed"));
                }
            }
        }
 /// <summary>
 /// Checks whether the given document is auto generated by a tool.
 /// </summary>
 /// <remarks>
 /// <para>This method uses <see cref="IsGeneratedDocument(SyntaxTree, ConcurrentDictionary{SyntaxTree, bool}, CancellationToken)"/> to determine which
 /// code is considered "generated".</para>
 /// </remarks>
 /// <param name="context">The analysis context for a <see cref="SyntaxTree"/>.</param>
 /// <param name="cache">The concurrent results cache.</param>
 /// <returns>
 /// <para><see langword="true"/> if the <see cref="SyntaxTree"/> contained in <paramref name="context"/> is
 /// located in generated code; otherwise, <see langword="false"/>.</para>
 /// </returns>
 internal static bool IsGeneratedDocument(this SyntaxTreeAnalysisContext context, ConcurrentDictionary <SyntaxTree, bool> cache)
 {
     return(IsGeneratedDocument(context.Tree, cache, context.CancellationToken));
 }
Exemplo n.º 46
0
 private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
 {
     OnAbstractMember("SyntaxTree");
     OnOptions(context.Options);
 }
Exemplo n.º 47
0
        private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation compilation)
        {
            if (context.IsGenerated())
            {
                return;
            }
            if (!compilation.SyntaxTrees.Contains(context.Tree))
            {
                return;
            }
            var        semanticModel = compilation.GetSemanticModel(context.Tree);
            SyntaxNode root;

            if (!context.Tree.TryGetRoot(out root))
            {
                return;
            }
            var types = GetTypesInRoot(root);

            foreach (var type in types)
            {
                var fieldDeclarations       = type.ChildNodes().OfType <FieldDeclarationSyntax>();
                var variablesToMakeReadonly = GetCandidateVariables(semanticModel, fieldDeclarations);
                var typeSymbol = semanticModel.GetDeclaredSymbol(type);
                if (typeSymbol == null)
                {
                    continue;
                }
                var methods = typeSymbol.GetAllMethodsIncludingFromInnerTypes();
                foreach (var method in methods)
                {
                    foreach (var syntaxReference in method.DeclaringSyntaxReferences)
                    {
                        var syntaxRefSemanticModel = syntaxReference.SyntaxTree.Equals(context.Tree)
                                ? semanticModel
                                : compilation.GetSemanticModel(syntaxReference.SyntaxTree);
                        var descendants = syntaxReference.GetSyntax().DescendantNodes().ToList();
                        var assignments = descendants.OfKind(SyntaxKind.SimpleAssignmentExpression,
                                                             SyntaxKind.AddAssignmentExpression, SyntaxKind.AndAssignmentExpression, SyntaxKind.DivideAssignmentExpression,
                                                             SyntaxKind.ExclusiveOrAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression, SyntaxKind.ModuloAssignmentExpression,
                                                             SyntaxKind.MultiplyAssignmentExpression, SyntaxKind.OrAssignmentExpression, SyntaxKind.RightShiftAssignmentExpression,
                                                             SyntaxKind.SubtractAssignmentExpression);
                        foreach (AssignmentExpressionSyntax assignment in assignments)
                        {
                            var fieldSymbol = syntaxRefSemanticModel.GetSymbolInfo(assignment.Left).Symbol as IFieldSymbol;
                            VerifyVariable(variablesToMakeReadonly, method, syntaxRefSemanticModel, assignment, fieldSymbol);
                        }
                        var postFixUnaries = descendants.OfKind(SyntaxKind.PostIncrementExpression, SyntaxKind.PostDecrementExpression);
                        foreach (PostfixUnaryExpressionSyntax postFixUnary in postFixUnaries)
                        {
                            var fieldSymbol = syntaxRefSemanticModel.GetSymbolInfo(postFixUnary.Operand).Symbol as IFieldSymbol;
                            VerifyVariable(variablesToMakeReadonly, method, syntaxRefSemanticModel, postFixUnary, fieldSymbol);
                        }
                        var preFixUnaries = descendants.OfKind(SyntaxKind.PreDecrementExpression, SyntaxKind.PreIncrementExpression);
                        foreach (PrefixUnaryExpressionSyntax preFixUnary in preFixUnaries)
                        {
                            var fieldSymbol = syntaxRefSemanticModel.GetSymbolInfo(preFixUnary.Operand).Symbol as IFieldSymbol;
                            VerifyVariable(variablesToMakeReadonly, method, syntaxRefSemanticModel, preFixUnary, fieldSymbol);
                        }
                    }
                }
                foreach (var readonlyVariable in variablesToMakeReadonly.Values)
                {
                    var props = new Dictionary <string, string> {
                        { "identifier", readonlyVariable.Identifier.Text }
                    }.ToImmutableDictionary();
                    var diagnostic = Diagnostic.Create(Rule, readonlyVariable.GetLocation(), props, readonlyVariable.Identifier.Text);
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
Exemplo n.º 48
0
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);
            var previousCommentNotOnOwnLine = false;

            foreach (var trivia in syntaxRoot.DescendantTrivia().Where(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia)))
            {
                if (trivia.FullSpan.Start == 0)
                {
                    // skip the trivia if it is at the start of the file
                    previousCommentNotOnOwnLine = false;
                    continue;
                }

                if (trivia.ToString().StartsWith("////", StringComparison.Ordinal))
                {
                    // ignore commented out code
                    previousCommentNotOnOwnLine = false;
                    continue;
                }

                int triviaIndex;
                var triviaList = TriviaHelper.GetContainingTriviaList(trivia, out triviaIndex);

                if (!IsOnOwnLine(triviaList, triviaIndex))
                {
                    // ignore comments after other code elements.
                    previousCommentNotOnOwnLine = true;
                    continue;
                }

                if (IsPrecededByBlankLine(triviaList, triviaIndex))
                {
                    // allow properly formatted blank line comments.
                    previousCommentNotOnOwnLine = false;
                    continue;
                }

                if (!previousCommentNotOnOwnLine && IsPrecededBySingleLineCommentOrDocumentation(triviaList, triviaIndex))
                {
                    // allow consecutive single line comments.
                    previousCommentNotOnOwnLine = false;
                    continue;
                }

                previousCommentNotOnOwnLine = false;

                if (IsAtStartOfScope(trivia))
                {
                    // allow single line comment at scope start.
                    continue;
                }

                if (IsPrecededByDirectiveTrivia(triviaList, triviaIndex))
                {
                    // allow single line comment that is preceded by some directive trivia (if, elif, else)
                    continue;
                }

                var diagnosticSpan = TextSpan.FromBounds(trivia.SpanStart, trivia.SpanStart + 2);
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, diagnosticSpan)));
            }
        }
Exemplo n.º 49
0
        private static void HandleSyntaxTreeAnalysis(SyntaxTreeAnalysisContext context, Compilation compilation)
        {
            var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);

            foreach (var trivia in syntaxRoot.DescendantTrivia().Where(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia)))
            {
                if (trivia.ToString().StartsWith("////", StringComparison.Ordinal))
                {
                    // ignore commented out code
                    continue;
                }

                int triviaIndex;

                // PERF: Explicitly cast to IReadOnlyList so we only box once.
                var triviaList = TriviaHelper.GetContainingTriviaList(trivia, out triviaIndex);

                if (!IsOnOwnLine(triviaList, triviaIndex))
                {
                    // ignore comments after other code elements.
                    continue;
                }

                if (IsPartOfFileHeader(triviaList, triviaIndex))
                {
                    // ignore comments that are part of the file header.
                    continue;
                }

                var trailingBlankLineCount = GetTrailingBlankLineCount(triviaList, ref triviaIndex);
                if (trailingBlankLineCount == 0)
                {
                    // ignore comments that are not followed by a blank line
                    continue;
                }
                else if (trailingBlankLineCount > 1)
                {
                    if (!compilation.IsAnalyzerSuppressed(SA1507CodeMustNotContainMultipleBlankLinesInARow.Descriptor))
                    {
                        // ignore comments that are followed by multiple blank lines -> the multiple blank lines will be reported by SA1507
                        continue;
                    }
                }
                else
                {
                    if (triviaIndex < triviaList.Count)
                    {
                        switch (triviaList[triviaIndex].Kind())
                        {
                        case SyntaxKind.SingleLineCommentTrivia:
                        case SyntaxKind.SingleLineDocumentationCommentTrivia:
                        case SyntaxKind.MultiLineCommentTrivia:
                        case SyntaxKind.MultiLineDocumentationCommentTrivia:
                            // ignore a single blank line in between two comments.
                            continue;
                        }
                    }
                }

                var diagnosticSpan = TextSpan.FromBounds(trivia.SpanStart, trivia.SpanStart + 2);
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, diagnosticSpan)));
            }
        }
Exemplo n.º 50
0
        private static void HandleGreaterThanToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            switch (token.Parent.Kind())
            {
            case SyntaxKind.TypeArgumentList:
            case SyntaxKind.TypeParameterList:
                break;

            default:
                // not a generic bracket
                return;
            }

            bool firstInLine     = token.IsFirstInLine();
            bool lastInLine      = token.IsLastInLine();
            bool precededBySpace = firstInLine || token.IsPrecededByWhitespace(context.CancellationToken);
            bool followedBySpace = token.IsFollowedByWhitespace();
            bool allowTrailingNoSpace;
            bool allowTrailingSpace;

            if (!lastInLine)
            {
                SyntaxToken nextToken = token.GetNextToken();
                switch (nextToken.Kind())
                {
                case SyntaxKind.OpenParenToken:
                // DotToken isn't listed above, but it's required for reasonable member access formatting
                case SyntaxKind.DotToken:
                // CommaToken isn't listed above, but it's required for reasonable nested generic type arguments formatting
                case SyntaxKind.CommaToken:
                // OpenBracketToken isn't listed above, but it's required for reasonable array type formatting
                case SyntaxKind.OpenBracketToken:
                // SemicolonToken isn't listed above, but it's required for reasonable using alias declaration formatting
                case SyntaxKind.SemicolonToken:
                case SyntaxKind.ColonToken when nextToken.Parent.IsKind(SyntaxKindEx.CasePatternSwitchLabel):
                    allowTrailingNoSpace = true;

                    allowTrailingSpace = false;
                    break;

                case SyntaxKind.CloseParenToken:
                case SyntaxKind.GreaterThanToken:
                    allowTrailingNoSpace = true;
                    allowTrailingSpace   = true;
                    break;

                case SyntaxKind.QuestionToken:
                    allowTrailingNoSpace = nextToken.Parent.IsKind(SyntaxKind.NullableType);
                    allowTrailingSpace   = true;
                    break;

                default:
                    allowTrailingNoSpace = false;
                    allowTrailingSpace   = true;
                    break;
                }
            }
            else
            {
                allowTrailingNoSpace = true;
                allowTrailingSpace   = true;
            }

            if (!firstInLine && precededBySpace)
            {
                // Closing generic bracket should{ not} be {preceded} by a space.
                var properties = TokenSpacingProperties.RemovePreceding;
                context.ReportDiagnostic(Diagnostic.Create(DescriptorNotPreceded, token.GetLocation(), properties));
            }

            if (!lastInLine)
            {
                if (!allowTrailingNoSpace && !followedBySpace)
                {
                    // Closing generic bracket should{} be {followed} by a space.
                    var properties = TokenSpacingProperties.InsertFollowing;
#pragma warning disable RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor (https://github.com/dotnet/roslyn-analyzers/issues/4103)
                    context.ReportDiagnostic(Diagnostic.Create(DescriptorFollowed, token.GetLocation(), properties));
#pragma warning restore RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor
                }
                else if (!allowTrailingSpace && followedBySpace)
                {
                    // Closing generic bracket should{ not} be {followed} by a space.
                    var properties = TokenSpacingProperties.RemoveFollowing;
#pragma warning disable RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor (https://github.com/dotnet/roslyn-analyzers/issues/4103)
                    context.ReportDiagnostic(Diagnostic.Create(DescriptorNotFollowed, token.GetLocation(), properties));
#pragma warning restore RS1005 // ReportDiagnostic invoked with an unsupported DiagnosticDescriptor
                }
            }
        }
Exemplo n.º 51
0
 private static void HandleDisallowedSpaceToken(ref SyntaxTreeAnalysisContext context, SyntaxToken token)
 => HandleDisallowedSpaceToken(ReportSyntaxTreeDiagnostic, ref context, token);
Exemplo n.º 52
0
 /// <summary>
 /// Gets the StyleCop settings.
 /// </summary>
 /// <param name="context">The context that will be used to determine the StyleCop settings.</param>
 /// <param name="cancellationToken">The cancellation token that the operation will observe.</param>
 /// <returns>A <see cref="StyleCopSettings"/> instance that represents the StyleCop settings for the given context.</returns>
 internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisContext context, CancellationToken cancellationToken)
 {
     return(context.Options.GetStyleCopSettings(cancellationToken));
 }
 public GatherVisitor(SyntaxTreeAnalysisContext ctx, SemanticModel semanticModel)
 {
     this.ctx           = ctx;
     this.semanticModel = semanticModel;
 }
 public static SyntaxTree GetSyntaxTree(this SyntaxTreeAnalysisContext context) =>
 context.Tree;
Exemplo n.º 55
0
        private static void ReportIncorrectTabUsage(SyntaxTreeAnalysisContext context, IndentationSettings indentationSettings, ImmutableArray <TextSpan> excludedSpans)
        {
            SyntaxTree syntaxTree = context.Tree;
            SourceText sourceText = syntaxTree.GetText(context.CancellationToken);

            string completeText = sourceText.ToString();
            int    length       = completeText.Length;

            bool useTabs = indentationSettings.UseTabs;
            int  tabSize = indentationSettings.TabSize;

            int      excludedSpanIndex = 0;
            var      lastExcludedSpan  = new TextSpan(completeText.Length, 0);
            TextSpan nextExcludedSpan  = !excludedSpans.IsEmpty ? excludedSpans[0] : lastExcludedSpan;

            int lastLineStart = 0;

            for (int startIndex = 0; startIndex < length; startIndex++)
            {
                if (startIndex == nextExcludedSpan.Start)
                {
                    startIndex = nextExcludedSpan.End - 1;
                    excludedSpanIndex++;
                    nextExcludedSpan = excludedSpanIndex < excludedSpans.Length ? excludedSpans[excludedSpanIndex] : lastExcludedSpan;
                    continue;
                }

                int  tabCount       = 0;
                bool containsSpaces = false;
                bool tabAfterSpace  = false;
                switch (completeText[startIndex])
                {
                case ' ':
                    containsSpaces = true;
                    break;

                case '\t':
                    tabCount++;
                    break;

                case '\r':
                case '\n':
                    // Handle newlines. We can ignore CR/LF/CRLF issues because we are only tracking column position
                    // in a line, and not the line numbers themselves.
                    lastLineStart = startIndex + 1;
                    continue;

                default:
                    continue;
                }

                int endIndex;
                for (endIndex = startIndex + 1; endIndex < length; endIndex++)
                {
                    if (endIndex == nextExcludedSpan.Start)
                    {
                        break;
                    }

                    if (completeText[endIndex] == ' ')
                    {
                        containsSpaces = true;
                    }
                    else if (completeText[endIndex] == '\t')
                    {
                        tabCount++;
                        tabAfterSpace = containsSpaces;
                    }
                    else
                    {
                        break;
                    }
                }

                if (useTabs && startIndex == lastLineStart)
                {
                    // For the case we care about in the following condition (tabAfterSpace is false), spaceCount is
                    // the number of consecutive trailing spaces.
                    int spaceCount = (endIndex - startIndex) - tabCount;
                    if (tabAfterSpace || spaceCount >= tabSize)
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptor,
                                Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)),
                                ConvertToTabsProperties));
                    }
                }
                else
                {
                    if (tabCount > 0)
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptor,
                                Location.Create(syntaxTree, TextSpan.FromBounds(startIndex, endIndex)),
                                ConvertToSpacesProperties));
                    }
                }

                // Make sure to not analyze overlapping spans
                startIndex = endIndex - 1;
            }
        }
Exemplo n.º 56
0
 protected abstract void ProcessCompilationUnit(SyntaxTreeAnalysisContext context, SyntaxGenerator generator, CodeStyleOption <AccessibilityModifiersRequired> option, TCompilationUnitSyntax compilationUnitSyntax);
        private static void AnalyzeWhitespace(SyntaxTreeAnalysisContext context)
        {
            var walker = new WhitespaceWalker(context);

            walker.Visit(context.Tree.GetRoot());
        }
 public WhitespaceWalker(SyntaxTreeAnalysisContext context)
     : base(SyntaxWalkerDepth.StructuredTrivia)
 {
     this.context = context;
 }
        private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation compilation)
        {
            if (context.IsGenerated())
            {
                return;
            }
            if (!compilation.SyntaxTrees.Contains(context.Tree))
            {
                return;
            }
            var        semanticModel = compilation.GetSemanticModel(context.Tree);
            SyntaxNode root;

            if (!context.Tree.TryGetRoot(out root))
            {
                return;
            }
            var types = GetTypesInRoot(root);

            foreach (var type in types)
            {
                var fieldDeclarations       = type.ChildNodes().OfType <FieldDeclarationSyntax>();
                var variablesToMakeReadonly = GetCandidateVariables(semanticModel, fieldDeclarations);
                var typeSymbol = semanticModel.GetDeclaredSymbol(type);
                if (typeSymbol == null)
                {
                    continue;
                }
                var methods = typeSymbol.GetAllMethodsIncludingFromInnerTypes();
                foreach (var method in methods)
                {
                    foreach (var syntaxReference in method.DeclaringSyntaxReferences)
                    {
                        var syntaxRefSemanticModel = syntaxReference.SyntaxTree.Equals(context.Tree)
                                ? semanticModel
                                : compilation.GetSemanticModel(syntaxReference.SyntaxTree);
                        var assignments = syntaxReference.GetSyntax().DescendantNodes().OfType <AssignmentExpressionSyntax>();
                        foreach (var assignment in assignments)
                        {
                            var fieldSymbol = syntaxRefSemanticModel.GetSymbolInfo(assignment.Left).Symbol as IFieldSymbol;
                            if (fieldSymbol == null)
                            {
                                continue;
                            }
                            if (method.MethodKind == MethodKind.StaticConstructor && fieldSymbol.IsStatic)
                            {
                                AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(variablesToMakeReadonly, fieldSymbol);
                            }
                            else if (method.MethodKind == MethodKind.Constructor && !fieldSymbol.IsStatic)
                            {
                                AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(variablesToMakeReadonly, fieldSymbol);
                            }
                            else
                            {
                                RemoveVariableThatHasAssignment(variablesToMakeReadonly, fieldSymbol);
                            }
                        }
                    }
                }
                foreach (var readonlyVariable in variablesToMakeReadonly.Values)
                {
                    var props = new Dictionary <string, string> {
                        { "identifier", readonlyVariable.Identifier.Text }
                    }.ToImmutableDictionary();
                    var diagnostic = Diagnostic.Create(Rule, readonlyVariable.GetLocation(), props, readonlyVariable.Identifier.Text);
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
Exemplo n.º 60
0
            public static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings, Compilation compilation)
            {
                var root = context.Tree.GetRoot(context.CancellationToken);

                // don't process empty files
                if (root.FullSpan.IsEmpty)
                {
                    return;
                }

                if (settings.DocumentationRules.XmlHeader)
                {
                    var fileHeader = FileHeaderHelpers.ParseXmlFileHeader(root);
                    if (fileHeader.IsMissing)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(SA1633DescriptorMissing, fileHeader.GetLocation(context.Tree)));
                        return;
                    }

                    if (fileHeader.IsMalformed)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(SA1633DescriptorMalformed, fileHeader.GetLocation(context.Tree)));
                        return;
                    }

                    if (!compilation.IsAnalyzerSuppressed(SA1634Identifier))
                    {
                        CheckCopyrightHeader(context, settings.DocumentationRules, compilation, fileHeader);
                    }

                    if (!compilation.IsAnalyzerSuppressed(SA1639Identifier))
                    {
                        CheckSummaryHeader(context, compilation, fileHeader);
                    }
                }
                else
                {
                    var fileHeader = FileHeaderHelpers.ParseFileHeader(root);
                    if (fileHeader.IsMissing)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(SA1633DescriptorMissing, fileHeader.GetLocation(context.Tree)));
                        return;
                    }

                    if (!compilation.IsAnalyzerSuppressed(SA1635Identifier))
                    {
                        if (string.IsNullOrWhiteSpace(fileHeader.CopyrightText))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(SA1635Descriptor, fileHeader.GetLocation(context.Tree)));
                            return;
                        }

                        if (compilation.IsAnalyzerSuppressed(SA1636Identifier))
                        {
                            return;
                        }

                        if (!CompareCopyrightText(context, settings.DocumentationRules, fileHeader.CopyrightText))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(SA1636Descriptor, fileHeader.GetLocation(context.Tree)));
                            return;
                        }
                    }
                }
            }