Skip to content
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<GlobalPackageReference Include="Meziantou.Analyzer" Version="3.0.141" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.301" />
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="18.7.23" />
<GlobalPackageReference Include="NetEvolve.Defaults" Version="2.6.95" />
<GlobalPackageReference Include="NetEvolve.Analyzer" Version="0.14.8" />
<GlobalPackageReference Include="NetEvolve.Defaults" Version="2.8.0" />
<GlobalPackageReference Include="Roslynator.Analyzers" Version="4.16.0" />
<GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.16.0" />
<GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.16.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.FrameShift.Generation;
namespace NetEvolve.FrameShift.Generation;

using System.Collections.Immutable;
using System.Text;
Expand Down Expand Up @@ -52,8 +52,8 @@ namespace NetEvolve.FrameShift.Generation;
/// grows with the size of the test project. This is unavoidable — the test surface is a property of the
/// entire compilation, not of any single syntax node — and it is stated here plainly rather than hidden.
/// If that cost is not wanted, disable FrameShift for the project by setting the MSBuild property
/// <c>FrameShiftEnabled</c> to <c>false</c>, or keep the analysis and only stop the manifest from being
/// written by setting <c>FrameShiftWriteTestSurfaceManifest</c> to <c>false</c>.
/// <c>FrameShiftEnabled</c> to <see langword="false"/>, or keep the analysis and only stop the manifest from being
/// written by setting <c>FrameShiftWriteTestSurfaceManifest</c> to <see langword="false"/>.
/// </para>
/// </remarks>
[Generator(LanguageNames.CSharp)]
Expand Down
10 changes: 5 additions & 5 deletions src/NetEvolve.FrameShift/Mutations/MutationKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal enum MutationKind
ShiftOperator,

/// <summary>
/// The <c>checked</c> and <c>unchecked</c> keyword of a checked expression or statement, swapped for
/// The <see langword="checked"/> and <see langword="unchecked"/> keyword of a checked expression or statement, swapped for
/// its counterpart. The keyword only decides how arithmetic overflow is handled at run time, so a
/// test suite that never distinguishes the two cannot tell whether the choice is actually enforced.
/// </summary>
Expand Down Expand Up @@ -228,17 +228,17 @@ internal enum MutationKind

/// <summary>
/// The element list of an array or collection initializer and of a collection expression, emptied
/// when it carries elements and, where provably safe, filled with a single <c>default</c> element
/// when it carries elements and, where provably safe, filled with a single <see langword="default"/> element
/// when it is empty. An emptied lookup table, default argument list or seed collection is otherwise
/// indistinguishable from the original to a test suite that never inspects its contents.
/// </summary>
CollectionInitializer,

/// <summary>
/// Whole statements removed outright: a bare <c>return;</c> inside a <see langword="void" />
/// returning member, a loop <c>break</c> or <c>continue</c>, a <c>throw</c> statement, and a
/// standalone invocation of a <see langword="void" /> returning method with no <c>ref</c> or
/// <c>out</c> arguments. A test suite that never distinguishes the statement being there from it
/// returning member, a loop <see langword="break"/> or <see langword="continue"/>, a <see langword="throw"/> statement, and a
/// standalone invocation of a <see langword="void" /> returning method with no <see langword="ref"/> or
/// <see langword="out"/> arguments. A test suite that never distinguishes the statement being there from it
/// being gone cannot tell an early return, a changed loop exit, a silently skipped guard or a
/// discarded side-effecting call apart from the code that no longer has it.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
/// <para>
/// The bound method symbol decides whether a call is mutated at all, and its containing type has to be
/// <see cref="string" /> itself. A <c>ToUpper</c> declared on another type, an extension method of that
/// name, and the <c>char</c> and <c>System.Globalization.TextInfo</c> conversions are all left
/// name, and the <see cref="char"/> and <c>System.Globalization.TextInfo</c> conversions are all left
/// untouched. So is a null-conditional call, whose receiver is not a plain member access, and a call in
/// a position that requires a compile time constant.
/// </para>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
namespace NetEvolve.FrameShift.Mutations.Operators;
namespace NetEvolve.FrameShift.Mutations.Operators;

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

/// <summary>
/// Swaps <c>checked</c> and <c>unchecked</c>, in both the expression form (<c>checked(expr)</c> /
/// Swaps <see langword="checked"/> and <see langword="unchecked"/>, in both the expression form (<c>checked(expr)</c> /
/// <c>unchecked(expr)</c>) and the statement form (<c>checked { }</c> / <c>unchecked { }</c>).
/// </summary>
/// <remarks>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.FrameShift.Mutations.Operators;
namespace NetEvolve.FrameShift.Mutations.Operators;

