Пример #1
0
        public bool CanOfferUseExpressionBody(
            OptionSet optionSet, TDeclaration declaration, bool forAnalyzer)
        {
            var currentOptionValue          = optionSet.GetOption(Option);
            var preference                  = currentOptionValue.Value;
            var userPrefersExpressionBodies = preference != ExpressionBodyPreference.Never;
            var analyzerDisabled            = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress;

            // If the user likes expression bodies, then we offer expression bodies from the diagnostic analyzer.
            // If the user does not like expression bodies then we offer expression bodies from the refactoring provider.
            // If the analyzer is disabled completely, the refactoring is enabled in both directions.
            if (userPrefersExpressionBodies == forAnalyzer || (!forAnalyzer && analyzerDisabled))
            {
                var expressionBody = GetExpressionBody(declaration);
                if (expressionBody == null)
                {
                    // They don't have an expression body.  See if we could convert the block they
                    // have into one.

                    var conversionPreference = forAnalyzer ? preference : ExpressionBodyPreference.WhenPossible;

                    return(TryConvertToExpressionBody(declaration, conversionPreference,
                                                      expressionWhenOnSingleLine: out _, semicolonWhenOnSingleLine: out _));
                }
            }

            return(false);
        }
Пример #2
0
            private static SyntaxNode GetNewNode(SyntaxNode node, OptionSet options)
            {
                var syntaxFacts  = CSharpSyntaxFacts.Instance;
                var modifiers    = syntaxFacts.GetModifiers(node);
                var newModifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.NewKeyword));

                var option = options.GetOption(CSharpCodeStyleOptions.PreferredModifierOrder);

                if (!CSharpOrderModifiersHelper.Instance.TryGetOrComputePreferredOrder(option.Value, out var preferredOrder) ||
                    !AbstractOrderModifiersHelpers.IsOrdered(preferredOrder, modifiers))
                {
                    return(syntaxFacts.WithModifiers(node, newModifiers));
                }

                var orderedModifiers = new SyntaxTokenList(
                    newModifiers.OrderBy(CompareModifiers));

                return(syntaxFacts.WithModifiers(node, orderedModifiers));

                int CompareModifiers(SyntaxToken left, SyntaxToken right)
                => GetOrder(left) - GetOrder(right);

                int GetOrder(SyntaxToken token)
                => preferredOrder.TryGetValue(token.RawKind, out var value) ? value : int.MaxValue;
            }
        public override bool OpenFileOnly(OptionSet options)
        {
            var qualifyFieldAccessOption =
                options.GetOption(
                    CodeStyleOptions2.QualifyFieldAccess,
                    GetLanguageName()
                    ).Notification;
            var qualifyPropertyAccessOption =
                options.GetOption(
                    CodeStyleOptions2.QualifyPropertyAccess,
                    GetLanguageName()
                    ).Notification;
            var qualifyMethodAccessOption =
                options.GetOption(
                    CodeStyleOptions2.QualifyMethodAccess,
                    GetLanguageName()
                    ).Notification;
            var qualifyEventAccessOption =
                options.GetOption(
                    CodeStyleOptions2.QualifyEventAccess,
                    GetLanguageName()
                    ).Notification;

            return(!(
                       qualifyFieldAccessOption == NotificationOption2.Warning ||
                       qualifyFieldAccessOption == NotificationOption2.Error ||
                       qualifyPropertyAccessOption == NotificationOption2.Warning ||
                       qualifyPropertyAccessOption == NotificationOption2.Error ||
                       qualifyMethodAccessOption == NotificationOption2.Warning ||
                       qualifyMethodAccessOption == NotificationOption2.Error ||
                       qualifyEventAccessOption == NotificationOption2.Warning ||
                       qualifyEventAccessOption == NotificationOption2.Error
                       ));
        }
