Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create synthesized record constructor #40625

Merged
merged 8 commits into from
Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -643,8 +643,10 @@ private Binder VisitTypeDeclarationCore(TypeDeclarationSyntax parent)

// we are visiting type declarations fairly frequently
// and position is more likely to be in the body, so lets check for "inBody" first.
if (LookupPosition.IsBetweenTokens(_position, parent.OpenBraceToken, parent.CloseBraceToken) ||
LookupPosition.IsInAttributeSpecification(_position, parent.AttributeLists))
if (parent.OpenBraceToken != default &&
parent.CloseBraceToken != default &&
(LookupPosition.IsBetweenTokens(_position, parent.OpenBraceToken, parent.CloseBraceToken) ||
LookupPosition.IsInAttributeSpecification(_position, parent.AttributeLists)))
{
extraInfo = NodeUsage.NamedTypeBodyOrTypeParameters;
}
Expand All @@ -654,7 +656,7 @@ private Binder VisitTypeDeclarationCore(TypeDeclarationSyntax parent)
}
else if (LookupPosition.IsBetweenTokens(_position, parent.Keyword, parent.OpenBraceToken))
{
extraInfo = NodeUsage.NamedTypeBaseList;
extraInfo = NodeUsage.NamedTypeBaseListOrParameterList;
}

