{"id":13593630,"url":"https://github.com/cezarypiatek/CSharpExtensions","last_synced_at":"2025-04-09T05:31:50.070Z","repository":{"id":40296658,"uuid":"244122100","full_name":"cezarypiatek/CSharpExtensions","owner":"cezarypiatek","description":"A set of annotations and analyzers that add additional constraints to your codebase","archived":false,"fork":false,"pushed_at":"2024-04-20T09:33:54.000Z","size":629,"stargazers_count":125,"open_issues_count":8,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-04T23:09:33.313Z","etag":null,"topics":["roslyn","roslyn-analyzers"],"latest_commit_sha":null,"homepage":"","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/cezarypiatek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://www.buymeacoffee.com/tmAJLYvWy"}},"created_at":"2020-03-01T09:36:44.000Z","updated_at":"2025-02-03T17:25:13.000Z","dependencies_parsed_at":"2024-05-28T09:53:16.287Z","dependency_job_id":"30c3539e-87f1-468e-b612-c2f539d79b73","html_url":"https://github.com/cezarypiatek/CSharpExtensions","commit_stats":{"total_commits":92,"total_committers":4,"mean_commits":23.0,"dds":0.03260869565217395,"last_synced_commit":"bd52d9714c0cd16861b153f7dc02a2adc042441b"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FCSharpExtensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FCSharpExtensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FCSharpExtensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FCSharpExtensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cezarypiatek","download_url":"https://codeload.github.com/cezarypiatek/CSharpExtensions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261612,"owners_count":20910108,"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":["roslyn","roslyn-analyzers"],"created_at":"2024-08-01T16:01:22.385Z","updated_at":"2025-04-09T05:31:49.778Z","avatar_url":"https://github.com/cezarypiatek.png","language":"C#","funding_links":["https://www.buymeacoffee.com/tmAJLYvWy"],"categories":["C#","C\\#"],"sub_categories":[],"readme":"# CSharpExtensions\r\n\r\nNuget packge: https://www.nuget.org/packages/SmartAnalyzers.CSharpExtensions.Annotations/\r\n\r\nArticles that explain implemented concepts:\r\n- [Immutable types in C# with Roslyn](https://cezarypiatek.github.io/post/immutable-types-with-roslyn/)\r\n- [Improving non-nullable reference types handling](https://cezarypiatek.github.io/post/better-non-nullable-handling/)\r\n- [Twin types - properties synchronization without inheritance](https://cezarypiatek.github.io/post/csharp-twin-types/)\r\n- [Pure functions and unused return values](https://cezarypiatek.github.io/post/pure-functions-and-unused-return-value/)\r\n\r\n## Analyzers\r\n\r\n|Rule|Description| Related attributes|Documentation|\r\n|----|-----------|-------------------|-------------|\r\n|CSE001|Required properties initialization| `[InitRequired]`, `[InitRequiredForNotNull]` | [link](https://cezarypiatek.github.io/post/immutable-types-with-roslyn/#convenient-initialization) |\r\n|CSE002|InitOnly member modification |`[InitOnly]`, `[InitOnlyOptional]`| [link](https://cezarypiatek.github.io/post/immutable-types-with-roslyn/#full-immutability) |\r\n|CSE003|Type should have the same fields as twin type| `[TwinType]` | [link](https://cezarypiatek.github.io/post/csharp-twin-types/#the-solution-extending-c-rules-with-custom-analyzer)|\r\n|CSE004| Member with InitOnlyOptional requires default value| `[InitOnlyOptional]` ||\r\n|CSE005| Return value unused | | [link](https://cezarypiatek.github.io/post/pure-functions-and-unused-return-value/)|\r\n|CSE006| Expression too complex | | |\r\n|CSE007| Return disposable value unused | | Same as `SE005` but tracks only `IDisposable` and `IAsyncDisposable` values |\r\n|CSE008| Return async result unused | | Same as `SE005` but tracks only `IAsyncResult` (`Task`, `ValueTask`) values |\r\n|CSE009| Task variable not awaited | | Check if task stored in a variable is awaited |\r\n\r\n\r\n## Configuration\r\n\r\nAdd `CSharpExtensions.json` file with custom configuration:\r\n\r\n```json\r\n{\r\n  \"CSE005\": {\r\n    \"IgnoredReturnTypes\": [ \r\n        \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\r\n        \"Microsoft.Extensions.Configuration.IConfigurationBuilder\",\r\n        \"Microsoft.Extensions.Logging.ILoggingBuilder\"\r\n        ] \r\n  } \r\n}\r\n```\r\n\r\nInclude config file as `AdditionalFile` in `csproj`:\r\n\r\n```xml\r\n\u003cItemGroup\u003e\r\n    \u003cAdditionalFiles Include=\"CSharpExtensions.json\" /\u003e\r\n\u003c/ItemGroup\u003e\r\n```\r\n\r\n## Migrating from Constructors to Initialization Blocks\r\n\r\n**Step 1:** Configure `CSharpExtensions` to report `CSE001` even when constructor invocation is present\r\n\r\n```json\r\n{\r\n  \"CSE001\": {\r\n    \"SkipWhenConstructorUsed\":  false \r\n  } \r\n}\r\n```\r\n\r\n**Step 2:** Execute `\"Try to move initialization from constructor to init block\"` CodeFix for `CSE001` occurrences.\r\n\r\n![](/doc/constructor_to_init.gif)\r\n\r\n## Init-related attributes vs [init keyword](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init) (C# 9+ feature)\r\n\r\n|Feature | Required in init block | Can be modified outside init block| Application level|\r\n|----|----|---|---|\r\n| `init` keyword | NO | NO| Property|\r\n|`[InitRequired]`| YES | YES | Property. Class|\r\n|`[InitOnly]`| YES | NO | Property. Class|\r\n|`[InitOnlyOptional]`| NO | NO | Property. Class|\r\n|`[InitRequiredForNotNull]`| YES for non-null references and not `Nullable\u003cT\u003e` | YES | assembly|\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcezarypiatek%2FCSharpExtensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcezarypiatek%2FCSharpExtensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcezarypiatek%2FCSharpExtensions/lists"}