Пример #4
0
        public bool CanOfferUseBlockBody(
            OptionSet optionSet,
            TDeclaration declaration,
            bool forAnalyzer,
            out bool fixesError,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?expressionBody)
        {
            var currentOptionValue     = optionSet.GetOption(Option);
            var preference             = currentOptionValue.Value;
            var userPrefersBlockBodies = preference == ExpressionBodyPreference.Never;
            var analyzerDisabled       = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress;

            expressionBody = GetExpressionBody(declaration);
            if (expressionBody?.TryConvertToBlock(
                    SyntaxFactory.Token(SyntaxKind.SemicolonToken), false, block: out _) != true)
            {
                fixesError = false;
                return(false);
            }

            var languageVersion = declaration.GetLanguageVersion();

            if (languageVersion < LanguageVersion.CSharp7)
            {
                if (expressionBody !.Expression.IsKind(SyntaxKind.ThrowExpression))
                {
                    // If they're using a throw expression in a declaration and it's prior to C# 7
                    // then always mark this as something that can be fixed by the analyzer.  This way
                    // we'll also get 'fix all' working to fix all these cases.
                    fixesError = true;
                    return(true);
                }

                if (declaration is AccessorDeclarationSyntax or ConstructorDeclarationSyntax)
                {
                    // If they're using expression bodies for accessors/constructors and it's prior to C# 7
                    // then always mark this as something that can be fixed by the analyzer.  This way
                    // we'll also get 'fix all' working to fix all these cases.
                    fixesError = true;
                    return(true);
                }
            }

            if (languageVersion < LanguageVersion.CSharp6)
            {
                // If they're using expression bodies prior to C# 6, then always mark this as something
                // that can be fixed by the analyzer.  This way we'll also get 'fix all' working to fix
                // all these cases.
                fixesError = true;
                return(true);
            }

            // If the user likes block bodies, then we offer block bodies from the diagnostic analyzer.
            // If the user does not like block bodies then we offer block bodies from the refactoring provider.
            // If the analyzer is disabled completely, the refactoring is enabled in both directions.
            fixesError = false;
            return(userPrefersBlockBodies == forAnalyzer || (!forAnalyzer && analyzerDisabled));
        }
        public override bool OpenFileOnly(OptionSet options)
        {
            var forIntrinsicTypesOption = options.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes).Notification;
            var whereApparentOption     = options.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent).Notification;
            var wherePossibleOption     = options.GetOption(CSharpCodeStyleOptions.VarElsewhere).Notification;

            return(!(forIntrinsicTypesOption == NotificationOption.Warning || forIntrinsicTypesOption == NotificationOption.Error ||
                     whereApparentOption == NotificationOption.Warning || whereApparentOption == NotificationOption.Error ||
                     wherePossibleOption == NotificationOption.Warning || wherePossibleOption == NotificationOption.Error));
        }
