{"id":15597619,"url":"https://github.com/ulrichb/implicitnullability","last_synced_at":"2025-04-28T10:27:54.135Z","repository":{"id":32446549,"uuid":"36024920","full_name":"ulrichb/ImplicitNullability","owner":"ulrichb","description":"Extends ReSharper's static nullability analysis by changing specific, configurable elements to be [NotNull] by default","archived":false,"fork":false,"pushed_at":"2021-05-12T07:51:53.000Z","size":2213,"stargazers_count":44,"open_issues_count":1,"forks_count":7,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-18T14:35:39.384Z","etag":null,"topics":["c-sharp","default-nullability","notnull","nullability","nullability-analysis","resharper","static-analysis"],"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/ulrichb.png","metadata":{"files":{"readme":"README.md","changelog":"History.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-21T16:39:42.000Z","updated_at":"2022-11-27T17:29:28.000Z","dependencies_parsed_at":"2022-08-27T09:11:22.289Z","dependency_job_id":null,"html_url":"https://github.com/ulrichb/ImplicitNullability","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulrichb%2FImplicitNullability","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulrichb%2FImplicitNullability/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulrichb%2FImplicitNullability/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulrichb%2FImplicitNullability/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ulrichb","download_url":"https://codeload.github.com/ulrichb/ImplicitNullability/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251294174,"owners_count":21566221,"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":["c-sharp","default-nullability","notnull","nullability","nullability-analysis","resharper","static-analysis"],"created_at":"2024-10-03T01:22:37.697Z","updated_at":"2025-04-28T10:27:54.115Z","avatar_url":"https://github.com/ulrichb.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":":warning: **End-of-life note:** C# 8+ (VS 2019+) supports [_nullable reference types_](https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/nullable-reference-types) which [supersedes](#c-nullable-reference-types) - and perfectly aligns with - _Implicit Nullability_. Therefore ReSharper/Rider 2020.1 is the last version supported by _Implicit Nullability_.\n\n## Implicit Nullability ReSharper Extension\n\n[![Build status](https://teamcity.jetbrains.com/app/rest/builds/buildType:(id:OpenSourceProjects_ImplicitNullability_Ci),branch:master,running:any/statusIcon.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=OpenSourceProjects_ImplicitNullability_Ci)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ulrichb/ImplicitNullability?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\u003ca href=\"https://teamcity.jetbrains.com/viewType.html?buildTypeId=OpenSourceProjects_ImplicitNullability_Ci\u0026branch=master\"\u003e\u003cimg src=\"https://dl.dropbox.com/s/tz8rhb0ucv3lruo/master-linecoverage.svg\" alt=\"Line Coverage\" title=\"Line Coverage\"\u003e\u003c/a\u003e\n\u003ca href=\"https://teamcity.jetbrains.com/viewType.html?buildTypeId=OpenSourceProjects_ImplicitNullability_Ci\u0026branch=master\"\u003e\u003cimg src=\"https://dl.dropbox.com/s/4pmdllotpgd46kj/master-branchcoverage.svg\" alt=\"Branch Coverage\" title=\"Branch Coverage\"\u003e\u003c/a\u003e\n\n[ReSharper Gallery Page](https://resharper-plugins.jetbrains.com/packages/ReSharper.ImplicitNullability/)\n\n[History of changes](History.md)\n\n## Idea\n\nThe basic idea of this extension is to change the behavior of ReSharper's [static nullability analysis](https://www.jetbrains.com/resharper/help/Code_Analysis__Code_Annotations.html) so that specific code elements get a default nullability annotation without specifying an explicit `[NotNull]` or `[CanBeNull]` attribute. For example, reference types in method parameters are by default `[NotNull]` (→ they need an explicit `[CanBeNull]` to become nullable).\n\n\u003cimg src=\"/Doc/Sample.png\" alt=\"Code Sample\" width=\"647\" /\u003e\n\nWith enabled _Implicit Nullability_ for specific, [configurable](#configuration), syntax elements, the following rules apply.\n\n\u003c!-- duplicated in the options page --\u003e\n * Reference types are by default implicitly `[NotNull]`.\n * Their nullability can be overridden with an explicit `[CanBeNull]` attribute.\n * Optional method parameters with a `null` default value are implicitly `[CanBeNull]`.\n\nIn a nutshell, the code showed in the picture above  ...\n```C#\npublic string Bar(string a, [CanBeNull] string b, string c = null)\n{\n    // ...\n}\n```\n... implicitly becomes ...\n```C#\n[NotNull]\npublic string Bar([NotNull] string a, [CanBeNull] string b, [CanBeNull] string c = null)\n{\n    // ...\n}\n```\n\n### `[NotNull]` as default\n\nWithout this extension the default nullability value is \"unknown\" which means that ReSharper excludes these elements for its nullability analysis. As a result of the changed default nullability of this extension we have to place `[CanBeNull]` annotations only for _specific_ code elements (e.g. a reference type parameter where it should be allowed to pass `null` as argument) and don't need explicit annotations for the majority of cases (in code bases which try to reduce passing `null` references to a minimum).\n\n### Async method return types (requires ReSharper 9.2)\n\nReSharper 9.2 [introduced](https://youtrack.jetbrains.com/issue/RSRP-376091) support for nullability analysis for `async` (`Task\u003cT\u003e` return typed) methods. With enabled _Implicit Nullability_ for method return values, `Task\u003cT\u003e` return typed methods also become implicitly `[ItemNotNull]` (ReSharper uses this attribute to refer to the _value_ of `Task\u003cT\u003e`). For nullable `Task\u003cT\u003e` return values, this can be overridden with `[ItemCanBeNull]`.\n\n### Improves static analysis quality\n\nThe following example program contains a potential `NullReferenceException` in `command​.Equals​(\"Hello\")` because the programmer missed that `GetCommand()` could also return `null`.\n\n```C#\npublic static void Main(string[] args)\n{\n    string command = GetCommand(args);\n\n    if (command.Equals(\"Hello\"))\n        Console.WriteLine(\"Hello World!\");\n}\n\nprivate static string GetCommand(string[] args)\n{\n    if (args.Length \u003c 1)\n        return null;\n\n    return args[0];\n}\n```\n\nWith enabled _Implicit Nullability_ this bug would have been detected by ReSharper's static analysis.\n\n 1. ReSharper would warn about returning `null` in `GetCommand()` because this method would be implicitly annotated as `[NotNull]`.\n 2. This warning would be solved by the programmer by adding `[CanBeNull]` to `GetCommand()`.\n 3. As a consequence of the `[CanBeNull]` attribute, ReSharper would now warn about the potential `NullReferenceException` in the `command​.Equals​(\"Hello\")` call in `Main()`.\n\n### Improves documentation\n\nIn the example above _Implicit Nullability_ forces the programmer to fix the missing `[CanBeNull]` attribute on `GetCommand()`. This shows how the number of `[CanBeNull]` annotations will be increased in the code base and therefore doesn't only improve ReSharper's static analysis but also the documentation of method signatures (contracts).\n\n### Fody NullGuard\n\nAnother goal of this extension is to bring ReSharper's static analysis in sync with the implicit null checks of [Fody NullGuard](https://github.com/Fody/NullGuard#readme). For example, this [Fody](https://github.com/Fody/Fody#readme) weaver injects `throw new ArgumentNullException​(/*...*/)` statements for method parameters into method bodies using the same rules as _Implicit Nullability_. In other words this weaver adds _runtime checks_ for nullability to ReSharper's _static_ analysis.\n\n### C# Nullable reference types\n\nC# 8 will get [_Nullable reference types_](https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/nullable-reference-types) which brings option types into the C# language. This matches the semantics of _Implicit Nullability_ and goes even further because it extends it to locals, generic parameters, ... because the nullability annotation works on type level.\n\n```C#\n[CanBeNull]\nstring Bar([CanBeNull] string a, string b)\n{\n    string result = a;\n    return result;\n}\n```\n... then corresponds to ...\n```C#\nstring? Bar(string? a, string b)\n{\n    string? result = a;\n    return result;\n}\n```\n\nThis will make _Implicit Nullability_ unnecessary in the future and at the same time a perfect \"upgrade path\" because a good `[CanBeNull]`-annotated code base will be easily portable to C# 8.\n\n### Differences to ReSharper's \"Implicit [NotNull] Value Analysis Mode\"\n\nSince version 2016.1 ReSharper supports (in the \"internal mode\") a comparable feature (see *Code Inspection | Settings*) with the following differences.\n\n_Implicit Nullability_ ...\n* ... rules can be enabled / disabled for _specific_ code elements like parameters or (readonly) fields.\n* ... supports (project specific) [configuration by code](#code-configuration).\n* ... adds additional [warnings](#code-inspection-warnings).\n* ... adds [type highlighting](#type-highlighting) for explicit or implicit `[NotNull]` elements.\n\n## Type highlighting\n\nExplicit or implicit `[NotNull]` element types are highlighted with a dotted underline. (See the pink underlines in the `Bar`-method in the sample screenshot [above](#idea).) This helps to recognize all `[NotNull]` elements, especially inferred `[NotNull]` elements from a base class and code elements which are configured as implicitly `[NotNull]`.\n\nThe highlighting can be enabled/disabled on the _Implicit Nullability_ options page, and the colors can be configured in Visual Studio's \"Fonts and Colors\" options.\n\n## Configuration\n\nImplicit nullability can be enabled or disabled for specific syntax elements in the *Code Inspection | Implicit Nullability* options page.\n\n\u003cimg src=\"/Doc/OptionsPage.png\" alt=\"Options Page\" /\u003e\n\n### Code configuration\n\n_Implicit Nullability_ can also be configured by code using an [`AssemblyMetadataAttribute`](https://msdn.microsoft.com/en-us/library/system.reflection.assemblymetadataattribute.aspx). This has the advantage that the configuration gets compiled into the assembly so that consumers of the assembly with installed _Implicit Nullability_ get the same implicit nullability annotations of the compiled code elements as _within_ the library's solution.\n\nExample:\n```C#\n[assembly: AssemblyMetadata(\"ImplicitNullability.AppliesTo\",\n                            \"InputParameters, RefParameters, OutParametersAndResult, Fields, Properties\")]\n[assembly: AssemblyMetadata(\"ImplicitNullability.Fields\", \"RestrictToReadonly\")]\n[assembly: AssemblyMetadata(\"ImplicitNullability.Properties\", \"RestrictToGetterOnly\")]\n[assembly: AssemblyMetadata(\"ImplicitNullability.GeneratedCode\", \"Exclude\")]\n```\n\n:warning: After changing the settings (either by code or in the options page), [cleaning the solution cache](https://www.jetbrains.com/help/resharper/Configuring_Caches_Location.html#cleanup) is necessary to update already analyzed code.\n\n## Code inspection warnings\n\nIn addition to the behavior change of the nullability analysis the following code inspection warnings are provided by this extension.\n\nFor more information about these warnings (and their motivation) see their description in the ReSharper *Code Inspection | Inspection Severity* options page.\n\n### \"Implicit NotNull conflicts with nullability in base type\"\nId: `ImplicitNotNullConflictInHierarchy`\n\n\u003c!-- Doc/Sample.cs --\u003e\n```C#\nabstract class Base\n{\n    public abstract void Method([CanBeNull] string a);\n}\n\nclass Derived : Base\n{\n    // \"Implicit NotNull conflicts with nullability in base type\":\n    public override void Method(string a)\n    {\n    }\n}\n```\n\n### \"Implicit NotNull element cannot override CanBeNull in base type, nullability should be explicit\"\nId: `ImplicitNotNullElementCannotOverrideCanBeNull`\n\n\u003c!-- Doc/Sample.cs --\u003e\n```C#\nabstract class Base\n{\n    [CanBeNull]\n    public abstract string Method();\n}\n\nclass Derived : Base\n{\n    // \"Implicit NotNull element cannot override CanBeNull in base type, nullability should be explicit\":\n    public override string Method() =\u003e \"\";\n}\n```\n\n### \"Implicit NotNull overrides unknown nullability of base member, nullability should be explicit\" resp. hint \"Implicit NotNull result or out parameter overrides unknown nullability of base member, nullability should be explicit\"\nIds: `ImplicitNotNullOverridesUnknownBaseMemberNullability` resp. `ImplicitNotNullResultOverridesUnknownBaseMemberNullability`\n\n\u003c!-- Doc/Sample.cs --\u003e\n```C#\nclass Derived : External.Class /* (external code with unannotated 'Method' and 'Function') */\n{\n    // \"Implicit NotNull overrides unknown nullability of base member, nullability should be explicit\":\n    public override void Method(string a)\n    {\n    }\n\n    // \"Implicit NotNull result or out parameter overrides unknown nullability of base member,\n    // nullability should be explicit\":\n    public override string Function() =\u003e \"\";\n}\n```\n\n### \"Implicit CanBeNull element has an explicit NotNull annotation\"\nId: `NotNullOnImplicitCanBeNull`\n\n\u003c!-- Doc/Sample.cs --\u003e\n```C#\n// \"Implicit CanBeNull element has an explicit NotNull annotation\":\nvoid Foo([NotNull] int? a)\n{\n}\n```\n\n## Credits\n\nBig thanks to [Fabian Schmied](https://github.com/fschmied) for supporting the design and conception of _Implicit Nullability_.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulrichb%2Fimplicitnullability","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fulrichb%2Fimplicitnullability","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulrichb%2Fimplicitnullability/lists"}