提交 97c66864 编写于 作者: A AlekseyTs

Merge pull request #9442 from AlekseyTs/ctor_initializer

Test/fix scoping rules for pattern locals
......@@ -760,5 +760,24 @@ internal Binder WithPatternVariablesIfAny(ExpressionSyntax scopeOpt)
Debug.Assert(Locals.Length == 0);
return new PatternVariableBinder(scopeOpt, scopeOpt, this);
}
internal Binder WithPatternVariablesIfAny(ArgumentListSyntax initializerArgumentListOpt)
{
Debug.Assert(Locals.Length == 0);
if (initializerArgumentListOpt == null || initializerArgumentListOpt.Arguments.Count == 0)
{
return this;
}
return new PatternVariableBinder(initializerArgumentListOpt, initializerArgumentListOpt.Arguments, this);
}
internal BoundExpression WrapWithVariablesIfAny(BoundExpression expression)
{
return (Locals.Length == 0)
? expression
: new BoundSequence(expression.Syntax, Locals, ImmutableArray<BoundExpression>.Empty, expression, expression.Type) { WasCompilerGenerated = true };
}
}
}
......@@ -94,7 +94,7 @@ internal static void BindAttributeTypes(ImmutableArray<Binder> binders, Immutabl
internal CSharpAttributeData GetAttribute(AttributeSyntax node, NamedTypeSymbol boundAttributeType, DiagnosticBag diagnostics)
{
var boundAttribute = BindAttribute(node, boundAttributeType, diagnostics);
var boundAttribute = new PatternVariableBinder(node, this).BindAttribute(node, boundAttributeType, diagnostics);
return GetAttribute(boundAttribute, diagnostics);
}
......
......@@ -339,7 +339,8 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic
ParameterSymbol parameter,
EqualsValueClauseSyntax defaultValueSyntax)
{
return new LocalScopeBinder(this.WithContainingMemberOrLambda(parameter.ContainingSymbol).WithAdditionalFlags(BinderFlags.ParameterDefaultValue));
return new LocalScopeBinder(this.WithContainingMemberOrLambda(parameter.ContainingSymbol).WithAdditionalFlags(BinderFlags.ParameterDefaultValue)).
WithPatternVariablesIfAny(defaultValueSyntax.Value);
}
internal BoundExpression BindParameterDefaultValue(
......@@ -357,7 +358,7 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic
// Always generate the conversion, even if the expression is not convertible to the given type.
// We want the erroneous conversion in the tree.
return GenerateConversionForAssignment(parameterType, valueBeforeConversion, diagnostics, isDefaultParameter: true);
return WrapWithVariablesIfAny(GenerateConversionForAssignment(parameterType, valueBeforeConversion, diagnostics, isDefaultParameter: true));
}
internal BoundExpression BindEnumConstantInitializer(
......@@ -2644,12 +2645,8 @@ private static bool IsNegativeConstantForArraySize(BoundExpression expression)
MethodSymbol constructor,
DiagnosticBag diagnostics)
{
// Handle scoping for possible pattern variables declared in the initializer
PatternVariableBinder patBinder = (initializerArgumentListOpt != null)
? new PatternVariableBinder(initializerArgumentListOpt, initializerArgumentListOpt.Arguments, this)
: null;
var result = (patBinder ?? this).BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics);
return patBinder?.WrapWithPatternVariables(result) ?? result;
var result = BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics);
return WrapWithVariablesIfAny(result);
}
private BoundExpression BindConstructorInitializerCore(
......
......@@ -270,7 +270,7 @@ internal struct ProcessedFieldInitializers
var collisionDetector = new LocalScopeBinder(binder);
var patternBinder = new PatternVariableBinder(equalsValueClauseNode, equalsValueClauseNode.Value, collisionDetector);
var boundInitValue = patternBinder.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);
boundInitValue = patternBinder.WrapWithPatternVariables(boundInitValue);
boundInitValue = patternBinder.WrapWithVariablesIfAny(boundInitValue);
if (isImplicitlyTypedField)
{
......
......@@ -3450,7 +3450,7 @@ private BoundExpression BindCatchFilter(CatchFilterClauseSyntax filter, Diagnost
Error(diagnostics, ErrorCode.WRN_FilterIsConstant, filter.FilterExpression);
}
boundFilter = patternBinder.WrapWithPatternVariables(boundFilter);
boundFilter = patternBinder.WrapWithVariablesIfAny(boundFilter);
boundFilter = new BoundSequencePointExpression(filter, boundFilter, boundFilter.Type);
return boundFilter;
}
......
......@@ -100,6 +100,23 @@ internal PatternVariableBinder(SyntaxNode syntax, ExpressionSyntax expression, B
this.Syntax = syntax;
}
internal PatternVariableBinder(AttributeSyntax syntax, Binder next) : base(next)
{
this.Syntax = syntax;
if (syntax.ArgumentList?.Arguments.Count > 0)
{
var expressions = ArrayBuilder<ExpressionSyntax>.GetInstance(syntax.ArgumentList.Arguments.Count);
foreach (var argument in syntax.ArgumentList.Arguments)
{
expressions.Add(argument.Expression);
}
this.Expressions = expressions.ToImmutableAndFree();
}
}
protected override ImmutableArray<LocalSymbol> BuildLocals()
{
var patterns = PatternVariableFinder.FindPatternVariables(Expression, Expressions, this.Patterns);
......@@ -111,12 +128,5 @@ protected override ImmutableArray<LocalSymbol> BuildLocals()
patterns.Free();
return builder.ToImmutableAndFree();
}
internal BoundExpression WrapWithPatternVariables(BoundExpression expression)
{
return (Locals.Length == 0)
? expression
: new BoundSequence(expression.Syntax, Locals, ImmutableArray<BoundExpression>.Empty, expression, expression.Type);
}
}
}
......@@ -32,6 +32,9 @@ class PatternVariableFinder : CSharpSyntaxWalker
if (subExpression != null) expressionsToVisit.Add(subExpression);
}
}
expressionsToVisit.ReverseContents();
finder.VisitExpressions();
if (!patterns.IsDefaultOrEmpty)
......
......@@ -28,7 +28,7 @@ private AttributeSemanticModel(CSharpCompilation compilation, AttributeSyntax sy
public static AttributeSemanticModel Create(CSharpCompilation compilation, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder)
{
var executableBinder = new ExecutableCodeBinder(syntax, attributeType, rootBinder);
return new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new LocalScopeBinder(executableBinder));
return new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new PatternVariableBinder(syntax, executableBinder));
}
/// <summary>
......
......@@ -194,6 +194,7 @@ private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax
}
if (result != null)
{
result = binder.WrapWithVariablesIfAny(result);
return new BoundFieldEqualsValue(equalsValue, field, result);
}
break;
......@@ -205,6 +206,7 @@ private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax
BoundExpression result = binder.BindVariableOrAutoPropInitializer(equalsValue, RefKind.None, property.Type, diagnostics);
if (result != null)
{
result = binder.WrapWithVariablesIfAny(result);
return new BoundPropertyEqualsValue(equalsValue, property, result);
}
break;
......
......@@ -926,7 +926,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
variableDecl, //pass in the entire field initializer to permit region analysis.
fieldSymbol,
//if we're in regular C#, then insert an extra binder to perform field initialization checks
GetFieldOrPropertyInitializerBinder(fieldSymbol, outer));
GetFieldOrPropertyInitializerBinder(fieldSymbol, outer, variableDecl.Initializer?.Value));
}
case SyntaxKind.PropertyDeclaration:
......@@ -937,7 +937,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
this.Compilation,
propertyDecl,
propertySymbol,
GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer));
GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer, propertyDecl.Initializer?.Value));
}
case SyntaxKind.Parameter:
......@@ -968,7 +968,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
this.Compilation,
enumDecl,
enumSymbol,
GetFieldOrPropertyInitializerBinder(enumSymbol, outer));
GetFieldOrPropertyInitializerBinder(enumSymbol, outer, enumDecl.EqualsValue?.Value));
}
default:
throw ExceptionUtilities.UnexpectedValue(node.Parent.Kind());
......@@ -1042,7 +1042,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
(ConstructorInitializerSyntax)node,
constructorSymbol,
//insert an extra binder to perform constructor initialization checks
outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol));
// Handle scoping for possible pattern variables declared in the initializer
outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol).
WithPatternVariablesIfAny(((ConstructorInitializerSyntax)node).ArgumentList));
}
case SyntaxKind.Attribute:
......@@ -1084,7 +1086,7 @@ private SourceMemberFieldSymbol GetDeclaredFieldSymbol(VariableDeclaratorSyntax
return null;
}
private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder outer)
private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder outer, ExpressionSyntax valueSyntaxOpt)
{
BinderFlags flags = BinderFlags.None;
......@@ -1094,7 +1096,13 @@ private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder ou
flags |= BinderFlags.FieldInitializer;
}
return new LocalScopeBinder(outer).WithAdditionalFlagsAndContainingMemberOrLambda(flags, symbol);
Binder result = new LocalScopeBinder(outer).WithAdditionalFlagsAndContainingMemberOrLambda(flags, symbol);
if (valueSyntaxOpt != null)
{
result = result.WithPatternVariablesIfAny(valueSyntaxOpt);
}
return result;
}
private static bool IsMemberDeclaration(CSharpSyntaxNode node)
......
......@@ -1726,7 +1726,9 @@ internal static BoundExpression BindConstructorInitializer(MethodSymbol construc
}
// wrap in ConstructorInitializerBinder for appropriate errors
Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor);
// Handle scoping for possible pattern variables declared in the initializer
Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor).
WithPatternVariablesIfAny(initializerArgumentListOpt);
return initializerBinder.BindConstructorInitializer(initializerArgumentListOpt, constructor, diagnostics);
}
......
......@@ -52,15 +52,21 @@ internal static class ConstantValueUtils
DiagnosticBag diagnostics)
{
var enumConstant = fieldSymbol as SourceEnumConstantSymbol;
var collisionDetector = new LocalScopeBinder(binder);
Binder collisionDetector = new LocalScopeBinder(binder);
collisionDetector = collisionDetector.WithPatternVariablesIfAny(initializer.Value);
BoundExpression result;
if ((object)enumConstant != null)
{
return collisionDetector.BindEnumConstantInitializer(enumConstant, initializer.Value, diagnostics);
result = collisionDetector.BindEnumConstantInitializer(enumConstant, initializer.Value, diagnostics);
}
else
{
return collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
result = collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
}
result = collisionDetector.WrapWithVariablesIfAny(result);
return result;
}
internal static ConstantValue GetAndValidateConstantValue(
......
......@@ -481,15 +481,12 @@ private static void M(string p = """" is object o ? o.ToString() : """")
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (2,28): error CS0103: The name 's' does not exist in the current context
// (2,11): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Obsolete("" is string s ? s : "")]
Diagnostic(ErrorCode.ERR_NameNotInContext, "s").WithArguments("s").WithLocation(2, 28),
// (8,55): error CS0103: The name 'o' does not exist in the current context
Diagnostic(ErrorCode.ERR_BadAttributeArgument, @""""" is string s ? s : """"").WithLocation(2, 11),
// (8,38): error CS1736: Default parameter value for 'p' must be a compile-time constant
// private static void M(string p = "" is object o ? o.ToString() : "")
Diagnostic(ErrorCode.ERR_NameNotInContext, "o").WithArguments("o").WithLocation(8, 55),
// (8,34): error CS1750: A value of type '?' cannot be used as a default parameter because there are no standard conversions to type 'string'
// private static void M(string p = "" is object o ? o.ToString() : "")
Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "p").WithArguments("?", "string").WithLocation(8, 34)
Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, @""""" is object o ? o.ToString() : """"").WithArguments("p").WithLocation(8, 38)
);
}
......@@ -3695,7 +3692,7 @@ public static void Main()
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions.WithLocalFunctionsFeature());
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (9,33): error CS1002: ; expected
// void Test1(object o) => let x1 = o;
......@@ -3825,7 +3822,7 @@ public static void Main()
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions.WithLocalFunctionsFeature());
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (9,33): error CS1002: ; expected
// bool Test1(object o) => let x1 = o;
......@@ -3909,5 +3906,910 @@ public static void Main()
var x11Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x11").Single();
VerifyModelForDeclarationPattern(model, x11Decl, x11Ref);
}
[Fact]
public void ScopeOfPatternVariables_FieldInitializers_01()
{
var source =
@"
public class X
{
public static void Main()
{
System.Console.WriteLine(Test1);
}
static bool Test1 = 1 is int x1 && Dummy(x1);
static bool Dummy(int x)
{
System.Console.WriteLine(x);
return true;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
CompileAndVerify(compilation, expectedOutput: @"1
True");
}
[Fact]
public void ScopeOfPatternVariables_FieldInitializers_02()
{
var source =
@"
public class X
{
public static void Main()
{
}
bool Test3 = 3 is int x3 && x3 > 0;
bool Test4 = x4 && 4 is int x4;
bool Test5 = 51 is int x5 &&
52 is int x5 &&
x5 > 0;
bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0;
bool Test71 = 7 is int x7 && x7 > 0;
bool Test72 = Dummy(x7, 2);
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (10,18): error CS0841: Cannot use local variable 'x4' before it is declared
// bool Test4 = x4 && 4 is int x4;
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 18),
// (13,28): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 28),
// (19,25): error CS0103: The name 'x7' does not exist in the current context
// bool Test72 = Dummy(x7, 2);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 25),
// (20,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref[0]);
VerifyModelForDeclarationPattern(model, x6Decl[1], x6Ref[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_FieldInitializers_03()
{
var source =
@"
public enum X
{
Test3 = 3 is int x3 ? x3 : 0,
Test4 = x4 && 4 is int x4 ? 1 : 0,
Test5 = 51 is int x5 &&
52 is int x5 &&
x5 > 0 ? 1 : 0,
Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0,
Test71 = 7 is int x7 && x7 > 0 ? 1 : 0,
Test72 = x7,
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugDll, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (6,13): error CS0841: Cannot use local variable 'x4' before it is declared
// Test4 = x4 && 4 is int x4 ? 1 : 0,
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(6, 13),
// (9,23): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(9, 23),
// (12,14): error CS0133: The expression being assigned to 'X.Test61' must be constant
// Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0,
Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0 ? 1 : 0").WithArguments("X.Test61").WithLocation(12, 14),
// (12,54): error CS0133: The expression being assigned to 'X.Test62' must be constant
// Test61 = 6 is int x6 && x6 > 0 ? 1 : 0, Test62 = 6 is int x6 && x6 > 0 ? 1 : 0,
Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0 ? 1 : 0").WithArguments("X.Test62").WithLocation(12, 54),
// (14,14): error CS0133: The expression being assigned to 'X.Test71' must be constant
// Test71 = 7 is int x7 && x7 > 0 ? 1 : 0,
Diagnostic(ErrorCode.ERR_NotConstantExpression, "7 is int x7 && x7 > 0 ? 1 : 0").WithArguments("X.Test71").WithLocation(14, 14),
// (15,14): error CS0103: The name 'x7' does not exist in the current context
// Test72 = x7,
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 14),
// (4,13): error CS0133: The expression being assigned to 'X.Test3' must be constant
// Test3 = 3 is int x3 ? x3 : 0,
Diagnostic(ErrorCode.ERR_NotConstantExpression, "3 is int x3 ? x3 : 0").WithArguments("X.Test3").WithLocation(4, 13)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref[0]);
VerifyModelForDeclarationPattern(model, x6Decl[1], x6Ref[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(2, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
}
[Fact]
public void ScopeOfPatternVariables_FieldInitializers_04()
{
var source =
@"
public class X
{
public static void Main()
{
}
const bool Test3 = 3 is int x3 && x3 > 0;
const bool Test4 = x4 && 4 is int x4;
const bool Test5 = 51 is int x5 &&
52 is int x5 &&
x5 > 0;
const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0;
const bool Test71 = 7 is int x7 && x7 > 0;
const bool Test72 = x7 > 2;
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (8,24): error CS0133: The expression being assigned to 'X.Test3' must be constant
// const bool Test3 = 3 is int x3 && x3 > 0;
Diagnostic(ErrorCode.ERR_NotConstantExpression, "3 is int x3 && x3 > 0").WithArguments("X.Test3").WithLocation(8, 24),
// (10,24): error CS0841: Cannot use local variable 'x4' before it is declared
// const bool Test4 = x4 && 4 is int x4;
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 24),
// (13,34): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 34),
// (16,25): error CS0133: The expression being assigned to 'X.Test61' must be constant
// const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0;
Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0").WithArguments("X.Test61").WithLocation(16, 25),
// (16,57): error CS0133: The expression being assigned to 'X.Test62' must be constant
// const bool Test61 = 6 is int x6 && x6 > 0, Test62 = 6 is int x6 && x6 > 0;
Diagnostic(ErrorCode.ERR_NotConstantExpression, "6 is int x6 && x6 > 0").WithArguments("X.Test62").WithLocation(16, 57),
// (18,25): error CS0133: The expression being assigned to 'X.Test71' must be constant
// const bool Test71 = 7 is int x7 && x7 > 0;
Diagnostic(ErrorCode.ERR_NotConstantExpression, "7 is int x7 && x7 > 0").WithArguments("X.Test71").WithLocation(18, 25),
// (19,25): error CS0103: The name 'x7' does not exist in the current context
// const bool Test72 = x7 > 2;
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 25),
// (20,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref[0]);
VerifyModelForDeclarationPattern(model, x6Decl[1], x6Ref[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_PropertyInitializers_01()
{
var source =
@"
public class X
{
public static void Main()
{
System.Console.WriteLine(Test1);
}
static bool Test1 {get;} = 1 is int x1 && Dummy(x1);
static bool Dummy(int x)
{
System.Console.WriteLine(x);
return true;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
CompileAndVerify(compilation, expectedOutput: @"1
True");
}
[Fact]
public void ScopeOfPatternVariables_PropertyInitializers_02()
{
var source =
@"
public class X
{
public static void Main()
{
}
bool Test3 {get;} = 3 is int x3 && x3 > 0;
bool Test4 {get;} = x4 && 4 is int x4;
bool Test5 {get;} = 51 is int x5 &&
52 is int x5 &&
x5 > 0;
bool Test61 {get;} = 6 is int x6 && x6 > 0; bool Test62 {get;} = 6 is int x6 && x6 > 0;
bool Test71 {get;} = 7 is int x7 && x7 > 0;
bool Test72 {get;} = Dummy(x7, 2);
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (10,25): error CS0841: Cannot use local variable 'x4' before it is declared
// bool Test4 {get;} = x4 && 4 is int x4;
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(10, 25),
// (13,28): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(13, 28),
// (19,32): error CS0103: The name 'x7' does not exist in the current context
// bool Test72 {get;} = Dummy(x7, 2);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(19, 32),
// (20,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(20, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref[0]);
VerifyModelForDeclarationPattern(model, x6Decl[1], x6Ref[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_ParameterDefault_01()
{
var source =
@"
public class X
{
public static void Main()
{
}
void Test3(bool p = 3 is int x3 && x3 > 0)
{}
void Test4(bool p = x4 && 4 is int x4)
{}
void Test5(bool p = 51 is int x5 &&
52 is int x5 &&
x5 > 0)
{}
void Test61(bool p1 = 6 is int x6 && x6 > 0, bool p2 = 6 is int x6 && x6 > 0)
{}
void Test71(bool p = 7 is int x7 && x7 > 0)
{
}
void Test72(bool p = x7 > 2)
{}
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (8,25): error CS1736: Default parameter value for 'p' must be a compile-time constant
// void Test3(bool p = 3 is int x3 && x3 > 0)
Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "3 is int x3 && x3 > 0").WithArguments("p").WithLocation(8, 25),
// (11,25): error CS0841: Cannot use local variable 'x4' before it is declared
// void Test4(bool p = x4 && 4 is int x4)
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(11, 25),
// (11,21): error CS1750: A value of type '?' cannot be used as a default parameter because there are no standard conversions to type 'bool'
// void Test4(bool p = x4 && 4 is int x4)
Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "p").WithArguments("?", "bool").WithLocation(11, 21),
// (15,35): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(15, 35),
// (14,21): error CS1750: A value of type '?' cannot be used as a default parameter because there are no standard conversions to type 'bool'
// void Test5(bool p = 51 is int x5 &&
Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "p").WithArguments("?", "bool").WithLocation(14, 21),
// (19,27): error CS1736: Default parameter value for 'p1' must be a compile-time constant
// void Test61(bool p1 = 6 is int x6 && x6 > 0, bool p2 = 6 is int x6 && x6 > 0)
Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "6 is int x6 && x6 > 0").WithArguments("p1").WithLocation(19, 27),
// (19,60): error CS1736: Default parameter value for 'p2' must be a compile-time constant
// void Test61(bool p1 = 6 is int x6 && x6 > 0, bool p2 = 6 is int x6 && x6 > 0)
Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "6 is int x6 && x6 > 0").WithArguments("p2").WithLocation(19, 60),
// (22,26): error CS1736: Default parameter value for 'p' must be a compile-time constant
// void Test71(bool p = 7 is int x7 && x7 > 0)
Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "7 is int x7 && x7 > 0").WithArguments("p").WithLocation(22, 26),
// (26,26): error CS0103: The name 'x7' does not exist in the current context
// void Test72(bool p = x7 > 2)
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(26, 26),
// (29,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(29, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref[0]);
VerifyModelForDeclarationPattern(model, x6Decl[1], x6Ref[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_Attribute_01()
{
var source =
@"
public class X
{
public static void Main()
{
}
[Test(p = 3 is int x3 && x3 > 0)]
[Test(p = x4 && 4 is int x4)]
[Test(p = 51 is int x5 &&
52 is int x5 &&
x5 > 0)]
[Test(p1 = 6 is int x6 && x6 > 0, p2 = 6 is int x6 && x6 > 0)]
[Test(p = 7 is int x7 && x7 > 0)]
[Test(p = x7 > 2)]
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
class Test : System.Attribute
{
public bool p {get; set;}
public bool p1 {get; set;}
public bool p2 {get; set;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (8,15): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Test(p = 3 is int x3 && x3 > 0)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, "3 is int x3 && x3 > 0").WithLocation(8, 15),
// (9,15): error CS0841: Cannot use local variable 'x4' before it is declared
// [Test(p = x4 && 4 is int x4)]
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(9, 15),
// (11,25): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(11, 25),
// (13,53): error CS0128: A local variable named 'x6' is already defined in this scope
// [Test(p1 = 6 is int x6 && x6 > 0, p2 = 6 is int x6 && x6 > 0)]
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(13, 53),
// (13,16): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Test(p1 = 6 is int x6 && x6 > 0, p2 = 6 is int x6 && x6 > 0)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, "6 is int x6 && x6 > 0").WithLocation(13, 16),
// (14,15): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Test(p = 7 is int x7 && x7 > 0)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, "7 is int x7 && x7 > 0").WithLocation(14, 15),
// (15,15): error CS0103: The name 'x7' does not exist in the current context
// [Test(p = x7 > 2)]
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 15),
// (16,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(16, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x6Decl[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_Attribute_02()
{
var source =
@"
public class X
{
public static void Main()
{
}
[Test(3 is int x3 && x3 > 0)]
[Test(x4 && 4 is int x4)]
[Test(51 is int x5 &&
52 is int x5 &&
x5 > 0)]
[Test(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)]
[Test(7 is int x7 && x7 > 0)]
[Test(x7 > 2)]
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
class Test : System.Attribute
{
public Test(bool p) {}
public Test(bool p1, bool p2) {}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (8,11): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Test(3 is int x3 && x3 > 0)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, "3 is int x3 && x3 > 0").WithLocation(8, 11),
// (9,11): error CS0841: Cannot use local variable 'x4' before it is declared
// [Test(x4 && 4 is int x4)]
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(9, 11),
// (11,21): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(11, 21),
// (13,43): error CS0128: A local variable named 'x6' is already defined in this scope
// [Test(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)]
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(13, 43),
// (14,11): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
// [Test(7 is int x7 && x7 > 0)]
Diagnostic(ErrorCode.ERR_BadAttributeArgument, "7 is int x7 && x7 > 0").WithLocation(14, 11),
// (15,11): error CS0103: The name 'x7' does not exist in the current context
// [Test(x7 > 2)]
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(15, 11),
// (16,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(16, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x6Decl[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_ConstructorInitializers_01()
{
var source =
@"
public class X
{
public static void Main()
{
}
X(byte x)
: this(3 is int x3 && x3 > 0)
{}
X(sbyte x)
: this(x4 && 4 is int x4)
{}
X(short x)
: this(51 is int x5 &&
52 is int x5 &&
x5 > 0)
{}
X(ushort x)
: this(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)
{}
X(int x)
: this(7 is int x7 && x7 > 0)
{}
X(uint x)
: this(x7, 2)
{}
void Test73() { Dummy(x7, 3); }
X(params object[] x) {}
bool Dummy(params object[] x) {return true;}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (13,16): error CS0841: Cannot use local variable 'x4' before it is declared
// : this(x4 && 4 is int x4)
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16),
// (18,26): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 26),
// (23,48): error CS0128: A local variable named 'x6' is already defined in this scope
// : this(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(23, 48),
// (30,16): error CS0103: The name 'x7' does not exist in the current context
// : this(x7, 2)
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16),
// (32,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(32, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x6Decl[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_ConstructorInitializers_02()
{
var source =
@"
public class X : Y
{
public static void Main()
{
}
X(byte x)
: base(3 is int x3 && x3 > 0)
{}
X(sbyte x)
: base(x4 && 4 is int x4)
{}
X(short x)
: base(51 is int x5 &&
52 is int x5 &&
x5 > 0)
{}
X(ushort x)
: base(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)
{}
X(int x)
: base(7 is int x7 && x7 > 0)
{}
X(uint x)
: base(x7, 2)
{}
void Test73() { Dummy(x7, 3); }
bool Dummy(params object[] x) {return true;}
}
public class Y
{
public Y(params object[] x) {}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (13,16): error CS0841: Cannot use local variable 'x4' before it is declared
// : base(x4 && 4 is int x4)
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x4").WithArguments("x4").WithLocation(13, 16),
// (18,26): error CS0128: A local variable named 'x5' is already defined in this scope
// 52 is int x5 &&
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x5").WithArguments("x5").WithLocation(18, 26),
// (23,48): error CS0128: A local variable named 'x6' is already defined in this scope
// : base(6 is int x6 && x6 > 0, 6 is int x6 && x6 > 0)
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x6").WithArguments("x6").WithLocation(23, 48),
// (30,16): error CS0103: The name 'x7' does not exist in the current context
// : base(x7, 2)
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(30, 16),
// (32,27): error CS0103: The name 'x7' does not exist in the current context
// void Test73() { Dummy(x7, 3); }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x7").WithArguments("x7").WithLocation(32, 27)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x3Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x3").Single();
var x3Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x3").Single();
VerifyModelForDeclarationPattern(model, x3Decl, x3Ref);
var x4Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x4").Single();
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").Single();
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref);
var x5Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x5").ToArray();
var x5Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x5").Single();
Assert.Equal(2, x5Decl.Length);
VerifyModelForDeclarationPattern(model, x5Decl[0], x5Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x5Decl[1]);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").ToArray();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
Assert.Equal(2, x6Decl.Length);
Assert.Equal(2, x6Ref.Length);
VerifyModelForDeclarationPattern(model, x6Decl[0], x6Ref);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x6Decl[1]);
var x7Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x7").Single();
var x7Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x7").ToArray();
Assert.Equal(3, x7Ref.Length);
VerifyModelForDeclarationPattern(model, x7Decl, x7Ref[0]);
VerifyNotInScope(model, x7Ref[1]);
VerifyNotInScope(model, x7Ref[2]);
}
[Fact]
public void ScopeOfPatternVariables_ConstructorInitializers_03()
{
var source =
@"using System;
public class X
{
public static void Main()
{
new D(1);
new D(10);
new D(1.2);
}
}
class D
{
public D(object o) : this(o is int x && x >= 5)
{
Console.WriteLine(x);
}
public D(bool b) { Console.WriteLine(b); }
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (15,27): error CS0103: The name 'x' does not exist in the current context
// Console.WriteLine(x);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27)
);
}
[Fact]
public void ScopeOfPatternVariables_ConstructorInitializers_04()
{
var source =
@"using System;
public class X
{
public static void Main()
{
new D(1);
new D(10);
new D(1.2);
}
}
class D : C
{
public D(object o) : base(o is int x && x >= 5)
{
Console.WriteLine(x);
}
}
class C
{
public C(bool b) { Console.WriteLine(b); }
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics(
// (15,27): error CS0103: The name 'x' does not exist in the current context
// Console.WriteLine(x);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(15, 27)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册