Пример #6
0
        private Diagnostic AnalyzeSyntax(
            OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper)
        {
            var preferExpressionBodiedOption = optionSet.GetOption(helper.Option);
            var severity = preferExpressionBodiedOption.Notification.Severity;

            if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true))
            {
                var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden
                    ? declaration.GetLocation()
                    : helper.GetDiagnosticLocation(declaration);

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                var properties          = ImmutableDictionary <string, string> .Empty.Add(nameof(UseExpressionBody), "");

                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.UseExpressionBodyTitle, helper.UseExpressionBodyTitle),
                           location, severity, additionalLocations: additionalLocations, properties: properties));
            }

            var(canOffer, fixesError) = helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true);
            if (canOffer)
            {
                // They have an expression body.  Create a diagnostic to convert it to a block
                // if they don't want expression bodies for this member.
                var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden
                    ? declaration.GetLocation()
                    : helper.GetExpressionBody(declaration).GetLocation();

                var properties = ImmutableDictionary <string, string> .Empty;
                if (fixesError)
                {
                    properties = properties.Add(FixesError, "");
                }

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle),
                           location, severity, additionalLocations: additionalLocations, properties: properties));
            }

            return(null);
        }
        private Diagnostic?AnalyzeNamespace(OptionSet optionSet, FileScopedNamespaceDeclarationSyntax declaration)
        {
            var tree   = declaration.SyntaxTree;
            var option = optionSet.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations);

            if (!ConvertNamespaceAnalysis.CanOfferUseBlockScoped(optionSet, declaration, forAnalyzer: true))
            {
                return(null);
            }

            // if the diagnostic is hidden, show it anywhere from the `namespace` keyword through the name.
            // otherwise, if it's not hidden, just squiggle the name.
            var severity           = option.Notification.Severity;
            var diagnosticLocation = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) != ReportDiagnostic.Hidden
                ? declaration.Name.GetLocation()
                : tree.GetLocation(TextSpan.FromBounds(declaration.SpanStart, declaration.SemicolonToken.Span.End));

            return(DiagnosticHelper.Create(
                       this.Descriptor,
                       diagnosticLocation,
                       severity,
                       ImmutableArray.Create(declaration.GetLocation()),
                       ImmutableDictionary <string, string> .Empty));
        }
 public override (bool canOffer, bool fixesError) CanOfferUseBlockBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer)
 => CanOfferUseBlockBody(optionSet, (TDeclaration)declaration, forAnalyzer);
 public override bool CanOfferUseExpressionBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer)
 => CanOfferUseExpressionBody(optionSet, (TDeclaration)declaration, forAnalyzer);
 public bool OpenFileOnly(OptionSet options)
 => false;
 internal CompilerAnalyzerConfigOptionsProvider WithGlobalOptions(
     AnalyzerConfigOptions globalOptions
     ) => new CompilerAnalyzerConfigOptionsProvider(_treeDict, globalOptions);
Пример #12
0
        internal static SyntaxNode Format(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, IEnumerable <TextSpan> spans, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken)
        {
            var formattingResult = GetFormattingResult(node, syntaxFormattingService, spans, options, rules, cancellationToken);

            return(formattingResult == null ? node : formattingResult.GetFormattedRoot(cancellationToken));
        }
Пример #13
0
 public override bool CanOfferUseBlockBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax?expressionBody)
 => CanOfferUseBlockBody(optionSet, (TDeclaration)declaration, forAnalyzer, out fixesError, out expressionBody);
Пример #14
0
 public static Task <SyntaxTree> FormatAsync(SyntaxTree syntaxTree, ISyntaxFormattingService syntaxFormattingService, IEnumerable <TextSpan> spans, OptionSet options, CancellationToken cancellationToken)
 => FormatAsync(syntaxTree, syntaxFormattingService, spans, options, rules: null, cancellationToken);
Пример #15
0
        internal static IFormattingResult GetFormattingResult(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, IEnumerable <TextSpan> spans, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (syntaxFormattingService is null)
            {
                return(null);
            }

            options ??= DictionaryAnalyzerConfigOptions.Empty;
            rules ??= GetDefaultFormattingRules(syntaxFormattingService);
            spans ??= SpecializedCollections.SingletonEnumerable(node.FullSpan);
            return(syntaxFormattingService.Format(node, spans, shouldUseFormattingSpanCollapse: false, options, rules, cancellationToken));
        }
Пример #16
0
 public AnalyzerConfigOptionSet(AnalyzerConfigOptions analyzerConfigOptions, OptionSet?optionSet)
 {
     _analyzerConfigOptions = analyzerConfigOptions;
     _optionSet             = optionSet;
 }
Пример #17
0
 public static IList <TextChange> GetFormattedTextChanges(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, OptionSet options, CancellationToken cancellationToken)
 => GetFormattedTextChanges(node, syntaxFormattingService, SpecializedCollections.SingletonEnumerable(node.FullSpan), options, rules: null, cancellationToken: cancellationToken);
Пример #18
0
        public static SyntaxNode Format(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, SyntaxAnnotation annotation, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken)
        {
            var spans = (annotation == SyntaxAnnotation.ElasticAnnotation)
                ? GetElasticSpans(node)
                : GetAnnotatedSpans(node, annotation);

            return(Format(node, syntaxFormattingService, spans, options, rules, cancellationToken: cancellationToken));
        }
