diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 2bd20be8accca..91b432bf77bf7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -17,24 +17,34 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node, var expression = BindExpression(node.Expression, diagnostics); var hasErrors = IsOperandErrors(node, expression, diagnostics); var pattern = BindPattern(node.Pattern, expression, expression.Type, hasErrors, diagnostics); - return new BoundIsPatternExpression(node, expression, pattern, GetSpecialType(SpecialType.System_Boolean, diagnostics, node), hasErrors); + return new BoundIsPatternExpression( + node, expression, pattern, GetSpecialType(SpecialType.System_Boolean, diagnostics, node), hasErrors); } - internal BoundPattern BindPattern(PatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) + internal BoundPattern BindPattern( + PatternSyntax node, + BoundExpression operand, + TypeSymbol operandType, + bool hasErrors, + DiagnosticBag diagnostics) { switch (node.Kind()) { case SyntaxKind.DeclarationPattern: - return BindDeclarationPattern((DeclarationPatternSyntax)node, operand, operandType, hasErrors, diagnostics); + return BindDeclarationPattern( + (DeclarationPatternSyntax)node, operand, operandType, hasErrors, diagnostics); case SyntaxKind.ConstantPattern: - return BindConstantPattern((ConstantPatternSyntax)node, operand, operandType, hasErrors, diagnostics); + return BindConstantPattern( + (ConstantPatternSyntax)node, operand, operandType, hasErrors, diagnostics); case SyntaxKind.PropertyPattern: - return BindPropertyPattern((PropertyPatternSyntax)node, operand, operandType, hasErrors, diagnostics); + return BindPropertyPattern( + (PropertyPatternSyntax)node, operand, operandType, hasErrors, diagnostics); case SyntaxKind.RecursivePattern: - return BindRecursivePattern((RecursivePatternSyntax)node, operand, operandType, hasErrors, diagnostics); + return BindRecursivePattern( + (RecursivePatternSyntax)node, operand, operandType, hasErrors, diagnostics); case SyntaxKind.WildcardPattern: return new BoundWildcardPattern(node); @@ -44,7 +54,12 @@ internal BoundPattern BindPattern(PatternSyntax node, BoundExpression operand, T } } - private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) + private BoundPattern BindRecursivePattern( + RecursivePatternSyntax node, + BoundExpression operand, + TypeSymbol operandType, + bool hasErrors, + DiagnosticBag diagnostics) { var type = (NamedTypeSymbol)this.BindType(node.Type, diagnostics); hasErrors = hasErrors || CheckValidPatternType(node.Type, operand, operandType, type, false, diagnostics); @@ -97,7 +112,8 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, BoundExpr if (!correspondingMembersForCtor.SequenceEqual(correspondingMembers, (s1, s2) => s1 == s2)) { correspondingMembersForCtor.Free(); - Error(diagnostics, ErrorCode.ERR_FeatureIsUnimplemented, node, "cannot infer a positional pattern from conflicting constructors"); + Error(diagnostics, ErrorCode.ERR_FeatureIsUnimplemented, node, + "cannot infer a positional pattern from conflicting constructors"); diagnostics.Add(node, useSiteDiagnostics); hasErrors = true; return new BoundWildcardPattern(node, hasErrors); @@ -108,7 +124,8 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, BoundExpr if (correspondingMembers == null) { - Error(diagnostics, ErrorCode.ERR_FeatureIsUnimplemented, node, "cannot infer a positional pattern from any accessible constructor"); + Error(diagnostics, ErrorCode.ERR_FeatureIsUnimplemented, node, + "cannot infer a positional pattern from any accessible constructor"); diagnostics.Add(node, useSiteDiagnostics); correspondingMembersForCtor.Free(); hasErrors = true; @@ -123,13 +140,28 @@ private BoundPattern BindRecursivePattern(RecursivePatternSyntax node, BoundExpr var builder = ArrayBuilder.GetInstance(properties.Length); for (int i = 0; i < properties.Length; i++) { - builder.Add(new BoundSubPropertyPattern(node.PatternList.SubPatterns[i], properties[i].GetTypeOrReturnType(), properties[i], LookupResultKind.Empty, boundPatterns[i], hasErrors)); + var member = new BoundPropertyPatternMember( + syntax: node.PatternList.SubPatterns[i], + memberSymbol: properties[i], + //arguments: ImmutableArray.Empty, + //argumentNamesOpt: ImmutableArray.Empty, + //argumentRefKindsOpt: ImmutableArray.Empty, + //expanded: false, + //argsToParamsOpt: default(ImmutableArray), + resultKind: LookupResultKind.Empty, + type: properties[i].GetTypeOrReturnType(), + hasErrors: hasErrors); + builder.Add(new BoundSubPropertyPattern(node.PatternList.SubPatterns[i], member, boundPatterns[i], hasErrors)); } return new BoundPropertyPattern(node, type, builder.ToImmutableAndFree(), hasErrors: hasErrors); } - private ImmutableArray BindRecursiveSubPropertyPatterns(RecursivePatternSyntax node, ImmutableArray properties, NamedTypeSymbol type, DiagnosticBag diagnostics) + private ImmutableArray BindRecursiveSubPropertyPatterns( + RecursivePatternSyntax node, + ImmutableArray properties, + NamedTypeSymbol type, + DiagnosticBag diagnostics) { var boundPatternsBuilder = ArrayBuilder.GetInstance(); for (int i = 0; i < properties.Length; i++) @@ -146,7 +178,10 @@ private ImmutableArray BindRecursiveSubPropertyPatterns(RecursiveP return boundPatternsBuilder.ToImmutableAndFree(); } - private Symbol LookupMatchableMemberInType(TypeSymbol operandType, string name, ref HashSet useSiteDiagnostics) + private Symbol LookupMatchableMemberInType( + TypeSymbol operandType, + string name, + ref HashSet useSiteDiagnostics) { var lookupResult = LookupResult.GetInstance(); this.LookupMembersInType( @@ -164,7 +199,12 @@ private Symbol LookupMatchableMemberInType(TypeSymbol operandType, string name, return result; } - private BoundPattern BindPropertyPattern(PropertyPatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) + private BoundPattern BindPropertyPattern( + PropertyPatternSyntax node, + BoundExpression operand, + TypeSymbol operandType, + bool hasErrors, + DiagnosticBag diagnostics) { var type = (NamedTypeSymbol)this.BindType(node.Type, diagnostics); hasErrors = hasErrors || CheckValidPatternType(node.Type, operand, operandType, type, false, diagnostics); @@ -172,77 +212,157 @@ private BoundPattern BindPropertyPattern(PropertyPatternSyntax node, BoundExpres return new BoundPropertyPattern(node, type, boundPatterns, hasErrors: hasErrors); } - private ImmutableArray BindSubPropertyPatterns(PropertyPatternSyntax node, TypeSymbol type, DiagnosticBag diagnostics) + private ImmutableArray BindSubPropertyPatterns( + PropertyPatternSyntax node, + TypeSymbol type, + DiagnosticBag diagnostics) { var result = ArrayBuilder.GetInstance(); - foreach (var syntax in node.PatternList.SubPatterns) + foreach (var e in node.SubPatterns) { - var propName = syntax.Left; - BoundPattern pattern; - HashSet useSiteDiagnostics = null; - LookupResultKind resultKind; - Symbol property = FindPropertyOrFieldByName(type, propName, out resultKind, ref useSiteDiagnostics); - if ((object)property != null) - { - bool hasErrors = false; - if (property.IsStatic) - { - Error(diagnostics, ErrorCode.ERR_ObjectProhibited, propName, property); - hasErrors = true; - } - else - { - diagnostics.Add(node, useSiteDiagnostics); - } - - var propertyType = property.GetTypeOrReturnType(); - pattern = this.BindPattern(syntax.Pattern, null, propertyType, hasErrors, diagnostics); - result.Add(new BoundSubPropertyPattern(syntax, propertyType, property, resultKind, pattern, hasErrors)); - } - else - { - Error(diagnostics, ErrorCode.ERR_NoSuchMember, propName, type, propName.ValueText); - pattern = new BoundWildcardPattern(node, hasErrors: true); - result.Add(new BoundSubPropertyPattern(syntax, CreateErrorType(), null, resultKind, pattern, true)); - } + var syntax = e as IsPatternExpressionSyntax; + var identifier = syntax?.Expression as IdentifierNameSyntax; + if (identifier == null) throw ExceptionUtilities.UnexpectedValue(syntax?.Expression.Kind() ?? e.Kind()); + var boundMember = BindPropertyPatternMember(type, identifier, diagnostics); + var boundPattern = BindPattern(syntax.Pattern, null, boundMember.Type, boundMember.HasErrors, diagnostics); + result.Add(new BoundSubPropertyPattern(e, boundMember, boundPattern, boundPattern.HasErrors)); } return result.ToImmutableAndFree(); } - private Symbol FindPropertyOrFieldByName(TypeSymbol type, SyntaxToken name, out LookupResultKind resultKind, ref HashSet useSiteDiagnostics) + // returns BadBoundExpression or BoundPropertyPatternMember + private BoundExpression BindPropertyPatternMember( + TypeSymbol patternType, + IdentifierNameSyntax memberName, + DiagnosticBag diagnostics) { - var symbols = ArrayBuilder.GetInstance(); - var lookupResult = LookupResult.GetInstance(); - this.LookupMembersWithFallback(lookupResult, type, name.ValueText, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics); - resultKind = lookupResult.Kind; - Symbol result = null; + // TODO: consider refactoring out common code with BindObjectInitializerMember + + BoundImplicitReceiver implicitReceiver = new BoundImplicitReceiver(memberName.Parent, patternType); + + BoundExpression boundMember = BindInstanceMemberAccess( + node: memberName, + right: memberName, + boundLeft: implicitReceiver, + rightName: memberName.Identifier.ValueText, + rightArity: 0, + typeArgumentsSyntax: default(SeparatedSyntaxList), + typeArguments: default(ImmutableArray), + invoked: false, + diagnostics: diagnostics); + LookupResultKind resultKind = boundMember.ResultKind; + if (boundMember.Kind == BoundKind.PropertyGroup) + { + boundMember = BindIndexedPropertyAccess( + (BoundPropertyGroup)boundMember, mustHaveAllOptionalParameters: true, diagnostics: diagnostics); + } + + bool hasErrors = boundMember.HasAnyErrors || implicitReceiver.HasAnyErrors; + + //ImmutableArray arguments = ImmutableArray.Empty; + //ImmutableArray argumentNamesOpt = default(ImmutableArray); + //ImmutableArray argsToParamsOpt = default(ImmutableArray); + //ImmutableArray argumentRefKindsOpt = default(ImmutableArray); + //bool expanded = false; + + switch (boundMember.Kind) + { + case BoundKind.FieldAccess: + case BoundKind.PropertyAccess: + break; + + case BoundKind.IndexerAccess: + // TODO: Should a property pattern be capable of referencing an indexed property? + // https://github.com/dotnet/roslyn/issues/9375 + //{ + // var indexer = (BoundIndexerAccess)boundMember; + // arguments = indexer.Arguments; + // argumentNamesOpt = indexer.ArgumentNamesOpt; + // argsToParamsOpt = indexer.ArgsToParamsOpt; + // argumentRefKindsOpt = indexer.ArgumentRefKindsOpt; + // expanded = indexer.Expanded; + // break; + //} + + case BoundKind.DynamicIndexerAccess: + // TODO: Should a property pattern be capable of referencing a dynamic indexer? + // https://github.com/dotnet/roslyn/issues/9375 + //{ + // var indexer = (BoundDynamicIndexerAccess)boundMember; + // arguments = indexer.Arguments; + // argumentNamesOpt = indexer.ArgumentNamesOpt; + // argumentRefKindsOpt = indexer.ArgumentRefKindsOpt; + // break; + //} + + case BoundKind.EventAccess: + // TODO: Should a property pattern be capable of referencing an event? + // https://github.com/dotnet/roslyn/issues/9515 + + default: + return BadSubpatternMemberAccess(boundMember, implicitReceiver, memberName, diagnostics, hasErrors); + } - if (lookupResult.IsMultiViable) + if (!hasErrors && !CheckValueKind(boundMember, BindValueKind.RValue, diagnostics)) { - foreach (var symbol in lookupResult.Symbols) + hasErrors = true; + resultKind = LookupResultKind.NotAValue; + } + + return new BoundPropertyPatternMember( + memberName, + boundMember.ExpressionSymbol, + //arguments, + //argumentNamesOpt, + //argumentRefKindsOpt, + //expanded, + //argsToParamsOpt, + resultKind, + boundMember.Type, + hasErrors); + } + + private BoundExpression BadSubpatternMemberAccess( + BoundExpression boundMember, + BoundImplicitReceiver implicitReceiver, + IdentifierNameSyntax memberName, + DiagnosticBag diagnostics, + bool suppressErrors) + { + if (!suppressErrors) + { + string member = memberName.Identifier.ValueText; + switch (boundMember.ResultKind) { - if (symbol.Kind == SymbolKind.Property || symbol.Kind == SymbolKind.Field) - { - if (result != null && symbol != result) - { - resultKind = LookupResultKind.Ambiguous; - result = null; - break; - } - else - { - result = symbol; - } - } + case LookupResultKind.Empty: + Error(diagnostics, ErrorCode.ERR_NoSuchMember, memberName, implicitReceiver.Type, member); + break; + + case LookupResultKind.Inaccessible: + boundMember = CheckValue(boundMember, BindValueKind.RValue, diagnostics); + Debug.Assert(boundMember.HasAnyErrors); + break; + + default: + // TODO: review and test this code path. + // https://github.com/dotnet/roslyn/issues/9542 + Error(diagnostics, ErrorCode.ERR_PropertyLacksGet, memberName, member); + break; } } - lookupResult.Free(); - return result; + // TODO: review and test this code path. Is LookupResultKind.Inaccessible appropriate? + // https://github.com/dotnet/roslyn/issues/9542 + return ToBadExpression(boundMember, LookupResultKind.Inaccessible); } - private BoundPattern BindConstantPattern(ConstantPatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) + private BoundPattern BindConstantPattern( + ConstantPatternSyntax node, + BoundExpression operand, + TypeSymbol operandType, + bool hasErrors, + DiagnosticBag diagnostics) { var expression = BindValue(node.Expression, diagnostics, BindValueKind.RValue); if (!node.HasErrors && expression.ConstantValue == null) @@ -255,7 +375,13 @@ private BoundPattern BindConstantPattern(ConstantPatternSyntax node, BoundExpres return new BoundConstantPattern(node, expression, hasErrors); } - private bool CheckValidPatternType(CSharpSyntaxNode typeSyntax, BoundExpression operand, TypeSymbol operandType, TypeSymbol patternType, bool isVar, DiagnosticBag diagnostics) + private bool CheckValidPatternType( + CSharpSyntaxNode typeSyntax, + BoundExpression operand, + TypeSymbol operandType, + TypeSymbol patternType, + bool isVar, + DiagnosticBag diagnostics) { if (operandType?.IsErrorType() == true || patternType?.IsErrorType() == true) { @@ -305,7 +431,11 @@ private bool CheckValidPatternType(CSharpSyntaxNode typeSyntax, BoundExpression } private BoundPattern BindDeclarationPattern( - DeclarationPatternSyntax node, BoundExpression operand, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) + DeclarationPatternSyntax node, + BoundExpression operand, + TypeSymbol operandType, + bool hasErrors, + DiagnosticBag diagnostics) { Debug.Assert(operand != null || (object)operandType != null); var typeSyntax = node.Type; @@ -358,7 +488,10 @@ private BoundPattern BindDeclarationPattern( return new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors); } - private TypeSymbol BestType(MatchExpressionSyntax node, ArrayBuilder cases, DiagnosticBag diagnostics) + private TypeSymbol BestType( + MatchExpressionSyntax node, + ArrayBuilder cases, + DiagnosticBag diagnostics) { var types = ArrayBuilder.GetInstance(); @@ -410,7 +543,9 @@ private TypeSymbol BestType(MatchExpressionSyntax node, ArrayBuilder.Empty, ImmutableArray.Create(expression), CreateErrorType()); + expression = new BoundBadExpression( + syntax: node.Expression, + resultKind: LookupResultKind.Viable, + symbols: ImmutableArray.Empty, + childBoundNodes: ImmutableArray.Create(expression), + type: CreateErrorType()); } BoundPattern pattern; @@ -511,9 +651,10 @@ private BoundStatement BindLetStatement(LetStatementSyntax node, DiagnosticBag d localSymbol.SetTypeSymbol(expression.Type); - pattern = new BoundDeclarationPattern(node, localSymbol, null, true, - expression.HasErrors | - this.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics)); // Check for variable declaration errors. + pattern = new BoundDeclarationPattern( + node, localSymbol, null, true, + // Check for variable declaration errors. + expression.HasErrors | this.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics)); } else { diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index a41aeaf75d730..d2a3acd2ba8e6 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -1450,12 +1450,24 @@ - - - + + + + + + + + + + + + + + + diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index 341553db05072..7dfb4938afb35 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -2772,14 +2772,8 @@ public override TResult Accept(OperationVisitor OperationKind.None; } partial class BoundMatchExpression @@ -2796,14 +2790,8 @@ public override TResult Accept(OperationVisitor OperationKind.None; } partial class BoundThrowExpression @@ -2820,13 +2808,27 @@ public override TResult Accept(OperationVisitor OperationKind.None; + } + + partial class BoundPropertyPatternMember + { + public override void Accept(OperationVisitor visitor) { - get - { - // TODO: implement IOperation for pattern-matching constructs (https://github.com/dotnet/roslyn/issues/8699) - return OperationKind.None; - } + // TODO: implement IOperation for pattern-matching constructs (https://github.com/dotnet/roslyn/issues/8699) + visitor.VisitNoneOperation(this); } + + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + // TODO: implement IOperation for pattern-matching constructs (https://github.com/dotnet/roslyn/issues/8699) + return visitor.VisitNoneOperation(this, argument); + } + + // TODO: implement IOperation for pattern-matching constructs (https://github.com/dotnet/roslyn/issues/8699) + protected override OperationKind ExpressionKind => OperationKind.None; + + public override Symbol ExpressionSymbol => this.MemberSymbol; } } diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs index bc3c4c4300579..d26d4f49fb39e 100644 --- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs +++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs @@ -430,22 +430,6 @@ public static Conversion ClassifyConversion(this Compilation compilation, ITypeS } } - /// - /// Gets the symbol information for the property of a sub-property pattern. - /// - public static SymbolInfo GetSymbolInfo(this SemanticModel semanticModel, SubPropertyPatternSyntax node, CancellationToken cancellationToken = default(CancellationToken)) - { - var csmodel = semanticModel as CSharpSemanticModel; - if (csmodel != null) - { - return csmodel.GetSymbolInfo(node, cancellationToken); - } - else - { - return SymbolInfo.None; - } - } - /// /// Returns what symbol(s), if any, the given expression syntax bound to in the program. /// diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index df85a18477e17..bee5bc9af9dba 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -495,11 +495,6 @@ internal virtual IOperation GetOperationWorker(CSharpSyntaxNode node, GetOperati /// public abstract SymbolInfo GetSymbolInfo(SelectOrGroupClauseSyntax node, CancellationToken cancellationToken = default(CancellationToken)); - /// - /// Gets the symbol information for the property of a sub-property pattern. - /// - public abstract SymbolInfo GetSymbolInfo(SubPropertyPatternSyntax node, CancellationToken cancellationToken = default(CancellationToken)); - /// /// Returns what symbol(s), if any, the given expression syntax bound to in the program. /// @@ -4351,12 +4346,6 @@ private SymbolInfo GetSymbolInfoFromNode(SyntaxNode node, CancellationToken canc return this.GetSymbolInfo(orderingSyntax, cancellationToken); } - var subPropertyPattern = node as SubPropertyPatternSyntax; - if (subPropertyPattern != null) - { - return this.GetSymbolInfo(subPropertyPattern, cancellationToken); - } - return SymbolInfo.None; } diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 1120d46e783c2..46310ea694f7c 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -948,23 +948,6 @@ internal override Optional GetConstantValueWorker(CSharpSyntaxNode node, return GetTypeInfoForQuery(bound); } - /// - /// Gets the symbol information for the property of a sub-property pattern. - /// - public override SymbolInfo GetSymbolInfo(SubPropertyPatternSyntax node, CancellationToken cancellationToken) - { - var boundNode = GetLowerBoundNode(node) as BoundSubPropertyPattern; - if (boundNode != null) - { - var property = boundNode.Property; - return new SymbolInfo(property, boundNode.ResultKind == LookupResultKind.Viable ? CandidateReason.None : boundNode.ResultKind.ToCandidateReason()); - } - else - { - return default(SymbolInfo); - } - } - private void GetBoundNodes(CSharpSyntaxNode node, out CSharpSyntaxNode bindableNode, out BoundNode lowestBoundNode, out BoundNode highestBoundNode, out BoundNode boundParent) { bindableNode = this.GetBindableSyntaxNode(node); @@ -1637,8 +1620,7 @@ internal protected virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo !(node is OrderingSyntax) && !(node is JoinIntoClauseSyntax) && !(node is QueryContinuationSyntax) && - !(node is ArrowExpressionClauseSyntax) && - !(node is SubPropertyPatternSyntax)) + !(node is ArrowExpressionClauseSyntax)) { return GetBindableSyntaxNode(parent); } diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index b254dafaba1b0..4fd3d08bdb327 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -423,13 +423,6 @@ internal override Optional GetConstantValueWorker(CSharpSyntaxNode node, return (model == null) ? default(TypeInfo) : model.GetTypeInfo(node, cancellationToken); } - public override SymbolInfo GetSymbolInfo(SubPropertyPatternSyntax node, CancellationToken cancellationToken) - { - CheckSyntaxNode(node); - var model = this.GetMemberModel(node); - return (model == null) ? default(SymbolInfo) : model.GetSymbolInfo(node, cancellationToken); - } - public override IPropertySymbol GetDeclaredSymbol(AnonymousObjectMemberDeclaratorSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)) { CheckSyntaxNode(declaratorSyntax); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass_Switch.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass_Switch.cs index 1f7a691b29660..8c78c4ffaf5cf 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass_Switch.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass_Switch.cs @@ -241,6 +241,11 @@ public virtual void VisitPattern(BoundExpression expression, BoundPattern patter } } + public override BoundNode VisitPropertyPatternMember(BoundPropertyPatternMember node) + { + throw ExceptionUtilities.Unreachable; + } + /// /// Check if the given expression is known to *always* match, or *always* fail against the given pattern. /// Return true for known match, false for known fail, and null otherwise. @@ -270,13 +275,12 @@ public virtual void VisitPattern(BoundExpression expression, BoundPattern patter { // so far so good: the expression is known to match the *type* of the property pattern. // Now check if each subpattern is irrefutable. - int n = propPattern.Subpatterns.Length; - for (int i = 0; i < n; i++) + foreach (var subpattern in propPattern.Subpatterns) { - var prop = propPattern.Subpatterns[i].Property; - var pat = propPattern.Subpatterns[i].Pattern; + var prop = (subpattern.Member as BoundPropertyPatternMember)?.MemberSymbol; + var pat = subpattern.Pattern; BoundExpression subExpr; - switch (prop.Kind) + switch (prop?.Kind) { case SymbolKind.Property: var propSymbol = (PropertySymbol)prop; @@ -286,6 +290,7 @@ public virtual void VisitPattern(BoundExpression expression, BoundPattern patter var fieldSymbol = (FieldSymbol)prop; subExpr = new BoundFieldAccess(pat.Syntax, null, fieldSymbol, null); break; + // TODO: what about events? default: return false; } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs index 190d9ed8083f3..b482406e76892 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs @@ -46,14 +46,32 @@ BoundExpression TranslatePattern(BoundExpression input, BoundPattern pattern) var temp = _factory.SynthesizedLocal(pat.Type); var matched = DeclPattern(syntax, input, temp); input = _factory.Local(temp); - for (int i = 0; i < pat.Subpatterns.Length; i++) + foreach (var subpattern in pat.Subpatterns) { - var subProperty = pat.Subpatterns[i].Property; - var subPattern = pat.Subpatterns[i].Pattern; - var subExpression = - subProperty.Kind == SymbolKind.Field - ? (BoundExpression)_factory.Field(input, (FieldSymbol)subProperty) - : _factory.Call(input, ((PropertySymbol)subProperty).GetMethod); + // TODO: review and test this code path. + // https://github.com/dotnet/roslyn/issues/9542 + // e.g. Can the `as` below result in `null`? + var subProperty = (subpattern.Member as BoundPropertyPatternMember)?.MemberSymbol; + var subPattern = subpattern.Pattern; + BoundExpression subExpression; + switch (subProperty?.Kind) + { + case SymbolKind.Field: + subExpression = _factory.Field(input, (FieldSymbol)subProperty); + break; + case SymbolKind.Property: + // TODO: review and test this code path. + // https://github.com/dotnet/roslyn/issues/9542 + // e.g. https://github.com/dotnet/roslyn/pull/9505#discussion_r55320220 + subExpression = _factory.Call(input, ((PropertySymbol)subProperty).GetMethod); + break; + case SymbolKind.Event: + // TODO: should a property pattern be capable of referencing an event? + // https://github.com/dotnet/roslyn/issues/9515 + default: + throw ExceptionUtilities.Unreachable; + } + var partialMatch = this.TranslatePattern(subExpression, subPattern); matched = _factory.LogicalAnd(matched, partialMatch); } @@ -128,7 +146,9 @@ BoundExpression DeclPattern(CSharpSyntaxNode syntax, BoundExpression input, Loca var tmpType = _factory.SpecialType(SpecialType.System_Nullable_T).Construct(type); var tmp = _factory.SynthesizedLocal(tmpType, syntax); var asg1 = _factory.AssignmentExpression(_factory.Local(tmp), _factory.As(input, tmpType)); - var value = _factory.Call(_factory.Local(tmp), GetNullableMethod(syntax, tmpType, SpecialMember.System_Nullable_T_GetValueOrDefault)); + var value = _factory.Call( + _factory.Local(tmp), + GetNullableMethod(syntax, tmpType, SpecialMember.System_Nullable_T_GetValueOrDefault)); var asg2 = _factory.AssignmentExpression(_factory.Local(target), value); var result = MakeNullableHasValue(syntax, _factory.Local(tmp)); return _factory.Sequence(tmp, asg1, asg2, result); @@ -143,7 +163,10 @@ BoundExpression DeclPattern(CSharpSyntaxNode syntax, BoundExpression input, Loca // return s; // } return _factory.Conditional(_factory.Is(input, type), - _factory.Sequence(_factory.AssignmentExpression(_factory.Local(target), _factory.Convert(type, input)), _factory.Literal(true)), + _factory.Sequence(_factory.AssignmentExpression( + _factory.Local(target), + _factory.Convert(type, input)), + _factory.Literal(true)), _factory.Literal(false), _factory.SpecialType(SpecialType.System_Boolean)); } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index e45380d017f9f..fdf4fc6845b5e 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -53,7 +53,7 @@ private CSharpSyntaxNode ParseTypeOrPattern() // X.Y.Z { ... } : PropertyPattern else if (tk == SyntaxKind.OpenBraceToken) { - node = _syntaxFactory.PropertyPattern(type, this.ParseSubPropertyPatternList()); + node = ParsePropertyPatternBody(type); } // X.Y.Z id else if (this.IsTrueIdentifier()) @@ -96,6 +96,14 @@ private CSharpSyntaxNode ParseTypeOrPattern() return node; } + private PropertyPatternSyntax ParsePropertyPatternBody(TypeSyntax type) + { + var open = this.EatToken(SyntaxKind.OpenBraceToken); + var list = this.ParseSubPropertyPatternList(ref open); + var close = this.EatToken(SyntaxKind.CloseBraceToken); + return _syntaxFactory.PropertyPattern(type, open, list, close); + } + private SubRecursivePatternListSyntax ParseSubRecursivePatternList() { if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNodeKind == SyntaxKind.SubRecursivePatternList) @@ -243,7 +251,7 @@ private CSharpSyntaxNode ParseExpressionOrPattern() // X.Y.Z { ... } : PropertyPattern else if (tk == SyntaxKind.OpenBraceToken) { - node = _syntaxFactory.PropertyPattern(type, this.ParseSubPropertyPatternList()); + node = ParsePropertyPatternBody(type); } // X.Y.Z id else if (this.IsTrueIdentifier()) @@ -272,28 +280,16 @@ private CSharpSyntaxNode ParseExpressionOrPattern() return node; } - private SubPropertyPatternListSyntax ParseSubPropertyPatternList() + private SeparatedSyntaxList ParseSubPropertyPatternList(ref SyntaxToken openBrace) { - var openBrace = this.EatToken(SyntaxKind.OpenBraceToken); - - var subPatterns = _pool.AllocateSeparated(); - try - { - this.ParseSubPropertyPatternList(ref openBrace, subPatterns); - - var closeBrace = this.EatToken(SyntaxKind.CloseBraceToken); - return _syntaxFactory.SubPropertyPatternList( - openBrace, - subPatterns, - closeBrace); - } - finally - { - _pool.Free(subPatterns); - } + var subPatterns = _pool.AllocateSeparated(); + this.ParseSubPropertyPatternList(ref openBrace, subPatterns); + var result = subPatterns.ToList(); + _pool.Free(subPatterns); + return result; } - private void ParseSubPropertyPatternList(ref SyntaxToken startToken, SeparatedSyntaxListBuilder list) + private void ParseSubPropertyPatternList(ref SyntaxToken openBrace, SeparatedSyntaxListBuilder list) { if (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken) { @@ -323,13 +319,13 @@ private void ParseSubPropertyPatternList(ref SyntaxToken startToken, SeparatedSy list.Add(ParseSubPropertyPattern()); continue; } - else if (this.SkipBadSubPatternListTokens(ref startToken, list, SyntaxKind.CommaToken, SyntaxKind.CloseBraceToken) == PostSkipAction.Abort) + else if (this.SkipBadSubPatternListTokens(ref openBrace, list, SyntaxKind.CommaToken, SyntaxKind.CloseBraceToken) == PostSkipAction.Abort) { break; } } } - else if (this.SkipBadSubPatternListTokens(ref startToken, list, SyntaxKind.IdentifierToken, SyntaxKind.CloseBraceToken) == PostSkipAction.Continue) + else if (this.SkipBadSubPatternListTokens(ref openBrace, list, SyntaxKind.IdentifierToken, SyntaxKind.CloseBraceToken) == PostSkipAction.Continue) { goto tryAgain; } @@ -341,16 +337,16 @@ private bool IsPossibleSubPropertyPattern() return (this.CurrentToken.Kind == SyntaxKind.IdentifierToken) && (this.PeekToken(1).Kind == SyntaxKind.IsKeyword); } - private SubPropertyPatternSyntax ParseSubPropertyPattern() + private IsPatternExpressionSyntax ParseSubPropertyPattern() { var name = this.EatToken(SyntaxKind.IdentifierToken); - var operandToken = this.EatToken(SyntaxKind.IsKeyword); + var identifier = _syntaxFactory.IdentifierName(name); + var isKeyword = this.EatToken(SyntaxKind.IsKeyword); PatternSyntax pattern = this.CurrentToken.Kind == SyntaxKind.CommaToken ? this.AddError(_syntaxFactory.ConstantPattern(this.CreateMissingIdentifierName()), ErrorCode.ERR_MissingArgument) : ParsePattern(); - - return _syntaxFactory.SubPropertyPattern(name, operandToken, pattern); + return _syntaxFactory.IsPatternExpression(identifier, isKeyword, pattern); } private PostSkipAction SkipBadSubPatternListTokens(ref SyntaxToken open, SeparatedSyntaxListBuilder list, SyntaxKind expected, SyntaxKind closeKind) where TNode : CSharpSyntaxNode diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index f616f6e845609..4fb92891ab2f3 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -130,11 +130,15 @@ Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.AccessorListSyntax accessorList, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.CSharp.Syntax.EqualsValueClauseSyntax initializer, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.AddPatternListSubPatterns(params Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.PatternList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.AddSubPatterns(params Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.CloseBraceToken.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.OpenBraceToken.get -> Microsoft.CodeAnalysis.SyntaxToken +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.SubPatterns.get -> Microsoft.CodeAnalysis.SeparatedSyntaxList Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax patternList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.WithPatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax patternList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.WithCloseBraceToken(Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.WithOpenBraceToken(Microsoft.CodeAnalysis.SyntaxToken openBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.WithSubPatterns(Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax.AddPatternListSubPatterns(params Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax @@ -149,23 +153,6 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax.WithRefKeyword(Micros Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode body) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.AddSubPatterns(params Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.CloseBraceToken.get -> Microsoft.CodeAnalysis.SyntaxToken -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.OpenBraceToken.get -> Microsoft.CodeAnalysis.SyntaxToken -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.SubPatterns.get -> Microsoft.CodeAnalysis.SeparatedSyntaxList -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.WithCloseBraceToken(Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.WithOpenBraceToken(Microsoft.CodeAnalysis.SyntaxToken openBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.WithSubPatterns(Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.IsKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.Left.get -> Microsoft.CodeAnalysis.SyntaxToken -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.Pattern.get -> Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken left, Microsoft.CodeAnalysis.SyntaxToken isKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.WithIsKeyword(Microsoft.CodeAnalysis.SyntaxToken isKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.WithLeft(Microsoft.CodeAnalysis.SyntaxToken left) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.WithPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax.AddSubPatterns(params Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax.CloseParenToken.get -> Microsoft.CodeAnalysis.SyntaxToken @@ -208,8 +195,6 @@ Microsoft.CodeAnalysis.CSharp.SyntaxKind.MatchKeyword = 8438 -> Microsoft.CodeAn Microsoft.CodeAnalysis.CSharp.SyntaxKind.MatchSection = 9010 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.PropertyPattern = 9006 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.RecursivePattern = 9003 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind -Microsoft.CodeAnalysis.CSharp.SyntaxKind.SubPropertyPattern = 9007 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind -Microsoft.CodeAnalysis.CSharp.SyntaxKind.SubPropertyPatternList = 9008 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.SubRecursivePattern = 9004 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.SubRecursivePatternList = 9005 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.ThrowExpression = 9012 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind @@ -225,8 +210,6 @@ override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitMatchExpression override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitMatchSection(Microsoft.CodeAnalysis.CSharp.Syntax.MatchSectionSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode -override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSubPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode -override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSubPropertyPatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSubRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSubRecursivePatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitThrowExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ThrowExpressionSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode @@ -254,10 +237,6 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.Accept(Micro override Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult override Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult -override Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void -override Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult -override Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void -override Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult override Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult override Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void @@ -270,7 +249,6 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.WildcardPatternSyntax.Accept(Micro override Microsoft.CodeAnalysis.CSharp.Syntax.WildcardPatternSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.DeclarationPatternSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.LetStatementSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol -static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetSymbolInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax node, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SymbolInfo static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.Update(this Microsoft.CodeAnalysis.CSharp.Syntax.IndexerDeclarationSyntax syntax, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken thisKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.BracketedParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.AccessorListSyntax accessorList) -> Microsoft.CodeAnalysis.CSharp.Syntax.IndexerDeclarationSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxExtensions.Update(this Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax syntax, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ArrowExpressionClause(Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax @@ -305,16 +283,12 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.MethodDeclaration(Microsoft.C static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode body) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.AccessorListSyntax accessorList, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.CSharp.Syntax.EqualsValueClauseSyntax initializer, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax patternList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax patternList) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ReturnStatement(Microsoft.CodeAnalysis.SyntaxToken returnKeyword, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SimpleLambdaExpression(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode body) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubPropertyPattern(Microsoft.CodeAnalysis.SyntaxToken left, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubPropertyPattern(Microsoft.CodeAnalysis.SyntaxToken left, Microsoft.CodeAnalysis.SyntaxToken isKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubPropertyPattern(string left, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubPropertyPatternList(Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns = default(Microsoft.CodeAnalysis.SeparatedSyntaxList)) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubPropertyPatternList(Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SubRecursivePatternList(Microsoft.CodeAnalysis.SeparatedSyntaxList subPatterns = default(Microsoft.CodeAnalysis.SeparatedSyntaxList)) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax @@ -382,8 +356,6 @@ virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitMatchExpression(M virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitMatchSection(Microsoft.CodeAnalysis.CSharp.Syntax.MatchSectionSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax node) -> void -virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax node) -> void -virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubPropertyPatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubRecursivePatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax node) -> void virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitThrowExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ThrowExpressionSyntax node) -> void @@ -399,8 +371,6 @@ virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitMatchExp virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitMatchSection(Microsoft.CodeAnalysis.CSharp.Syntax.MatchSectionSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.RecursivePatternSyntax node) -> TResult -virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubPropertyPattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternSyntax node) -> TResult -virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubPropertyPatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubPropertyPatternListSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubRecursivePattern(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitSubRecursivePatternList(Microsoft.CodeAnalysis.CSharp.Syntax.SubRecursivePatternListSyntax node) -> TResult virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitThrowExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ThrowExpressionSyntax node) -> TResult diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 3499be8770d11..d7c6462e0597f 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1716,33 +1716,30 @@ - - - - - SyntaxToken representing open brace. + SyntaxToken representing the open brace. + + + + + + The list of "ID is Pattern" expressions in the property pattern represented as IsPatternExpressionSyntax nodes. - - SyntaxToken representing close brace. + SyntaxToken representing the close brace. - - - - - - - - - - + + Class which represents the syntax node for a property pattern. + + + Creates a PropertyPatternSyntax node. + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index ce1ab2b4e4478..1a7fe43aa9983 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -547,8 +547,7 @@ public enum SyntaxKind : ushort SubRecursivePattern = 9004, SubRecursivePatternList = 9005, PropertyPattern = 9006, - SubPropertyPattern = 9007, - SubPropertyPatternList = 9008, + CasePatternSwitchLabel = 9009, MatchSection = 9010, MatchExpression = 9011, diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs index 0de28dc041ffb..0888390b0cf5e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs @@ -1040,38 +1040,80 @@ public class Program public static void Main() { object o = nameof(Main); - Console.WriteLine(o is string { Length is 4 }); - Console.WriteLine(o is string { NotFound is 4 }); + Console.WriteLine(o is P { Good is 4 }); + Console.WriteLine(o is P { NotFound is 4 }); + Console.WriteLine(o is P { Unreadable1 is 4 }); + Console.WriteLine(o is P { Unreadable2 is 4 }); + Console.WriteLine(o is P { Unreadable3 is 4 }); + } } +class P +{ + public int Good = 2; + public int Unreadable1 { set { } } + public int Unreadable2 { set { } protected get { return 0; } } + protected int Unreadable3 = 3; +} "; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions); compilation.VerifyDiagnostics( - // (9,41): error CS0117: 'string' does not contain a definition for 'NotFound' - // Console.WriteLine(o is string { NotFound is 4 }); - Diagnostic(ErrorCode.ERR_NoSuchMember, "NotFound").WithArguments("string", "NotFound").WithLocation(9, 41) + // (9,36): error CS0117: 'P' does not contain a definition for 'NotFound' + // Console.WriteLine(o is P { NotFound is 4 }); + Diagnostic(ErrorCode.ERR_NoSuchMember, "NotFound").WithArguments("P", "NotFound").WithLocation(9, 36), + // (10,36): error CS0154: The property or indexer 'P.Unreadable1' cannot be used in this context because it lacks the get accessor + // Console.WriteLine(o is P { Unreadable1 is 4 }); + Diagnostic(ErrorCode.ERR_PropertyLacksGet, "Unreadable1").WithArguments("P.Unreadable1").WithLocation(10, 36), + // (11,36): error CS0271: The property or indexer 'P.Unreadable2' cannot be used in this context because the get accessor is inaccessible + // Console.WriteLine(o is P { Unreadable2 is 4 }); + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "Unreadable2").WithArguments("P.Unreadable2").WithLocation(11, 36), + // (12,36): error CS0122: 'P.Unreadable3' is inaccessible due to its protection level + // Console.WriteLine(o is P { Unreadable3 is 4 }); + Diagnostic(ErrorCode.ERR_BadAccess, "Unreadable3").WithArguments("P.Unreadable3").WithLocation(12, 36) ); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); - var propPats = tree.GetRoot().DescendantNodes().OfType().ToArray(); - Assert.Equal(2, propPats.Length); - var p = propPats[0]; // Length is 4 + var propPats = tree.GetRoot().DescendantNodes().OfType().Where(e => e.Parent is PropertyPatternSyntax).ToArray(); + Assert.Equal(5, propPats.Length); + + var p = propPats[0].Expression; // 'Good' in Good is 4 var si = model.GetSymbolInfo(p); Assert.NotNull(si.Symbol); - Assert.Equal("Length", si.Symbol.Name); + Assert.Equal("Good", si.Symbol.Name); Assert.Equal(CandidateReason.None, si.CandidateReason); Assert.True(si.CandidateSymbols.IsDefaultOrEmpty); - p = propPats[1]; // NotFound is 4 + p = propPats[1].Expression; // 'NotFound' in NotFound is 4 si = model.GetSymbolInfo(p); Assert.Null(si.Symbol); Assert.Equal(CandidateReason.None, si.CandidateReason); Assert.True(si.CandidateSymbols.IsDefaultOrEmpty); + + p = propPats[2].Expression; // 'Unreadable1' in Unreadable1 is 4 + si = model.GetSymbolInfo(p); + Assert.Null(si.Symbol); + Assert.Equal(CandidateReason.NotAValue, si.CandidateReason); + Assert.Equal(1, si.CandidateSymbols.Length); + Assert.Equal("Unreadable1", si.CandidateSymbols[0].Name); + + p = propPats[3].Expression; // 'Unreadable2' in Unreadable2 is 4 + si = model.GetSymbolInfo(p); + Assert.Null(si.Symbol); + Assert.Equal(CandidateReason.NotAValue, si.CandidateReason); + Assert.Equal(1, si.CandidateSymbols.Length); + Assert.Equal("Unreadable2", si.CandidateSymbols[0].Name); + + p = propPats[4].Expression; // 'Unreadable3' in Unreadable3 is 4 + si = model.GetSymbolInfo(p); + Assert.Null(si.Symbol); + Assert.Equal(CandidateReason.Inaccessible, si.CandidateReason); + Assert.Equal(1, si.CandidateSymbols.Length); + Assert.Equal("Unreadable3", si.CandidateSymbols[0].Name); } - [Fact] + [Fact, WorkItem(9284, "https://github.com/dotnet/roslyn/issues/9284")] public void AmbiguousNamedProperty() { var source = @@ -1081,7 +1123,7 @@ public class Program { public static void Main() { - object o = nameof(Main); + object o = null; Console.WriteLine(o is I3 { Property is 4 }); } } @@ -1098,20 +1140,102 @@ interface I3 : I1, I2 { } var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions); compilation.VerifyDiagnostics( - // (8,37): error CS0117: 'I3' does not contain a definition for 'Property' + // (8,37): error CS0229: Ambiguity between 'I1.Property' and 'I2.Property' // Console.WriteLine(o is I3 { Property is 4 }); - Diagnostic(ErrorCode.ERR_NoSuchMember, "Property").WithArguments("I3", "Property").WithLocation(8, 37) + Diagnostic(ErrorCode.ERR_AmbigMember, "Property").WithArguments("I1.Property", "I2.Property").WithLocation(8, 37) ); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); - var propPats = tree.GetRoot().DescendantNodes().OfType().ToArray(); + var propPats = tree.GetRoot().DescendantNodes().OfType().SelectMany(s => s.SubPatterns).OfType().ToArray(); Assert.Equal(1, propPats.Length); - var p = propPats[0]; // Property is 4 + var p = propPats[0].Expression; // 'Property' in "Property is 4" var si = model.GetSymbolInfo(p); Assert.Null(si.Symbol); Assert.Equal(CandidateReason.Ambiguous, si.CandidateReason); - // Assert.Equal(2, si.CandidateSymbols.Length); // skipped due to https://github.com/dotnet/roslyn/issues/9284 + Assert.Equal(2, si.CandidateSymbols.Length); + Assert.Equal("I1", si.CandidateSymbols[0].ContainingSymbol.Name); + Assert.Equal("I2", si.CandidateSymbols[1].ContainingSymbol.Name); + } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/9284"), WorkItem(9284, "https://github.com/dotnet/roslyn/issues/9284")] + public void StaticNamedProperty() + { + var source = +@" +using System; +public class Program +{ + public static void Main() + { + object o = null; + Console.WriteLine(o is Point { X is 4 }); + } +} +class Point +{ + public static int X => 0; +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions); + + // TODO: need a better diagnostic for this + compilation.VerifyDiagnostics( + // (8,40): error CS0176: Member 'Point.X' cannot be accessed with an instance reference; qualify it with a type name instead + // Console.WriteLine(o is Point { X is 4 }); + Diagnostic(ErrorCode.ERR_ObjectProhibited, "X").WithArguments("Point.X").WithLocation(8, 40) + ); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + var propPats = tree.GetRoot().DescendantNodes().OfType().SelectMany(s => s.SubPatterns).OfType().ToArray(); + Assert.Equal(1, propPats.Length); + + var p = propPats[0].Expression; // 'X' in "X is 4" + var si = model.GetSymbolInfo(p); + Assert.Null(si.Symbol); + Assert.Equal(1, si.CandidateSymbols.Length); + Assert.Equal("X", si.CandidateSymbols[0].Name); + Assert.Equal(CandidateReason.StaticInstanceMismatch, si.CandidateReason); + } + + [Fact] + public void InaccessibleNamedProperty() + { + var source = +@" +using System; +public class Program +{ + public static void Main() + { + object o = null; + Console.WriteLine(o is Point { X is 4 }); + } +} +class Point +{ + protected int X => 0; +} +"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions); + + // TODO: need a better diagnostic for this + compilation.VerifyDiagnostics( + // (8,40): error CS0122: 'Point.X' is inaccessible due to its protection level + // Console.WriteLine(o is Point { X is 4 }); + Diagnostic(ErrorCode.ERR_BadAccess, "X").WithArguments("Point.X").WithLocation(8, 40) + ); + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree); + var propPats = tree.GetRoot().DescendantNodes().OfType().SelectMany(s => s.SubPatterns).OfType().ToArray(); + Assert.Equal(1, propPats.Length); + + var p = propPats[0].Expression; // 'X' in "X is 4" + var si = model.GetSymbolInfo(p); + Assert.Null(si.Symbol); + Assert.Equal(1, si.CandidateSymbols.Length); + Assert.Equal("X", si.CandidateSymbols[0].Name); + Assert.Equal(CandidateReason.Inaccessible, si.CandidateReason); } private static void VerifyModelForDeclarationPattern(SemanticModel model, DeclarationPatternSyntax decl, params IdentifierNameSyntax[] references) diff --git a/src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs index fa1932425da2f..358bb476296fa 100644 --- a/src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs +++ b/src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs @@ -866,10 +866,10 @@ public static ValueTuple GetBraces(this SyntaxNode nod return ValueTuple.Create(initializeExpressionNode.OpenBraceToken, initializeExpressionNode.CloseBraceToken); } - var propertyList = node as SubPropertyPatternListSyntax; - if (propertyList != null) + var propertyPattern = node as PropertyPatternSyntax; + if (propertyPattern != null) { - return ValueTuple.Create(propertyList.OpenBraceToken, propertyList.CloseBraceToken); + return ValueTuple.Create(propertyPattern.OpenBraceToken, propertyPattern.CloseBraceToken); } return new ValueTuple(); diff --git a/src/Workspaces/CSharp/Portable/Formatting/Rules/IndentBlockFormattingRule.cs b/src/Workspaces/CSharp/Portable/Formatting/Rules/IndentBlockFormattingRule.cs index e00fb6652f863..427cd0549547d 100644 --- a/src/Workspaces/CSharp/Portable/Formatting/Rules/IndentBlockFormattingRule.cs +++ b/src/Workspaces/CSharp/Portable/Formatting/Rules/IndentBlockFormattingRule.cs @@ -156,9 +156,9 @@ private void AddAlignmentBlockOperation(List list, SyntaxN } var propertyPattern = node as PropertyPatternSyntax; - if (propertyPattern?.PatternList != null) + if (propertyPattern != null) { - SetAlignmentBlockOperation(list, propertyPattern.Type.GetFirstToken(), propertyPattern.PatternList.OpenBraceToken, propertyPattern.PatternList.CloseBraceToken, IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine); + SetAlignmentBlockOperation(list, propertyPattern.Type.GetFirstToken(), propertyPattern.OpenBraceToken, propertyPattern.CloseBraceToken, IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine); return; } } diff --git a/src/Workspaces/CSharp/Portable/Formatting/Rules/SuppressFormattingRule.cs b/src/Workspaces/CSharp/Portable/Formatting/Rules/SuppressFormattingRule.cs index 3fc949e9ab91f..97cd9c4f2c850 100644 --- a/src/Workspaces/CSharp/Portable/Formatting/Rules/SuppressFormattingRule.cs +++ b/src/Workspaces/CSharp/Portable/Formatting/Rules/SuppressFormattingRule.cs @@ -159,9 +159,9 @@ private void AddSpecificNodesSuppressOperations(List list, Sy } var propertyPattern = node as PropertyPatternSyntax; - if (propertyPattern?.PatternList != null) + if (propertyPattern != null) { - AddSuppressWrappingIfOnSingleLineOperation(list, propertyPattern.Type.GetFirstToken(), propertyPattern.PatternList.CloseBraceToken); + AddSuppressWrappingIfOnSingleLineOperation(list, propertyPattern.Type.GetFirstToken(), propertyPattern.CloseBraceToken); } var casePatternLabel = node as CasePatternSwitchLabelSyntax; @@ -172,7 +172,7 @@ private void AddSpecificNodesSuppressOperations(List list, Sy propertyPattern = casePatternLabel.Pattern as PropertyPatternSyntax; if (propertyPattern != null) { - AddSuppressOperation(list, propertyPattern.PatternList.CloseBraceToken, casePatternLabel.ColonToken, SuppressOption.NoWrapping); + AddSuppressOperation(list, propertyPattern.CloseBraceToken, casePatternLabel.ColonToken, SuppressOption.NoWrapping); } } }