Skip to content

Commit ba1e510

Browse files
committed
chore: clean up code and add comments
1 parent 97d69de commit ba1e510

18 files changed

+270
-247
lines changed

src/Stryker.Core/Stryker.Core.UnitTest/AssertExtensions.cs

+6-14
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ public static class AssertionExtensions
1717
/// </summary>
1818
/// <param name="actual">Resulted code</param>
1919
/// <param name="expected">Expected code</param>
20-
public static void ShouldBeSemantically(this string actual, string expected)
21-
{
22-
ShouldBeSemantically(CSharpSyntaxTree.ParseText(actual).GetRoot(), CSharpSyntaxTree.ParseText(expected).GetRoot());
23-
}
20+
public static void ShouldBeSemantically(this string actual, string expected) => ShouldBeSemantically(CSharpSyntaxTree.ParseText(actual), CSharpSyntaxTree.ParseText(expected));
2421

2522
/// <summary>
2623
/// Compares two syntax trees and asserts equality
@@ -29,14 +26,9 @@ public static void ShouldBeSemantically(this string actual, string expected)
2926
/// <param name="expected">Expected code</param>
3027
/// <remarks>Warning: this code tries to pinpoint the first different lines, but it will work on string comparison, so it may pinpoint spaces
3128
/// or new line variations, hiding the real differences.</remarks>
32-
public static void ShouldBeSemantically(this SyntaxNode actual, SyntaxNode expected)
29+
public static void ShouldBeSemantically(this SyntaxTree actual, SyntaxTree expected)
3330
{
34-
// for some reason, nodes can be different while being textually the same
35-
if (actual.ToFullString() == expected.ToFullString())
36-
{
37-
return;
38-
}
39-
var isSame = SyntaxFactory.AreEquivalent(actual, expected);
31+
var isSame = actual.IsEquivalentTo(expected);
4032

4133
if (!isSame)
4234
{
@@ -63,12 +55,12 @@ public static void ShouldBeWithNewlineReplace(this string actual, string expecte
6355
actual.ShouldBe(replaced);
6456
}
6557

66-
public static void ShouldNotContainErrors(this SyntaxNode actual)
58+
public static void ShouldNotContainErrors(this SyntaxTree actual)
6759
{
68-
var errors = actual.SyntaxTree.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error);
60+
var errors = actual.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error);
6961
if (errors > 0)
7062
{
71-
errors.ShouldBe(0, $"Actual code has build errors!\n{actual.ToFullString()}\nerrors: {string.Join(Environment.NewLine, actual.SyntaxTree.GetDiagnostics())}");
63+
errors.ShouldBe(0, $"Actual code has build errors!\n{actual.GetText()}\nerrors: {string.Join(Environment.NewLine, actual.GetDiagnostics())}");
7264
}
7365
}
7466

src/Stryker.Core/Stryker.Core.UnitTest/Compiling/CSharpRollbackProcessTests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ public void SomeLinq()
119119
helpers.Add(CSharpSyntaxTree.ParseText(code, path: name, encoding: Encoding.UTF32));
120120
}
121121

122-
var mutant = mutator.Mutate(syntaxTree.GetRoot(), null);
123-
helpers.Add(mutant.SyntaxTree);
122+
var mutant = mutator.Mutate(syntaxTree, null);
123+
helpers.Add(mutant);
124124

125125
var references = new List<string> {
126126
typeof(object).Assembly.Location,
@@ -203,8 +203,8 @@ private void RefreshAccountNumber()
203203
helpers.Add(CSharpSyntaxTree.ParseText(code, path: name, encoding: Encoding.UTF32));
204204
}
205205

206-
var mutant = mutator.Mutate(syntaxTree.GetRoot(), null);
207-
helpers.Add(mutant.SyntaxTree);
206+
var mutant = mutator.Mutate(syntaxTree, null);
207+
helpers.Add(mutant);
208208

209209
var references = new List<string> {
210210
typeof(object).Assembly.Location,

src/Stryker.Core/Stryker.Core.UnitTest/Mutants/CsharpMutantOrchestratorTests.cs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,7 @@ public void MutationsShouldHaveLinespan()
12241224
{
12251225
var test3 = 2 + 5;
12261226
}";
1227-
_target.Mutate(CSharpSyntaxTree.ParseText(source).GetRoot(), null);
1227+
_target.Mutate(CSharpSyntaxTree.ParseText(source), null);
12281228

12291229
var mutants = _target.GetLatestMutantBatch().ToList();
12301230
mutants.Count.ShouldBe(2);
@@ -1251,7 +1251,7 @@ public static bool InvokeIfNotNull(this Action a)
12511251
}
12521252
}
12531253
}";
1254-
_target.Mutate(CSharpSyntaxTree.ParseText(source).GetRoot(), null);
1254+
_target.Mutate(CSharpSyntaxTree.ParseText(source), null);
12551255

