Skip to content

Commit 1462b1e

Browse files
author
msftbot[bot]
authored
Merge pull request #45400 from dotnet/merges/master-to-master-vs-deps
Merge master to master-vs-deps
2 parents 11e94bd + 9a658fa commit 1462b1e

File tree

152 files changed

+2507
-485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+2507
-485
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
### `BaseTypeSyntax` Design
2+
3+
In master, we currently have added an optional argument list to `SimpleBaseTypeSyntax` for record primary constructors. However, there is an argument to be made that we should add a new subtype of `BaseTypeSyntax`, something like `PrimaryConstructorTypeSyntax`, to represent these new base type clauses. This was an explicit extension point added in the original design for this very purpose. For either of these designs, GetSymbolInfo will behave consistently: if the `BaseTypeSyntax` has an argument list (either because it's a separate type or because it's a `PrimaryConstructorTypeSyntax`), it will return the constructor symbol or candidates as appropriate. If there are no arguments, then it will return nothing.
4+
5+
Pros for keeping the optional argument list on `SimpleBaseTypeSyntax`:
6+
* The primary constructor arguments feel like an extension to existing nodes, not a totally new node type
7+
* Existing analyzers/fixers might pick things up right without much modification
8+
9+
Pros for extending `BaseTypeSyntax`:
10+
* This extension point was put in explicitly for this
11+
* Existing code might be less likely to erroneously use it
12+
* There was some feeling that it would serve as a more clear delineation for future additions to this syntax (if such C# features ever come to pass)
13+
14+
#### Conclusion
15+
16+
We lean towards extending `BaseTypeSyntax` in the next preview.
17+
18+
### `CompilationOutputFilePaths`
19+
20+
The plural when this struct only has one path in it currently felt wrong. Some options for renaming:
21+
22+
* `CompilationOutputFileInfo`
23+
* `CompilationOutputInfo`
24+
* `CompilationOutputFiles`
25+
26+
We leave it up to whoever does the rename to choose among these.
27+
28+
### `SolutionInfo.Create`
29+
30+
Add `EditorBrowsable(Never)` to the backcompat overload.
31+
32+
### `SymbolKind.FunctionPointer`
33+
34+
Suffix with `Type` for consistency with the other kinds that are also `TypeKind`s.
35+
36+
### `SyntaxFactory.ParseType`
37+
38+
The new overload should use `ParseOptions` instead of the specific C#/VB type in both factories.
39+
Most of the Parse overloads that take a `ParseOptions` here use the non-specific one, and it can be very convenient for IDE APIs here.
40+
While it is marginally less type-safe, the ergonomic and consistency benefits are a deciding factor.
41+
42+
### `WithExpressionSyntax.Receiver`
43+
44+
This should be renamed to `Expression` for consistency with other `SyntaxNode`s.
45+
46+
### `SymbolFinder.Find(Derived(Classes|Interfaces)|Interfaces)Async`
47+
48+
We should reconsider adding multiple overloads, and instead remove the default parameters from the existing overload and introduce a new overload with `transitive` set to `true` to match current behavior.
49+
This is our standard modus operandi for these scenarios.
50+
51+
### `INegatedPatternOperation.NegatedPattern`
52+
53+
Rename to just `Pattern`.
54+
55+
### `IWithOperation.Value`
56+
57+
Rename to `Operand`.
58+
59+
### `Renamer.RenameDocumentAsync`
60+
61+
Make this and the related structs internal unless we have a partner team ready to consume the API in 16.7. We can make the API public again when someone is ready to consume and validate the API shape.

src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ private ImmutableArray<TypedConstant> GetRewrittenAttributeConstructorArguments(
666666
}
667667
else if (reorderedArgument.Kind == TypedConstantKind.Array &&
668668
parameter.Type.TypeKind == TypeKind.Array &&
669-
!((TypeSymbol)reorderedArgument.TypeInternal).Equals(parameter.Type, TypeCompareKind.AllIgnoreOptions))
669+
!((TypeSymbol)reorderedArgument.TypeInternal!).Equals(parameter.Type, TypeCompareKind.AllIgnoreOptions))
670670
{
671671
// NOTE: As in dev11, we don't allow array covariance conversions (presumably, we don't have a way to
672672
// represent the conversion in metadata).
@@ -922,6 +922,7 @@ private static bool TryGetNormalParamValue(ParameterSymbol parameter, ImmutableA
922922
}
923923

924924
HashSet<DiagnosticInfo>? useSiteDiagnostics = null; // ignoring, since already bound argument and parameter
925+
Debug.Assert(argument.TypeInternal is object);
925926
Conversion conversion = conversions.ClassifyBuiltInConversion((TypeSymbol)argument.TypeInternal, parameter.Type, ref useSiteDiagnostics);
926927

927928
// NOTE: Won't always succeed, even though we've performed overload resolution.

src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,9 +3777,8 @@ private static bool IsNegativeConstantForArraySize(BoundExpression expression)
37773777
/// </summary>
37783778
/// <param name="initializerArgumentListOpt">
37793779
/// Null for implicit,
3780-
/// BaseConstructorInitializerSyntax.ArgumentList, or
3781-
/// ThisConstructorInitializerSyntax.ArgumentList, or
3782-
/// SimpleBaseTypeSyntax.ArgumentList for explicit.</param>
3780+
/// <see cref="ConstructorInitializerSyntax.ArgumentList"/>, or
3781+
/// <see cref="PrimaryConstructorBaseTypeSyntax.ArgumentList"/> for explicit.</param>
37833782
/// <param name="constructor">Constructor containing the initializer.</param>
37843783
/// <param name="diagnostics">Accumulates errors (e.g. unable to find constructor to invoke).</param>
37853784
/// <returns>A bound expression for the constructor initializer call.</returns>
@@ -3921,9 +3920,8 @@ private BoundExpression BindConstructorInitializerCore(
39213920
errorLocation = initializerSyntax.ThisOrBaseKeyword.GetLocation();
39223921
break;
39233922

3924-
case SimpleBaseTypeSyntax baseWithArguments:
3925-
Debug.Assert(baseWithArguments.Parent?.Parent is RecordDeclarationSyntax recordDecl && recordDecl.BaseList.Types.FirstOrDefault() == baseWithArguments);
3926-
nonNullSyntax = initializerArgumentListOpt;
3923+
case PrimaryConstructorBaseTypeSyntax baseWithArguments:
3924+
nonNullSyntax = baseWithArguments;
39273925
errorLocation = initializerArgumentListOpt.GetLocation();
39283926
break;
39293927

@@ -6241,9 +6239,9 @@ private BoundExpression BindInstanceMemberAccess(
62416239
lookupResult,
62426240
flags);
62436241

6244-
if (!boundMethodGroup.HasErrors && boundMethodGroup.ResultKind == LookupResultKind.Empty && typeArgumentsSyntax.Any(SyntaxKind.OmittedTypeArgument))
6242+
if (!boundMethodGroup.HasErrors && typeArgumentsSyntax.Any(SyntaxKind.OmittedTypeArgument))
62456243
{
6246-
Error(diagnostics, ErrorCode.ERR_BadArity, node, rightName, MessageID.IDS_MethodGroup.Localize(), typeArgumentsSyntax.Count);
6244+
Error(diagnostics, ErrorCode.ERR_OmittedTypeArgument, node);
62476245
}
62486246

62496247
return boundMethodGroup;

src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ internal BoundPattern BindConstantPatternWithFallbackToTypePattern(
180180
bool hasErrors,
181181
DiagnosticBag diagnostics)
182182
{
183-
ExpressionSyntax innerExpression = expression.SkipParens();
183+
ExpressionSyntax innerExpression = SkipParensAndNullSuppressions(expression);
184184
if (innerExpression.Kind() == SyntaxKind.DefaultLiteralExpression)
185185
{
186186
diagnostics.Add(ErrorCode.ERR_DefaultPattern, innerExpression.Location);
@@ -204,6 +204,24 @@ internal BoundPattern BindConstantPatternWithFallbackToTypePattern(
204204
}
205205
}
206206

207+
private ExpressionSyntax SkipParensAndNullSuppressions(ExpressionSyntax e)
208+
{
209+
while (true)
210+
{
211+
switch (e)
212+
{
213+
case ParenthesizedExpressionSyntax p:
214+
e = p.Expression;
215+
break;
216+
case PostfixUnaryExpressionSyntax { RawKind: (int)SyntaxKind.SuppressNullableWarningExpression } p:
217+
e = p.Operand;
218+
break;
219+
default:
220+
return e;
221+
}
222+
}
223+
}
224+
207225
/// <summary>
208226
/// Binds the expression for a pattern. Sets <paramref name="wasExpression"/> if it was a type rather than an expression,
209227
/// and in that case it returns a <see cref="BoundTypeExpression"/>.
@@ -1239,6 +1257,12 @@ private BoundPattern BindRelationalPattern(
12391257
DiagnosticBag diagnostics)
12401258
{
12411259
BoundExpression value = BindExpressionForPattern(inputType, node.Expression, ref hasErrors, diagnostics, out var constantValueOpt, out _);
1260+
ExpressionSyntax innerExpression = SkipParensAndNullSuppressions(node.Expression);
1261+
if (innerExpression.Kind() == SyntaxKind.DefaultLiteralExpression)
1262+
{
1263+
diagnostics.Add(ErrorCode.ERR_DefaultPattern, innerExpression.Location);
1264+
hasErrors = true;
1265+
}
12421266
RoslynDebug.Assert(value.Type is { });
12431267
BinaryOperatorKind operation = tokenKindToBinaryOperatorKind(node.OperatorToken.Kind());
12441268
if (operation == BinaryOperatorKind.Equal)

src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,7 +3322,7 @@ private BoundNode BindRecordConstructorBody(RecordDeclarationSyntax recordDecl,
33223322
Debug.Assert(bodyBinder != null);
33233323

33243324
BoundExpressionStatement initializer = null;
3325-
if (recordDecl.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
3325+
if (recordDecl.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments)
33263326
{
33273327
initializer = bodyBinder.BindConstructorInitializer(baseWithArguments, diagnostics);
33283328
}
@@ -3334,10 +3334,8 @@ private BoundNode BindRecordConstructorBody(RecordDeclarationSyntax recordDecl,
33343334
expressionBody: null);
33353335
}
33363336

3337-
internal BoundExpressionStatement BindConstructorInitializer(SimpleBaseTypeSyntax initializer, DiagnosticBag diagnostics)
3337+
internal virtual BoundExpressionStatement BindConstructorInitializer(PrimaryConstructorBaseTypeSyntax initializer, DiagnosticBag diagnostics)
33383338
{
3339-
Debug.Assert(initializer.Parent?.Parent is RecordDeclarationSyntax recordDecl && recordDecl.ParameterList is object && recordDecl.BaseWithArguments == initializer);
3340-
33413339
BoundExpression initializerInvocation = GetBinder(initializer).BindConstructorInitializer(initializer.ArgumentList, (MethodSymbol)this.ContainingMember(), diagnostics);
33423340
var constructorInitializer = new BoundExpressionStatement(initializer, initializerInvocation);
33433341
Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");

src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ protected void FindExpressionVariables(
4949
case SyntaxKind.GotoCaseStatement:
5050
break;
5151
case SyntaxKind.ArgumentList:
52-
Debug.Assert(node.Parent is ConstructorInitializerSyntax);
52+
Debug.Assert(node.Parent is ConstructorInitializerSyntax || node.Parent is PrimaryConstructorBaseTypeSyntax);
5353
break;
5454
case SyntaxKind.RecordDeclaration:
5555
Debug.Assert(((RecordDeclarationSyntax)node).ParameterList is object);
@@ -397,7 +397,7 @@ public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
397397
{
398398
Debug.Assert(node.ParameterList is object);
399399

400-
if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
400+
if (node.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments)
401401
{
402402
VisitNodeToBind(baseWithArguments);
403403
}

src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,14 @@ public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
162162

163163
Binder enclosing = new ExpressionVariableBinder(node, _enclosing);
164164
AddToMap(node, enclosing);
165+
Visit(node.PrimaryConstructorBaseType, enclosing);
166+
}
165167

166-
if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
167-
{
168-
enclosing = enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
169-
AddToMap(baseWithArguments, enclosing);
170-
Visit(baseWithArguments.ArgumentList, enclosing);
171-
}
168+
public override void VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node)
169+
{
170+
Binder enclosing = _enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
171+
AddToMap(node, enclosing);
172+
VisitConstructorInitializerArgumentList(node, node.ArgumentList, enclosing);
172173
}
173174

174175
public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node)
@@ -317,16 +318,20 @@ public override void VisitConstructorInitializer(ConstructorInitializerSyntax no
317318
{
318319
var binder = _enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
319320
AddToMap(node, binder);
321+
VisitConstructorInitializerArgumentList(node, node.ArgumentList, binder);
322+
}
320323

321-
if (node.ArgumentList != null)
324+
private void VisitConstructorInitializerArgumentList(CSharpSyntaxNode node, ArgumentListSyntax argumentList, Binder binder)
325+
{
326+
if (argumentList != null)
322327
{
323328
if (_root == node)
324329
{
325-
binder = new ExpressionVariableBinder(node.ArgumentList, binder);
326-
AddToMap(node.ArgumentList, binder);
330+
binder = new ExpressionVariableBinder(argumentList, binder);
331+
AddToMap(argumentList, binder);
327332
}
328333

329-
Visit(node.ArgumentList, binder);
334+
Visit(argumentList, binder);
330335
}
331336
}
332337

src/Compilers/CSharp/Portable/Binder/SwitchBinder_Patterns.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ private BoundSwitchLabel BindSwitchSectionLabel(
237237
case SyntaxKind.CaseSwitchLabel:
238238
{
239239
var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
240-
SyntaxNode innerExpression = caseLabelSyntax.Value.SkipParens();
241240
bool hasErrors = node.HasErrors;
242241
BoundPattern pattern = sectionBinder.BindConstantPatternWithFallbackToTypePattern(
243242
caseLabelSyntax.Value, caseLabelSyntax.Value, SwitchGoverningType, hasErrors, diagnostics);

src/Compilers/CSharp/Portable/CSharpExtensions.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,22 @@ public static Conversion ClassifyConversion(this Compilation? compilation, IType
537537
}
538538
}
539539

540+
/// <summary>
541+
/// Returns what symbol(s), if any, the given constructor initializer syntax bound to in the program.
542+
/// </summary>
543+
public static SymbolInfo GetSymbolInfo(this SemanticModel? semanticModel, PrimaryConstructorBaseTypeSyntax constructorInitializer, CancellationToken cancellationToken = default(CancellationToken))
544+
{
545+
var csmodel = semanticModel as CSharpSemanticModel;
546+
if (csmodel != null)
547+
{
548+
return csmodel.GetSymbolInfo(constructorInitializer, cancellationToken);
549+
}
550+
else
551+
{
552+
return SymbolInfo.None;
553+
}
554+
}
555+
540556
/// <summary>
541557
/// Returns what symbol(s), if any, the given attribute syntax bound to in the program.
542558
/// </summary>
@@ -643,6 +659,27 @@ public static SymbolInfo GetSpeculativeSymbolInfo(this SemanticModel? semanticMo
643659
}
644660
}
645661

662+
/// <summary>
663+
/// Bind the constructor initializer in the context of the specified location and get semantic information
664+
/// about symbols. This method is used to get semantic information about a constructor
665+
/// initializer that did not actually appear in the source code.
666+
///
667+
/// NOTE: This will only work in locations where there is already a constructor initializer.
668+
/// <see cref="PrimaryConstructorBaseTypeSyntax"/>.
669+
/// </summary>
670+
public static SymbolInfo GetSpeculativeSymbolInfo(this SemanticModel? semanticModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer)
671+
{
672+
var csmodel = semanticModel as CSharpSemanticModel;
673+
if (csmodel != null)
674+
{
675+
return csmodel.GetSpeculativeSymbolInfo(position, constructorInitializer);
676+
}
677+
else
678+
{
679+
return SymbolInfo.None;
680+
}
681+
}
682+
646683
/// <summary>
647684
/// Gets type information about a constructor initializer.
648685
/// </summary>
@@ -1178,6 +1215,27 @@ public static bool TryGetSpeculativeSemanticModel([NotNullWhen(true)] this Seman
11781215
}
11791216
}
11801217

1218+
/// <summary>
1219+
/// Get a SemanticModel object that is associated with a constructor initializer that did not appear in
1220+
/// this source code. This can be used to get detailed semantic information about sub-parts
1221+
/// of a constructor initializer that did not appear in source code.
1222+
///
1223+
/// NOTE: This will only work in locations where there is already a constructor initializer.
1224+
/// </summary>
1225+
public static bool TryGetSpeculativeSemanticModel([NotNullWhen(true)] this SemanticModel? semanticModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, [NotNullWhen(true)] out SemanticModel? speculativeModel)
1226+
{
1227+
var csmodel = semanticModel as CSharpSemanticModel;
1228+
if (csmodel != null)
1229+
{
1230+
return csmodel.TryGetSpeculativeSemanticModel(position, constructorInitializer, out speculativeModel);
1231+
}
1232+
else
1233+
{
1234+
speculativeModel = null;
1235+
return false;
1236+
}
1237+
}
1238+
11811239
/// <summary>
11821240
/// Get a SemanticModel object that is associated with an attribute that did not appear in
11831241
/// this source code. This can be used to get detailed semantic information about sub-parts

src/Compilers/CSharp/Portable/CSharpResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@
471471
<data name="ERR_ThisInBadContext" xml:space="preserve">
472472
<value>Keyword 'this' is not available in the current context</value>
473473
</data>
474+
<data name="ERR_OmittedTypeArgument" xml:space="preserve">
475+
<value>Omitting the type argument is not allowed in the current context</value>
476+
</data>
474477
<data name="WRN_InvalidMainSig" xml:space="preserve">
475478
<value>'{0}' has the wrong signature to be an entry point</value>
476479
</data>

0 commit comments

Comments
 (0)