diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs
index 160b935861b28..e3ed6efd59edb 100644
--- a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs
+++ b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs
@@ -476,11 +476,15 @@ private static async Task RefactorInitializersAsync(
var symbolReferences = await SymbolFinder
.FindReferencesAsync(type, solutionEditor.OriginalSolution, cancellationToken).ConfigureAwait(false);
var referenceLocations = symbolReferences.SelectMany(reference => reference.Locations);
- var documentLookup = referenceLocations.ToLookup(refLoc => refLoc.Document.Id);
- foreach (var (documentID, documentLocations) in documentLookup)
+ var documentLookup = referenceLocations.ToLookup(refLoc => refLoc.Document);
+ foreach (var (document, documentLocations) in documentLookup)
{
+ // We don't want to process source-generated documents. Make sure we can get back to a real document here.
+ if (document is SourceGeneratedDocument)
+ continue;
+
var documentEditor = await solutionEditor
- .GetDocumentEditorAsync(documentID, cancellationToken).ConfigureAwait(false);
+ .GetDocumentEditorAsync(document.Id, cancellationToken).ConfigureAwait(false);
if (documentEditor.OriginalDocument.Project.Language != LanguageNames.CSharp)
{
// since this is a CSharp-dependent file, we need to have specific VB support.
diff --git a/src/Analyzers/CSharp/Tests/ConvertToRecord/ConvertToRecordCodeFixTests.cs b/src/Analyzers/CSharp/Tests/ConvertToRecord/ConvertToRecordCodeFixTests.cs
index a09910d3e0a9a..63ad65169d356 100644
--- a/src/Analyzers/CSharp/Tests/ConvertToRecord/ConvertToRecordCodeFixTests.cs
+++ b/src/Analyzers/CSharp/Tests/ConvertToRecord/ConvertToRecordCodeFixTests.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
@@ -11,172 +9,169 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
-using Microsoft.CodeAnalysis.Testing;
-using Roslyn.Test.Utilities;
using Xunit;
-namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertToRecord
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertToRecord;
+
+[Trait(Traits.Feature, Traits.Features.CodeActionsConvertToRecord)]
+public class ConvertToRecordCodeFixTests
{
- [Trait(Traits.Feature, Traits.Features.CodeActionsConvertToRecord)]
- public class ConvertToRecordCodeFixTests
+ [Fact]
+ public async Task TestMovePropertySimpleRecordInheritance_CodeFix()
{
- [Fact]
- public async Task TestMovePropertySimpleRecordInheritance_CodeFix()
- {
- var initialMarkup = """
- namespace N
+ var initialMarkup = """
+ namespace N
+ {
+ public record B
{
- public record B
- {
- public int Foo { get; init; }
- }
+ public int Foo { get; init; }
+ }
- public class C : [|B|]
- {
- public int P { get; init; }
- }
+ public class C : [|B|]
+ {
+ public int P { get; init; }
}
- """;
- var changedMarkup = """
- namespace N
+ }
+ """;
+ var changedMarkup = """
+ namespace N
+ {
+ public record B
{
- public record B
- {
- public int Foo { get; init; }
- }
-
- public record C(int P) : B;
+ public int Foo { get; init; }
}
- """;
- await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
- }
- [Fact]
- public async Task TestMovePropertyPositionalParameterRecordInheritance_CodeFix()
- {
- var initialMarkup = """
- namespace N
- {
- public record B(int Foo, int Bar);
+ public record C(int P) : B;
+ }
+ """;
+ await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
+ }
- public class {|CS1729:C|} : [|B|]
- {
- public int P { get; init; }
- }
- }
- """;
- var changedMarkup = """
- namespace N
- {
- public record B(int Foo, int Bar);
+ [Fact]
+ public async Task TestMovePropertyPositionalParameterRecordInheritance_CodeFix()
+ {
+ var initialMarkup = """
+ namespace N
+ {
+ public record B(int Foo, int Bar);
- public record C(int Foo, int Bar, int P) : B(Foo, Bar);
+ public class {|CS1729:C|} : [|B|]
+ {
+ public int P { get; init; }
}
- """;
- await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
- }
+ }
+ """;
+ var changedMarkup = """
+ namespace N
+ {
+ public record B(int Foo, int Bar);
- [Fact]
- public async Task TestMovePropertyPositionalParameterRecordInheritanceWithComments_CodeFix()
- {
- var initialMarkup = """
- namespace N
- {
- /// B
- /// Foo is an int
- /// Bar is an int as well
- public record B(int Foo, int Bar);
+ public record C(int Foo, int Bar, int P) : B(Foo, Bar);
+ }
+ """;
+ await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
+ }
- /// C inherits from B
- public class {|CS1729:C|} : [|B|]
- {
- /// P can be initialized
- public int P { get; init; }
- }
- }
- """;
- var changedMarkup = """
- namespace N
+ [Fact]
+ public async Task TestMovePropertyPositionalParameterRecordInheritanceWithComments_CodeFix()
+ {
+ var initialMarkup = """
+ namespace N
+ {
+ /// B
+ /// Foo is an int
+ /// Bar is an int as well
+ public record B(int Foo, int Bar);
+
+ /// C inherits from B
+ public class {|CS1729:C|} : [|B|]
{
- /// B
- /// Foo is an int
- /// Bar is an int as well
- public record B(int Foo, int Bar);
-
- /// C inherits from B
- ///
- ///
- /// P can be initialized
- public record C(int Foo, int Bar, int P) : B(Foo, Bar);
+ /// P can be initialized
+ public int P { get; init; }
}
- """;
- await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
- }
+ }
+ """;
+ var changedMarkup = """
+ namespace N
+ {
+ /// B
+ /// Foo is an int
+ /// Bar is an int as well
+ public record B(int Foo, int Bar);
+
+ /// C inherits from B
+ ///
+ ///
+ /// P can be initialized
+ public record C(int Foo, int Bar, int P) : B(Foo, Bar);
+ }
+ """;
+ await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
+ }
- [Fact]
- public async Task TestMovePropertyAndReorderWithPositionalParameterRecordInheritance_CodeFix()
- {
- var initialMarkup = """
- namespace N
+ [Fact]
+ public async Task TestMovePropertyAndReorderWithPositionalParameterRecordInheritance_CodeFix()
+ {
+ var initialMarkup = """
+ namespace N
+ {
+ public record B(int Foo, int Bar);
+
+ public class C : [|B|]
{
- public record B(int Foo, int Bar);
+ public int P { get; init; }
- public class C : [|B|]
+ public {|CS1729:C|}(int p, int bar, int foo)
{
- public int P { get; init; }
-
- public {|CS1729:C|}(int p, int bar, int foo)
- {
- P = p;
- Bar = bar;
- Foo = foo;
- }
+ P = p;
+ Bar = bar;
+ Foo = foo;
}
}
- """;
- var changedMarkup = """
- namespace N
- {
- public record B(int Foo, int Bar);
+ }
+ """;
+ var changedMarkup = """
+ namespace N
+ {
+ public record B(int Foo, int Bar);
- public record C(int P, int Bar, int Foo) : B(Foo, Bar);
- }
- """;
- await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
- }
+ public record C(int P, int Bar, int Foo) : B(Foo, Bar);
+ }
+ """;
+ await TestCodeFixAsync(initialMarkup, changedMarkup).ConfigureAwait(false);
+ }
- private class CodeFixTest : CSharpCodeFixVerifier.Test
- {
- }
+ private class CodeFixTest : CSharpCodeFixVerifier.Test
+ {
+ }
- private static async Task TestCodeFixAsync(string initialMarkup, string fixedMarkup)
+ private static async Task TestCodeFixAsync(string initialMarkup, string fixedMarkup)
+ {
+ var test = new CodeFixTest()
{
- var test = new CodeFixTest()
- {
- TestCode = initialMarkup,
- FixedCode = fixedMarkup,
- LanguageVersion = LanguageVersion.CSharp10,
- ReferenceAssemblies = Testing.ReferenceAssemblies.Net.Net60,
- };
- await test.RunAsync().ConfigureAwait(false);
- }
+ TestCode = initialMarkup,
+ FixedCode = fixedMarkup,
+ LanguageVersion = LanguageVersion.CSharp10,
+ ReferenceAssemblies = Testing.ReferenceAssemblies.Net.Net60,
+ };
+ await test.RunAsync().ConfigureAwait(false);
+ }
- private class TestAnalyzer : DiagnosticAnalyzer
- {
- public override ImmutableArray SupportedDiagnostics
+ private class TestAnalyzer : DiagnosticAnalyzer
+ {
+ public override ImmutableArray SupportedDiagnostics
#pragma warning disable RS0030 // Do not used banned APIs
- => ImmutableArray.Create(new DiagnosticDescriptor(
- "CS8865",
- "Only records may inherit from records.",
- "Only records may inherit from records.",
- "Compiler error",
- DiagnosticSeverity.Error,
- isEnabledByDefault: true));
+ => ImmutableArray.Create(new DiagnosticDescriptor(
+ "CS8865",
+ "Only records may inherit from records.",
+ "Only records may inherit from records.",
+ "Compiler error",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true));
#pragma warning restore RS0030 // Do not used banned APIs
- public override void Initialize(AnalysisContext context)
- {
- }
+ public override void Initialize(AnalysisContext context)
+ {
}
}
}
diff --git a/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs b/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs
index f0fe4191e33dc..105c39fc1c568 100644
--- a/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs
+++ b/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs
@@ -4480,6 +4480,68 @@ public record [|C|](int P)
await TestRefactoringAsync(initialMarkup, fixedMarkup);
}
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72067")]
+ public async Task TestMovePropertiesAndRefactorInitializer_SourceGeneratedDocuments()
+ {
+ await new RefactoringTestWithGenerator
+ {
+ TestCode = """
+ namespace N
+ {
+ public class [|C|]
+ {
+ public int P { get; init; }
+ public bool B { get; init; }
+ }
+ }
+ """,
+ FixedState =
+ {
+ Sources =
+ {
+ """
+ namespace N
+ {
+ public record C(int P, bool B);
+ }
+ """
+ },
+ ExpectedDiagnostics =
+ {
+ // Microsoft.CodeAnalysis.CSharp.Features.UnitTests\Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertToRecord.ConvertToRecordCodeRefactoringTests+ConvertToRecordTestGenerator\file.cs(7,24): error CS7036: There is no argument given that corresponds to the required parameter 'P' of 'C.C(int, bool)'
+ DiagnosticResult.CompilerError("CS7036").WithSpan(@"Microsoft.CodeAnalysis.CSharp.Features.UnitTests\Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertToRecord.ConvertToRecordCodeRefactoringTests+ConvertToRecordTestGenerator\file.cs", 7, 24, 7, 25).WithArguments("P", "N.C.C(int, bool)"),
+ }
+ }
+ }.RunAsync();
+ }
+
+ private sealed class ConvertToRecordTestGenerator : ISourceGenerator
+ {
+ public void Initialize(GeneratorInitializationContext context) { }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ context.AddSource(
+ "file.cs",
+ """
+ namespace N
+ {
+ public static class D
+ {
+ public static C GetC()
+ {
+ return new C
+ {
+ P = 0,
+ B = false
+ };
+ }
+ }
+ }
+ """);
+ }
+ }
+
#region selection
[Fact]
@@ -4654,6 +4716,14 @@ protected override Workspace CreateWorkspaceImpl()
}
}
+ private class RefactoringTestWithGenerator : RefactoringTest
+ {
+ protected override IEnumerable GetSourceGenerators()
+ {
+ yield return typeof(ConvertToRecordTestGenerator);
+ }
+ }
+
private static async Task TestRefactoringAsync(
string initialMarkup,
string changedMarkup)