Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -2625,8 +2625,6 @@ private readonly bool PrintMembers(System.Text.StringBuilder builder)
[Fact]
public void Record_ImplementSynthesized_WrongParameterName()
{
// TODO: Remove this requirement with https://github.com/dotnet/roslyn/issues/52563

var src1 = "record C { }";
var src2 = @"
record C
Expand All @@ -2652,6 +2650,17 @@ protected C(C other)
Diagnostic(RudeEditKind.ExplicitRecordMethodParameterNamesMustMatch, "protected virtual bool PrintMembers(System.Text.StringBuilder sb)", "PrintMembers(System.Text.StringBuilder builder)"),
Diagnostic(RudeEditKind.ExplicitRecordMethodParameterNamesMustMatch, "public virtual bool Equals(C rhs)", "Equals(C other)"),
Diagnostic(RudeEditKind.ExplicitRecordMethodParameterNamesMustMatch, "protected C(C other)", "C(C original)"));

edits.VerifySemantics(
ActiveStatementsDescription.Empty,
new[]
{
SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")),
SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").GetMembers("Equals").OfType<IMethodSymbol>().First(m => SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, m.ContainingType))),
SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").Constructors.Single(c => c.Parameters.FirstOrDefault()?.Type.ToDisplayString() == "C"), preserveLocalVariables: true),
SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").Constructors.Single(c => c.Parameters.Length == 0), preserveLocalVariables: true),
},
EditAndContinueTestHelpers.Net6RuntimeCapabilities);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ private static IEnumerable<SyntaxNode> GetChildNodes(SyntaxNode root, SyntaxNode
}
}

internal override void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeEditDiagnostic> diagnostics, SyntaxNode oldNode, SyntaxNode newNode, ISymbol oldSymbol, ISymbol newSymbol, CancellationToken cancellationToken)
internal override void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeEditDiagnostic> diagnostics, SyntaxNode oldNode, SyntaxNode newNode, ISymbol oldSymbol, ISymbol newSymbol, EditAndContinueCapabilities capabilities, CancellationToken cancellationToken)
{
// Global statements have a declaring syntax reference to the compilation unit itself, which we can just ignore
// for the purposes of declaration rude edits
Expand All @@ -675,7 +675,7 @@ internal override void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeE
// declaration kind has changed. If it hasn't changed, then our standard code will handle it.
if (oldNode.RawKind == newNode.RawKind)
{
base.ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldNode, newNode, oldSymbol, newSymbol, cancellationToken);
base.ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldNode, newNode, oldSymbol, newSymbol, capabilities, cancellationToken);
return;
}

Expand Down Expand Up @@ -709,11 +709,12 @@ internal override void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeE
}
else if (oldNode is RecordDeclarationSyntax &&
newNode is MethodDeclarationSyntax &&
!capabilities.HasFlag(EditAndContinueCapabilities.UpdateParameters) &&
!oldSymbol.GetParameters().Select(p => p.Name).SequenceEqual(newSymbol.GetParameters().Select(p => p.Name)))
{
// TODO: Remove this requirement with https://github.com/dotnet/roslyn/issues/52563
// Explicitly implemented methods must have parameter names that match the compiler generated versions
// exactly otherwise symbol matching won't work for them.
// exactly if the runtime doesn't support updating parameters, otherwise the debugger would show incorrect
// parameter names.
// We don't need to worry about parameter types, because if they were different then we wouldn't get here
// as this wouldn't be the explicit implementation of a known method.
// We don't need to worry about access modifiers because the symbol matching still works, and most of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ private void ReportTopLevelSyntacticRudeEdits(ArrayBuilder<RudeEditDiagnostic> d
/// <see cref="EditKind.Move"/> or <see cref="EditKind.Reorder"/>.
/// The scenarios include moving a type declaration from one file to another and moving a member of a partial type from one partial declaration to another.
/// </summary>
internal virtual void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeEditDiagnostic> diagnostics, SyntaxNode oldNode, SyntaxNode newNode, ISymbol oldSymbol, ISymbol newSymbol, CancellationToken cancellationToken)
internal virtual void ReportDeclarationInsertDeleteRudeEdits(ArrayBuilder<RudeEditDiagnostic> diagnostics, SyntaxNode oldNode, SyntaxNode newNode, ISymbol oldSymbol, ISymbol newSymbol, EditAndContinueCapabilities capabilities, CancellationToken cancellationToken)
{
// When a method is moved to a different declaration and its parameters are changed at the same time
// the new method symbol key will not resolve to the old one since the parameters are different.
Expand Down Expand Up @@ -2787,7 +2787,7 @@ private async Task<ImmutableArray<SemanticEditInfo>> AnalyzeSemanticsAsync(
if (oldSymbol.DeclaringSyntaxReferences.Length == 1)
{
Contract.ThrowIfNull(oldDeclaration);
ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldDeclaration, newDeclaration, oldSymbol, newSymbol, cancellationToken);
ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldDeclaration, newDeclaration, oldSymbol, newSymbol, capabilities, cancellationToken);

if (IsPropertyAccessorDeclarationMatchingPrimaryConstructorParameter(newDeclaration, newContainingType, out var isFirst))
{
Expand Down Expand Up @@ -2822,7 +2822,7 @@ private async Task<ImmutableArray<SemanticEditInfo>> AnalyzeSemanticsAsync(

// Compare the old declaration syntax of the symbol with its new declaration and report rude edits
// if it changed in any way that's not allowed.
ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldDeclaration, newDeclaration, oldSymbol, newSymbol, cancellationToken);
ReportDeclarationInsertDeleteRudeEdits(diagnostics, oldDeclaration, newDeclaration, oldSymbol, newSymbol, capabilities, cancellationToken);

var oldBody = TryGetDeclarationBody(oldDeclaration);
if (oldBody != null)
Expand Down Expand Up @@ -4395,9 +4395,10 @@ private void AddConstructorEdits(
ReportMemberBodyUpdateRudeEdits(diagnostics, newDeclaration, firstSpan);
}

// When explicitly implementing the copy constructor of a record the parameter name must match for symbol matching to work
// TODO: Remove this requirement with https://github.com/dotnet/roslyn/issues/52563
if (oldCtor != null &&
// When explicitly implementing the copy constructor of a record the parameter name if the runtime doesn't support
// updating parameters, otherwise the debugger would show the incorrect name in the autos/locals/watch window
if (!capabilities.HasFlag(EditAndContinueCapabilities.UpdateParameters) &&
oldCtor != null &&
!isPrimaryRecordConstructor &&
oldCtor.DeclaringSyntaxReferences.Length == 0 &&
newCtor.Parameters.Length == 1 &&
Expand Down