using System.Collections.Immutable;
using System.Linq;
Expand Down Expand Up @@ -33,7 +33,7 @@ namespace NetEvolve.FrameShift.Mutations.Operators;
/// The reverse direction, turning <c>[]</c> into <c>[default]</c>, is only offered for a collection
/// expression, never for the brace initializer syntax, and only when it is safe: the target type of the
/// collection expression has to resolve, through the semantic model, to a concrete element type, and that
/// element type has to be a value type, a nullable reference type, or <c>dynamic</c>/<c>object</c>.
/// element type has to be a value type, a nullable reference type, or <see langword="dynamic"/>/<see cref="object"/>.
/// Everything else - an unresolved element type, an unconstrained type parameter, or a non-nullable
/// reference type the nullable context has not annotated - is skipped, because <see langword="default" />
/// is not guaranteed to compile there without deeper analysis this operator deliberately does not
Expand Down Expand Up @@ -200,7 +200,7 @@ private static bool IsGenericEnumerable(INamedTypeSymbol type) =>

/// <summary>
/// Determines whether <see langword="default" /> is safe to write for <paramref name="elementType" />:
/// a value type, a nullable reference type, or <c>dynamic</c>/<c>object</c>. Every other reference
/// a value type, a nullable reference type, or <see langword="dynamic"/>/<see cref="object"/>. Every other reference
/// type, including one the nullable context leaves oblivious, is rejected, because whether
/// <see langword="default" /> compiles there without a warning depends on analysis this operator does
/// not perform.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.FrameShift.Mutations.Operators;
namespace NetEvolve.FrameShift.Mutations.Operators;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -27,7 +27,7 @@ internal static class ConstantContext
/// <summary>
/// Determines whether <paramref name="node" /> sits in a position that only accepts a compile time
/// constant, such as an attribute argument, a <see langword="const" /> initializer, a default parameter
/// value, a <c>case</c> label, a <c>goto case</c> statement, a constant pattern, a relational pattern
/// value, a <see langword="case"/> label, a <c>goto case</c> statement, a constant pattern, a relational pattern
/// or an enumeration member declaration.
/// </summary>
/// <param name="node">The node to inspect.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
/// The argument is located by name for a named argument and by position for a positional one, which
/// covers arguments written out of order and optional parameters left out entirely. Positional matching
/// stays exact even next to a named argument, because C# only allows a positional argument to follow a
/// named one when that named one already sits in its own declared position. A <c>params</c> parameter is
/// named one when that named one already sits in its own declared position. A <see langword="params"/> parameter is
/// never treated as the provider parameter: its argument is one element of an expanded collection, and
/// removing an element does not remove the provider the call formats with.
/// </para>
Expand Down Expand Up @@ -151,7 +151,7 @@ private Mutation CreateRemoval(ArgumentListSyntax argumentList, int argumentInde

/// <summary>
/// Finds the first parameter of <paramref name="method" /> whose type is or implements
/// <paramref name="provider" />, skipping a <c>params</c> parameter.
/// <paramref name="provider" />, skipping a <see langword="params"/> parameter.
/// </summary>
/// <param name="method">The bound symbol of the invocation.</param>
/// <param name="provider">The <c>System.IFormatProvider</c> of the analysed compilation.</param>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.FrameShift.Mutations.Operators;
namespace NetEvolve.FrameShift.Mutations.Operators;

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
Expand All @@ -7,7 +7,7 @@ namespace NetEvolve.FrameShift.Mutations.Operators;

/// <summary>
/// Removes an existing logical negation (<c>!x</c> becomes <c>x</c>) and introduces a negation around
/// the boolean condition of an <c>if</c>, <c>while</c> or <c>do</c> statement and of a conditional
/// the boolean condition of an <see langword="if"/>, <see langword="while"/> or <see langword="do"/> statement and of a conditional
/// expression (<c>x</c> becomes <c>!(x)</c>).
/// </summary>
/// <remarks>
Expand All @@ -16,7 +16,7 @@ namespace NetEvolve.FrameShift.Mutations.Operators;
/// because <c>!x</c> on a <c>bool?</c> is itself a <c>bool?</c>, so the operand can take the place of the
/// whole expression without changing the type of the position. Introducing one rejects it, because the
/// wrapped <c>!(x)</c> would again be a <c>bool?</c>, and a <c>bool?</c> is not a valid condition of an
/// <c>if</c>, <c>while</c> or <c>do</c> statement nor of a conditional expression, so the mutant would
/// <see langword="if"/>, <see langword="while"/> or <see langword="do"/> statement nor of a conditional expression, so the mutant would
/// never compile.
/// </para>
/// <para>
Expand Down Expand Up @@ -110,11 +110,11 @@ CancellationToken cancellationToken
}

