Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
partial class Derived
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Verify.MSTest.SourceGenerator", "1.0.0.0")]
public global::Microsoft.VisualStudio.TestTools.UnitTesting.TestContext TestContext
public override global::Microsoft.VisualStudio.TestTools.UnitTesting.TestContext TestContext
{
get => global::VerifyMSTest.Verifier.CurrentTestContext.Value!.TestContext;
set => global::VerifyMSTest.Verifier.CurrentTestContext.Value = new global::VerifyMSTest.TestExecutionContext(value, GetType());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
Item1: UsesVerify.g.cs,
Item2:
//-----------------------------------------------------
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior
// and will be lost when the code is regenerated.
// <auto-generated />
//-----------------------------------------------------

partial class Derived
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Verify.MSTest.SourceGenerator", "1.0.0.0")]
public override global::Microsoft.VisualStudio.TestTools.UnitTesting.TestContext TestContext
{
get => global::VerifyMSTest.Verifier.CurrentTestContext.Value!.TestContext;
set => global::VerifyMSTest.Verifier.CurrentTestContext.Value = new global::VerifyMSTest.TestExecutionContext(value, GetType());
}
}

}
24 changes: 23 additions & 1 deletion src/Verify.MSTest.SourceGenerator.Tests/InheritanceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,29 @@ public partial class Derived : Base
}
""";

return VerifyGenerator(TestDriver.Run(source), ["CS0108"]);
return VerifyGenerator(TestDriver.Run(source), ["CS0506"]);
}

[Fact]
public Task HasAttributeOnDerivedClassAndVirtualPropertyManuallyDefinedInBase()
{
var source = """
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VerifyMSTest;

public class Base
{
public virtual TestContext TestContext { get; set; }
}

[TestClass]
[UsesVerify]
public partial class Derived : Base
{
}
""";

return VerifyGenerator(TestDriver.Run(source));
}

[Fact]
Expand Down
5 changes: 4 additions & 1 deletion src/Verify.MSTest.SourceGenerator/ClassToGenerate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
/// The built in equality and hash code implementations won't work because this type includes a
/// collection (which has reference equality semantics), so we must implement them ourselves.
/// </remarks>
readonly record struct ClassToGenerate(string? Namespace, string ClassName, ParentClass[] ParentClasses)
readonly record struct ClassToGenerate(string? Namespace, string ClassName, bool OverrideTestContext, ParentClass[] ParentClasses)
{
public string? Namespace { get; } = Namespace;
public string ClassName { get; } = ClassName;
public ParentClass[] ParentClasses { get; } = ParentClasses;
public bool OverrideTestContext { get; } = OverrideTestContext;

public bool Equals(ClassToGenerate other) =>
Namespace == other.Namespace &&
ClassName == other.ClassName &&
OverrideTestContext == other.OverrideTestContext &&
ParentClasses.SequenceEqual(other.ParentClasses);

public override int GetHashCode()
Expand All @@ -27,6 +29,7 @@ public override int GetHashCode()
var hash = 1430287;
hash = hash * 7302013 ^ (Namespace ?? string.Empty).GetHashCode();
hash = hash * 7302013 ^ ClassName.GetHashCode();
hash = hash * 7302013 ^ OverrideTestContext.GetHashCode();

// Include (up to) the last 8 elements in the hash code to balance performance and specificity.
// The runtime also does this for structural equality; see
Expand Down
7 changes: 6 additions & 1 deletion src/Verify.MSTest.SourceGenerator/Emitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ void WriteClass(ClassToGenerate classToGenerate) =>
.AppendLine("{")
.IncreaseIndent()
.AppendLine(GeneratedCodeAttribute)
.AppendLine("public global::Microsoft.VisualStudio.TestTools.UnitTesting.TestContext TestContext")
.Append("public ")
.Append(TestContextModifiers(classToGenerate))
.AppendLine("global::Microsoft.VisualStudio.TestTools.UnitTesting.TestContext TestContext")
.AppendLine("{")
.IncreaseIndent()
.AppendLine("get => global::VerifyMSTest.Verifier.CurrentTestContext.Value!.TestContext;")
Expand All @@ -81,4 +83,7 @@ public string GenerateExtensionClasses(IReadOnlyCollection<ClassToGenerate> clas

return builder.ToString();
}

static string TestContextModifiers(ClassToGenerate classToGenerate)
=> classToGenerate.OverrideTestContext ? "override " : string.Empty;
}
28 changes: 27 additions & 1 deletion src/Verify.MSTest.SourceGenerator/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,33 @@ static class Parser
var name = typeSyntax.GetTypeNameWithGenericParameters();
var parents = GetParentClasses(typeSyntax, cancel);

return new ClassToGenerate(ns, name, parents);
return new ClassToGenerate(
Namespace: ns,
ClassName: name,
OverrideTestContext: BaseClassHasTestContext(typeSymbol),
ParentClasses: parents);
}

static bool BaseClassHasTestContext(INamedTypeSymbol typeSymbol) =>
BaseClassesOf(typeSymbol)
.Any(HasTestContextProperty);

static bool HasTestContextProperty(INamedTypeSymbol typeSymbol) =>
typeSymbol
.GetMembers()
.OfType<IPropertySymbol>()
.Any(property =>
property.Name == "TestContext" &&
property.DeclaredAccessibility == Accessibility.Public);

static IEnumerable<INamedTypeSymbol> BaseClassesOf(INamedTypeSymbol typeSymbol)
{
var baseType = typeSymbol.BaseType;
while (baseType?.TypeKind == TypeKind.Class)
{
yield return baseType;
baseType = baseType.BaseType;
}
}

static ParentClass[] GetParentClasses(TypeDeclarationSyntax typeSyntax, Cancel cancel)
Expand Down