示例#1
0
        /// <summary>
        /// Add a using directive.
        /// </summary>
        /// <param name="compilationUnit">The <see cref="CompilationUnitSyntax"/>.</param>
        /// <param name="usingDirective">The <see cref="UsingDirectiveSyntax"/>.</param>
        /// <param name="semanticModel">The <see cref="SemanticModel"/>.</param>
        /// <returns>The updated <see cref="CompilationUnitSyntax"/>.</returns>
        public static CompilationUnitSyntax AddUsing(this CompilationUnitSyntax compilationUnit, UsingDirectiveSyntax usingDirective, SemanticModel semanticModel)
        {
            if (compilationUnit is null)
            {
                throw new System.ArgumentNullException(nameof(compilationUnit));
            }

            if (semanticModel is null)
            {
                throw new System.ArgumentNullException(nameof(semanticModel));
            }

            if (usingDirective is null)
            {
                throw new System.ArgumentNullException(nameof(usingDirective));
            }

            if (compilationUnit.Members.TrySingleOfType <MemberDeclarationSyntax, NamespaceDeclarationSyntax>(out NamespaceDeclarationSyntax? ns) &&
                UsingDirectiveComparer.IsSameOrContained(ns, usingDirective))
            {
                return(compilationUnit);
            }

            using (var walker = UsingDirectiveWalker.Borrow(compilationUnit))
            {
                if (walker.UsingDirectives.Count == 0)
                {
                    if (walker.NamespaceDeclarations.TryFirst(out var namespaceDeclaration))
                    {
                        if (CodeStyle.UsingDirectivesInsideNamespace(semanticModel) != CodeStyleResult.No)
                        {
                            return(compilationUnit.ReplaceNode(namespaceDeclaration, namespaceDeclaration.WithUsings(SyntaxFactory.SingletonList(usingDirective))));
                        }

                        return(compilationUnit.ReplaceNode(compilationUnit, compilationUnit.WithUsings(SyntaxFactory.SingletonList(usingDirective))));
                    }

                    return(compilationUnit);
                }

                UsingDirectiveSyntax?previous = null;
                foreach (var directive in walker.UsingDirectives)
                {
                    var compare = UsingDirectiveComparer.Compare(directive, usingDirective);
                    if (compare == 0)
                    {
                        return(compilationUnit);
                    }

                    if (compare > 0)
                    {
                        return(compilationUnit.InsertNodesBefore(directive, new[] { usingDirective.WithTrailingElasticLineFeed() }));
                    }

                    previous = directive;
                }

                return(compilationUnit.InsertNodesAfter(previous, new[] { usingDirective.WithTrailingElasticLineFeed() }));
            }
        }
示例#2
0
        public static void Borrow()
        {
            var tree     = CSharpSyntaxTree.ParseText(@"
namespace N
{
    using System;
    using static NUnit.Framework.Assert;

    public class C
    {
        public C()
        {
            AreEqual(1, 1);
        }
    }
}");
            var expected = new[] { "using System;", "using static NUnit.Framework.Assert;" };

            using (var walker = UsingDirectiveWalker.Borrow(tree))
            {
                CollectionAssert.AreEqual(expected, walker.UsingDirectives.Select(x => x.ToString()));
            }

            using (var walker = UsingDirectiveWalker.Borrow(tree.GetRoot(CancellationToken.None)))
            {
                CollectionAssert.AreEqual(expected, walker.UsingDirectives.Select(x => x.ToString()));
            }
        }
示例#3
0
        private static Result UsingDirectivesInsideNamespace(this SyntaxTree tree, UsingDirectiveWalker walker)
        {
            if (IsExcluded(tree))
            {
                return(Result.Unknown);
            }

            if (tree.TryGetRoot(out var root))
            {
                walker.Visit(root);
            }

            return(walker.UsingDirectivesInside());
        }
示例#4
0
        private static SyntaxNode AddUsing(CompilationUnitSyntax root, SemanticModel semanticModel, UsingDirectiveSyntax usingDirective)
        {
            if (root == null)
            {
                return(null);
            }

            using (var walker = UsingDirectiveWalker.Borrow(root))
            {
                if (walker.UsingDirectives.Count == 0)
                {
                    if (walker.NamespaceDeclarations.TryFirst(out var namespaceDeclaration))
                    {
                        if (CodeStyle.UsingDirectivesInsideNamespace(semanticModel))
                        {
                            return(root.ReplaceNode(namespaceDeclaration, namespaceDeclaration.WithUsings(SyntaxFactory.SingletonList(usingDirective))));
                        }

                        return(root.ReplaceNode(root, root.WithUsings(SyntaxFactory.SingletonList(usingDirective))));
                    }

                    return(root);
                }

                UsingDirectiveSyntax previous = null;
                foreach (var directive in walker.UsingDirectives)
                {
                    var compare = UsingDirectiveComparer.Compare(directive, usingDirective);
                    if (compare == 0)
                    {
                        return(root);
                    }

                    if (compare > 0)
                    {
                        return(root.InsertNodesBefore(directive, new[] { usingDirective }));
                    }

                    previous = directive;
                }

                return(root.InsertNodesAfter(previous, new[] { usingDirective }));
            }
        }
示例#5
0
        protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context)
        {
            var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)
                             .ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                if (syntaxRoot?.FindNode(diagnostic.Location.SourceSpan) is MemberAccessExpressionSyntax memberAccess)
                {
                    if (diagnostic.Id == "GULOC04" &&
                        diagnostic.Properties.TryGetValue(nameof(Translate), out var call))
                    {
                        context.RegisterCodeFix(
                            $"{call}",
                            (editor, _) => editor.ReplaceNode(memberAccess, SyntaxFactory.ParseExpression(call)),
                            $"{call}",
                            diagnostic);
                    }

                    context.RegisterCodeFix(
                        "Gu.Localization.Translator.Translate",
                        (editor, _) => editor.ReplaceNode(
                            memberAccess,
                            SyntaxFactory.ParseExpression($"Gu.Localization.Translator.Translate({memberAccess.Expression}.ResourceManager, nameof({memberAccess}))")
                            .WithSimplifiedNames()),
                        "Gu.Localization.Translator.Translate",
                        diagnostic);

                    if (!UsingDirectiveWalker.Contains(syntaxRoot, "Gu.Localization"))
                    {
                        context.RegisterCodeFix(
                            "Add using and call Translator.Translate",
                            (editor, _) => editor.AddUsing(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Gu.Localization")))
                            .ReplaceNode(
                                memberAccess,
                                SyntaxFactory.ParseExpression(
                                    $"Translator.Translate({memberAccess.Expression}.ResourceManager, nameof({memberAccess}))")
                                .WithSimplifiedNames()),
                            "Add using and call Translator.Translate",
                            diagnostic);
                    }
                }
            }
        }