/// <summary>
/// Determines whether <paramref name="type" /> is <c>bool</c> or <c>bool?</c>, which are the two
/// Determines whether <paramref name="type" /> is <see cref="bool"/> or <c>bool?</c>, which are the two
/// operand types the removal of a negation leaves in a well typed position.
/// </summary>
/// <param name="type">The type to inspect, which may be <see langword="null" /> for an unresolved node.</param>
/// <returns><see langword="true" /> if the type is <c>bool</c> or <c>bool?</c>.</returns>
/// <returns><see langword="true" /> if the type is <see cref="bool"/> or <c>bool?</c>.</returns>
private static bool IsBoolean(ITypeSymbol? type)
{
if (type is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace NetEvolve.FrameShift.Mutations.Operators;
/// </para>
/// <para>
/// <see cref="System.Math" /> does not declare every member for every numeric type: the trigonometric
/// functions and <c>Floor</c> / <c>Ceiling</c> only have <c>double</c>, <c>float</c> and <c>decimal</c>
/// functions and <c>Floor</c> / <c>Ceiling</c> only have <see cref="double"/>, <see cref="float"/> and <see cref="decimal"/>
/// overloads, while <c>Min</c>, <c>Max</c> and <c>Abs</c> have one for every numeric type including the
/// integral ones. Rather than hard-coding that shape, the counterpart is only offered when
/// <see cref="System.Math" /> itself declares a static overload of that name whose parameters match the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ namespace NetEvolve.FrameShift.Mutations.Operators;
/// <see langword="null" /> - so both directions out of <see langword="null" /> are worth provoking.
/// </para>
/// <para>
/// <c>System.Guid?</c> is included even though <c>Guid</c> has no literal syntax of its own: there is no
/// way to write a <c>Guid</c> value as a literal token, so this operator only ever encounters one for it
/// <c>System.Guid?</c> is included even though <see cref="Guid"/> has no literal syntax of its own: there is no
/// way to write a <see cref="Guid"/> value as a literal token, so this operator only ever encounters one for it
/// on the <see langword="null" /> side, moving it to <c>Guid.Empty</c>, the type's default value.
/// </para>
/// <para>
/// The converted type is resolved through the semantic model and has to be a nullable value type built
/// over <see langword="bool" />, <c>char</c>, one of the built-in numeric types or <c>System.Guid</c>,
/// over <see langword="bool" />, <see cref="char"/>, one of the built-in numeric types or <c>System.Guid</c>,
/// never the corresponding non-nullable type and never a reference type. The check is load bearing
/// rather than cosmetic: on a plain, non-nullable type the mutant that introduces <see langword="null" />
/// does not compile, and although <c>MutantCompiler</c> would discard it afterwards, it would already
Expand All @@ -61,8 +61,8 @@ namespace NetEvolve.FrameShift.Mutations.Operators;
/// A <see langword="null" /> literal on a reference type is deliberately out of scope. It belongs to a
/// separate and considerably riskier family, because the surviving mutant then depends on whether the
/// dereference is guarded rather than on the presence-of-a-value distinction this operator targets.
/// Other types without a literal syntax of their own - an <see langword="enum" />, <c>DateTime</c> or a
/// user-defined struct - are equally out of scope, since <c>Guid</c> is special-cased explicitly and
/// Other types without a literal syntax of their own - an <see langword="enum" />, <see cref="DateTime"/> or a
/// user-defined struct - are equally out of scope, since <see cref="Guid"/> is special-cased explicitly and
/// there is no literal node for this operator to mutate for any of the others in the first place.
/// </para>
/// </remarks>
Expand Down Expand Up @@ -352,7 +352,7 @@ type is INamedTypeSymbol named
/// mutation at all.
/// </summary>
/// <remarks>
/// <c>Guid</c> has no literal syntax, so <paramref name="valueNode" /> can never actually resolve to
/// <see cref="Guid"/> has no literal syntax, so <paramref name="valueNode" /> can never actually resolve to
/// it here; the case exists only to keep the switch exhaustive.
/// </remarks>
private static bool IsDefaultValue(
Expand Down Expand Up @@ -397,7 +397,7 @@ CancellationToken cancellationToken

/// <summary>
/// Builds the expression for the default value of <paramref name="underlyingKind" />: a literal for
/// every built-in type, and <c>global::System.Guid.Empty</c> for <c>Guid</c>, which has no literal of
/// every built-in type, and <c>global::System.Guid.Empty</c> for <see cref="Guid"/>, which has no literal of
/// its own.
/// </summary>
private static ExpressionSyntax? CreateDefaultExpression(UnderlyingKind underlyingKind) =>
Expand Down Expand Up @@ -443,7 +443,7 @@ CancellationToken cancellationToken
/// <summary>
/// The human-readable text for a default-value expression, which is the expression's own text for a
/// plain literal, and the short, unqualified <c>Guid.Empty</c> for the globally-qualified expression
/// this operator builds for <c>Guid</c>.
/// this operator builds for <see cref="Guid"/>.
/// </summary>
private static string DisplayText(UnderlyingKind underlyingKind, ExpressionSyntax defaultExpression) =>
underlyingKind == UnderlyingKind.Guid ? "Guid.Empty" : defaultExpression.ToString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.FrameShift.Mutations.Operators;
namespace NetEvolve.FrameShift.Mutations.Operators;

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
Expand All @@ -7,9 +7,9 @@ namespace NetEvolve.FrameShift.Mutations.Operators;

/// <summary>
/// Removes a whole statement outright, by replacing it with an empty statement (<c>;</c>): a bare
/// <c>return;</c> inside a <see langword="void" /> returning member, a loop <c>break</c> or
/// <c>continue</c>, a <c>throw</c> statement, and a standalone invocation of a <see langword="void" />
/// returning method with no <c>ref</c> or <c>out</c> arguments.
/// <c>return;</c> inside a <see langword="void" /> returning member, a loop <see langword="break"/> or
/// <see langword="continue"/>, a <see langword="throw"/> statement, and a standalone invocation of a <see langword="void" />
/// returning method with no <see langword="ref"/> or <see langword="out"/> arguments.
/// </summary>
/// <remarks>
/// <para>
Expand Down Expand Up @@ -119,9 +119,9 @@ CancellationToken cancellationToken
}

/// <summary>
/// Removes a <c>break</c>, unless the nearest enclosing breakable construct - stopping the search at
/// a member or lambda boundary - is a <c>switch</c> section rather than a loop; removing a
/// switch-section <c>break</c> changes fall-through semantics this operator does not touch.
/// Removes a <see langword="break"/>, unless the nearest enclosing breakable construct - stopping the search at
/// a member or lambda boundary - is a <see langword="switch"/> section rather than a loop; removing a
/// switch-section <see langword="break"/> changes fall-through semantics this operator does not touch.
/// </summary>
private IEnumerable<Mutation> CreateForBreak(BreakStatementSyntax breakStatement)
{
Expand All @@ -136,7 +136,7 @@ private IEnumerable<Mutation> CreateForBreak(BreakStatementSyntax breakStatement
}

/// <summary>
/// Removes a <c>continue</c>, unless no enclosing loop can be found before crossing a member or
/// Removes a <see langword="continue"/>, unless no enclosing loop can be found before crossing a member or
/// lambda boundary.
/// </summary>
private IEnumerable<Mutation> CreateForContinue(ContinueStatementSyntax continueStatement)
Expand All @@ -152,7 +152,7 @@ private IEnumerable<Mutation> CreateForContinue(ContinueStatementSyntax continue
}

/// <summary>
/// Removes a <c>throw</c> statement, unless it is the trailing statement of the body of a member that
/// Removes a <see langword="throw"/> statement, unless it is the trailing statement of the body of a member that
/// does not return <see langword="void" /> - removing it would leave that code path without a
/// required return, which the compiler would reject.
/// </summary>
Expand All @@ -178,7 +178,7 @@ owner is not null

/// <summary>
/// Removes a standalone invocation statement, provided the invoked method is known to return
/// <see langword="void" /> and none of its arguments are passed by <c>ref</c> or <c>out</c>.
/// <see langword="void" /> and none of its arguments are passed by <see langword="ref"/> or <see langword="out"/>.
/// </summary>
private IEnumerable<Mutation> CreateForInvocation(
ExpressionStatementSyntax expressionStatement,
Expand Down Expand Up @@ -273,7 +273,7 @@ private static bool IsTrailingStatementOfMemberBody(StatementSyntax statement, S

/// <summary>
/// Walks upwards from <paramref name="node" />, without crossing a member or lambda boundary, and
/// returns the nearest loop, or the nearest <c>switch</c> statement when <paramref name="includeSwitch" />
/// returns the nearest loop, or the nearest <see langword="switch"/> statement when <paramref name="includeSwitch" />
/// is <see langword="true" />, whichever comes first.
/// </summary>
private static SyntaxNode? FindNearestBreakableConstruct(SyntaxNode node, bool includeSwitch)
Expand Down
Loading
Loading