12561256
var mutants = _target.GetLatestMutantBatch().ToList();
12571257
mutants.Count.ShouldBe(7);
@@ -1402,6 +1402,21 @@ public void ShouldNotAddReturnDefaultToMethodsWithReturnTypeVoid()
14021402
ShouldMutateSourceInClassToExpected(source, expected);
14031403
}
14041404

1405+
[Theory]
1406+
[InlineData("{return 0;}")]
1407+
[InlineData("{return 1; throw Exception();}")]
1408+
[InlineData("{return 1;yield return 0;}")]
1409+
[InlineData("{return 1;yield break;}")]
1410+
[InlineData("{;}")]
1411+
public void ShouldNotAddReturnOnSomeBlocks(string code)
1412+
{
1413+
string source = @$"
1414+
int TestMethod()
1415+
// Stryker disable all
1416+
{code}";
1417+
ShouldMutateSourceInClassToExpected(source, source);
1418+
}
1419+
14051420
[Fact]
14061421
public void ShouldSkipStringsInSwitchExpression()
14071422
{

src/Stryker.Core/Stryker.Core.UnitTest/Mutants/MutantOrchestratorTestsBase.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public MutantOrchestratorTestsBase()
2626

2727
protected void ShouldMutateSourceToExpected(string actual, string expected)
2828
{
29-
var actualNode = _target.Mutate(CSharpSyntaxTree.ParseText(actual).GetRoot(), null);
30-
actual = actualNode.ToFullString();
29+
var actualNode = _target.Mutate(CSharpSyntaxTree.ParseText(actual), null);
30+
actual = actualNode.GetRoot().ToFullString();
3131
actual = actual.Replace(_injector.HelperNamespace, "StrykerNamespace");
32-
actualNode = CSharpSyntaxTree.ParseText(actual).GetRoot();
33-
var expectedNode = CSharpSyntaxTree.ParseText(expected).GetRoot();
32+
actualNode = CSharpSyntaxTree.ParseText(actual);
33+
var expectedNode = CSharpSyntaxTree.ParseText(expected);
3434
actualNode.ShouldBeSemantically(expectedNode);
3535
actualNode.ShouldNotContainErrors();
3636
}

src/Stryker.Core/Stryker.Core.UnitTest/Mutants/MutantPlacerTests.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ public void ShouldInjectInitializersAndRestore()
184184
var expected = "class Test {bool Method(out int x) {{x = default(int);}x=0;}}";
185185

186186
CheckMutantPlacerProperlyPlaceAndRemoveHelpers<BlockSyntax>(source, expected,
187-
(n) => MutantPlacer.AddDefaultInitializers(n,
188-
new[]{SyntaxFactory.Parameter(SyntaxFactory.Identifier("x")).WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword))
187+
(n) => MutantPlacer.InjectOutParametersInitialization(n,
188+
new[]{SyntaxFactory.Parameter(SyntaxFactory.Identifier("x")).WithModifiers(SyntaxFactory.TokenList(new[] {SyntaxFactory.Token(SyntaxKind.OutKeyword)})).WithType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword))
189189
)}));
190190
}
191191

@@ -215,7 +215,7 @@ public void ShouldRollBackFailedConstructor()
215215
OptimizationMode = OptimizationModes.CoverageBasedTest,
216216
MutationLevel = MutationLevel.Complete
217217
});
218-
var actualNode = orchestrator.Mutate(CSharpSyntaxTree.ParseText(source).GetRoot(), null);
218+
var actualNode = orchestrator.Mutate(CSharpSyntaxTree.ParseText(source), null).GetRoot();
219219

220220
var node = actualNode.DescendantNodes().First(t => t is BlockSyntax);
221221

@@ -233,10 +233,10 @@ public void ShouldRollBackFailedConstructor()
233233
restored = MutantPlacer.RemoveMutant(node);
234234
actualNode = actualNode.ReplaceNode(node, restored);
235235

