{"id":13594615,"url":"https://github.com/GuOrg/Gu.Roslyn.Extensions","last_synced_at":"2025-04-09T07:33:22.594Z","repository":{"id":28103908,"uuid":"116278047","full_name":"GuOrg/Gu.Roslyn.Extensions","owner":"GuOrg","description":"Extensions for analyzers \u0026 code fixes.","archived":false,"fork":false,"pushed_at":"2024-05-18T08:37:45.000Z","size":2441,"stargazers_count":18,"open_issues_count":7,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-29T06:11:16.083Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GuOrg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-04T15:48:28.000Z","updated_at":"2024-05-18T08:37:50.000Z","dependencies_parsed_at":"2023-11-06T13:43:51.916Z","dependency_job_id":"abff8e43-931e-4a00-b319-2a65a7ee89db","html_url":"https://github.com/GuOrg/Gu.Roslyn.Extensions","commit_stats":{"total_commits":1181,"total_committers":4,"mean_commits":295.25,"dds":0.04826418289585099,"last_synced_commit":"bbc45fb44b67157e73956da75a0380126785fc76"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuOrg%2FGu.Roslyn.Extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuOrg%2FGu.Roslyn.Extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuOrg%2FGu.Roslyn.Extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuOrg%2FGu.Roslyn.Extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GuOrg","download_url":"https://codeload.github.com/GuOrg/Gu.Roslyn.Extensions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223137689,"owners_count":17093598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T16:01:36.532Z","updated_at":"2024-11-06T16:31:39.284Z","avatar_url":"https://github.com/GuOrg.png","language":"C#","funding_links":[],"categories":["C#","C\\#"],"sub_categories":[],"readme":"# Gu.Roslyn.Extensions\nExtensions for analyzers \u0026amp; code fixes.\n\n[![Build status](https://ci.appveyor.com/api/projects/status/ipk8pqx4n4m7y8u8/branch/master?svg=true)](https://ci.appveyor.com/project/JohanLarsson/gu-roslyn-extensions/branch/master)\n[![Build Status](https://dev.azure.com/guorg/Gu.Roslyn.Extensions/_apis/build/status/GuOrg.Gu.Roslyn.Extensions?branchName=master)](https://dev.azure.com/guorg/Gu.Roslyn.Extensions/_build/latest?definitionId=9\u0026branchName=master)\n[![NuGet](https://img.shields.io/nuget/v/Gu.Roslyn.Extensions.Source.svg)](https://www.nuget.org/packages/Gu.Roslyn.Extensions.Source/)\n\nReason there are three packages is if analyzer author writes analyzers and fixes in separate projetcs. In that case the separate `Gu.Roslyn.AnalyzerExtensions` and `Gu.Roslyn.CodeFixExtensions` should be used.\n\nThe `Gu.Roslyn.Extensions` package is a merge of `Gu.Roslyn.AnalyzerExtensions` and `Gu.Roslyn.CodeFixExtensions`.\n\n- [Pooled](#pooled)\n  - [PooledSet\u003cT\u003e](#pooledset-t)\n  - [StringBuilderPool](#stringbuilderpool)\n- [StyleCopComparers](#stylecopcomparers)\n- [Symbols](#symbols)\n  - [QualifiedType](#qualifiedtype)\n  - [QualifiedMember](#qualifiedmember)\n  - [SymbolExt](#symbolext)\n    - [TrySingleDeclaration](#trysingledeclaration)\n  - [TypeSymbolExt](#typesymbolext)\n    - [IsAssignableTo](#isassignableto)\n    - [TryFindMember](#tryfindmember)\n    - [TryFindMemberRecursive](#tryfindmemberrecursive)\n- [Syntax](#syntax)\n  - [ArgumentListSyntaxExt](#argumentlistsyntaxext)\n    - [TryFind](#tryfind)\n  - [ArgumentSyntaxExt](#argumentsyntaxext)\n    - [TryGetStringValue](#trygetstringvalue)\n    - [TryFindParameter](#tryfindparameter)\n  - [BasePropertyDeclarationSyntaxExt](#basepropertydeclarationsyntaxext)\n    - [TryGetGetter and TryGetSetter](#trygetgetter-and-trygetsetter)\n    - [IsGetOnly](#isgetonly)\n    - [IsAutoProperty](#isautoproperty)\n  - [SyntaxNodeExt](#syntaxnodeext)\n    - [IsExecutedBefore](#isexecutedbefore)\n  - [TypeSyntaxExt](#typesyntaxext)\n    - [TryFindMember](#tryfindmember)\n- [Doc comments](#doc-comments)\n  - [MemberDeclarationSyntaxExtensions.TryGetDocumentationComment](#memberdeclarationsyntaxextensionstrygetdocumentationcomment)\n  - [DocumentationCommentTriviaSyntaxExtensions.TryGetX](#documentationcommenttriviasyntaxextensionstrygetx)\n  - [DocumentationCommentTriviaSyntaxExtensions.WithX](#documentationcommenttriviasyntaxextensionswithx)\n  - [DocumentationCommentTriviaSyntaxExtensions.WithX](#documentationcommenttriviasyntaxextensionswithx)\n- [Walkers](#walkers)\n  - [ExecutionWalker\u003cT\u003e : PooledWalker\u003cT\u003e](#executionwalker-t--pooledwalker-t)\n    - [PooledWalker\u003cT\u003e](#pooledwalker-t)\n    - [Cache\u003cTKey, TValue\u003e](#cache-tkey--tvalue)\n    - [EnumarebleExt](#enumarebleext)\n- [FixAll](#fixall)\n  - [DocumentEditorCodeFixProvider](#documenteditorcodefixprovider)\n- [CodeStyle](#codestyle)\n  - [UnderscoreFields](#underscorefields)\n  - [UsingDirectivesInsideNamespace](#usingdirectivesinsidenamespace)\n  - [BackingFieldsAdjacent](#backingfieldsadjacent)\n- [DocumentEditorExt](#documenteditorext)\n  - [AddUsing](#addusing)\n  - [AddField](#addfield)\n  - [AddProperty](#addproperty)\n  - [AddMethod](#addmethod)\n- [Simplify](#simplify)\n  - [WithSimplifiedNames\u003cT\u003e](#withsimplifiednames-t)\n- [Trivia](#trivia)\n  - [WithTriviaFrom](#withtriviafrom)\n  - [WithLeadingTriviaFrom](#withleadingtriviafrom)\n  - [WithTrailingTriviaFrom](#withtrailingtriviafrom)\n\n# Pooled\n\n## PooledSet\u003cT\u003e\n```cs\nusing (var set = PooledSet\u003cint\u003e.Borrow())\n{\n}\n```\n\nOr when used recursively:\n```cs\n// set can be null here if so a new set its returned.\nusing (var current = set.IncrementUsage())\n{\n}\n\n## StringBuilderPool\n```cs\nvar text = StringBuilderPool.Borrow()\n                            .AppendLine(\"a\")\n                            .AppendLine()\n                            .AppendLine(\"b\")\n                            .Return();\n```\n\n# StyleCopComparers\n\nComparers that compare member declarations with stylecop order.\n\n# Symbols\n\n## QualifiedType\nFor comparing with `ITypeSymbol`\n\n```cs\npublic static readonly QualifiedType Object = new QualifiedType(\"System.Object\", \"object\");\n```\n\n## QualifiedMember\nSame as `QualifiedType` but for members.\n\n## SymbolExt\n\nExtension methods for `ISymbol`.\n\n### TrySingleDeclaration\n\nGet the declaration if it exists. If the symbol is from a binary reference the declaration will not exist.\n\n## TypeSymbolExt\n\nExtension methods for `ItypeSymbol`.\n\n### IsAssignableTo\n\nFor checking if `C is Type`\n\n### TryFindMember\n\nFind members by name or predicate.\n\n### TryFindMemberRecursive\n\nFind members by name or predicate in type or base types.\n\n# Syntax\n\n## ArgumentListSyntaxExt\n\n### TryFind\n\nFind the argument that matches the parameter.\n\n## ArgumentSyntaxExt\n\n### TryGetStringValue\n\nTry get the constant string value of the argument.\n\n### TryFindParameter\n\nTry get the matching parameter\n\n## BasePropertyDeclarationSyntaxExt\n\n### TryGetGetter and TryGetSetter\nGet the getter or setter if exists.\n\n### IsGetOnly\n\nCheck if the property is `public int Value { get; }`\n\n### IsAutoProperty\n\nCheck if the property is an auto property.\n\n## SyntaxNodeExt\n\n### IsExecutedBefore\n\nCheck if a node is executed before another node.\n\n## TypeSyntaxExt\n\n### TryFindMember\n\nHelper methods for finding members by name or predicate.\n\n# Doc comments\n\n## MemberDeclarationSyntaxExtensions.TryGetDocumentationComment\n\n```cs\nif(member.TryGetDocumentationComment(out DocumentationCommentTriviaSyntax comment))\n{\n}\n```\n\n## DocumentationCommentTriviaSyntaxExtensions.TryGetX\n\n```cs\nif(comment.TryGetSummary(out XmlElementSyntax comment))\n{\n}\n\nif(comment.TryGetTypeParam(\"T\", out XmlElementSyntax comment))\n{\n}\n\nif(comment.TryGetParam(\"x\", out XmlElementSyntax comment))\n{\n}\n\nif(comment.TryGetReturns(out XmlElementSyntax comment))\n{\n}\n```\n\n## DocumentationCommentTriviaSyntaxExtensions.WithX\n\n```cs\nvar updated = comment.WithSummaryText(\"Lorem ipsum.\")\nvar updated = comment.WithTypeParamText(\"T\", \"Lorem ipsum.\")\nvar updated = comment.WithParamText(\"x\", \"Lorem ipsum.\")\nvar updated = comment.WithReturnsText(\"x\", \"Lorem ipsum.\")\n```\n\n## MemberDeclarationSyntax.WithDocumentationText\n\n```cs\nvar method = syntaxTree.FindMethodDeclaration(\"Bar\");\nvar text = \"/// \u003csummary\u003eNew summary.\u003c/summary\u003e\\r\\n\" +\n           \"/// \u003creturns\u003eNew returns.\u003c/returns\u003e\";\nvar updated = method.WithDocumentationText(text);\n```\n\n\n# Walkers\n\n## ExecutionWalker\u003cT\u003e : PooledWalker\u003cT\u003e\n\nBase type for a walker that walks code in execution order. Use the `Search` enum to specify if walk should be recursive walking invoked methods etc.\nRemember to clear locals in the `Clear` method.\n\n```cs\ninternal sealed class AssignmentExecutionWalker : ExecutionWalker\u003cAssignmentExecutionWalker\u003e\n{\n    private readonly List\u003cAssignmentExpressionSyntax\u003e assignments = new List\u003cAssignmentExpressionSyntax\u003e();\n\n    private AssignmentExecutionWalker()\n    {\n    }\n\n    /// \u003csummary\u003e\n    /// Gets a list with all \u003csee cref=\"AssignmentExpressionSyntax\"/\u003e in the scope.\n    /// \u003c/summary\u003e\n    public IReadOnlyList\u003cAssignmentExpressionSyntax\u003e Assignments =\u003e this.assignments;\n\n    public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)\n    {\n        this.assignments.Add(node);\n        base.VisitAssignmentExpression(node);\n    }\n\n    internal static AssignmentExecutionWalker Borrow(SyntaxNode node, Search search, SemanticModel semanticModel, CancellationToken cancellationToken)\n    {\n        var walker = Borrow(() =\u003e new AssignmentExecutionWalker());\n        walker.SemanticModel = semanticModel;\n        walker.CancellationToken = cancellationToken;\n        walker.Search = search;\n        walker.Visit(node);\n        return walker;\n    }\n\n\n    protected override void Clear()\n    {\n        this.assignments.Clear();\n        base.Clear();\n    }\n}\n```\n\n### PooledWalker\u003cT\u003e\n\nA pooled walker for reuse.\nRemember to clear locals in the `Clear` method.\n\n```cs\ninternal sealed class IdentifierNameWalker : PooledWalker\u003cIdentifierNameWalker\u003e\n{\n    private readonly List\u003cIdentifierNameSyntax\u003e identifierNames = new List\u003cIdentifierNameSyntax\u003e();\n\n    private IdentifierNameWalker()\n    {\n    }\n\n    public IReadOnlyList\u003cIdentifierNameSyntax\u003e IdentifierNames =\u003e this.identifierNames;\n\n    public static IdentifierNameWalker Borrow(SyntaxNode node) =\u003e BorrowAndVisit(node, () =\u003e new IdentifierNameWalker());\n\n    public override void VisitIdentifierName(IdentifierNameSyntax node)\n    {\n        this.identifierNames.Add(node);\n        base.VisitIdentifierName(node);\n    }\n\n    protected override void Clear()\n    {\n        this.identifierNames.Clear();\n    }\n}\n```\n\n### Cache\u003cTKey, TValue\u003e\n\nFor caching expensive calls\n\n```cs\npublic override void Initialize(AnalysisContext context)\n{\n    context.CacheToCompilationEnd\u003cSyntaxTree, SemanticModel\u003e();\n}\n```\n\n### EnumarebleExt\n\nExtension methods for enumarebls \n- TrySingle\n- TryLast\n- TryElementAt\n\n# FixAll\n## DocumentEditorCodeFixProvider\nA fix all provider that use document editor for batch fixes.\n\n```cs\n[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UseParameterCodeFixProvider))]\n[Shared]\ninternal class UseParameterCodeFixProvider : DocumentEditorCodeFixProvider\n{\n    /// \u003cinheritdoc/\u003e\n    public override ImmutableArray\u003cstring\u003e FixableDiagnosticIds { get; } =\n        ImmutableArray.Create(GU0014PreferParameter.DiagnosticId);\n\n    /// \u003cinheritdoc/\u003e\n    protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context)\n    {\n        var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)\n                                        .ConfigureAwait(false);\n\n        foreach (var diagnostic in context.Diagnostics)\n        {\n            if (diagnostic.Properties.TryGetValue(\"Name\", out var name))\n            {\n                if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) is MemberAccessExpressionSyntax memberAccess)\n                {\n                    context.RegisterCodeFix(\n                        \"Prefer parameter.\",\n                        (editor, _) =\u003e editor.ReplaceNode(\n                            memberAccess,\n                            SyntaxFactory.IdentifierName(name)\n                                            .WithLeadingTriviaFrom(memberAccess)),\n                        \"Prefer parameter.\",\n                        diagnostic);\n                }\n                else if (syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) is IdentifierNameSyntax identifierName)\n                {\n                    context.RegisterCodeFix(\n                        \"Prefer parameter.\",\n                        (editor, _) =\u003e editor.ReplaceNode(\n                            identifierName,\n                            identifierName.WithIdentifier(SyntaxFactory.Identifier(name))\n                                            .WithLeadingTriviaFrom(identifierName)),\n                        \"Prefer parameter.\",\n                        diagnostic);\n                }\n            }\n        }\n    }\n}\n```\n\n# CodeStyle\n\nHelpers for determinining the code style used in the project.\n\n## UnderscoreFields\n\n## UsingDirectivesInsideNamespace\n\n## BackingFieldsAdjacent \nFigures out if backing field is placed like stylecop wants it or adjacent to the property.\n\n# DocumentEditorExt\n\nHelpers for adding members sorted according to how StyleCop wants it.\n\n## AddUsing\n\nAdds the using sorted and figures out if it shoul add outside or insside the namespace from the current document then project.\n\n## AddField \n\nAdds the field at the position StyleCop wants it.\n\n## AddProperty \n\nAdds the property at the position StyleCop wants it.\n\n## AddMethod \n\nAdds the method at the position StyleCop wants it.\n\n# Simplify\n\n## WithSimplifiedNames\u003cT\u003e \nUses a syntax rewriter that adds `Simplifier.Annotation` to all `QualifiedNameSyntax`\n\n# Trivia\n\nHelpers for copying trivia from other nodes.\n\n## WithTriviaFrom\nCopy trivia from a node.\n\n## WithLeadingTriviaFrom\n\nCopy leading trivia from a node.\n\n## WithTrailingTriviaFrom\n\nCopy trailing trivia from a node.\n\n# Source package\n\nGu.Roslyn.Extensions.Source is a package containing the sources for embedding in consuming analyzer.\nThis is probably the best way to consume this library as Visual Studio and other tools do not work well when an analyzer has a binary dependency.\nTo work it requires:\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cPackageDownload Include=\"Microsoft.NETCore.App.Ref\" Version=\"[5.0.0]\" /\u003e\n    \u003cPackageReference Include=\"TunnelVisionLabs.ReferenceAssemblyAnnotator\" Version=\"1.0.0-alpha.160\" PrivateAssets=\"all\"/\u003e\n  \u003c/ItemGroup\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGuOrg%2FGu.Roslyn.Extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGuOrg%2FGu.Roslyn.Extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGuOrg%2FGu.Roslyn.Extensions/lists"}