示例#6
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (context.Node is ClassDeclarationSyntax classDeclaration &&
                context.ContainingSymbol is INamedTypeSymbol type)
            {
                if (InvocationWalker.TryFindName(classDeclaration, out var name) &&
                    type.Name != name &&
                    type.ContainingType?.Name != name)
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.GURA04NameClassToMatchAsserts,
                            classDeclaration.Identifier.GetLocation(),
                            ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), name),
                            context.ContainingSymbol.ToMinimalDisplayString(context.SemanticModel, classDeclaration.SpanStart),
                            name));
                }

                if (ShouldRenameFile(classDeclaration.SyntaxTree, type, out name))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.GURA05NameFileToMatchClass,
                            classDeclaration.Identifier.GetLocation(),
                            ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), name),
                            context.ContainingSymbol.ToMinimalDisplayString(context.SemanticModel, classDeclaration.SpanStart),
                            name));
                }

                if ((!type.IsStatic || type.DeclaredAccessibility != Accessibility.Public) &&
                    UsingDirectiveWalker.IsUsingNUnit(context.SemanticModel.SyntaxTree) &&
                    type.BaseType == KnownSymbols.Object &&
                    type.Interfaces.IsDefaultOrEmpty &&
                    type.TryFindFirstMethod(x => x.TryGetAttribute(KnownSymbols.NUnitTestAttribute, out _) || x.TryGetAttribute(KnownSymbols.NUnitTestCaseAttribute, out _), out _))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.GURA07TestClassShouldBePublicStatic,
                            classDeclaration.Identifier.GetLocation(),
                            type.ToMinimalDisplayString(context.SemanticModel, classDeclaration.SpanStart)));
                }
            }
        }
示例#7
0
        /// <summary>
        /// Figuring out if the code uses using directives inside namespaces.
        /// </summary>
        /// <param name="semanticModel">The <see cref="SemanticModel"/></param>
        /// <returns>True if the code is found to prefix field names with underscore.</returns>
        internal static bool UsingDirectivesInsideNamespace(SemanticModel semanticModel)
        {
            using (var walker = UsingDirectiveWalker.Borrow())
            {
                switch (UsingDirectivesInsideNamespace(semanticModel.SyntaxTree, walker))
                {
                case Result.Unknown:
                case Result.Maybe:
                    break;

                case Result.Yes:
                    return(true);

                case Result.No:
                    return(false);

                default:
                    throw new ArgumentOutOfRangeException();
                }

                foreach (var tree in semanticModel.Compilation.SyntaxTrees)
                {
                    switch (UsingDirectivesInsideNamespace(tree, walker))
                    {
                    case Result.Unknown:
                    case Result.Maybe:
                        break;

                    case Result.Yes:
                        return(true);

                    case Result.No:
                        return(false);

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }

            return(true);
        }