236-
var expectedNode = CSharpSyntaxTree.ParseText(source.Replace("StrykerNamespace", codeInjection.HelperNamespace)).GetRoot();
236+
var expectedNode = CSharpSyntaxTree.ParseText(source.Replace("StrykerNamespace", codeInjection.HelperNamespace));
237237
expectedNode.ShouldNotContainErrors();
238-
actualNode.ShouldBeSemantically(expectedNode);
239-
actualNode.ShouldNotContainErrors();
238+
actualNode.SyntaxTree.ShouldBeSemantically(expectedNode);
239+
actualNode.SyntaxTree.ShouldNotContainErrors();
240240
}
241241
}
242242
}

src/Stryker.Core/Stryker.Core.UnitTest/MutationTest/CSharpMutationTestProcessTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ public void MutateShouldWriteToDisk_IfCompilationIsSuccessful()
7878

7979
// create mocks
8080
var options = new StrykerOptions();
81-
var orchestratorMock = new Mock<BaseMutantOrchestrator<SyntaxNode, SemanticModel>>(MockBehavior.Strict, options);
81+
var orchestratorMock = new Mock<BaseMutantOrchestrator<SyntaxTree, SemanticModel>>(MockBehavior.Strict, options);
8282

8383
fileSystem.AddDirectory(Path.Combine(FilesystemRoot, "TestProject", "bin", "Debug", "netcoreapp2.0"));
8484

8585
// setup mocks
86-
orchestratorMock.Setup(x => x.Mutate(It.IsAny<SyntaxNode>(), It.IsAny<SemanticModel>())).Returns(CSharpSyntaxTree.ParseText(SourceFile).GetRoot());
86+
orchestratorMock.Setup(x => x.Mutate(It.IsAny<SyntaxTree>(), It.IsAny<SemanticModel>())).Returns(CSharpSyntaxTree.ParseText(SourceFile));
8787
orchestratorMock.SetupAllProperties();
8888
orchestratorMock.Setup(x => x.GetLatestMutantBatch()).Returns(mockMutants);
8989

src/Stryker.Core/Stryker.Core/Instrumentation/BaseEngine.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Stryker.Core.Instrumentation;
1313
/// <remarks>Multiple helpers can work on the same type of constructs.</remarks>
1414
internal abstract class BaseEngine<T>: IInstrumentCode where T: CSharpSyntaxNode
1515
{
16-
protected BaseEngine() => Marker = new SyntaxAnnotation(MutantPlacer.Injector, InstrumentEngineId);
16+
protected BaseEngine() => Marker = MutantPlacer.RegisterEngine(this);
1717

1818
/// <summary>
1919
/// Annotation to be added to the instrumented node

src/Stryker.Core/Stryker.Core/Instrumentation/DefaultInitializationEngine.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Stryker.Core.Instrumentation;
1313
/// <remarks>No check is made on the visibility of the variable.</remarks>
1414
/// <exception cref="InvalidOperationException">If the method has no body (virtual or expression form).</exception>
1515
/// </summary>
16-
/// <remarks>Parameters/variables are added on a one by one basis but they are all removed simultaneously.</remarks>
16+
/// <remarks>Parameters/variables are added on a one by one basis, but they are all removed simultaneously.</remarks>
1717
internal class DefaultInitializationEngine : BaseEngine<BlockSyntax>
1818
{
1919
private static readonly SyntaxAnnotation BlockMarker = new("InitializationBlock");
@@ -24,14 +24,14 @@ internal class DefaultInitializationEngine : BaseEngine<BlockSyntax>
2424
/// <param name="body">method/accessor body where to inject the assignment</param>
2525
/// <param name="parameters">parameters to initialize</param>
2626
/// <returns>the method with a block containing initializations to default for the given variables/parameters</returns>
27-
public BlockSyntax AddDefaultInitializers(BlockSyntax body, IEnumerable<ParameterSyntax> parameters)
27+
public BlockSyntax InjectOutParametersInitialization(BlockSyntax body, IEnumerable<ParameterSyntax> parameters)
2828
{
2929
if (body == null)
3030
{
3131
throw new InvalidOperationException(
3232
"Can't add default initializer(s) to expression bodied or virtual method.");
3333
}
34-
34+
parameters = parameters.Where(p => p.Modifiers.Any(m => m.IsKind(SyntaxKind.OutKeyword))).ToList();
3535
if (!parameters.Any())
3636
{
3737
return body;
@@ -42,7 +42,7 @@ public BlockSyntax AddDefaultInitializers(BlockSyntax body, IEnumerable<Paramete
4242
if (body.Statements.Count > 0 && body.Statements[0].HasAnnotation(BlockMarker))
4343
{
4444
// we add a new initializer, we need to get the existing ones
45-
initializers = (body.Statements[0] as BlockSyntax).Statements;
45+
initializers = ((BlockSyntax)body.Statements[0]).Statements;
4646
// we can skip the initializer helper block
4747
originalStatements = body.Statements.Skip(1);
4848
}
@@ -59,7 +59,7 @@ public BlockSyntax AddDefaultInitializers(BlockSyntax body, IEnumerable<Paramete
5959
p.Type.BuildDefaultExpression())))))
6060
.WithAdditionalAnnotations(BlockMarker);
6161

62-
return body.WithStatements(new SyntaxList<StatementSyntax>(originalStatements.Prepend(initializersBlock))).WithAdditionalAnnotations(Marker);
62+
return body.WithStatements(new(originalStatements.Prepend(initializersBlock))).WithAdditionalAnnotations(Marker);
6363
}
6464

