diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 1547b6856a583..5f757bf562b92 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -2794,7 +2794,7 @@ private BoundExpression BindArrayCreationExpression(ArrayCreationExpressionSynta // // SPEC ends - var type = (ArrayTypeSymbol)BindType(node.Type, diagnostics).TypeSymbol; + var type = (ArrayTypeSymbol)BindArrayType(node.Type, diagnostics, permitDimensions: true, basesBeingResolved: null).TypeSymbol; // CONSIDER: // @@ -2810,7 +2810,8 @@ private BoundExpression BindArrayCreationExpression(ArrayCreationExpressionSynta // error has already been reported) so that "go to definition" works. ArrayBuilder sizes = ArrayBuilder.GetInstance(); - foreach (var arg in node.Type.RankSpecifiers[0].Sizes) + ArrayRankSpecifierSyntax firstRankSpecifier = node.Type.RankSpecifiers[0]; + foreach (var arg in firstRankSpecifier.Sizes) { // These make the parse tree nicer, but they shouldn't actually appear in the bound tree. if (arg.Kind() != SyntaxKind.OmittedArraySizeExpression) @@ -2827,6 +2828,27 @@ private BoundExpression BindArrayCreationExpression(ArrayCreationExpressionSynta sizes.Add(size); } + else if (node.Initializer is null && arg == firstRankSpecifier.Sizes[0]) + { + Error(diagnostics, ErrorCode.ERR_MissingArraySize, firstRankSpecifier); + } + } + + // produce errors for additional sizes in the ranks + for (int additionalRankIndex = 1; additionalRankIndex < node.Type.RankSpecifiers.Count; additionalRankIndex++) + { + var rank = node.Type.RankSpecifiers[additionalRankIndex]; + var dimension = rank.Sizes; + foreach (var arg in dimension) + { + if (arg.Kind() != SyntaxKind.OmittedArraySizeExpression) + { + var size = BindValue(arg, diagnostics, BindValueKind.RValue); + Error(diagnostics, ErrorCode.ERR_InvalidArray, dimension[0]); + // Capture the invalid sizes for `SemanticModel` and `IOperation` + sizes.Add(size); + } + } } ImmutableArray arraySizes = sizes.ToImmutableAndFree(); @@ -3231,8 +3253,9 @@ private void BindArrayInitializerExpressions(InitializerExpressionSyntax initial } ArrayTypeSyntax arrayTypeSyntax = (ArrayTypeSyntax)typeSyntax; - TypeSyntax elementTypeSyntax = arrayTypeSyntax.ElementType; - var elementType = BindType(elementTypeSyntax, diagnostics); + var elementTypeSyntax = arrayTypeSyntax.ElementType; + var arrayType = (ArrayTypeSymbol)BindArrayType(arrayTypeSyntax, diagnostics, permitDimensions: true, basesBeingResolved: null).TypeSymbol; + var elementType = arrayType.ElementType; TypeSymbol type = GetStackAllocType(node, elementType, diagnostics, out bool hasErrors); if (!elementType.IsErrorType() && elementType.IsManagedType) @@ -3290,7 +3313,7 @@ private void BindArrayInitializerExpressions(InitializerExpressionSyntax initial } else if (node.Initializer == null) { - // ERR_MissingArraySize is already reported + Error(diagnostics, ErrorCode.ERR_MissingArraySize, rankSpecifiers[0]); count = BadExpression(countSyntax); hasErrors = true; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index 9d7d03823df01..926ff9f712de3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2724,7 +2724,8 @@ private BoundExpression BindIsOperator(BinaryExpressionSyntax node, DiagnosticBa // try binding as a type, but back off to binding as an expression if that does not work. AliasSymbol alias; var isTypeDiagnostics = DiagnosticBag.GetInstance(); - TypeSymbol targetType = BindType(node.Right, isTypeDiagnostics, out alias).TypeSymbol; + TypeSymbolWithAnnotations targetTypeWithAnnotations = BindType(node.Right, isTypeDiagnostics, out alias); + TypeSymbol targetType = targetTypeWithAnnotations.TypeSymbol; bool wasUnderscore = node.Right is IdentifierNameSyntax name && name.Identifier.ContextualKind() == SyntaxKind.UnderscoreToken; if (!wasUnderscore && targetType?.IsErrorType() == true && isTypeDiagnostics.HasAnyResolvedErrors() && @@ -2757,6 +2758,12 @@ private BoundExpression BindIsOperator(BinaryExpressionSyntax node, DiagnosticBa } diagnostics.AddRangeAndFree(isTypeDiagnostics); + if (targetType.IsReferenceType && targetTypeWithAnnotations.NullableAnnotation == NullableAnnotation.Annotated) + { + Error(diagnostics, ErrorCode.ERR_IsNullableType, node.Right, targetType); + operandHasErrors = true; + } + var typeExpression = new BoundTypeExpression(node.Right, alias, targetType); var targetTypeKind = targetType.TypeKind; if (operandHasErrors || IsOperatorErrors(node, operand.Type, typeExpression, diagnostics)) @@ -3123,7 +3130,8 @@ private BoundExpression BindAsOperator(BinaryExpressionSyntax node, DiagnosticBa { var operand = BindValue(node.Left, diagnostics, BindValueKind.RValue); AliasSymbol alias; - var targetType = BindType(node.Right, diagnostics, out alias).TypeSymbol; + TypeSymbolWithAnnotations targetTypeWithAnnotations = BindType(node.Right, diagnostics, out alias); + TypeSymbol targetType = targetTypeWithAnnotations.TypeSymbol; var typeExpression = new BoundTypeExpression(node.Right, alias, targetType); var targetTypeKind = targetType.TypeKind; var resultType = targetType; @@ -3163,13 +3171,16 @@ private BoundExpression BindAsOperator(BinaryExpressionSyntax node, DiagnosticBa return new BoundAsOperator(node, operand, typeExpression, Conversion.NoConversion, resultType, hasErrors: true); } - // SPEC: In an operation of the form E as T, E must be an expression and T must be a - // SPEC: reference type, a type parameter known to be a reference type, or a nullable type. + if (targetType.IsReferenceType && targetTypeWithAnnotations.NullableAnnotation == NullableAnnotation.Annotated) + { + Error(diagnostics, ErrorCode.ERR_AsNullableType, node.Right, targetType); - if (!targetType.IsReferenceType && !targetType.IsNullableType()) + return new BoundAsOperator(node, operand, typeExpression, Conversion.NoConversion, resultType, hasErrors: true); + } + else if (!targetType.IsReferenceType && !targetType.IsNullableType()) { - // target type for an as expression cannot be a non-nullable value type. - // generate appropriate error + // SPEC: In an operation of the form E as T, E must be an expression and T must be a + // SPEC: reference type, a type parameter known to be a reference type, or a nullable type. if (targetTypeKind == TypeKind.TypeParameter) { Error(diagnostics, ErrorCode.ERR_AsWithTypeVar, node, targetType); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index ef1877e1b32d0..8511666456a71 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -378,6 +378,7 @@ private BoundPattern BindDiscardPattern(DiscardPatternSyntax node, TypeSymbol in Debug.Assert(!typeSyntax.IsVar); // if the syntax had `var`, it would have been parsed as a var pattern. TypeSymbolWithAnnotations declType = BindType(typeSyntax, diagnostics, out AliasSymbol aliasOpt); Debug.Assert(!declType.IsNull); + Debug.Assert(typeSyntax.Kind() != SyntaxKind.NullableType); // the syntax does not permit nullable annotations BoundTypeExpression boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: false, type: declType.TypeSymbol); hasErrors |= CheckValidPatternType(typeSyntax, inputType, declType.TypeSymbol, patternTypeWasInSource: true, diagnostics: diagnostics); return boundDeclType; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 972f35804c2c9..07de2178bd504 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -413,44 +413,7 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS case SyntaxKind.ArrayType: { - var node = (ArrayTypeSyntax)syntax; - TypeSymbolWithAnnotations type = BindType(node.ElementType, diagnostics, basesBeingResolved); - if (type.IsStatic) - { - // CS0719: '{0}': array elements cannot be of static type - Error(diagnostics, ErrorCode.ERR_ArrayOfStaticClass, node.ElementType, type.TypeSymbol); - } - - if (ShouldCheckConstraints) - { - if (type.IsRestrictedType()) - { - // CS0611: Array elements cannot be of type '{0}' - Error(diagnostics, ErrorCode.ERR_ArrayElementCantBeRefAny, node.ElementType, type.TypeSymbol); - } - } - else - { - diagnostics.Add(new LazyArrayElementCantBeRefAnyDiagnosticInfo(type), node.ElementType.GetLocation()); - } - - for (int i = node.RankSpecifiers.Count - 1; i >= 0; i--) - { - var a = node.RankSpecifiers[i]; - var array = ArrayTypeSymbol.CreateCSharpArray(this.Compilation.Assembly, type, a.Rank); - - if (a.QuestionToken.IsKind(SyntaxKind.QuestionToken)) - { - type = TypeSymbolWithAnnotations.Create(array, NullableAnnotation.Annotated); - reportNullableReferenceTypesIfNeeded(a.QuestionToken); - } - else - { - type = TypeSymbolWithAnnotations.Create(IsNullableEnabled(a.CloseBracketToken), array); - } - } - - return type; + return BindArrayType((ArrayTypeSyntax)syntax, diagnostics, permitDimensions: false, basesBeingResolved); } case SyntaxKind.PointerType: @@ -523,6 +486,50 @@ void reportNullableReferenceTypesIfNeeded(SyntaxToken questionToken, TypeSymbolW } } + private TypeSymbolWithAnnotations BindArrayType( + ArrayTypeSyntax node, + DiagnosticBag diagnostics, + bool permitDimensions, + ConsList basesBeingResolved) + { + TypeSymbolWithAnnotations type = BindType(node.ElementType, diagnostics, basesBeingResolved); + if (type.IsStatic) + { + // CS0719: '{0}': array elements cannot be of static type + Error(diagnostics, ErrorCode.ERR_ArrayOfStaticClass, node.ElementType, type.TypeSymbol); + } + + if (ShouldCheckConstraints) + { + if (type.IsRestrictedType()) + { + // CS0611: Array elements cannot be of type '{0}' + Error(diagnostics, ErrorCode.ERR_ArrayElementCantBeRefAny, node.ElementType, type.TypeSymbol); + } + } + else + { + diagnostics.Add(new LazyArrayElementCantBeRefAnyDiagnosticInfo(type), node.ElementType.GetLocation()); + } + + for (int i = node.RankSpecifiers.Count - 1; i >= 0; i--) + { + var rankSpecifier = node.RankSpecifiers[i]; + var dimension = rankSpecifier.Sizes; + if (!permitDimensions && dimension.Count != 0 && dimension[0].Kind() != SyntaxKind.OmittedArraySizeExpression) + { + // https://github.com/dotnet/roslyn/issues/32464 + // Should capture invalid dimensions for use in `SemanticModel` and `IOperation`. + Error(diagnostics, ErrorCode.ERR_ArraySizeInDeclaration, rankSpecifier); + } + + var array = ArrayTypeSymbol.CreateCSharpArray(this.Compilation.Assembly, type, rankSpecifier.Rank); + type = TypeSymbolWithAnnotations.Create(IsNullableEnabled(rankSpecifier.CloseBracketToken), array); + } + + return type; + } + private TypeSymbol BindTupleType(TupleTypeSyntax syntax, DiagnosticBag diagnostics) { int numElements = syntax.Elements.Count; diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 08c9473b98a06..4ab9b6df925d9 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -582,6 +582,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead.. + /// + internal static string ERR_AsNullableType { + get { + return ResourceManager.GetString("ERR_AsNullableType", resourceCulture); + } + } + /// /// Looks up a localized string similar to Assembly '{0}' with identity '{1}' uses '{2}' which has a higher version than referenced assembly '{3}' with identity '{4}'. /// @@ -6288,6 +6297,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead.. + /// + internal static string ERR_IsNullableType { + get { + return ResourceManager.GetString("ERR_IsNullableType", resourceCulture); + } + } + /// /// Looks up a localized string similar to An expression of type '{0}' can never match the provided pattern.. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 1b95a2f4cbb3f..5707777e616a6 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5037,6 +5037,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead. + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + Invalid operand for pattern match; value required, but found '{0}'. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 6155ed6a40c49..d4e06c3f1cdff 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1676,6 +1676,9 @@ internal enum ErrorCode ERR_UsingVarInSwitchCase = 8647, ERR_GoToForwardJumpOverUsingVar = 8648, ERR_GoToBackwardJumpOverUsingVar = 8649, + ERR_IsNullableType = 8650, + ERR_AsNullableType = 8651, + #endregion diagnostics introduced for C# 8.0 // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs index e592d9baef87a..a640b2eec16ec 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs @@ -996,12 +996,11 @@ internal sealed partial class ArrayRankSpecifierSyntax : CSharpSyntaxNode internal readonly SyntaxToken openBracketToken; internal readonly GreenNode sizes; internal readonly SyntaxToken closeBracketToken; - internal readonly SyntaxToken questionToken; - internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) + internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) : base(kind, diagnostics, annotations) { - this.SlotCount = 4; + this.SlotCount = 3; this.AdjustFlagsAndWidth(openBracketToken); this.openBracketToken = openBracketToken; if (sizes != null) @@ -1011,19 +1010,14 @@ internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, } this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; - if (questionToken != null) - { - this.AdjustFlagsAndWidth(questionToken); - this.questionToken = questionToken; - } } - internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken, SyntaxFactoryContext context) + internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken, SyntaxFactoryContext context) : base(kind) { this.SetFactoryContext(context); - this.SlotCount = 4; + this.SlotCount = 3; this.AdjustFlagsAndWidth(openBracketToken); this.openBracketToken = openBracketToken; if (sizes != null) @@ -1033,18 +1027,13 @@ internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, } this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; - if (questionToken != null) - { - this.AdjustFlagsAndWidth(questionToken); - this.questionToken = questionToken; - } } - internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, GreenNode sizes, SyntaxToken closeBracketToken) : base(kind) { - this.SlotCount = 4; + this.SlotCount = 3; this.AdjustFlagsAndWidth(openBracketToken); this.openBracketToken = openBracketToken; if (sizes != null) @@ -1054,18 +1043,11 @@ internal ArrayRankSpecifierSyntax(SyntaxKind kind, SyntaxToken openBracketToken, } this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; - if (questionToken != null) - { - this.AdjustFlagsAndWidth(questionToken); - this.questionToken = questionToken; - } } public SyntaxToken OpenBracketToken { get { return this.openBracketToken; } } public Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList Sizes { get { return new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(this.sizes)); } } public SyntaxToken CloseBracketToken { get { return this.closeBracketToken; } } - /// SyntaxToken representing the question mark. - public SyntaxToken QuestionToken { get { return this.questionToken; } } internal override GreenNode GetSlot(int index) { @@ -1074,7 +1056,6 @@ internal override GreenNode GetSlot(int index) case 0: return this.openBracketToken; case 1: return this.sizes; case 2: return this.closeBracketToken; - case 3: return this.questionToken; default: return null; } } @@ -1094,11 +1075,11 @@ public override void Accept(CSharpSyntaxVisitor visitor) visitor.VisitArrayRankSpecifier(this); } - public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) { - if (openBracketToken != this.OpenBracketToken || sizes != this.Sizes || closeBracketToken != this.CloseBracketToken || questionToken != this.QuestionToken) + if (openBracketToken != this.OpenBracketToken || sizes != this.Sizes || closeBracketToken != this.CloseBracketToken) { - var newNode = SyntaxFactory.ArrayRankSpecifier(openBracketToken, sizes, closeBracketToken, questionToken); + var newNode = SyntaxFactory.ArrayRankSpecifier(openBracketToken, sizes, closeBracketToken); var diags = this.GetDiagnostics(); if (diags != null && diags.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -1113,18 +1094,18 @@ public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, Microsoft.C internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics) { - return new ArrayRankSpecifierSyntax(this.Kind, this.openBracketToken, this.sizes, this.closeBracketToken, this.questionToken, diagnostics, GetAnnotations()); + return new ArrayRankSpecifierSyntax(this.Kind, this.openBracketToken, this.sizes, this.closeBracketToken, diagnostics, GetAnnotations()); } internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations) { - return new ArrayRankSpecifierSyntax(this.Kind, this.openBracketToken, this.sizes, this.closeBracketToken, this.questionToken, GetDiagnostics(), annotations); + return new ArrayRankSpecifierSyntax(this.Kind, this.openBracketToken, this.sizes, this.closeBracketToken, GetDiagnostics(), annotations); } internal ArrayRankSpecifierSyntax(ObjectReader reader) : base(reader) { - this.SlotCount = 4; + this.SlotCount = 3; var openBracketToken = (SyntaxToken)reader.ReadValue(); if (openBracketToken != null) { @@ -1143,12 +1124,6 @@ internal ArrayRankSpecifierSyntax(ObjectReader reader) AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; } - var questionToken = (SyntaxToken)reader.ReadValue(); - if (questionToken != null) - { - AdjustFlagsAndWidth(questionToken); - this.questionToken = questionToken; - } } internal override void WriteTo(ObjectWriter writer) @@ -1157,7 +1132,6 @@ internal override void WriteTo(ObjectWriter writer) writer.WriteValue(this.openBracketToken); writer.WriteValue(this.sizes); writer.WriteValue(this.closeBracketToken); - writer.WriteValue(this.questionToken); } static ArrayRankSpecifierSyntax() @@ -37760,8 +37734,7 @@ public override CSharpSyntaxNode VisitArrayRankSpecifier(ArrayRankSpecifierSynta var openBracketToken = (SyntaxToken)this.Visit(node.OpenBracketToken); var sizes = this.VisitList(node.Sizes); var closeBracketToken = (SyntaxToken)this.Visit(node.CloseBracketToken); - var questionToken = (SyntaxToken)this.Visit(node.QuestionToken); - return node.Update(openBracketToken, sizes, closeBracketToken, questionToken); + return node.Update(openBracketToken, sizes, closeBracketToken); } public override CSharpSyntaxNode VisitPointerType(PointerTypeSyntax node) @@ -39779,7 +39752,7 @@ public ArrayTypeSyntax ArrayType(TypeSyntax elementType, Microsoft.CodeAnalysis. return result; } - public ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + public ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) { #if DEBUG if (openBracketToken == null) @@ -39800,20 +39773,19 @@ public ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, default: throw new ArgumentException(nameof(closeBracketToken)); } - if (questionToken != null) - { - switch (questionToken.Kind) +#endif + + int hash; + var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken, this.context, out hash); + if (cached != null) return (ArrayRankSpecifierSyntax)cached; + + var result = new ArrayRankSpecifierSyntax(SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken, this.context); + if (hash >= 0) { - case SyntaxKind.QuestionToken: - case SyntaxKind.None: - break; - default: - throw new ArgumentException(nameof(questionToken)); - } + SyntaxNodeCache.AddNode(result, hash); } -#endif - return new ArrayRankSpecifierSyntax(SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken, questionToken, this.context); + return result; } public PointerTypeSyntax PointerType(TypeSyntax elementType, SyntaxToken asteriskToken) @@ -47110,7 +47082,7 @@ public static ArrayTypeSyntax ArrayType(TypeSyntax elementType, Microsoft.CodeAn return result; } - public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) { #if DEBUG if (openBracketToken == null) @@ -47131,20 +47103,19 @@ public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracke default: throw new ArgumentException(nameof(closeBracketToken)); } - if (questionToken != null) - { - switch (questionToken.Kind) +#endif + + int hash; + var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken, out hash); + if (cached != null) return (ArrayRankSpecifierSyntax)cached; + + var result = new ArrayRankSpecifierSyntax(SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken); + if (hash >= 0) { - case SyntaxKind.QuestionToken: - case SyntaxKind.None: - break; - default: - throw new ArgumentException(nameof(questionToken)); - } + SyntaxNodeCache.AddNode(result, hash); } -#endif - return new ArrayRankSpecifierSyntax(SyntaxKind.ArrayRankSpecifier, openBracketToken, sizes.Node, closeBracketToken, questionToken); + return result; } public static PointerTypeSyntax PointerType(TypeSyntax elementType, SyntaxToken asteriskToken) diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs index e171d5e5c6547..02e82c35a09b0 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs @@ -2657,8 +2657,7 @@ public override SyntaxNode VisitArrayRankSpecifier(ArrayRankSpecifierSyntax node var openBracketToken = this.VisitToken(node.OpenBracketToken); var sizes = this.VisitList(node.Sizes); var closeBracketToken = this.VisitToken(node.CloseBracketToken); - var questionToken = this.VisitToken(node.QuestionToken); - return node.Update(openBracketToken, sizes, closeBracketToken, questionToken); + return node.Update(openBracketToken, sizes, closeBracketToken); } public override SyntaxNode VisitPointerType(PointerTypeSyntax node) @@ -4621,7 +4620,7 @@ public static ArrayTypeSyntax ArrayType(TypeSyntax elementType) } /// Creates a new ArrayRankSpecifierSyntax instance. - public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) { switch (openBracketToken.Kind()) { @@ -4637,22 +4636,14 @@ public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracke default: throw new ArgumentException(nameof(closeBracketToken)); } - switch (questionToken.Kind()) - { - case SyntaxKind.QuestionToken: - case SyntaxKind.None: - break; - default: - throw new ArgumentException(nameof(questionToken)); - } - return (ArrayRankSpecifierSyntax)Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.ArrayRankSpecifier((Syntax.InternalSyntax.SyntaxToken)openBracketToken.Node, sizes.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBracketToken.Node, (Syntax.InternalSyntax.SyntaxToken)questionToken.Node).CreateRed(); + return (ArrayRankSpecifierSyntax)Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.ArrayRankSpecifier((Syntax.InternalSyntax.SyntaxToken)openBracketToken.Node, sizes.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBracketToken.Node).CreateRed(); } /// Creates a new ArrayRankSpecifierSyntax instance. public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SeparatedSyntaxList sizes = default(SeparatedSyntaxList)) { - return SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), sizes, SyntaxFactory.Token(SyntaxKind.CloseBracketToken), default(SyntaxToken)); + return SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), sizes, SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); } /// Creates a new PointerTypeSyntax instance. diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs index df3117a313c5b..513588facc211 100644 --- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs @@ -649,19 +649,6 @@ public SyntaxToken CloseBracketToken get { return new SyntaxToken(this, ((Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.ArrayRankSpecifierSyntax)this.Green).closeBracketToken, this.GetChildPosition(2), this.GetChildIndex(2)); } } - /// SyntaxToken representing the question mark. - public SyntaxToken QuestionToken - { - get - { - var slot = ((Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.ArrayRankSpecifierSyntax)this.Green).questionToken; - if (slot != null) - return new SyntaxToken(this, slot, this.GetChildPosition(3), this.GetChildIndex(3)); - - return default(SyntaxToken); - } - } - internal override SyntaxNode GetNodeSlot(int index) { switch (index) @@ -689,11 +676,11 @@ public override void Accept(CSharpSyntaxVisitor visitor) visitor.VisitArrayRankSpecifier(this); } - public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken, SyntaxToken questionToken) + public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) { - if (openBracketToken != this.OpenBracketToken || sizes != this.Sizes || closeBracketToken != this.CloseBracketToken || questionToken != this.QuestionToken) + if (openBracketToken != this.OpenBracketToken || sizes != this.Sizes || closeBracketToken != this.CloseBracketToken) { - var newNode = SyntaxFactory.ArrayRankSpecifier(openBracketToken, sizes, closeBracketToken, questionToken); + var newNode = SyntaxFactory.ArrayRankSpecifier(openBracketToken, sizes, closeBracketToken); var annotations = this.GetAnnotations(); if (annotations != null && annotations.Length > 0) return newNode.WithAnnotations(annotations); @@ -705,22 +692,17 @@ public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, SeparatedSy public ArrayRankSpecifierSyntax WithOpenBracketToken(SyntaxToken openBracketToken) { - return this.Update(openBracketToken, this.Sizes, this.CloseBracketToken, this.QuestionToken); + return this.Update(openBracketToken, this.Sizes, this.CloseBracketToken); } public ArrayRankSpecifierSyntax WithSizes(SeparatedSyntaxList sizes) { - return this.Update(this.OpenBracketToken, sizes, this.CloseBracketToken, this.QuestionToken); + return this.Update(this.OpenBracketToken, sizes, this.CloseBracketToken); } public ArrayRankSpecifierSyntax WithCloseBracketToken(SyntaxToken closeBracketToken) { - return this.Update(this.OpenBracketToken, this.Sizes, closeBracketToken, this.QuestionToken); - } - - public ArrayRankSpecifierSyntax WithQuestionToken(SyntaxToken questionToken) - { - return this.Update(this.OpenBracketToken, this.Sizes, this.CloseBracketToken, questionToken); + return this.Update(this.OpenBracketToken, this.Sizes, closeBracketToken); } public ArrayRankSpecifierSyntax AddSizes(params ExpressionSyntax[] items) diff --git a/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs b/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs index 21b471e15d080..ff8d7b04a285c 100644 --- a/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/DocumentationCommentParser.cs @@ -1407,14 +1407,7 @@ private TypeSyntax ParseCrefTypeSuffix(TypeSyntax type) // Eat the close brace and we're done. var close = this.EatToken(SyntaxKind.CloseBracketToken); - SyntaxToken questionToken = null; - - if (this.CurrentToken.Kind == SyntaxKind.QuestionToken) - { - questionToken = CheckFeatureAvailability(this.EatToken(), MessageID.IDS_FeatureNullableReferenceTypes); - } - - rankList.Add(SyntaxFactory.ArrayRankSpecifier(open, dimensionList, close, questionToken)); + rankList.Add(SyntaxFactory.ArrayRankSpecifier(open, dimensionList, close)); } finally { diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 0bb99247edfc6..63f2eab29afd8 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -4524,7 +4524,7 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS case SyntaxKind.OpenBracketToken: bool sawNonOmittedSize; _termState |= TerminatorState.IsPossibleEndOfVariableDeclaration; - var specifier = this.ParseArrayRankSpecifier(isArrayCreation: false, expectSizes: flags == VariableFlags.Fixed, questionTokenModeOpt: null, sawNonOmittedSize: out sawNonOmittedSize); + var specifier = this.ParseArrayRankSpecifier(sawNonOmittedSize: out sawNonOmittedSize); _termState = saveTerm; var open = specifier.OpenBracketToken; var sizes = specifier.Sizes; @@ -4543,6 +4543,12 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS var expression = item as ExpressionSyntax; if (expression != null) { + bool isOmitted = expression.Kind == SyntaxKind.OmittedArraySizeExpression; + if (!isFixed && !isOmitted) + { + expression = this.AddError(expression, ErrorCode.ERR_ArraySizeInDeclaration); + } + args.Add(_syntaxFactory.Argument(null, default(SyntaxToken), expression)); } else @@ -5886,15 +5892,9 @@ private bool IsPossibleType() return IsPredefinedType(tk) || this.IsTrueIdentifier(); } - private bool IsPossibleName() - { - return this.IsTrueIdentifier(); - } - private ScanTypeFlags ScanType(bool forPattern = false) { - SyntaxToken lastTokenOfType; - return ScanType(out lastTokenOfType, forPattern); + return ScanType(out _, forPattern); } private ScanTypeFlags ScanType(out SyntaxToken lastTokenOfType, bool forPattern = false) @@ -5902,42 +5902,6 @@ private ScanTypeFlags ScanType(out SyntaxToken lastTokenOfType, bool forPattern return ScanType(forPattern ? ParseTypeMode.DefinitePattern : ParseTypeMode.Normal, out lastTokenOfType); } - private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfType) - { - ScanTypeFlags result = this.ScanNonArrayType(mode, out lastTokenOfType); - - if (result == ScanTypeFlags.NotType) - { - return result; - } - - // Finally, check for array types. - while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) - { - this.EatToken(); - while (this.CurrentToken.Kind == SyntaxKind.CommaToken) - { - this.EatToken(); - } - - if (this.CurrentToken.Kind != SyntaxKind.CloseBracketToken) - { - lastTokenOfType = null; - return ScanTypeFlags.NotType; - } - - lastTokenOfType = this.EatToken(); - result = ScanTypeFlags.MustBeType; - - if (this.CurrentToken.Kind == SyntaxKind.QuestionToken) - { - lastTokenOfType = this.EatToken(); - } - } - - return result; - } - private void ScanNamedTypePart() { SyntaxToken lastTokenOfType; @@ -5963,14 +5927,9 @@ private ScanTypeFlags ScanNamedTypePart(out SyntaxToken lastTokenOfType) } } - private ScanTypeFlags ScanNonArrayType() - { - SyntaxToken lastTokenOfType; - return ScanNonArrayType(ParseTypeMode.Normal, out lastTokenOfType); - } - - private ScanTypeFlags ScanNonArrayType(ParseTypeMode mode, out SyntaxToken lastTokenOfType) + private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfType) { + Debug.Assert(mode != ParseTypeMode.NewExpression); ScanTypeFlags result; if (this.CurrentToken.Kind == SyntaxKind.RefKeyword) @@ -6040,44 +5999,71 @@ private ScanTypeFlags ScanNonArrayType(ParseTypeMode mode, out SyntaxToken lastT return ScanTypeFlags.NotType; } - if (this.CurrentToken.Kind == SyntaxKind.QuestionToken) - { - lastTokenOfType = this.EatToken(); - result = ScanTypeFlags.NullableType; - } - - // Now check for pointer type(s) - switch (mode) + int lastTokenPosition = -1; + while (IsMakingProgress(ref lastTokenPosition)) { - case ParseTypeMode.FirstElementOfPossibleTupleLiteral: - case ParseTypeMode.AfterTupleComma: - // We are parsing the type for a declaration expression in a tuple, which does - // not permit pointer types except as an element type of an array type. - // In that context a `*` is parsed as a multiplication. - if (PointerTypeModsFollowedByRankAndDimensionSpecifier()) - { - goto default; - } - break; - case ParseTypeMode.DefinitePattern: - // pointer type syntax is not supported in patterns. - break; - default: - while (this.CurrentToken.Kind == SyntaxKind.AsteriskToken) - { + switch (this.CurrentToken.Kind) + { + case SyntaxKind.QuestionToken + when lastTokenOfType.Kind != SyntaxKind.QuestionToken && // don't allow `Type??` + lastTokenOfType.Kind != SyntaxKind.AsteriskToken: // don't allow `Type*?` lastTokenOfType = this.EatToken(); - if (result == ScanTypeFlags.GenericTypeOrExpression || result == ScanTypeFlags.NonGenericTypeOrExpression) + result = ScanTypeFlags.NullableType; + break; + case SyntaxKind.AsteriskToken + when lastTokenOfType.Kind != SyntaxKind.CloseBracketToken: // don't allow `Type[]*` + // Check for pointer type(s) + switch (mode) { - result = ScanTypeFlags.PointerOrMultiplication; + case ParseTypeMode.FirstElementOfPossibleTupleLiteral: + case ParseTypeMode.AfterTupleComma: + // We are parsing the type for a declaration expression in a tuple, which does + // not permit pointer types except as an element type of an array type. + // In that context a `*` is parsed as a multiplication. + if (PointerTypeModsFollowedByRankAndDimensionSpecifier()) + { + goto default; + } + goto done; + case ParseTypeMode.DefinitePattern: + // pointer type syntax is not supported in patterns. + goto done; + default: + lastTokenOfType = this.EatToken(); + if (result == ScanTypeFlags.GenericTypeOrExpression || result == ScanTypeFlags.NonGenericTypeOrExpression) + { + result = ScanTypeFlags.PointerOrMultiplication; + } + else if (result == ScanTypeFlags.GenericTypeOrMethod) + { + result = ScanTypeFlags.MustBeType; + } + break; + } + break; + case SyntaxKind.OpenBracketToken: + // Check for array types. + this.EatToken(); + while (this.CurrentToken.Kind == SyntaxKind.CommaToken) + { + this.EatToken(); } - else if (result == ScanTypeFlags.GenericTypeOrMethod) + + if (this.CurrentToken.Kind != SyntaxKind.CloseBracketToken) { - result = ScanTypeFlags.MustBeType; + lastTokenOfType = null; + return ScanTypeFlags.NotType; } - } - break; + + lastTokenOfType = this.EatToken(); + result = ScanTypeFlags.MustBeType; + break; + default: + goto done; + } } +done:; return result; } @@ -6150,42 +6136,6 @@ private TypeSyntax ParseTypeOrVoid() return this.ParseType(); } - private bool IsTerm() - { - switch (this.CurrentToken.Kind) - { - case SyntaxKind.ArgListKeyword: - case SyntaxKind.MakeRefKeyword: - case SyntaxKind.RefTypeKeyword: - case SyntaxKind.RefValueKeyword: - case SyntaxKind.BaseKeyword: - case SyntaxKind.CheckedKeyword: - case SyntaxKind.DefaultKeyword: - case SyntaxKind.DelegateKeyword: - case SyntaxKind.FalseKeyword: - case SyntaxKind.NewKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.SizeOfKeyword: - case SyntaxKind.ThisKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.TypeOfKeyword: - case SyntaxKind.UncheckedKeyword: - case SyntaxKind.NumericLiteralToken: - case SyntaxKind.StringKeyword: - case SyntaxKind.StringLiteralToken: - case SyntaxKind.CharacterLiteralToken: - case SyntaxKind.OpenParenToken: - case SyntaxKind.EqualsGreaterThanToken: - case SyntaxKind.InterpolatedStringToken: - case SyntaxKind.InterpolatedStringStartToken: - return true; - case SyntaxKind.IdentifierToken: - return this.IsTrueIdentifier(); - default: - return false; - } - } - private enum ParseTypeMode { Normal, @@ -6195,15 +6145,13 @@ private enum ParseTypeMode AfterOut, AfterTupleComma, AsExpression, - ArrayCreation, + NewExpression, FirstElementOfPossibleTupleLiteral } - private TypeSyntax ParseType( - ParseTypeMode mode = ParseTypeMode.Normal, - bool expectSizes = false) + private TypeSyntax ParseType(ParseTypeMode mode = ParseTypeMode.Normal) { - if (mode == ParseTypeMode.Normal && !expectSizes && this.CurrentToken.Kind == SyntaxKind.RefKeyword) + if (this.CurrentToken.Kind == SyntaxKind.RefKeyword) { var refKeyword = this.EatToken(); refKeyword = this.CheckFeatureAvailability(refKeyword, MessageID.IDS_FeatureRefLocalsReturns); @@ -6215,16 +6163,14 @@ private enum ParseTypeMode readonlyKeyword = this.CheckFeatureAvailability(readonlyKeyword, MessageID.IDS_FeatureReadOnlyReferences); } - var type = ParseTypeCore(mode, expectSizes); + var type = ParseTypeCore(mode); return _syntaxFactory.RefType(refKeyword, readonlyKeyword, type); } - return ParseTypeCore(mode, expectSizes); + return ParseTypeCore(mode); } - private TypeSyntax ParseTypeCore( - ParseTypeMode mode, - bool expectSizes) + private TypeSyntax ParseTypeCore(ParseTypeMode mode) { NameOptions nameOptions; switch (mode) @@ -6244,7 +6190,7 @@ private enum ParseTypeMode case ParseTypeMode.FirstElementOfPossibleTupleLiteral: nameOptions = NameOptions.InExpression | NameOptions.FirstElementOfPossibleTupleLiteral; break; - case ParseTypeMode.ArrayCreation: + case ParseTypeMode.NewExpression: case ParseTypeMode.AsExpression: case ParseTypeMode.Normal: case ParseTypeMode.Parameter: @@ -6257,59 +6203,84 @@ private enum ParseTypeMode var type = this.ParseUnderlyingType(parentIsParameter: mode == ParseTypeMode.Parameter, options: nameOptions); Debug.Assert(type != null); - if (this.CurrentToken.Kind == SyntaxKind.QuestionToken && - // we do not permit nullable types in a declaration pattern - (mode != ParseTypeMode.AfterIs && mode != ParseTypeMode.DefinitePattern || !IsTrueIdentifier(this.PeekToken(1)))) - { - var question = EatNullableQualifierIfApplicable(mode); - if (question != null) - { - type = _syntaxFactory.NullableType(type, question); - } - } - - switch (mode) - { - case ParseTypeMode.AfterIs: - case ParseTypeMode.DefinitePattern: - case ParseTypeMode.AfterTupleComma: - case ParseTypeMode.FirstElementOfPossibleTupleLiteral: - // these contexts do not permit a pointer type except as an element type of an array. - if (PointerTypeModsFollowedByRankAndDimensionSpecifier()) - { - type = this.ParsePointerTypeMods(type); - } - break; - case ParseTypeMode.Normal: - case ParseTypeMode.Parameter: - case ParseTypeMode.AfterOut: - case ParseTypeMode.ArrayCreation: - case ParseTypeMode.AsExpression: - type = this.ParsePointerTypeMods(type); - break; - } - - // Now check for arrays. - if (this.IsPossibleRankAndDimensionSpecifier()) + int lastTokenPosition = -1; + while (IsMakingProgress(ref lastTokenPosition)) { - var ranks = _pool.Allocate(); - try + switch (this.CurrentToken.Kind) { - while (this.IsPossibleRankAndDimensionSpecifier()) - { - bool unused; - var rank = this.ParseArrayRankSpecifier(mode == ParseTypeMode.ArrayCreation, expectSizes, questionTokenModeOpt: mode, out unused); - ranks.Add(rank); - expectSizes = false; - } + case SyntaxKind.QuestionToken when canBeNullableType(): + { + var question = EatNullableQualifierIfApplicable(mode); + if (question != null) + { + type = _syntaxFactory.NullableType(type, question); + continue; + } + goto done; // token not consumed + } + bool canBeNullableType() + { + // These are the fast tests for (in)applicability. + // More expensive tests are in `EatNullableQualifierIfApplicable` + if (type.Kind == SyntaxKind.NullableType || type.Kind == SyntaxKind.PointerType) + return false; + if (this.PeekToken(1).Kind == SyntaxKind.OpenBracketToken) + return true; + if (mode == ParseTypeMode.DefinitePattern) + return false; + if (mode == ParseTypeMode.NewExpression && type.Kind == SyntaxKind.TupleType && + this.PeekToken(1).Kind != SyntaxKind.OpenParenToken && this.PeekToken(1).Kind != SyntaxKind.OpenBraceToken) + return false; // Permit `new (int, int)?(t)` (creation) and `new (int, int) ? x : y` (ternary) + return true; + } + case SyntaxKind.AsteriskToken when type.Kind != SyntaxKind.ArrayType: + switch (mode) + { + case ParseTypeMode.AfterIs: + case ParseTypeMode.DefinitePattern: + case ParseTypeMode.AfterTupleComma: + case ParseTypeMode.FirstElementOfPossibleTupleLiteral: + // these contexts do not permit a pointer type except as an element type of an array. + if (PointerTypeModsFollowedByRankAndDimensionSpecifier()) + { + type = this.ParsePointerTypeMods(type); + continue; + } + break; + case ParseTypeMode.Normal: + case ParseTypeMode.Parameter: + case ParseTypeMode.AfterOut: + case ParseTypeMode.AsExpression: + case ParseTypeMode.NewExpression: + type = this.ParsePointerTypeMods(type); + continue; + } + goto done; // token not consumed + case SyntaxKind.OpenBracketToken: + // Now check for arrays. + { + var ranks = _pool.Allocate(); + try + { + while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + { + var rank = this.ParseArrayRankSpecifier(out _); + ranks.Add(rank); + } - type = _syntaxFactory.ArrayType(type, ranks); - } - finally - { - _pool.Free(ranks); + type = _syntaxFactory.ArrayType(type, ranks); + } + finally + { + _pool.Free(ranks); + } + continue; + } + default: + goto done; // token not consumed } } +done:; Debug.Assert(type != null); return type; @@ -6318,31 +6289,49 @@ private enum ParseTypeMode private SyntaxToken EatNullableQualifierIfApplicable(ParseTypeMode mode) { Debug.Assert(this.CurrentToken.Kind == SyntaxKind.QuestionToken); - - // we do not permit nullable types in a declaration pattern - if (mode != ParseTypeMode.AfterIs && mode != ParseTypeMode.DefinitePattern || !IsTrueIdentifier(this.PeekToken(1))) + var resetPoint = this.GetResetPoint(); + try { - var resetPoint = this.GetResetPoint(); - try + var questionToken = this.EatToken(); + if (!canFollowNullableType()) { - var question = this.EatToken(); + // Restore current token index + this.Reset(ref resetPoint); + return null; + } - var isOrAs = mode == ParseTypeMode.AsExpression || mode == ParseTypeMode.AfterIs; - if (isOrAs && (IsTerm() || IsPredefinedType(this.CurrentToken.Kind) || SyntaxFacts.IsAnyUnaryExpression(this.CurrentToken.Kind))) - { - this.Reset(ref resetPoint); - return null; + return CheckFeatureAvailability(questionToken, MessageID.IDS_FeatureNullable); + + bool canFollowNullableType() + { + switch (mode) + { + case ParseTypeMode.AfterIs: + case ParseTypeMode.DefinitePattern: + case ParseTypeMode.AsExpression: + // These contexts might be a type that is at the end of an expression. + // In these contexts we only permit the nullable qualifier if it is followed + // by a token that could not start an expression, because for backward + // compatibility we want to consider a `?` token as part of the `?:` + // operator if possible. + return !CanStartExpression(); + case ParseTypeMode.NewExpression: + // A nullable qualifier is permitted as part of the type in a `new` expression. + // e.g. `new int?()` is allowed. It creates a null value of type `Nullable`. + // But the object initializer syntax `new int? {}` is not permitted. + return + this.CurrentToken.Kind == SyntaxKind.OpenParenToken || // ctor parameters + this.CurrentToken.Kind == SyntaxKind.OpenBracketToken || // array type + this.CurrentToken.Kind == SyntaxKind.OpenBraceToken; // object initializer + default: + return true; } - - return CheckFeatureAvailability(question, MessageID.IDS_FeatureNullable); - } - finally - { - this.Release(ref resetPoint); } } - - return null; + finally + { + this.Release(ref resetPoint); + } } private bool PointerTypeModsFollowedByRankAndDimensionSpecifier() @@ -6362,12 +6351,7 @@ private bool PointerTypeModsFollowedByRankAndDimensionSpecifier() } } - private bool IsPossibleRankAndDimensionSpecifier() - { - return this.CurrentToken.Kind == SyntaxKind.OpenBracketToken; - } - - private ArrayRankSpecifierSyntax ParseArrayRankSpecifier(bool isArrayCreation, bool expectSizes, ParseTypeMode? questionTokenModeOpt, out bool sawNonOmittedSize) + private ArrayRankSpecifierSyntax ParseArrayRankSpecifier(out bool sawNonOmittedSize) { sawNonOmittedSize = false; bool sawOmittedSize = false; @@ -6389,11 +6373,6 @@ private ArrayRankSpecifierSyntax ParseArrayRankSpecifier(bool isArrayCreation, b { var size = this.ParseExpressionCore(); sawNonOmittedSize = true; - if (!expectSizes) - { - size = this.AddError(size, isArrayCreation ? ErrorCode.ERR_InvalidArray : ErrorCode.ERR_ArraySizeInDeclaration); - } - list.Add(size); if (this.CurrentToken.Kind != SyntaxKind.CloseBracketToken) @@ -6432,14 +6411,7 @@ private ArrayRankSpecifierSyntax ParseArrayRankSpecifier(bool isArrayCreation, b // Eat the close brace and we're done. var close = this.EatToken(SyntaxKind.CloseBracketToken); - - SyntaxToken questionToken = null; - if (questionTokenModeOpt != null && this.CurrentToken.Kind == SyntaxKind.QuestionToken) - { - questionToken = EatNullableQualifierIfApplicable(questionTokenModeOpt.GetValueOrDefault()); - } - - return _syntaxFactory.ArrayRankSpecifier(open, list, close, questionToken); + return _syntaxFactory.ArrayRankSpecifier(open, list, close); } finally { @@ -8807,9 +8779,25 @@ private ExpressionSyntax ParseExpressionCore() return this.ParseSubExpression(Precedence.Expression); } - private bool IsPossibleExpression(bool allowBinaryExpressions = true, bool allowAssignmentExpressions = true) + /// + /// Is the current token one that could start an expression? + /// + private bool CanStartExpression() { - var tk = this.CurrentToken.Kind; + return IsPossibleExpression(allowBinaryExpressions: false, allowAssignmentExpressions: false); + } + + /// + /// Is the current token one that could be in an expression? + /// + private bool IsPossibleExpression() + { + return IsPossibleExpression(allowBinaryExpressions: true, allowAssignmentExpressions: true); + } + + private bool IsPossibleExpression(bool allowBinaryExpressions, bool allowAssignmentExpressions) + { + SyntaxKind tk = this.CurrentToken.Kind; switch (tk) { case SyntaxKind.TypeOfKeyword: @@ -9124,7 +9112,7 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence) newPrecedence = GetPrecedence(opKind); ExpressionSyntax rightOperand; - if (IsPossibleExpression(allowBinaryExpressions: false, allowAssignmentExpressions: false)) + if (CanStartExpression()) { rightOperand = this.ParseSubExpression(newPrecedence); } @@ -9278,7 +9266,7 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence) Debug.Assert(opKind == SyntaxKind.RangeExpression); ExpressionSyntax rightOperand; - if (IsPossibleExpression(allowBinaryExpressions: false, allowAssignmentExpressions: false)) + if (CanStartExpression()) { newPrecedence = GetPrecedence(opKind); rightOperand = this.ParseSubExpression(newPrecedence); @@ -10579,8 +10567,7 @@ private bool IsDictionaryInitializer() private ExpressionSyntax ParseArrayOrObjectCreationExpression() { SyntaxToken @new = this.EatToken(SyntaxKind.NewKeyword); - bool isPossibleArrayCreation = this.IsPossibleArrayCreationExpression(); - var type = this.ParseType(isPossibleArrayCreation ? ParseTypeMode.ArrayCreation : ParseTypeMode.Normal, expectSizes: isPossibleArrayCreation); + var type = this.ParseType(ParseTypeMode.NewExpression); if (type.Kind == SyntaxKind.ArrayType) { @@ -10590,14 +10577,6 @@ private ExpressionSyntax ParseArrayOrObjectCreationExpression() { initializer = this.ParseArrayInitializer(); } - else - { - var rankSpec = ((ArrayTypeSyntax)type).RankSpecifiers[0]; - if (GetNumberOfNonOmittedArraySizes(rankSpec) == 0) - { - type = this.AddError(type, rankSpec, ErrorCode.ERR_MissingArraySize); - } - } return _syntaxFactory.ArrayCreationExpression(@new, (ArrayTypeSyntax)type, initializer); } @@ -10628,37 +10607,6 @@ private ExpressionSyntax ParseArrayOrObjectCreationExpression() } } - private static int GetNumberOfNonOmittedArraySizes(ArrayRankSpecifierSyntax rankSpec) - { - int count = rankSpec.Sizes.Count; - int result = 0; - for (int i = 0; i < count; i++) - { - if (rankSpec.Sizes[i].Kind != SyntaxKind.OmittedArraySizeExpression) - { - result++; - } - } - return result; - } - - private bool IsPossibleArrayCreationExpression() - { - // previous token should be NewKeyword - - var resetPoint = this.GetResetPoint(); - try - { - ScanTypeFlags isType = this.ScanNonArrayType(); - return isType != ScanTypeFlags.NotType && this.CurrentToken.Kind == SyntaxKind.OpenBracketToken; - } - finally - { - this.Reset(ref resetPoint); - this.Release(ref resetPoint); - } - } - private InitializerExpressionSyntax ParseObjectOrCollectionInitializer() { var openBrace = this.EatToken(SyntaxKind.OpenBraceToken); @@ -11031,21 +10979,13 @@ private ExpressionSyntax ParseImplicitlyTypedStackAllocExpression() private ExpressionSyntax ParseRegularStackAllocExpression() { var @stackalloc = this.EatToken(SyntaxKind.StackAllocKeyword); - var elementType = this.ParseType(expectSizes: true); + var elementType = this.ParseType(); InitializerExpressionSyntax initializer = null; if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) { @stackalloc = CheckFeatureAvailability(@stackalloc, MessageID.IDS_FeatureStackAllocInitializer); initializer = this.ParseArrayInitializer(); } - else if (elementType.Kind == SyntaxKind.ArrayType) - { - var rankSpec = ((ArrayTypeSyntax)elementType).RankSpecifiers[0]; - if (GetNumberOfNonOmittedArraySizes(rankSpec) == 0) - { - elementType = this.AddError(elementType, rankSpec, ErrorCode.ERR_MissingArraySize); - } - } return _syntaxFactory.StackAllocArrayCreationExpression(@stackalloc, elementType, initializer); } diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 7d6ebab467ca3..d94536b2ab334 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -31,9 +31,6 @@ Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.CSharpCompilationOptions( Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8 = 800 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.WithAsyncKeyword(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.WithBody(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode body) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax.QuestionToken.get -> Microsoft.CodeAnalysis.SyntaxToken -Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken openBracketToken, Microsoft.CodeAnalysis.SeparatedSyntaxList sizes, Microsoft.CodeAnalysis.SyntaxToken closeBracketToken, Microsoft.CodeAnalysis.SyntaxToken questionToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax -Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax.WithQuestionToken(Microsoft.CodeAnalysis.SyntaxToken questionToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BaseArgumentListSyntax.AddArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseArgumentListSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BaseArgumentListSyntax.WithArguments(Microsoft.CodeAnalysis.SeparatedSyntaxList arguments) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseArgumentListSyntax Microsoft.CodeAnalysis.CSharp.Syntax.BaseCrefParameterListSyntax.AddParameters(params Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseCrefParameterListSyntax @@ -228,7 +225,6 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.NullableDirectiveTriviaSyntax.IsAc override Microsoft.CodeAnalysis.CSharp.Syntax.RangeExpressionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.RangeExpressionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts.TryParse(string version, out Microsoft.CodeAnalysis.CSharp.LanguageVersion result) -> bool -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ArrayRankSpecifier(Microsoft.CodeAnalysis.SyntaxToken openBracketToken, Microsoft.CodeAnalysis.SeparatedSyntaxList sizes, Microsoft.CodeAnalysis.SyntaxToken closeBracketToken, Microsoft.CodeAnalysis.SyntaxToken questionToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ClassOrStructConstraint(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxToken classOrStructKeyword, Microsoft.CodeAnalysis.SyntaxToken questionToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ClassOrStructConstraintSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ForEachStatement(Microsoft.CodeAnalysis.SyntaxToken awaitKeyword, Microsoft.CodeAnalysis.SyntaxToken forEachKeyword, Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.SyntaxToken inKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken closeParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.ForEachStatementSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ForEachVariableStatement(Microsoft.CodeAnalysis.SyntaxToken awaitKeyword, Microsoft.CodeAnalysis.SyntaxToken forEachKeyword, Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax variable, Microsoft.CodeAnalysis.SyntaxToken inKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken closeParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax statement) -> Microsoft.CodeAnalysis.CSharp.Syntax.ForEachVariableStatementSyntax diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 4943fbb7402d5..70a8a94e3c54c 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -16,15 +16,8 @@ private void VisitTypeSymbolWithAnnotations(TypeSymbolWithAnnotations type, Abst var visitor = (SymbolDisplayVisitor)(visitorOpt ?? this.NotFirstVisitor); var typeSymbol = type.TypeSymbol; - if (typeSymbol.TypeKind == TypeKind.Array) - { - visitor.VisitArrayType((IArrayTypeSymbol)typeSymbol, typeOpt: type); - } - else - { - typeSymbol.Accept(visitor); - AddNullableAnnotations(type); - } + typeSymbol.Accept(visitor); + AddNullableAnnotations(type); } public override void VisitArrayType(IArrayTypeSymbol symbol) @@ -40,7 +33,7 @@ private void VisitArrayType(IArrayTypeSymbol symbol, TypeSymbolWithAnnotations t } //See spec section 12.1 for the order of rank specifiers - //e.g. int[][,][,,] is stored as + //e.g. int[][,][,,] is stored as // ArrayType // Rank = 1 // ElementType = ArrayType @@ -57,59 +50,66 @@ private void VisitArrayType(IArrayTypeSymbol symbol, TypeSymbolWithAnnotations t return; } - TypeSymbolWithAnnotations underlyingNonArrayTypeWithAnnotations = (symbol as ArrayTypeSymbol)?.ElementType ?? default; - var underlyingNonArrayType = symbol.ElementType; - while (underlyingNonArrayType.Kind == SymbolKind.ArrayType) + TypeSymbolWithAnnotations underlyingTypeWithAnnotations; + ITypeSymbol underlyingType = symbol; + do { - underlyingNonArrayTypeWithAnnotations = (underlyingNonArrayType as ArrayTypeSymbol)?.ElementType ?? default; - underlyingNonArrayType = ((IArrayTypeSymbol)underlyingNonArrayType).ElementType; + underlyingTypeWithAnnotations = (underlyingType as ArrayTypeSymbol)?.ElementType ?? default; + underlyingType = ((IArrayTypeSymbol)underlyingType).ElementType; } + while (underlyingType.Kind == SymbolKind.ArrayType && !ShouldAddNullableAnnotation(underlyingTypeWithAnnotations)); - if (!underlyingNonArrayTypeWithAnnotations.IsNull) + if (!underlyingTypeWithAnnotations.IsNull) { - VisitTypeSymbolWithAnnotations(underlyingNonArrayTypeWithAnnotations); + VisitTypeSymbolWithAnnotations(underlyingTypeWithAnnotations); } else { - underlyingNonArrayType.Accept(this.NotFirstVisitor); + underlyingType.Accept(this.NotFirstVisitor); } var arrayType = symbol; - while (arrayType != null) + while (arrayType != null && arrayType != underlyingType) { - if (!this.isFirstSymbolVisited) + if (!(arrayType is null) && !this.isFirstSymbolVisited) { AddCustomModifiersIfRequired(arrayType.CustomModifiers, leadingSpace: true); } AddArrayRank(arrayType); - AddNullableAnnotations(typeOpt); - - typeOpt = (arrayType as ArrayTypeSymbol)?.ElementType ?? default; arrayType = arrayType.ElementType as IArrayTypeSymbol; } } private void AddNullableAnnotations(TypeSymbolWithAnnotations typeOpt) { - if (typeOpt.IsNull) + if (ShouldAddNullableAnnotation(typeOpt)) { - return; + AddPunctuation(typeOpt.NullableAnnotation.IsAnyNullable() ? SyntaxKind.QuestionToken : SyntaxKind.ExclamationToken); } + } - if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier) && + private bool ShouldAddNullableAnnotation(TypeSymbolWithAnnotations typeOpt) + { + if (typeOpt.IsNull) + { + return false; + } + else if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier) && !typeOpt.IsNullableType() && !typeOpt.IsValueType && (typeOpt.NullableAnnotation == NullableAnnotation.Annotated || (typeOpt.NullableAnnotation == NullableAnnotation.Nullable && !typeOpt.TypeSymbol.IsTypeParameterDisallowingAnnotation()))) { - AddPunctuation(SyntaxKind.QuestionToken); + return true; } else if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier) && !typeOpt.IsValueType && typeOpt.NullableAnnotation.IsAnyNotNullable() && !typeOpt.TypeSymbol.IsTypeParameterDisallowingAnnotation()) { - AddPunctuation(SyntaxKind.ExclamationToken); + return true; } + + return false; } private void AddArrayRank(IArrayTypeSymbol symbol) diff --git a/src/Compilers/CSharp/Portable/Syntax/ArrayRankSpecifierSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/ArrayRankSpecifierSyntax.cs index b56af7241142c..b5e022acac6f2 100644 --- a/src/Compilers/CSharp/Portable/Syntax/ArrayRankSpecifierSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/ArrayRankSpecifierSyntax.cs @@ -11,10 +11,5 @@ public int Rank return this.Sizes.Count; } } - - public ArrayRankSpecifierSyntax Update(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) - { - return this.Update(openBracketToken, sizes, closeBracketToken, this.QuestionToken); - } } } diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 757d1caca91ca..971f92a86c458 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -198,12 +198,6 @@ - - - - SyntaxToken representing the question mark. - - diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs index b1c3aac6524d3..c10c516ecdf08 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs @@ -2485,12 +2485,6 @@ public static UsingDirectiveSyntax UsingDirective(NameEqualsSyntax alias, NameSy semicolonToken: Token(SyntaxKind.SemicolonToken)); } - /// Creates a new ArrayRankSpecifierSyntax instance. - public static ArrayRankSpecifierSyntax ArrayRankSpecifier(SyntaxToken openBracketToken, SeparatedSyntaxList sizes, SyntaxToken closeBracketToken) - { - return ArrayRankSpecifier(openBracketToken, sizes, closeBracketToken, questionToken: default(SyntaxToken)); - } - /// Creates a new ClassOrStructConstraintSyntax instance. public static ClassOrStructConstraintSyntax ClassOrStructConstraint(SyntaxKind kind, SyntaxToken classOrStructKeyword) { diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index f34157da44986..017cb541cb1df 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index c884bcbf80f7a..21c631a3eac96 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 1fc01922aebdf..cf57013338c97 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index aae7a26d91e00..7a0a9c73dbbb3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index bcccf78186ef2..069a5cde6f53c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index e6844fcfdce91..0e23e1c2d603c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 88af20c38ffa1..a35238562e5d7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index b06b41ff14ee3..ba46a3f6a91bb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 451af03c10701..883f3d4f68bb5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 31fc85b1c91c9..092ca9b107f41 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index f151f7c55703f..a42c44b84ddc6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 41c3659e425e7..5bb20c6210b84 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 61a32ed7dac40..6a164caa49654 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -27,6 +27,11 @@ Element names are not permitted when pattern-matching via 'System.Runtime.CompilerServices.ITuple'. + + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an as expression; use the underlying type '{0}' instead. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' @@ -172,6 +177,11 @@ "Invalid rank specifier: expected ']' + + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead. + + An expression of type '{0}' can never match the provided pattern. An expression of type '{0}' can never match the provided pattern. diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefLocalTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefLocalTests.cs index 501fa69e92f97..92730f4b568d9 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefLocalTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefLocalTests.cs @@ -3396,12 +3396,12 @@ public static void Main() var expectedDiagnostics = new[] { - // file.cs(6,31): error CS1031: Type expected + // file.cs(6,28): error CS8386: Invalid object creation // _ = /**/ new ref[] { 1 } /**/ ; - Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(6, 31), - // file.cs(6,28): error CS8382: Invalid object creation + Diagnostic(ErrorCode.ERR_InvalidObjectCreation, "ref[]").WithArguments("?[]").WithLocation(6, 28), + // file.cs(6,31): error CS1031: Type expected // _ = /**/ new ref[] { 1 } /**/ ; - Diagnostic(ErrorCode.ERR_InvalidObjectCreation, "ref[]").WithArguments("?[]").WithLocation(6, 28) + Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(6, 31) }; VerifyOperationTreeAndDiagnosticsForTest(text, expectedOperationTree, expectedDiagnostics); diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IVariableDeclaration.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IVariableDeclaration.cs index b2b7b1e2870aa..08c3578c49142 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IVariableDeclaration.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IVariableDeclaration.cs @@ -436,14 +436,11 @@ static void Main(string[] args) null "; var expectedDiagnostics = new DiagnosticDescription[] { - // CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // /**/int[2, 3] a/**/; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(6, 23), - // CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // /**/int[2, 3] a/**/; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(6, 26), - // CS0168: The variable 'a' is declared but never used - // /**/int[2, 3] a/**/; + // file.cs(6,22): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // /**/int[2, 3] a;/**/ + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[2, 3]").WithLocation(6, 22), + // file.cs(6,29): warning CS0168: The variable 'a' is declared but never used + // /**/int[2, 3] a;/**/ Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(6, 29) }; @@ -477,17 +474,14 @@ static void Main(string[] args) null "; var expectedDiagnostics = new DiagnosticDescription[] { - // CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // /**/int[2, 3] a, b/**/; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(6, 23), - // CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // /**/int[2, 3] a, b/**/; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(6, 26), - // CS0168: The variable 'a' is declared but never used - // /**/int[2, 3] a, b/**/; + // file.cs(6,22): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // /**/int[2, 3] a, b;/**/ + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[2, 3]").WithLocation(6, 22), + // file.cs(6,29): warning CS0168: The variable 'a' is declared but never used + // /**/int[2, 3] a, b;/**/ Diagnostic(ErrorCode.WRN_UnreferencedVar, "a").WithArguments("a").WithLocation(6, 29), - // CS0168: The variable 'b' is declared but never used - // /**/int[2, 3] a, b/**/; + // file.cs(6,32): warning CS0168: The variable 'b' is declared but never used + // /**/int[2, 3] a, b;/**/ Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(6, 32) }; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index e65ce1c3bbfd1..056cc31b1030f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -31,7 +31,11 @@ class C comp.VerifyDiagnostics( // (7,52): error CS1586: Array creation must have array size or array initializer // Expression> e = x => new object[](x); - Diagnostic(ErrorCode.ERR_MissingArraySize, "[]")); + Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(7, 52), + // (7,42): error CS0149: Method name expected + // Expression> e = x => new object[](x); + Diagnostic(ErrorCode.ERR_MethodNameExpected, "new object[]").WithLocation(7, 42) + ); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 8f73a87231d36..1b02374c079d4 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -1251,18 +1251,18 @@ public void NullableAndConditionalOperators() static void F1(object x) { _ = x is string? 1 : 2; - _ = x is string? ? 1 : 2; - _ = x is string ? ? 1 : 2; + _ = x is string? ? 1 : 2; // error 1: is a nullable reference type + _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type _ = x as string?? x; - _ = x as string ? ?? x; + _ = x as string ? ?? x; // error 3: as a nullable reference type } static void F2(object y) { _ = y is object[]? 1 : 2; - _ = y is object[]? ? 1 : 2; - _ = y is object[] ? ? 1 : 2; + _ = y is object[]? ? 1 : 2; // error 4 + _ = y is object[] ? ? 1 : 2; // error 5 _ = y as object[]?? y; - _ = y as object[] ? ?? y; + _ = y as object[] ? ?? y; // error 6 } static void F3(object z) { @@ -1276,23 +1276,41 @@ static void F3(object z) var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics( + // (6,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. + // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type + Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(6, 18), // (6,24): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = x is string? ? 1 : 2; + // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(6, 24), + // (7,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. + // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type + Diagnostic(ErrorCode.ERR_IsNullableType, "string ?").WithArguments("string").WithLocation(7, 18), // (7,25): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = x is string ? ? 1 : 2; + // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(7, 25), + // (9,18): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. + // _ = x as string ? ?? x; // error 3: as a nullable reference type + Diagnostic(ErrorCode.ERR_AsNullableType, "string ?").WithArguments("string").WithLocation(9, 18), // (9,25): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = x as string ? ?? x; + // _ = x as string ? ?? x; // error 3: as a nullable reference type Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(9, 25), + // (14,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. + // _ = y is object[]? ? 1 : 2; // error 4 + Diagnostic(ErrorCode.ERR_IsNullableType, "object[]?").WithArguments("object[]").WithLocation(14, 18), // (14,26): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = y is object[]? ? 1 : 2; + // _ = y is object[]? ? 1 : 2; // error 4 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(14, 26), + // (15,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. + // _ = y is object[] ? ? 1 : 2; // error 5 + Diagnostic(ErrorCode.ERR_IsNullableType, "object[] ?").WithArguments("object[]").WithLocation(15, 18), // (15,27): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = y is object[] ? ? 1 : 2; + // _ = y is object[] ? ? 1 : 2; // error 5 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(15, 27), + // (17,18): error CS8651: It is not legal to use nullable reference type 'object[]?' in an as expression; use the underlying type 'object[]' instead. + // _ = y as object[] ? ?? y; // error 6 + Diagnostic(ErrorCode.ERR_AsNullableType, "object[] ?").WithArguments("object[]").WithLocation(17, 18), // (17,27): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. - // _ = y as object[] ? ?? y; + // _ = y as object[] ? ?? y; // error 6 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(17, 27), // (22,21): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. // _ = z is T[]?[] ? 1 : 2; @@ -1302,10 +1320,30 @@ static void F3(object z) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(23, 22), // (25,22): error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater. // _ = z as T[] ? [] ?? z; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(25, 22)); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "?").WithArguments("nullable reference types", "8.0").WithLocation(25, 22) + ); comp = CreateCompilation(source, options: WithNonNullTypesTrue()); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (6,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. + // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type + Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(6, 18), + // (7,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. + // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type + Diagnostic(ErrorCode.ERR_IsNullableType, "string ?").WithArguments("string").WithLocation(7, 18), + // (9,18): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. + // _ = x as string ? ?? x; // error 3: as a nullable reference type + Diagnostic(ErrorCode.ERR_AsNullableType, "string ?").WithArguments("string").WithLocation(9, 18), + // (14,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. + // _ = y is object[]? ? 1 : 2; // error 4 + Diagnostic(ErrorCode.ERR_IsNullableType, "object[]?").WithArguments("object[]").WithLocation(14, 18), + // (15,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. + // _ = y is object[] ? ? 1 : 2; // error 5 + Diagnostic(ErrorCode.ERR_IsNullableType, "object[] ?").WithArguments("object[]").WithLocation(15, 18), + // (17,18): error CS8651: It is not legal to use nullable reference type 'object[]?' in an as expression; use the underlying type 'object[]' instead. + // _ = y as object[] ? ?? y; // error 6 + Diagnostic(ErrorCode.ERR_AsNullableType, "object[] ?").WithArguments("object[]").WithLocation(17, 18) + ); } [Fact, WorkItem(29318, "https://github.com/dotnet/roslyn/issues/29318")] @@ -1478,14 +1516,14 @@ static void Main() "; var tree = Parse(source); var specifier = tree.GetRoot().DescendantNodes().OfType().Single(); - Assert.Equal("[]?", specifier.ToString()); + Assert.Equal("[]", specifier.ToString()); var newSpecifier = specifier.Update( specifier.OpenBracketToken, SyntaxFactory.SeparatedList( new[] { SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(3)) }), specifier.CloseBracketToken); - Assert.Equal("[3]?", newSpecifier.ToString()); + Assert.Equal("[3]", newSpecifier.ToString()); } [Fact] @@ -19886,17 +19924,18 @@ void Test7() void Test8() { object []?[,] u8 = null; - u8[0] = null; - u8[0][0,0] = null; - u8[0][0,0].ToString(); + u8[0,0] = null; + u8[0,0].ToString(); + u8[0,0][0] = null; + u8[0,0][0].ToString(); } void Test9() { object []?[,]? u9 = null; - u9[0] = null; - u9[0][0,0] = null; - u9[0][0,0].ToString(); + u9[0,0] = null; + u9[0,0][0] = null; + u9[0,0][0].ToString(); } } " }, options: WithNonNullTypesTrue()); @@ -19917,21 +19956,15 @@ void Test9() // (33,16): warning CS8603: Possible null reference return. // return u5; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "u5").WithLocation(33, 16), - // (38,28): warning CS8600: Converting null literal or possible null value to non-nullable type. - // object [][,]? u6 = null; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 28), // (39,9): warning CS8602: Possible dereference of a null reference. // u6[0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6").WithLocation(39, 9), - // (40,9): warning CS8602: Possible dereference of a null reference. - // u6[0][0,0] = null; - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(40, 9), + // (39,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // u6[0] = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(39, 17), // (40,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u6[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(40, 22), - // (41,9): warning CS8602: Possible dereference of a null reference. - // u6[0][0,0].ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(41, 9), // (46,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // object [][,] u7 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(46, 27), @@ -19944,27 +19977,36 @@ void Test9() // (48,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u7[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 22), + // (53,28): warning CS8600: Converting null literal or possible null value to non-nullable type. + // object []?[,] u8 = null; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(53, 28), // (54,9): warning CS8602: Possible dereference of a null reference. - // u8[0] = null; + // u8[0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8").WithLocation(54, 9), - // (54,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // u8[0] = null; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(54, 17), - // (55,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // u8[0][0,0] = null; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(55, 22), - // (62,9): warning CS8602: Possible dereference of a null reference. - // u9[0] = null; - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9").WithLocation(62, 9), + // (55,9): warning CS8602: Possible dereference of a null reference. + // u8[0,0].ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(55, 9), + // (56,9): warning CS8602: Possible dereference of a null reference. + // u8[0,0][0] = null; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(56, 9), + // (56,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // u8[0,0][0] = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(56, 22), + // (57,9): warning CS8602: Possible dereference of a null reference. + // u8[0,0][0].ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(57, 9), // (63,9): warning CS8602: Possible dereference of a null reference. - // u9[0][0,0] = null; - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0]").WithLocation(63, 9), - // (63,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // u9[0][0,0] = null; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(63, 22), + // u9[0,0] = null; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9").WithLocation(63, 9), // (64,9): warning CS8602: Possible dereference of a null reference. - // u9[0][0,0].ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0]").WithLocation(64, 9) + // u9[0,0][0] = null; + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0,0]").WithLocation(64, 9), + // (64,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // u9[0,0][0] = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(64, 22), + // (65,9): warning CS8602: Possible dereference of a null reference. + // u9[0,0][0].ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0,0]").WithLocation(65, 9) ); } @@ -19985,8 +20027,8 @@ void Test3() void Test6() { - var u6 = new object [][,]? {null, - new object[,]? {{null}}}; + var u6 = new object [,]?[] {null, + new object[,] {{null}}}; u6[0] = null; u6[0][0,0] = null; u6[0][0,0].ToString(); @@ -20002,7 +20044,7 @@ void Test7() void Test8() { - var u8 = new object []?[,] {null, + object [][,]? u8 = new object [][,] {null, new object[,] {{null}}}; u8[0] = null; u8[0][0,0] = null; @@ -20011,8 +20053,8 @@ void Test8() void Test9() { - var u9 = new object []?[,]? {null, - new object[,]? {{null}}}; + object [,]?[]? u9 = new object [,]?[] {null, + new object[,] {{null}}}; u9[0] = null; u9[0][0,0] = null; u9[0][0,0].ToString(); @@ -20021,9 +20063,10 @@ void Test9() " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( - // (16,54): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // new object[,]? {{null}}}; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 54), + + // (16,53): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // new object[,] {{null}}}; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 53), // (18,9): warning CS8602: Possible dereference of a null reference. // u6[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(18, 9), @@ -20033,33 +20076,33 @@ void Test9() // (19,9): warning CS8602: Possible dereference of a null reference. // u6[0][0,0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(19, 9), - // (25,52): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // new object[,] {{null}}}; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 52), // (24,36): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // var u7 = new object [][,] {null, Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(24, 36), + // (25,52): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // new object[,] {{null}}}; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 52), // (26,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u7[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(26, 17), // (27,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u7[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 22), + // (32,46): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // object [][,]? u8 = new object [][,] {null, + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(32, 46), // (33,53): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // new object[,] {{null}}}; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(33, 53), - // (32,37): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // var u8 = new object []?[,] {null, - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(32, 37), // (34,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u8[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(34, 17), // (35,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // u8[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(35, 22), - // (42,55): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. - // new object[,]? {{null}}}; - Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(42, 55), + // (42,54): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. + // new object[,] {{null}}}; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(42, 54), // (44,9): warning CS8602: Possible dereference of a null reference. // u9[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0]").WithLocation(44, 9), @@ -24278,102 +24321,109 @@ static void F1() x1 = new object?(); // error 1 x1 = new object? { }; // error 2 x1 = (new object?[1])[0]; + x1 = new object[]? {}; // error 3 } static void F2() { object? x2; - x2 = new T2?(); // error 3 and 4 - x2 = new T2? { }; // error 5 and 6 + x2 = new T2?(); // error 4 + x2 = new T2? { }; // error 5 x2 = (new T2?[1])[0]; } static void F3() where T3 : class, new() { object? x3; - x3 = new T3?(); // error 7 - x3 = new T3? { }; // error 8 + x3 = new T3?(); // error 6 + x3 = new T3? { }; // error 7 x3 = (new T3?[1])[0]; } static void F4() where T4 : new() { object? x4; - x4 = new T4?(); // error 9 - x4 = new T4? { }; // error 10 + x4 = new T4?(); // error 8 + x4 = new T4? { }; // error 9 x4 = (new T4?[1])[0]; x4 = new System.Nullable? { }; // error 11 } static void F5() where T5 : class { object? x5; - x5 = new T5?(); // error 12 and 13 - x5 = new T5? { }; // error 14 and 15 - x5 = (new T5?[1])[0]; // error 16 + x5 = new T5?(); // error 10 + x5 = new T5? { }; // error 11 + x5 = (new T5?[1])[0]; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (6,14): error CS8630: Cannot use a nullable reference type in object creation. + // (6,14): error CS8628: Cannot use a nullable reference type in object creation. // x1 = new object?(); // error 1 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object?()").WithArguments("object").WithLocation(6, 14), - // (7,14): error CS8630: Cannot use a nullable reference type in object creation. + // (7,14): error CS8628: Cannot use a nullable reference type in object creation. // x1 = new object? { }; // error 2 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object? { }").WithArguments("object").WithLocation(7, 14), - // (13,14): error CS8630: Cannot use a nullable reference type in object creation. - // x2 = new T2?(); // error 3 and 4 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2?()").WithArguments("T2").WithLocation(13, 14), - // (13,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint - // x2 = new T2?(); // error 3 and 4 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2?()").WithArguments("T2").WithLocation(13, 14), - // (13,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. - // x2 = new T2?(); // error 3 and 4 - Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(13, 18), - // (14,14): error CS8630: Cannot use a nullable reference type in object creation. - // x2 = new T2? { }; // error 5 and 6 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2? { }").WithArguments("T2").WithLocation(14, 14), - // (14,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint - // x2 = new T2? { }; // error 5 and 6 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2? { }").WithArguments("T2").WithLocation(14, 14), + // (9,14): error CS8628: Cannot use a nullable reference type in object creation. + // x1 = new object[]? {}; // error 3 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object[]? {}").WithArguments("object[]").WithLocation(9, 14), + // (9,18): error CS8386: Invalid object creation + // x1 = new object[]? {}; // error 3 + Diagnostic(ErrorCode.ERR_InvalidObjectCreation, "object[]?").WithArguments("object[]").WithLocation(9, 18), // (14,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. - // x2 = new T2? { }; // error 5 and 6 + // x2 = new T2?(); // error 4 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(14, 18), - // (15,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. + // (14,14): error CS8628: Cannot use a nullable reference type in object creation. + // x2 = new T2?(); // error 4 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2?()").WithArguments("T2").WithLocation(14, 14), + // (14,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint + // x2 = new T2?(); // error 4 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2?()").WithArguments("T2").WithLocation(14, 14), + // (15,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. + // x2 = new T2? { }; // error 5 + Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(15, 18), + // (15,14): error CS8628: Cannot use a nullable reference type in object creation. + // x2 = new T2? { }; // error 5 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2? { }").WithArguments("T2").WithLocation(15, 14), + // (15,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint + // x2 = new T2? { }; // error 5 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2? { }").WithArguments("T2").WithLocation(15, 14), + // (16,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x2 = (new T2?[1])[0]; - Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(15, 19), - // (20,14): error CS8630: Cannot use a nullable reference type in object creation. - // x3 = new T3?(); // error 7 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3?()").WithArguments("T3").WithLocation(20, 14), - // (21,14): error CS8630: Cannot use a nullable reference type in object creation. - // x3 = new T3? { }; // error 8 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3? { }").WithArguments("T3").WithLocation(21, 14), - // (27,14): error CS8630: Cannot use a nullable reference type in object creation. - // x4 = new T4?(); // error 9 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4?()").WithArguments("T4").WithLocation(27, 14), - // (27,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. - // x4 = new T4?(); // error 9 - Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(27, 18), - // (28,14): error CS8630: Cannot use a nullable reference type in object creation. - // x4 = new T4? { }; // error 10 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4? { }").WithArguments("T4").WithLocation(28, 14), + Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(16, 19), + // (21,14): error CS8628: Cannot use a nullable reference type in object creation. + // x3 = new T3?(); // error 6 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3?()").WithArguments("T3").WithLocation(21, 14), + // (22,14): error CS8628: Cannot use a nullable reference type in object creation. + // x3 = new T3? { }; // error 7 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3? { }").WithArguments("T3").WithLocation(22, 14), // (28,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. - // x4 = new T4? { }; // error 10 + // x4 = new T4?(); // error 8 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(28, 18), - // (30,18): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' - // x4 = new System.Nullable? { }; // error 11 - Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "System.Nullable?").WithArguments("System.Nullable", "T", "int?").WithLocation(30, 18), - // (29,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. + // (28,14): error CS8628: Cannot use a nullable reference type in object creation. + // x4 = new T4?(); // error 8 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4?()").WithArguments("T4").WithLocation(28, 14), + // (29,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. + // x4 = new T4? { }; // error 9 + Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(29, 18), + // (29,14): error CS8628: Cannot use a nullable reference type in object creation. + // x4 = new T4? { }; // error 9 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4? { }").WithArguments("T4").WithLocation(29, 14), + // (30,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x4 = (new T4?[1])[0]; - Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(29, 19), - // (35,14): error CS8630: Cannot use a nullable reference type in object creation. - // x5 = new T5?(); // error 12 and 13 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5?()").WithArguments("T5").WithLocation(35, 14), - // (35,14): error CS0304: Cannot create an instance of the variable type 'T5' because it does not have the new() constraint - // x5 = new T5?(); // error 12 and 13 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5?()").WithArguments("T5").WithLocation(35, 14), - // (36,14): error CS8630: Cannot use a nullable reference type in object creation. - // x5 = new T5? { }; // error 14 and 15 - Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5? { }").WithArguments("T5").WithLocation(36, 14), + Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(30, 19), + // (31,18): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' + // x4 = new System.Nullable? { }; // error 11 + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "System.Nullable?").WithArguments("System.Nullable", "T", "int?").WithLocation(31, 18), + // (36,14): error CS8628: Cannot use a nullable reference type in object creation. + // x5 = new T5?(); // error 10 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5?()").WithArguments("T5").WithLocation(36, 14), // (36,14): error CS0304: Cannot create an instance of the variable type 'T5' because it does not have the new() constraint - // x5 = new T5? { }; // error 14 and 15 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5? { }").WithArguments("T5").WithLocation(36, 14) + // x5 = new T5?(); // error 10 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5?()").WithArguments("T5").WithLocation(36, 14), + // (37,14): error CS8628: Cannot use a nullable reference type in object creation. + // x5 = new T5? { }; // error 11 + Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5? { }").WithArguments("T5").WithLocation(37, 14), + // (37,14): error CS0304: Cannot create an instance of the variable type 'T5' because it does not have the new() constraint + // x5 = new T5? { }; // error 11 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5? { }").WithArguments("T5").WithLocation(37, 14) ); } @@ -33820,6 +33870,9 @@ static void F(Person p) // (16,22): warning CS8601: Possible null reference assignment. // p.LastName = null as string?; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "null as string?").WithLocation(16, 22), + // (16,30): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // p.LastName = null as string?; + Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(16, 30), // (17,22): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // p.LastName = default(string); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(17, 22), @@ -33831,7 +33884,8 @@ static void F(Person p) Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "p.MiddleName").WithLocation(19, 23), // (20,22): warning CS8601: Possible null reference assignment. // p.LastName = p.MiddleName ?? null; - Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "p.MiddleName ?? null").WithLocation(20, 22)); + Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "p.MiddleName ?? null").WithLocation(20, 22) + ); } [Fact] @@ -33869,6 +33923,9 @@ internal static void F(this string s) new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( + // (15,18): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // (null as string?).F(); + Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(15, 18), // (12,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((string)null).F(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(12, 10), @@ -33881,9 +33938,6 @@ internal static void F(this string s) // (14,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // (null as string).F(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string").WithArguments("s", "void Extensions.F(string s)").WithLocation(14, 10), - // (15,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. - // (null as string?).F(); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string?").WithArguments("s", "void Extensions.F(string s)").WithLocation(15, 10), // (16,9): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // default(string).F(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(16, 9), @@ -33895,7 +33949,8 @@ internal static void F(this string s) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("s", "void Extensions.F(string s)").WithLocation(17, 10), // (18,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // (p.MiddleName ?? null).F(); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("s", "void Extensions.F(string s)").WithLocation(18, 10)); + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("s", "void Extensions.F(string s)").WithLocation(18, 10) + ); } [Fact] @@ -33932,6 +33987,9 @@ static void G(string name) new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( + // (16,19): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // G(null as string?); + Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(16, 19), // (12,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // G(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 11), @@ -33947,9 +34005,6 @@ static void G(string name) // (15,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G(null as string); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string").WithArguments("name", "void Program.G(string name)").WithLocation(15, 11), - // (16,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. - // G(null as string?); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string?").WithArguments("name", "void Program.G(string name)").WithLocation(16, 11), // (17,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // G(default(string)); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(17, 11), @@ -33964,7 +34019,8 @@ static void G(string name) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("name", "void Program.G(string name)").WithLocation(19, 11), // (20,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G(p.MiddleName ?? null); - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("name", "void Program.G(string name)").WithLocation(20, 11)); + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("name", "void Program.G(string name)").WithLocation(20, 11) + ); } [Fact] @@ -34010,6 +34066,9 @@ class Program // (13,27): warning CS8603: Possible null reference return. // static string F4() => null as string; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null as string").WithLocation(13, 27), + // (14,35): error CS8651: It is not legal to use nullable type 'string?' in an as expression; use the underlying type 'string' instead. + // static string F5() => null as string?; + Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(14, 35), // (14,27): warning CS8603: Possible null reference return. // static string F5() => null as string?; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null as string?").WithLocation(14, 27), @@ -34027,7 +34086,8 @@ class Program Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(p != null) ? p.MiddleName : null").WithLocation(17, 35), // (18,35): warning CS8603: Possible null reference return. // static string F9(Person p) => p.MiddleName ?? null; - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "p.MiddleName ?? null").WithLocation(18, 35)); + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "p.MiddleName ?? null").WithLocation(18, 35) + ); } [Fact] @@ -73781,6 +73841,28 @@ static void G(T? x, object y) comp.VerifyTypes(); } + [Fact] + public void DisplayMultidimensionalArray() + { + var source = @" +class C +{ + void M(A o, A s) + { + o = s; + } +} +interface A {} +"; + var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics( + // (6,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. + // o = s; + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "s").WithArguments("A", "A").WithLocation(6, 13) + ); + comp.VerifyTypes(); + } + [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_01() diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs index 05cfd136a4fce..b9e72ce86ecf7 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs @@ -20538,15 +20538,9 @@ public static void Main() // (6,13): error CS1003: Syntax error, ',' expected // int[out var x1] a = null; // fatal syntax error - 'out' is skipped Diagnostic(ErrorCode.ERR_SyntaxError, "out").WithArguments(",", "out").WithLocation(6, 13), - // (6,17): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // int[out var x1] a = null; // fatal syntax error - 'out' is skipped - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "var").WithLocation(6, 17), // (6,21): error CS1003: Syntax error, ',' expected // int[out var x1] a = null; // fatal syntax error - 'out' is skipped Diagnostic(ErrorCode.ERR_SyntaxError, "x1").WithArguments(",", "").WithLocation(6, 21), - // (6,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // int[out var x1] a = null; // fatal syntax error - 'out' is skipped - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "x1").WithLocation(6, 21), // (7,27): error CS1002: ; expected // int b(out var x2) = null; // parsed as a local function with syntax error Diagnostic(ErrorCode.ERR_SemicolonExpected, "=").WithLocation(7, 27), @@ -20577,7 +20571,10 @@ public static void Main() // (10,28): error CS1003: Syntax error, ']' expected // int d, e(out var x4); // parsed as a broken bracketed argument list on the declarator Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]", ")").WithLocation(10, 28), - // (7,13): error CS08112: 'b(out var)' is a local function and must therefore always have a body. + // (6,12): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // int[out var x1] a = null; // fatal syntax error - 'out' is skipped + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[out var x1]").WithLocation(6, 12), + // (7,13): error CS8112: 'b(out var)' is a local function and must therefore always have a body. // int b(out var x2) = null; // parsed as a local function with syntax error Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "b").WithArguments("b(out var)").WithLocation(7, 13), // (7,19): error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs index 3b647147ea239..a1f3473cbf906 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs @@ -138,9 +138,9 @@ public static void T(object x) }"; var compilation = CreateCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( - // (11,18): error CS8105: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead. - // if (x is Nullable y) Console.WriteLine($"expression {x} is Nullable y"); - Diagnostic(ErrorCode.ERR_PatternNullableType, "Nullable").WithArguments("int?", "int").WithLocation(11, 18) + // (11,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead. + // if (x is Nullable y) Console.WriteLine($"expression {x} is Nullable y"); + Diagnostic(ErrorCode.ERR_PatternNullableType, "Nullable").WithArguments("int?", "int").WithLocation(11, 18) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests4.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests4.cs index 4f1b66a67dc5c..d58a65df094f4 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests4.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests4.cs @@ -3096,5 +3096,119 @@ public class SwitchExpressionException : InvalidOperationException CompileAndVerify(compilation, expectedOutput: @"3 SwitchExpressionException((1, 3, 3, 4, 5, 6, 7, 8, 9))"); } + + [Fact] + public void NullableArrayDeclarationPattern_Good_01() + { + var source = +@"#nullable enable +public class A +{ + static void M(object o, bool c) + { + if (o is A[]? c && c : c) { } // ok 3 (for compat) + if (o is A[][]? c : c) { } // ok 4 (for compat) + } +} +"; + var compilation = CreatePatternCompilation(source, options: TestOptions.DebugDll); + compilation.VerifyDiagnostics( + ); + } + + [Fact] + public void NullableArrayDeclarationPattern_Good_02() + { + var source = +@"#nullable enable +public class A +{ + static void M(object o, bool c) + { + if (o is A[]?[,] b3) { } + if (o is A[,]?[] b4 && c) { } + if (o is A[,]?[]?[] b5 && c) { } + } +} +"; + var compilation = CreatePatternCompilation(source, options: TestOptions.DebugDll); + compilation.VerifyDiagnostics(); + } + + [Fact] + public void NullableArrayDeclarationPattern_Bad_02() + { + var source = +@"#nullable enable +public class A +{ + public static bool b1, b2, b5, b6, b7, b8; + static void M(object o, bool c) + { + if (o is A?) { } // error 1 (can't test for is nullable reference type) + if (o is A? b1) { } // error 2 (missing :) + if (o is A? b2 && c) { } // error 3 (missing :) + if (o is A[]? b5) { } // error 4 (missing :) + if (o is A[]? b6 && c) { } // error 5 (missing :) + if (o is A[][]? b7) { } // error 6 (missing :) + if (o is A[][]? b8 && c) { } // error 7 (missing :) + if (o is A? && c) { } // error 8 (can't test for is nullable reference type) + _ = o is A[][]?; // error 9 (can't test for is nullable reference type) + _ = o as A[][]?; // error 10 (can't 'as' nullable reference type) + } +} +"; + var compilation = CreatePatternCompilation(source, options: TestOptions.DebugDll); + compilation.VerifyDiagnostics( + // (7,18): error CS8650: It is not legal to use nullable reference type 'A?' in an is-type expression; use the underlying type 'A' instead. + // if (o is A?) { } // error 1 (can't test for is nullable reference type) + Diagnostic(ErrorCode.ERR_IsNullableType, "A?").WithArguments("A").WithLocation(7, 18), + // (8,23): error CS1003: Syntax error, ':' expected + // if (o is A? b1) { } // error 2 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(8, 23), + // (8,23): error CS1525: Invalid expression term ')' + // if (o is A? b1) { } // error 2 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(8, 23), + // (9,28): error CS1003: Syntax error, ':' expected + // if (o is A? b2 && c) { } // error 3 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(9, 28), + // (9,28): error CS1525: Invalid expression term ')' + // if (o is A? b2 && c) { } // error 3 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(9, 28), + // (10,25): error CS1003: Syntax error, ':' expected + // if (o is A[]? b5) { } // error 4 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(10, 25), + // (10,25): error CS1525: Invalid expression term ')' + // if (o is A[]? b5) { } // error 4 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(10, 25), + // (11,30): error CS1003: Syntax error, ':' expected + // if (o is A[]? b6 && c) { } // error 5 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(11, 30), + // (11,30): error CS1525: Invalid expression term ')' + // if (o is A[]? b6 && c) { } // error 5 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(11, 30), + // (12,27): error CS1003: Syntax error, ':' expected + // if (o is A[][]? b7) { } // error 6 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(12, 27), + // (12,27): error CS1525: Invalid expression term ')' + // if (o is A[][]? b7) { } // error 6 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(12, 27), + // (13,32): error CS1003: Syntax error, ':' expected + // if (o is A[][]? b8 && c) { } // error 7 (missing :) + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":", ")").WithLocation(13, 32), + // (13,32): error CS1525: Invalid expression term ')' + // if (o is A[][]? b8 && c) { } // error 7 (missing :) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(13, 32), + // (14,18): error CS8650: It is not legal to use nullable reference type 'A?' in an is-type expression; use the underlying type 'A' instead. + // if (o is A? && c) { } // error 8 (can't test for is nullable reference type) + Diagnostic(ErrorCode.ERR_IsNullableType, "A?").WithArguments("A").WithLocation(14, 18), + // (15,18): error CS8650: It is not legal to use nullable reference type 'A[][]?' in an is-type expression; use the underlying type 'A[][]' instead. + // _ = o is A[][]?; // error 9 (can't test for is nullable reference type) + Diagnostic(ErrorCode.ERR_IsNullableType, "A[][]?").WithArguments("A[][]").WithLocation(15, 18), + // (16,18): error CS8651: It is not legal to use nullable reference type 'A[][]?' in an as expression; use the underlying type 'A[][]' instead. + // _ = o as A[][]?; // error 10 (can't 'as' nullable reference type) + Diagnostic(ErrorCode.ERR_AsNullableType, "A[][]?").WithArguments("A[][]").WithLocation(16, 18) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs index 0396d1721be34..ed8090c9d28f9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs @@ -769,6 +769,9 @@ public void Method1() }", TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics( + // (6,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int[]') + // var obj1 = stackalloc int[][] { 1 }; + Diagnostic(ErrorCode.ERR_ManagedAddr, "int").WithArguments("int[]").WithLocation(6, 31), // (6,31): error CS1575: A stackalloc expression requires [] after type // var obj1 = stackalloc int[][] { 1 }; Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[][]").WithLocation(6, 31) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocSpanExpressionsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocSpanExpressionsTests.cs index 6771d53673642..4af5dacddfacb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocSpanExpressionsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocSpanExpressionsTests.cs @@ -694,12 +694,19 @@ void M() // (8,14): error CS0306: The type 'S' may not be used as a type argument // Span explicitError = default; Diagnostic(ErrorCode.ERR_BadTypeArgument, "S").WithArguments("S").WithLocation(8, 14), + // (9,67): error CS0611: Array elements cannot be of type 'S' + // var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100]; + Diagnostic(ErrorCode.ERR_ArrayElementCantBeRefAny, "S").WithArguments("S").WithLocation(9, 67), // (9,67): error CS0306: The type 'S' may not be used as a type argument // var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100]; Diagnostic(ErrorCode.ERR_BadTypeArgument, "S[10]").WithArguments("S").WithLocation(9, 67), + // (9,86): error CS0611: Array elements cannot be of type 'S' + // var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100]; + Diagnostic(ErrorCode.ERR_ArrayElementCantBeRefAny, "S").WithArguments("S").WithLocation(9, 86), // (9,86): error CS0306: The type 'S' may not be used as a type argument // var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100]; - Diagnostic(ErrorCode.ERR_BadTypeArgument, "S[100]").WithArguments("S").WithLocation(9, 86)); + Diagnostic(ErrorCode.ERR_BadTypeArgument, "S[100]").WithArguments("S").WithLocation(9, 86) + ); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 8c0237f03f145..226c92d78e2d3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -7711,30 +7711,30 @@ static void Main() // (6,34): error CS1586: Array creation must have array size or array initializer // { int* p = stackalloc int[]; } Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(6, 34), - // (8,34): error CS1586: Array creation must have array size or array initializer - // { int* p = stackalloc int[][]; } - Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(8, 34), - // (9,34): error CS1586: Array creation must have array size or array initializer - // { int* p = stackalloc int[][1]; } - Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(9, 34), - // (9,37): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // { int* p = stackalloc int[][1]; } - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(9, 37), - // (11,38): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // { int* p = stackalloc int[1][1]; } - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(11, 38), // (7,31): error CS1575: A stackalloc expression requires [] after type // { int* p = stackalloc int[1, 1]; } Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[1, 1]").WithLocation(7, 31), + // (8,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int[]') + // { int* p = stackalloc int[][]; } + Diagnostic(ErrorCode.ERR_ManagedAddr, "int").WithArguments("int[]").WithLocation(8, 31), // (8,31): error CS1575: A stackalloc expression requires [] after type // { int* p = stackalloc int[][]; } Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[][]").WithLocation(8, 31), + // (9,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int[]') + // { int* p = stackalloc int[][1]; } + Diagnostic(ErrorCode.ERR_ManagedAddr, "int").WithArguments("int[]").WithLocation(9, 31), // (9,31): error CS1575: A stackalloc expression requires [] after type // { int* p = stackalloc int[][1]; } Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[][1]").WithLocation(9, 31), + // (10,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int[]') + // { int* p = stackalloc int[1][]; } + Diagnostic(ErrorCode.ERR_ManagedAddr, "int").WithArguments("int[]").WithLocation(10, 31), // (10,31): error CS1575: A stackalloc expression requires [] after type // { int* p = stackalloc int[1][]; } Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[1][]").WithLocation(10, 31), + // (11,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int[]') + // { int* p = stackalloc int[1][1]; } + Diagnostic(ErrorCode.ERR_ManagedAddr, "int").WithArguments("int[]").WithLocation(11, 31), // (11,31): error CS1575: A stackalloc expression requires [] after type // { int* p = stackalloc int[1][1]; } Diagnostic(ErrorCode.ERR_BadStackAllocExpr, "int[1][1]").WithLocation(11, 31) diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 9ea2ff7e0d063..d7f56b2056498 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -6017,7 +6017,7 @@ class C SymbolDisplayPartKind.FieldName); Verify( SymbolDisplay.ToDisplayParts(member, formatWithBothModifiers), - "static object?[,]![]! F1", + "static object?[]![,]! F1", SymbolDisplayPartKind.Keyword, SymbolDisplayPartKind.Space, SymbolDisplayPartKind.Keyword, @@ -6035,7 +6035,7 @@ class C member = comp.GetMember("C.F2"); Verify( SymbolDisplay.ToDisplayParts(member, formatWithoutModifiers), - "static object[,][] F2"); + "static object[][,] F2"); Verify( SymbolDisplay.ToDisplayParts(member, formatWithNullableModifier), "static object[,]?[] F2"); @@ -6052,7 +6052,7 @@ class C "static object[,][]? F3"); Verify( SymbolDisplay.ToDisplayParts(member, formatWithBothModifiers), - "static object![,]![]? F3"); + "static object![]![,]? F3"); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 9f69687c3b107..ef1a9be583bd7 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -46,7 +46,7 @@ private static Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.ArrayTypeSynt private static Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.ArrayRankSpecifierSyntax GenerateArrayRankSpecifier() { - return Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.ArrayRankSpecifier(Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.Token(SyntaxKind.OpenBracketToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.Token(SyntaxKind.CloseBracketToken), null); + return Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.ArrayRankSpecifier(Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.Token(SyntaxKind.OpenBracketToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); } private static Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.PointerTypeSyntax GeneratePointerType() @@ -1172,7 +1172,6 @@ public void TestArrayRankSpecifierFactoryAndProperties() Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind); Assert.NotNull(node.Sizes); Assert.Equal(SyntaxKind.CloseBracketToken, node.CloseBracketToken.Kind); - Assert.Null(node.QuestionToken); AttachAndCheckDiagnostics(node); } @@ -9450,7 +9449,7 @@ private static ArrayTypeSyntax GenerateArrayType() private static ArrayRankSpecifierSyntax GenerateArrayRankSpecifier() { - return SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBracketToken), default(SyntaxToken)); + return SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); } private static PointerTypeSyntax GeneratePointerType() @@ -10576,8 +10575,7 @@ public void TestArrayRankSpecifierFactoryAndProperties() Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind()); Assert.NotNull(node.Sizes); Assert.Equal(SyntaxKind.CloseBracketToken, node.CloseBracketToken.Kind()); - Assert.Equal(SyntaxKind.None, node.QuestionToken.Kind()); - var newNode = node.WithOpenBracketToken(node.OpenBracketToken).WithSizes(node.Sizes).WithCloseBracketToken(node.CloseBracketToken).WithQuestionToken(node.QuestionToken); + var newNode = node.WithOpenBracketToken(node.OpenBracketToken).WithSizes(node.Sizes).WithCloseBracketToken(node.CloseBracketToken); Assert.Equal(node, newNode); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs index 280533619b47c..9d099c6d329b5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs @@ -79,22 +79,25 @@ public void NullableArray_Cast_01() N(SyntaxKind.CastExpression); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.CloseParenToken); N(SyntaxKind.NullLiteralExpression); @@ -203,20 +206,26 @@ public void NullableArray_Cast_04() { N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.QuestionToken); - } - N(SyntaxKind.ArrayRankSpecifier); - { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } } - N(SyntaxKind.CloseBracketToken); N(SyntaxKind.QuestionToken); } N(SyntaxKind.ArrayRankSpecifier); @@ -246,41 +255,50 @@ public void NullableArray_Cast_05() N(SyntaxKind.CastExpression); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.ArrayRankSpecifier); - { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); - { - N(SyntaxKind.OmittedArraySizeExpressionToken); - } - N(SyntaxKind.CloseBracketToken); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.NullableType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); - } - N(SyntaxKind.ArrayRankSpecifier); - { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.ArrayRankSpecifier); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.CloseParenToken); N(SyntaxKind.NullLiteralExpression); @@ -416,22 +434,25 @@ public void ConditionalOperator_NullableArray() N(SyntaxKind.IdentifierToken, "x"); } N(SyntaxKind.IsKeyword); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "T"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } } N(SyntaxKind.QuestionToken); @@ -607,22 +628,25 @@ public void NullCoalescingOperator_NullableArray() N(SyntaxKind.IdentifierToken, "x"); } N(SyntaxKind.AsKeyword); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "T"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } } N(SyntaxKind.QuestionQuestionToken); @@ -844,18 +868,24 @@ public void DeclarationPattern_NullableArrayOfArray() { N(SyntaxKind.ArrayType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "T"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.NullableType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } } - N(SyntaxKind.CloseBracketToken); N(SyntaxKind.QuestionToken); } N(SyntaxKind.ArrayRankSpecifier); @@ -898,40 +928,46 @@ public void NullableArray_TypeArgument() N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "A"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.CommaToken); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.GreaterThanToken); } @@ -958,43 +994,49 @@ public void NullableArray_TupleType() N(SyntaxKind.OpenParenToken); N(SyntaxKind.TupleElement); { - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } } N(SyntaxKind.CommaToken); N(SyntaxKind.TupleElement); { - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.IdentifierToken, "A"); - } - N(SyntaxKind.ArrayRankSpecifier); - { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } } N(SyntaxKind.CloseParenToken); @@ -1019,22 +1061,25 @@ public void NullableArray_Using() N(SyntaxKind.OpenParenToken); N(SyntaxKind.VariableDeclaration); { - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "A"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.VariableDeclarator); { @@ -1068,22 +1113,25 @@ public void NullableArray_Query() N(SyntaxKind.FromClause); { N(SyntaxKind.FromKeyword); - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "A"); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.IdentifierToken, "a"); N(SyntaxKind.InKeyword); @@ -1129,22 +1177,25 @@ public void NullableArray_ExplicitlyTypedLambda() N(SyntaxKind.OpenParenToken); N(SyntaxKind.Parameter); { - N(SyntaxKind.ArrayType); + N(SyntaxKind.NullableType); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.ObjectKeyword); - } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBracketToken); - N(SyntaxKind.QuestionToken); } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.IdentifierToken, "a"); } @@ -1181,11 +1232,265 @@ public void NullableArray_PartialMember() N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PartialKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.IdentifierToken, "F"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void CreateNullableArray_01() + { + UsingExpression("new object[,][]?", + // (1,17): error CS1733: Expected expression + // new object[,][]? + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 17), + // (1,17): error CS1003: Syntax error, ':' expected + // new object[,][]? + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 17), + // (1,17): error CS1733: Expected expression + // new object[,][]? + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 17) + ); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.QuestionToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void CreateNullableArray_02() + { + UsingExpression("new object[,][]? { 1, 2 }"); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.CollectionInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void CreateNullableArray_03() + { + UsingExpression("new object[1,2]?[3]?[4]"); + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.NullableType); + { N(SyntaxKind.ArrayType); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.NullableType); { - N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "4"); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void CreateNullableArray_04() + { + UsingExpression("new object[,]?[]?[]"); + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); } N(SyntaxKind.ArrayRankSpecifier); { @@ -1195,20 +1500,111 @@ public void NullableArray_PartialMember() N(SyntaxKind.OmittedArraySizeExpressionToken); } N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void CreateNullableArray_05() + { + UsingExpression("new object[1,2]?[3]?[]"); + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + N(SyntaxKind.CloseBracketToken); + } + } N(SyntaxKind.QuestionToken); } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + N(SyntaxKind.CloseBracketToken); + } } - N(SyntaxKind.IdentifierToken, "F"); - N(SyntaxKind.ParameterList); + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OmittedArraySizeExpressionToken); } - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void CreateNullableArray_06() + { + UsingExpression("new object[]"); + N(SyntaxKind.ArrayCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.EndOfFileToken); } EOF(); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 1df14a49f2c98..a308287365345 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -265,19 +265,23 @@ public static int Main() } "; - ParseAndValidate(test, - // (6,32): error CS0178: Invalid rank specifier: expected ',' or ']' - // int[] arr = new int[5][5; - Diagnostic(ErrorCode.ERR_InvalidArray, "5"), - // (6,33): error CS1003: Syntax error, ',' expected - // int[] arr = new int[5][5; - Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",", ";"), - // (6,33): error CS0443: Syntax error; value expected - // int[] arr = new int[5][5; - Diagnostic(ErrorCode.ERR_ValueExpected, ""), - // (6,33): error CS1003: Syntax error, ']' expected - // int[] arr = new int[5][5; - Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("]", ";")); + CreateCompilation(test).VerifyDiagnostics( + // (6,32): error CS0178: Invalid rank specifier: expected ',' or ']' + // int[] arr = new int[5][5; + Diagnostic(ErrorCode.ERR_InvalidArray, "5").WithLocation(6, 32), + // (6,32): error CS0178: Invalid rank specifier: expected ',' or ']' + // int[] arr = new int[5][5; + Diagnostic(ErrorCode.ERR_InvalidArray, "5").WithLocation(6, 32), + // (6,33): error CS1003: Syntax error, ',' expected + // int[] arr = new int[5][5; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",", ";").WithLocation(6, 33), + // (6,33): error CS0443: Syntax error; value expected + // int[] arr = new int[5][5; + Diagnostic(ErrorCode.ERR_ValueExpected, "").WithLocation(6, 33), + // (6,33): error CS1003: Syntax error, ']' expected + // int[] arr = new int[5][5; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("]", ";").WithLocation(6, 33) + ); } [Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")] @@ -693,58 +697,94 @@ public class MyClass enum E { } public static void Main() { - int myarray[2]; - MyClass m[0]; - byte b[13,5]; - double d[14,5,6]; - E e[,50]; + int[2] myarray; + MyClass[0] m; + byte[13,5] b; + double[14,5,6] d; + E[,50] e; } + + static int[2] myarray; + static MyClass[0] m; + static byte[13,5] b; + static double[14,5,6] d; + static E[,50] e; } "; - - ParseAndValidate(test, - // (7,20): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // int myarray[2]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[2]"), - // (7,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // int myarray[2]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2"), - // (8,18): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // MyClass m[0]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[0]"), - // (8,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // MyClass m[0]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "0"), - // (9,15): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[13,5]"), - // (9,16): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "13"), - // (9,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5"), - // (10,17): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[14,5,6]"), - // (10,18): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "14"), - // (10,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5"), - // (10,23): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "6"), - // (11,12): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // E e[,50]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[,50]"), - // (11,13): error CS0443: Syntax error; value expected - // E e[,50]; - Diagnostic(ErrorCode.ERR_ValueExpected, ""), - // (11,14): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // E e[,50]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "50")); + CreateCompilation(test).VerifyDiagnostics( + // (7,12): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // int[2] myarray; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[2]").WithLocation(7, 12), + // (7,16): warning CS0168: The variable 'myarray' is declared but never used + // int[2] myarray; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "myarray").WithArguments("myarray").WithLocation(7, 16), + // (8,9): error CS0119: 'MyClass' is a type, which is not valid in the given context + // MyClass[0] m; + Diagnostic(ErrorCode.ERR_BadSKunknown, "MyClass").WithArguments("MyClass", "type").WithLocation(8, 9), + // (8,20): error CS1002: ; expected + // MyClass[0] m; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "m").WithLocation(8, 20), + // (8,20): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // MyClass[0] m; + Diagnostic(ErrorCode.ERR_IllegalStatement, "m").WithLocation(8, 20), + // (9,13): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // byte[13,5] b; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[13,5]").WithLocation(9, 13), + // (9,20): warning CS0168: The variable 'b' is declared but never used + // byte[13,5] b; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(9, 20), + // (10,15): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // double[14,5,6] d; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[14,5,6]").WithLocation(10, 15), + // (10,24): warning CS0168: The variable 'd' is declared but never used + // double[14,5,6] d; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "d").WithArguments("d").WithLocation(10, 24), + // (11,9): error CS0119: 'MyClass.E' is a type, which is not valid in the given context + // E[,50] e; + Diagnostic(ErrorCode.ERR_BadSKunknown, "E").WithArguments("MyClass.E", "type").WithLocation(11, 9), + // (11,11): error CS0443: Syntax error; value expected + // E[,50] e; + Diagnostic(ErrorCode.ERR_ValueExpected, ",").WithLocation(11, 11), + // (11,16): error CS1002: ; expected + // E[,50] e; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "e").WithLocation(11, 16), + // (11,16): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // E[,50] e; + Diagnostic(ErrorCode.ERR_IllegalStatement, "e").WithLocation(11, 16), + // (14,15): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // static int[2] myarray; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[2]").WithLocation(14, 15), + // (14,19): warning CS0169: The field 'MyClass.myarray' is never used + // static int[2] myarray; + Diagnostic(ErrorCode.WRN_UnreferencedField, "myarray").WithArguments("MyClass.myarray").WithLocation(14, 19), + // (15,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // static MyClass[0] m; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[0]").WithLocation(15, 19), + // (15,23): warning CS0649: Field 'MyClass.m' is never assigned to, and will always have its default value null + // static MyClass[0] m; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "m").WithArguments("MyClass.m", "null").WithLocation(15, 23), + // (16,16): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // static byte[13,5] b; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[13,5]").WithLocation(16, 16), + // (16,23): warning CS0169: The field 'MyClass.b' is never used + // static byte[13,5] b; + Diagnostic(ErrorCode.WRN_UnreferencedField, "b").WithArguments("MyClass.b").WithLocation(16, 23), + // (17,18): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // static double[14,5,6] d; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[14,5,6]").WithLocation(17, 18), + // (17,27): warning CS0169: The field 'MyClass.d' is never used + // static double[14,5,6] d; + Diagnostic(ErrorCode.WRN_UnreferencedField, "d").WithArguments("MyClass.d").WithLocation(17, 27), + // (18,13): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // static E[,50] e; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[,50]").WithLocation(18, 13), + // (18,14): error CS0443: Syntax error; value expected + // static E[,50] e; + Diagnostic(ErrorCode.ERR_ValueExpected, "").WithLocation(18, 14), + // (18,19): warning CS0649: Field 'MyClass.e' is never assigned to, and will always have its default value null + // static E[,50] e; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "e").WithArguments("MyClass.e", "null").WithLocation(18, 19) + ); } [Fact] @@ -986,41 +1026,53 @@ public static void Main() } } "; - - ParseAndValidate(test, - // (6,20): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // int myarray[2]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[2]"), - // (6,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // int myarray[2]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2"), - // (7,18): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // MyClass m[0]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[0]"), - // (7,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // MyClass m[0]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "0"), - // (8,15): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[13,5]"), - // (8,16): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "13"), - // (8,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // byte b[13,5]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5"), - // (9,17): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_CStyleArray, "[14,5,6]"), - // (9,18): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "14"), - // (9,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5"), - // (9,23): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) - // double d[14,5,6]; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "6")); + CreateCompilation(test).VerifyDiagnostics( + // (6,20): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // int myarray[2]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[2]").WithLocation(6, 20), + // (6,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // int myarray[2]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(6, 21), + // (7,18): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // MyClass m[0]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[0]").WithLocation(7, 18), + // (7,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // MyClass m[0]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "0").WithLocation(7, 19), + // (8,15): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // byte b[13,5]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[13,5]").WithLocation(8, 15), + // (8,16): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // byte b[13,5]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "13").WithLocation(8, 16), + // (8,19): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // byte b[13,5]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5").WithLocation(8, 19), + // (9,17): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // double d[14,5,6]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[14,5,6]").WithLocation(9, 17), + // (9,18): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // double d[14,5,6]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "14").WithLocation(9, 18), + // (9,21): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // double d[14,5,6]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "5").WithLocation(9, 21), + // (9,23): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // double d[14,5,6]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "6").WithLocation(9, 23), + // (6,13): warning CS0168: The variable 'myarray' is declared but never used + // int myarray[2]; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "myarray").WithArguments("myarray").WithLocation(6, 13), + // (7,17): warning CS0168: The variable 'm' is declared but never used + // MyClass m[0]; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "m").WithArguments("m").WithLocation(7, 17), + // (8,14): warning CS0168: The variable 'b' is declared but never used + // byte b[13,5]; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "b").WithArguments("b").WithLocation(8, 14), + // (9,16): warning CS0168: The variable 'd' is declared but never used + // double d[14,5,6]; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "d").WithArguments("d").WithLocation(9, 16) + ); } [Fact, WorkItem(535883, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/535883")] @@ -4766,7 +4818,11 @@ unsafe public class Test int* p = stackalloc int[1]; } "; - CreateCompilation(test, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)).GetParseDiagnostics().Verify(); + CreateCompilation(test, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (4,14): error CS1525: Invalid expression term 'stackalloc' + // int* p = stackalloc int[1]; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "stackalloc").WithArguments("stackalloc").WithLocation(4, 14) + ); } [Fact] @@ -4782,7 +4838,11 @@ void M() } } "; - CreateCompilation(test, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)).GetParseDiagnostics().Verify(); + CreateCompilation(test, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,33): error CS1525: Invalid expression term 'stackalloc' + // int*[] p = new int*[] { stackalloc int[1] }; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "stackalloc").WithArguments("stackalloc").WithLocation(6, 33) + ); } [Fact] @@ -4944,6 +5004,7 @@ class Test public static int Main() { int[] a = new int[]; + int[,] t = new int[,]; byte[] b = new byte[]; string[] s = new string[]; return 1; @@ -4951,10 +5012,20 @@ public static int Main() } "; - ParseAndValidate(test, -Diagnostic(ErrorCode.ERR_MissingArraySize, "[]"), -Diagnostic(ErrorCode.ERR_MissingArraySize, "[]"), -Diagnostic(ErrorCode.ERR_MissingArraySize, "[]")); + CreateCompilation(test, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( + // (6,26): error CS1586: Array creation must have array size or array initializer + // int[] a = new int[]; + Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(6, 26), + // (7,27): error CS1586: Array creation must have array size or array initializer + // int[,] t = new int[,]; + Diagnostic(ErrorCode.ERR_MissingArraySize, "[,]").WithLocation(7, 27), + // (8,28): error CS1586: Array creation must have array size or array initializer + // byte[] b = new byte[]; + Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(8, 28), + // (9,32): error CS1586: Array creation must have array size or array initializer + // string[] s = new string[]; + Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(9, 32) + ); } [Fact, WorkItem(535935, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/535935")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index c711a9d5d417f..e8ae8926f0843 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs @@ -2767,7 +2767,7 @@ public void WhenAsPatternVariable02() public void ParseFuzz() { Random random = new Random(); - for (int i = 0; i < 2000; i++) + for (int i = 0; i < 4000; i++) { string source = $"class C{{void M(){{switch(e){{case {makePattern0()}:T v = e;}}}}}}"; try @@ -2836,7 +2836,7 @@ string makePattern(int maxDepth) } } } - string makePattern0() => makePattern(random.Next(5)); + string makePattern0() => makePattern(random.Next(6)); } [Fact] @@ -6122,6 +6122,233 @@ public void NestedShortTuplePatterns() EOF(); } + [Fact] + public void IsNullableArray01() + { + // OK, this means `(o is A[]) ? b : c` because nullable types are not permitted for a pattern's type + UsingExpression("o is A[] ? b : c"); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "o"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + EOF(); + } + + [Fact] + public void IsNullableArray02() + { + // error: 'cannot use nullable reference type for a pattern' or 'expected :' + UsingExpression("o is A[] ? b && c", + // (1,18): error CS1003: Syntax error, ':' expected + // o is A[] ? b && c + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 18), + // (1,18): error CS1733: Expected expression + // o is A[] ? b && c + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 18) + ); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "o"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.LogicalAndExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.AmpersandAmpersandToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void IsNullableArray03() + { + // OK, this means `(o is A[][]) ? b : c` + UsingExpression("o is A[][] ? b : c"); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "o"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + EOF(); + } + + [Fact] + public void IsNullableType01() + { + UsingExpression("o is A ? b : c"); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "o"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + EOF(); + } + + [Fact] + public void IsNullableType02() + { + UsingExpression("o is A? ? b : c"); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "o"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.QuestionToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + EOF(); + } + [Fact, WorkItem(32161, "https://github.com/dotnet/roslyn/issues/32161")] public void ParenthesizedSwitchCase() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs index 8d3ecba08e767..5e461dd06637b 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs @@ -491,7 +491,6 @@ public void TestNewRefArray() // new ref[]; Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(1, 10) ); - N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.ObjectCreationExpression); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs index 4490950b0fe9d..20f1723fc922a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs @@ -843,7 +843,7 @@ class AAttribute : Attribute { class C { } "; - ParseAndRoundTripping(text, -1); + ParseAndRoundTripping(text); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs index 8edbc554e343f..0b4d9e905a742 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs @@ -3454,7 +3454,7 @@ static void Test(int arg1, (byte, byte) arg2) } "; var tree = SyntaxFactory.ParseSyntaxTree(source, options: TestOptions.Regular); - Assert.Equal(false, tree.GetRoot().ContainsDiagnostics); + tree.GetDiagnostics().Verify(); } [Fact] diff --git a/src/Workspaces/Core/Portable/Formatting/Context/FormattingContext.cs b/src/Workspaces/Core/Portable/Formatting/Context/FormattingContext.cs index 0368a877c0b51..89ea3edd6111b 100644 --- a/src/Workspaces/Core/Portable/Formatting/Context/FormattingContext.cs +++ b/src/Workspaces/Core/Portable/Formatting/Context/FormattingContext.cs @@ -353,7 +353,7 @@ private void AddWrappingSuppressOperation(SuppressOperation operation, bool twoT return; } - var ignoreElastic = option.IsMaskOn(SuppressOption.IgnoreElasticWrapping) || + var ignoreElastic = option.IsMaskOn(SuppressOption.IgnoreElasticWrapping) || !operation.ContainsElasticTrivia(_tokenStream); var data = new SuppressWrappingData(operation.TextSpan, ignoreElastic: ignoreElastic); diff --git a/src/Workspaces/Core/Portable/Formatting/Context/SuppressWrappingData.cs b/src/Workspaces/Core/Portable/Formatting/Context/SuppressWrappingData.cs index 57222b390525a..ce057a46ded9d 100644 --- a/src/Workspaces/Core/Portable/Formatting/Context/SuppressWrappingData.cs +++ b/src/Workspaces/Core/Portable/Formatting/Context/SuppressWrappingData.cs @@ -17,7 +17,7 @@ public SuppressWrappingData(TextSpan textSpan, bool ignoreElastic) public TextSpan TextSpan { get; } public bool IgnoreElastic { get; } - + #if DEBUG public override string ToString() => $"Suppress wrapping on '{TextSpan}' with IgnoreElastic={IgnoreElastic}";