return VisitTypeDeclarationCore(parent, extraInfo);
Expand All @@ -679,7 +681,7 @@ private Binder VisitTypeDeclarationCore(TypeDeclarationSyntax parent, NodeUsage
{
var typeSymbol = ((NamespaceOrTypeSymbol)resultBinder.ContainingMemberOrLambda).GetSourceTypeMember(parent);

if (extraInfo == NodeUsage.NamedTypeBaseList)
if (extraInfo == NodeUsage.NamedTypeBaseListOrParameterList)
{
// even though there could be no type parameter, we need this binder
// for its "IsAccessible"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal enum NodeUsage : byte
OperatorBody = 1 << 0,

NamedTypeBodyOrTypeParameters = 1 << 0,
NamedTypeBaseList = 1 << 1,
NamedTypeBaseListOrParameterList = 1 << 1,

NamespaceBody = 1 << 0,
NamespaceUsings = 1 << 1,
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5930,4 +5930,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="IDS_FeatureRecords" xml:space="preserve">
<value>records</value>
</data>
<data name="ERR_BadRecordDeclaration" xml:space="preserve">
<value>Records must have both a 'data' modifier and parameter list</value>
</data>
</root>
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,7 @@ internal enum ErrorCode
ERR_InternalError = 8751,

ERR_ExternEventInitializer = 8760,
ERR_BadRecordDeclaration = 8761,

// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Syntax;
333fred marked this conversation as resolved.
Show resolved Hide resolved

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SynthesizedRecordConstructor : SynthesizedInstanceConstructor
{
public override ImmutableArray<ParameterSymbol> Parameters { get; }

public SynthesizedRecordConstructor(
NamedTypeSymbol containingType,
Binder parameterBinder,
ParameterListSyntax parameterList,
DiagnosticBag diagnostics)
: base(containingType)
{
Parameters = ParameterHelpers.MakeParameters(
parameterBinder,
this,
parameterList,
out _,
diagnostics,
allowRefOrOut: true,
allowThis: false,
addRefReadOnlyModifier: false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ public sealed override ImmutableArray<FieldSymbol> TupleElements
return IsTupleType ? TupleData!.GetTupleMemberSymbolForUnderlyingMember(underlyingMemberOpt) : default;
}

protected ArrayBuilder<Symbol>? AddOrWrapTupleMembers(ImmutableArray<Symbol> currentMembers)
protected ArrayBuilder<Symbol> AddOrWrapTupleMembers(ImmutableArray<Symbol> currentMembers)
{
Debug.Assert(IsTupleType);
Debug.Assert(currentMembers.All(m => !(m is TupleVirtualElementFieldSymbol)));
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ internal static bool IsInParameterList(int position, BaseMethodDeclarationSyntax
return IsBeforeToken(position, parameterList, parameterList.CloseParenToken);
}

internal static bool IsInParameterList(int position, ParameterListSyntax parameterList)
=> parameterList != null && IsBeforeToken(position, parameterList, parameterList.CloseParenToken);

internal static bool IsInMethodDeclaration(int position, BaseMethodDeclarationSyntax methodDecl)
{
Debug.Assert(methodDecl != null);
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Neplatný operand pro porovnávací vzorek. Vyžaduje se hodnota, ale nalezeno: {0}.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Ungültiger Operand für die Musterübereinstimmung. Ein Wert ist erforderlich, gefunden wurde aber "{0}".</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Operando no válido para la coincidencia de patrones. Se requería un valor, pero se encontró '{0}'.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Opérande non valide pour les critères spéciaux ; la valeur nécessaire n'est pas celle trouvée, '{0}'.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">L'operando non è valido per i criteri di ricerca. È richiesto un valore ma è stato trovato '{0}'.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">パターン マッチには使用できないオペランドです。値が必要ですが、'{0}' が見つかりました。</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">패턴 일치에 대한 피연산자가 잘못되었습니다. 값이 필요하지만 '{0}'을(를) 찾았습니다.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Nieprawidłowy operand dla dopasowania wzorca; wymagana jest wartość, a znaleziono „{0}”.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Operando inválido para correspondência de padrão. Um valor era obrigatório, mas '{0}' foi encontrado.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Недопустимый операнд для сопоставления с шаблоном. Требуется значение, но найдено "{0}".</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">Desen eşleşmesi için işlenen geçersiz. Değer gerekiyordu ancak '{0}' bulundu.</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">用于模式匹配的操作数无效;需要值,但找到的是“{0}”。</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<target state="translated">模式比對運算元無效; 需要值,但找到 '{0}'。</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadRecordDeclaration">
<source>Records must have both a 'data' modifier and parameter list</source>
<target state="new">Records must have both a 'data' modifier and parameter list</target>
<note />
</trans-unit>
<trans-unit id="ERR_BadSwitchValue">
<source>Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</source>
<target state="new">Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,47 @@ public class LookupPositionTests : CompilingTestBase
{
private const char KeyPositionMarker = '`';

[Fact]
public void PositionalRecord1()
{
var text = @"
class C(int x, int y);";
var expectedNames = MakeExpectedSymbols(
Add( // Global
"System",
"Microsoft",
"C"));

TestLookupNames(text, expectedNames);
}

[Fact]
public void PositionalRecord2()
{
var text = @"
`class C`<T`>(int x, T t = default(T));";
var expectedNames = MakeExpectedSymbols(
Add( // Global
"System",
"Microsoft",
"C<T>"),
Add( // C Type parameters
"T"),
Add( // Members
"System.Boolean System.Object.Equals(System.Object obj)",
"System.Boolean System.Object.Equals(System.Object objA, System.Object objB)",
"System.Boolean System.Object.ReferenceEquals(System.Object objA, System.Object objB)",
"System.Int32 System.Object.GetHashCode()",
"System.Object System.Object.MemberwiseClone()",
"void System.Object.Finalize()",
"System.String System.Object.ToString()",
"System.Type System.Object.GetType()"),
s_pop
);

TestLookupNames(text, expectedNames);
}

[Fact]
public void ExpressionBodiedProp()
{
Expand Down
20 changes: 17 additions & 3 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ data class Point { }
// (2,12): error CS8652: The feature 'records' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// class Point(int x, int y);
Diagnostic(ErrorCode.ERR_FeatureInPreview, "(int x, int y)").WithArguments("records").WithLocation(2, 12),
// (2,12): error CS8761: Records must have both a 'data' modifier and parameter list
// class Point(int x, int y);
Diagnostic(ErrorCode.ERR_BadRecordDeclaration, "(int x, int y)").WithLocation(2, 12),
// (2,26): error CS8652: The feature 'records' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// class Point(int x, int y);
Diagnostic(ErrorCode.ERR_FeatureInPreview, ";").WithArguments("records").WithLocation(2, 26)
Expand All @@ -34,7 +37,10 @@ data class Point { }
comp.VerifyDiagnostics(
// (2,1): error CS8652: The feature 'records' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// data class Point { }
Diagnostic(ErrorCode.ERR_FeatureInPreview, "data").WithArguments("records").WithLocation(2, 1)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "data").WithArguments("records").WithLocation(2, 1),
// (2,12): error CS8761: Records must have both a 'data' modifier and parameter list
// data class Point { }
Diagnostic(ErrorCode.ERR_BadRecordDeclaration, "Point").WithLocation(2, 12)
);
comp = CreateCompilation(src3);
comp.VerifyDiagnostics(
Expand All @@ -50,9 +56,17 @@ data class Point { }
);

comp = CreateCompilation(src1, parseOptions: TestOptions.RegularPreview);
comp.VerifyDiagnostics();
comp.VerifyDiagnostics(
// (2,12): error CS8761: Records must have both a 'data' modifier and parameter list
// class Point(int x, int y);
Diagnostic(ErrorCode.ERR_BadRecordDeclaration, "(int x, int y)").WithLocation(2, 12)
);
comp = CreateCompilation(src2, parseOptions: TestOptions.RegularPreview);
comp.VerifyDiagnostics();
comp.VerifyDiagnostics(
// (2,12): error CS8761: Records must have both a 'data' modifier and parameter list
// data class Point { }
Diagnostic(ErrorCode.ERR_BadRecordDeclaration, "Point").WithLocation(2, 12)
);
comp = CreateCompilation(src3, parseOptions: TestOptions.RegularPreview);
comp.VerifyDiagnostics();
}
Expand Down
Loading