6565
/// <summary>

src/Stryker.Core/Stryker.Core/Instrumentation/EndingReturnEngine.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Linq;
32
using Microsoft.CodeAnalysis;
43
using Microsoft.CodeAnalysis.CSharp;
54
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -17,7 +16,8 @@ public BlockSyntax InjectReturn(BlockSyntax block, TypeSyntax type)
1716
// if we had no body or the last statement is a return, no need to add one, or this is an iterator method
1817
if (block == null
1918
|| block.Statements.Count == 0
20-
|| block.Statements.Last().Kind() == SyntaxKind.ReturnStatement
19+
|| block.Statements.Last().IsKind(SyntaxKind.ReturnStatement)
20+
|| block.Statements.Last().IsKind(SyntaxKind.ThrowStatement)
2121
|| type.IsVoid()
2222
|| block.ScanChildStatements(x => x.IsKind(SyntaxKind.YieldReturnStatement) || x.IsKind(SyntaxKind.YieldBreakStatement))
2323
|| !block.ScanChildStatements(x => x.IsKind(SyntaxKind.ReturnStatement)))

src/Stryker.Core/Stryker.Core/Instrumentation/StaticInstrumentationEngine.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ internal class StaticInstrumentationEngine : BaseEngine<BlockSyntax>
1414
/// injects a 'using' block with static marker class used by coverage logic.
1515
/// </summary>
1616
/// <param name="block"></param>
17+
/// <param name="injector"></param>
1718
/// <returns></returns>
1819
public BlockSyntax PlaceStaticContextMarker(BlockSyntax block, CodeInjection injector) =>
1920
SyntaxFactory.Block(
2021
SyntaxFactory.UsingStatement(null, injector.GetContextClassConstructor(), block)).WithAdditionalAnnotations(Marker);
21-
22+
2223
protected override SyntaxNode Revert(BlockSyntax node)
2324
{
2425
if ( node.Statements.Count == 1 && node.Statements[0] is UsingStatementSyntax usingStatement)

src/Stryker.Core/Stryker.Core/Mutants/BaseMutantOrchestrator.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ namespace Stryker.Core.Mutants
66
{
77
public abstract class BaseMutantOrchestrator
88
{
9-
public readonly StrykerOptions _options;
9+
public readonly StrykerOptions Options;
1010

1111
public bool MustInjectCoverageLogic =>
12-
_options != null && _options.OptimizationMode.HasFlag(OptimizationModes.CoverageBasedTest) &&
13-
!_options.OptimizationMode.HasFlag(OptimizationModes.CaptureCoveragePerTest);
12+
Options != null && Options.OptimizationMode.HasFlag(OptimizationModes.CoverageBasedTest) &&
13+
!Options.OptimizationMode.HasFlag(OptimizationModes.CaptureCoveragePerTest);
1414

1515
public ICollection<Mutant> Mutants { get; set; }
1616

1717
public int MutantCount { get; set; }
1818

19-
protected BaseMutantOrchestrator(StrykerOptions options) => _options = options;
19+
protected BaseMutantOrchestrator(StrykerOptions options) => Options = options;
2020

2121
/// <summary>
2222
/// Gets the stored mutants and resets the mutant list to an empty collection
@@ -34,6 +34,7 @@ public virtual IReadOnlyCollection<Mutant> GetLatestMutantBatch()
3434
/// Orchestrator: to arrange or manipulate, especially by means of clever or thorough planning or maneuvering.
3535
/// </summary>
3636
/// <typeparam name="T">The type of syntax node to mutate</typeparam>
37+
/// <typeparam name="TY">Associated semantic model if any</typeparam>
3738
public abstract class BaseMutantOrchestrator<T, TY> : BaseMutantOrchestrator
3839
{
3940
protected BaseMutantOrchestrator(StrykerOptions input) : base(input)

0 commit comments

Comments
 (0)