Пример #19
0
 public static SyntaxNode Format(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, OptionSet options, CancellationToken cancellationToken)
 => Format(node, syntaxFormattingService, SpecializedCollections.SingletonEnumerable(node.FullSpan), options, rules: null, cancellationToken: cancellationToken);
Пример #20
0
        internal static async Task <SyntaxTree> FormatAsync(SyntaxTree syntaxTree, ISyntaxFormattingService syntaxFormattingService, IEnumerable <TextSpan> spans, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException(nameof(syntaxTree));
            }

            var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var documentOptions = options ?? DictionaryAnalyzerConfigOptions.Empty;

            return(syntaxTree.WithRootAndOptions(Format(root, syntaxFormattingService, spans, documentOptions, rules, cancellationToken), syntaxTree.Options));
        }
        internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, FormatterState formatterState, DiagnosticDescriptor descriptor, OptionSet options)
        {
            var tree = context.Tree;
            var cancellationToken = context.CancellationToken;

            var oldText           = tree.GetText(cancellationToken);
            var formattingChanges = Formatter.GetFormattedTextChanges(tree.GetRoot(cancellationToken), formatterState, options, cancellationToken);

            // formattingChanges could include changes that impact a larger section of the original document than
            // necessary. Before reporting diagnostics, process the changes to minimize the span of individual
            // diagnostics.
            foreach (var formattingChange in formattingChanges)
            {
                var change = formattingChange;
                if (change.NewText.Length > 0 && !change.Span.IsEmpty)
                {
                    // Handle cases where the change is a substring removal from the beginning. In these cases, we want
                    // the diagnostic span to cover the unwanted leading characters (which should be removed), and
                    // nothing more.
                    var offset = change.Span.Length - change.NewText.Length;
                    if (offset >= 0)
                    {
                        if (oldText.GetSubText(new TextSpan(change.Span.Start + offset, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText)))
                        {
                            change = new TextChange(new TextSpan(change.Span.Start, offset), "");
                        }
                        else
                        {
                            // Handle cases where the change is a substring removal from the end. In these cases, we want
                            // the diagnostic span to cover the unwanted trailing characters (which should be removed), and
                            // nothing more.
                            if (oldText.GetSubText(new TextSpan(change.Span.Start, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText)))
                            {
                                change = new TextChange(new TextSpan(change.Span.Start + change.NewText.Length, offset), "");
                            }
                        }
                    }
                }

                if (change.NewText.Length == 0 && change.Span.IsEmpty)
                {
                    // No actual change (allows for the formatter to report a NOP change without triggering a
                    // diagnostic that can't be fixed).
                    continue;
                }

                var location = Location.Create(tree, change.Span);
                context.ReportDiagnostic(Diagnostic.Create(
                                             descriptor,
                                             location,
                                             additionalLocations: null,
                                             properties: null));
            }
        }
Пример #22
0
        internal static IList <TextChange> GetFormattedTextChanges(SyntaxNode node, ISyntaxFormattingService syntaxFormattingService, IEnumerable <TextSpan> spans, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken)
        {
            var formattingResult = GetFormattingResult(node, syntaxFormattingService, spans, options, rules, cancellationToken);

            return(formattingResult == null
                ? SpecializedCollections.EmptyList <TextChange>()
                : formattingResult.GetTextChanges(cancellationToken));
        }
Пример #23
0
 public static Task <SyntaxTree> FormatAsync(SyntaxTree syntaxTree, ISyntaxFormattingService syntaxFormattingService, TextSpan span, OptionSet options, CancellationToken cancellationToken)
 => FormatAsync(syntaxTree, syntaxFormattingService, SpecializedCollections.SingletonEnumerable(span), options, cancellationToken);
 public virtual bool OpenFileOnly(OptionSet options)
 => false;
 public AnalyzerConfigOptionsImpl(AnalyzerConfigOptions options, AnalyzerConfigOptions fallbackOptions)
 {
     _options         = options;
     _fallbackOptions = fallbackOptions;
 }