/// <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() })); } }
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())); } }
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()); }
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 })); } }
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); } } } }
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))); } } }
/// <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); }