Skip to content

Only emit the JetBrains annotation types the source export actually uses #181

Description

@feO2x

Context

BrilliantMessaging consumes a curated single-file export for netstandard2.0. Its generation script initially removed all JetBrains annotations, but ReSharper then reports PossibleMultipleEnumeration at every call site that applies a guard clause to an IEnumerable<T> and enumerates it afterwards:

public TopologyRuntimeHostedService(IEnumerable<ITopologyRuntime> runtimes)
{
    runtimes.MustNotBeNull(); // ReSharper counts this as an enumeration

    _runtimes = runtimes.ToArray();
}

Retaining [NoEnumeration] fixes this; InspectCode confirms all four occurrences in BrilliantMessaging disappear and no new issues surface. The export is therefore now generated with:

  • IncludeJetBrainsAnnotations true
  • IncludeJetBrainsAnnotationsUsing true
  • RemoveNoEnumeration false
  • RemoveContractAnnotations true
  • RemoveValidatedNotNull true and IncludeValidatedNotNullAttribute false

Problem

ReSharperAnnotations.cs is copied into the export wholesale — see CheckIfFileShouldBeProcessed and ShouldAlwaysProcessWholeFileInWhitelistMode in SourceFileMerger.cs. Enabling IncludeJetBrainsAnnotations to obtain a single attribute therefore also emits the other two, and with the configuration above neither of them is referenced by the generated code:

  • ContractAnnotationAttribute — all usages are removed by RemoveContractAnnotations.
  • NotNullAttributeIncludeJetBrainsAnnotationsUsing also emits using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute;, so every [NotNull] in the export resolves to the code-analysis attribute, not the JetBrains one.

This is harmless in practice: the types are internal, add roughly 40 lines, and produce no compiler or inspection warnings. It does however contradict the promise that a whitelisted export contains only the selected assertions and their transitive dependencies, and it forces consumers to carry dead attribute types they explicitly configured away.

Suggestion

Extend the existing reachability idea to annotation types: after the cleanup step has removed the disabled annotations, emit only those JetBrains annotation types that the generated file still references. That keeps the behavior correct for every combination of the removal flags without introducing per-attribute configuration options, and it makes IncludeJetBrainsAnnotations mean "provide the annotation types this export needs" rather than "provide all of them".

While looking at this, it is worth deciding whether the JetBrains NotNullAttribute should ever be emitted alongside the IncludeJetBrainsAnnotationsUsing alias, since the two options currently overlap.

Notes

Not urgent — BrilliantMessaging works fine with the extra types. Reported so the source export stays as deliberate as its whitelist suggests.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions