diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 1e95566482aba..112f15b9b8343 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -150,6 +150,10 @@ public enum SyntaxKind : ushort /// Represents >>>= token. GreaterThanGreaterThanGreaterThanEqualsToken = 8287, + // When adding punctuation, the following functions must be adapted: + // + // + // Keywords /// Represents . BoolKeyword = 8304, diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs index 41fcb7da7ff89..1ffefc6557ffb 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs @@ -143,7 +143,7 @@ public static IEnumerable GetPreprocessorKeywordKinds() public static bool IsPunctuation(SyntaxKind kind) { - return kind >= SyntaxKind.TildeToken && kind <= SyntaxKind.QuestionQuestionEqualsToken; + return kind >= SyntaxKind.TildeToken && kind <= SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken; } public static bool IsLanguagePunctuation(SyntaxKind kind) @@ -164,7 +164,7 @@ private static bool IsDebuggerSpecialPunctuation(SyntaxKind kind) public static IEnumerable GetPunctuationKinds() { - for (int i = (int)SyntaxKind.TildeToken; i <= (int)SyntaxKind.PercentEqualsToken; i++) + for (int i = (int)SyntaxKind.TildeToken; i <= (int)SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken; i++) { yield return (SyntaxKind)i; } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs index 9fd93e28050f4..84d77a6b0063d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs @@ -5203,6 +5203,7 @@ public void BinaryComparisonCastToVoidStar_NoWarning(string @operator) [InlineData("%")] [InlineData("<<")] [InlineData(">>")] + [InlineData(">>>")] [InlineData("&&")] [InlineData("||")] [InlineData("&")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ImplicitObjectCreationTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ImplicitObjectCreationTests.cs index 47b4cacbefd34..54f4396fab31d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ImplicitObjectCreationTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ImplicitObjectCreationTests.cs @@ -3370,6 +3370,7 @@ static void Main() var q = new() && new(); var r = new() || new(); var s = new() ?? new(); + var t = new() >>> new(); } } "; @@ -3438,7 +3439,10 @@ static void Main() Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(23, 26), // (24,17): error CS8754: There is no target type for 'new()' // var s = new() ?? new(); - Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(24, 17) + Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(24, 17), + // (25,17): error CS8310: Operator '>>>' cannot be applied to operand 'new()' + // var t = new() >>> new(); + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "new() >>> new()").WithArguments(">>>", "new()").WithLocation(25, 17) ); } @@ -3469,6 +3473,7 @@ static void Main() _ = new() && 1; _ = new() || 1; _ = new() ?? 1; + _ = new() >>> 1; } } "; @@ -3531,7 +3536,10 @@ static void Main() Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(23, 13), // (24,13): error CS8754: There is no target type for 'new()' // _ = new() ?? 1; - Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(24, 13) + Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(24, 13), + // (25,13): error CS8310: Operator '>>>' cannot be applied to operand 'new()' + // _ = new() >>> 1; + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "new() >>> 1").WithArguments(">>>", "new()").WithLocation(25, 13) ); } @@ -3562,6 +3570,7 @@ static void Main() _ = 1 && new(); _ = 1 || new(); _ = 1 ?? new(); + _ = 1 >>> new(); } } "; @@ -3624,7 +3633,10 @@ static void Main() Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(23, 18), // (24,13): error CS0019: Operator '??' cannot be applied to operands of type 'int' and 'new()' // _ = 1 ?? new(); - Diagnostic(ErrorCode.ERR_BadBinaryOps, "1 ?? new()").WithArguments("??", "int", "new()").WithLocation(24, 13) + Diagnostic(ErrorCode.ERR_BadBinaryOps, "1 ?? new()").WithArguments("??", "int", "new()").WithLocation(24, 13), + // (25,13): error CS8310: Operator '>>>' cannot be applied to operand 'new()' + // _ = 1 >>> new(); + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 >>> new()").WithArguments(">>>", "new()").WithLocation(25, 13) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs index 1c82e2586ee3e..7c0374d96ca67 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs @@ -1191,6 +1191,7 @@ public void TestLiftedBuiltInBinaryArithmetic() { "/", "divide" }, { "%", "remainder" }, { ">>", "rshift" }, + { ">>>", "urshift" }, { "<<", "lshift" }, { "&", "and" }, { "|", "or" }, @@ -1280,6 +1281,7 @@ static void METHOD_TYPEX_NAME_TYPEY() // UNDONE: so this test is disabled: // UNDONE: Tuple.Create("-", enumSubtraction), Tuple.Create(">>", shift1), + Tuple.Create(">>>", shift1), Tuple.Create("<<", shift2), Tuple.Create("&", logical1), Tuple.Create("|", logical2), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs index 01ea85dca7cac..5f2f3048de4e5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs @@ -3136,6 +3136,7 @@ public void TestOperatorOverloadResolution() TestOperatorKinds(GenerateTest(ArithmeticTemplate, "%", "Remainder")); TestOperatorKinds(GenerateTest(ShiftTemplate, "<<", "LeftShift")); TestOperatorKinds(GenerateTest(ShiftTemplate, ">>", "RightShift")); + TestOperatorKinds(GenerateTest(ShiftTemplate, ">>>", "UnsignedRightShift")); TestOperatorKinds(GenerateTest(ArithmeticTemplate, "==", "Equal")); TestOperatorKinds(GenerateTest(ArithmeticTemplate, "!=", "NotEqual")); TestOperatorKinds(GenerateTest(EqualityTemplate, "!=", "NotEqual")); @@ -6756,7 +6757,7 @@ class op_RightShift } class op_UnsignedRightShift { - + public static long operator >>> (op_UnsignedRightShift c, int i) { return 0; } } "; CreateCompilation(source).VerifyDiagnostics( @@ -6804,7 +6805,11 @@ class op_UnsignedRightShift Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "<<").WithArguments("op_LeftShift"), // (60,30): error CS0542: 'op_RightShift': member names cannot be the same as their enclosing type // public static long operator >> (op_RightShift c, int i) { return 0; } - Diagnostic(ErrorCode.ERR_MemberNameSameAsType, ">>").WithArguments("op_RightShift")); + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, ">>").WithArguments("op_RightShift"), + // (64,30): error CS0542: 'op_UnsignedRightShift': member names cannot be the same as their enclosing type + // public static long operator >>> (op_UnsignedRightShift c, int i) { return 0; } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, ">>>").WithArguments("op_UnsignedRightShift").WithLocation(64, 30) + ); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs index 91e7494d4c76c..3fb356ea0dd52 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TargetTypedDefaultTests.cs @@ -1281,6 +1281,7 @@ static void Main() var q = default && default; var r = default || default; var s = default ?? default; + var t = default >>> default; } } "; @@ -1348,7 +1349,10 @@ static void Main() Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(23, 28), // (24,17): error CS8716: There is no target type for the default literal. // var s = default ?? default; - Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(24, 17) + Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(24, 17), + // (25,17): error CS8310: Operator '>>>' cannot be applied to operand 'default' + // var t = default >>> default; + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >>> default").WithArguments(">>>", "default").WithLocation(25, 17) }; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1); @@ -1386,6 +1390,7 @@ static void Main() var r = default || 1; var s = default ?? 1; var t = default ?? default(int?); + var u = default >>> 1; } } "; @@ -1450,7 +1455,10 @@ static void Main() Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "o").WithArguments("o").WithLocation(20, 13), // (21,13): warning CS0219: The variable 'p' is assigned but its value is never used // var p = default != 1; // ok - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "p").WithArguments("p").WithLocation(21, 13) + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "p").WithArguments("p").WithLocation(21, 13), + // (26,17): error CS8310: Operator '>>>' cannot be applied to operand 'default' + // var u = default >>> 1; + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default >>> 1").WithArguments(">>>", "default").WithLocation(26, 17) }; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1); @@ -1488,6 +1496,7 @@ static void Main() var r = 1 || default; var s = new object() ?? default; // ok var t = 1 ?? default; + var u = 1 >>> default; } } "; @@ -1549,7 +1558,10 @@ static void Main() Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "o").WithArguments("o").WithLocation(20, 13), // (21,13): warning CS0219: The variable 'p' is assigned but its value is never used // var p = 1 != default; // ok - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "p").WithArguments("p").WithLocation(21, 13) + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "p").WithArguments("p").WithLocation(21, 13), + // (26,17): error CS8310: Operator '>>>' cannot be applied to operand 'default' + // var u = 1 >>> default; + Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "1 >>> default").WithArguments(">>>", "default").WithLocation(26, 17) }; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 8fe2f5f595fd0..ad82a923d0c55 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -5961,6 +5961,8 @@ void M(byte* p, int i) var r14 = i | p; var r15 = p ^ i; var r16 = i ^ p; + var r17 = p >>> i; + var r18 = i >>> p; } } "; @@ -6013,7 +6015,14 @@ void M(byte* p, int i) Diagnostic(ErrorCode.ERR_BadBinaryOps, "p ^ i").WithArguments("^", "byte*", "int"), // (21,19): error CS0019: Operator '^' cannot be applied to operands of type 'int' and 'byte*' // var r16 = i ^ p; - Diagnostic(ErrorCode.ERR_BadBinaryOps, "i ^ p").WithArguments("^", "int", "byte*")); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "i ^ p").WithArguments("^", "int", "byte*"), + // (22,19): error CS0019: Operator '>>>' cannot be applied to operands of type 'byte*' and 'int' + // var r17 = p >>> i; + Diagnostic(ErrorCode.ERR_BadBinaryOps, "p >>> i").WithArguments(">>>", "byte*", "int").WithLocation(22, 19), + // (23,19): error CS0019: Operator '>>>' cannot be applied to operands of type 'int' and 'byte*' + // var r18 = i >>> p; + Diagnostic(ErrorCode.ERR_BadBinaryOps, "i >>> p").WithArguments(">>>", "int", "byte*").WithLocation(23, 19) + ); } [Fact] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs index 09209bf3fa7bf..575f4d1fa2929 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs @@ -41273,6 +41273,12 @@ public static bool operator false(I1 x) System.Console.WriteLine(""<=""); return x; } + + public static I1 operator >>>(I1 x, int y) + { + System.Console.WriteLine("">>>""); + return x; + } } "; @@ -41306,6 +41312,8 @@ static void Main() x = x < y; x = x >= y; x = x <= y; + + x = x >>> 3; } } "; @@ -41334,11 +41342,12 @@ static void Main() < >= <= +>>> "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); @@ -41348,13 +41357,13 @@ static void Main() var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); @@ -41429,12 +41438,18 @@ static void Main() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">=").WithArguments("default interface implementation", "8.0").WithLocation(124, 31), // (130,31): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator <=(I1 x, I1 y) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "<=").WithArguments("default interface implementation", "8.0").WithLocation(130, 31) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "<=").WithArguments("default interface implementation", "8.0").WithLocation(130, 31), + // (136,31): error CS8652: The feature 'unsigned right shift' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static I1 operator >>>(I1 x, int y) + Diagnostic(ErrorCode.ERR_FeatureInPreview, ">>>").WithArguments("unsigned right shift").WithLocation(136, 31), + // (136,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. + // public static I1 operator >>>(I1 x, int y) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">>>").WithArguments("default interface implementation", "8.0").WithLocation(136, 31) ); var compilation61 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, targetFramework: TargetFramework.DesktopLatestExtended, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); compilation61.VerifyDiagnostics( // (4,31): error CS8701: Target runtime doesn't support default interface implementation. @@ -41502,7 +41517,10 @@ static void Main() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, ">=").WithLocation(124, 31), // (130,31): error CS8701: Target runtime doesn't support default interface implementation. // public static I1 operator <=(I1 x, I1 y) - Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "<=").WithLocation(130, 31) + Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "<=").WithLocation(130, 31), + // (136,31): error CS8701: Target runtime doesn't support default interface implementation. + // public static I1 operator >>>(I1 x, int y) + Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, ">>>").WithLocation(136, 31) ); var compilation7 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, @@ -41573,7 +41591,13 @@ static void Main() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >= y").WithArguments("default interface implementation", "8.0").WithLocation(28, 13), // (29,13): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x <= y; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x <= y").WithArguments("default interface implementation", "8.0").WithLocation(29, 13) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x <= y").WithArguments("default interface implementation", "8.0").WithLocation(29, 13), + // (31,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. + // x = x >>> 3; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >>> 3").WithArguments("default interface implementation", "8.0").WithLocation(31, 13), + // (31,13): error CS8652: The feature 'unsigned right shift' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // x = x >>> 3; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "x >>> 3").WithArguments("unsigned right shift").WithLocation(31, 13) }; compilation7.VerifyDiagnostics(expected7); @@ -43847,11 +43871,12 @@ public interface I1 public static I1 operator <(int x, int y) => throw null; public static I1 operator >=(int x, int y) => throw null; public static I1 operator <=(int x, int y) => throw null; + public static I1 operator >>>(int x, int y) => throw null; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); + parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,31): error CS0562: The parameter of a unary operator must be the containing type @@ -43919,7 +43944,10 @@ public interface I1 Diagnostic(ErrorCode.ERR_BadBinaryOperatorSignature, ">=").WithLocation(24, 31), // (25,31): error CS0563: One of the parameters of a binary operator must be the containing type // public static I1 operator <=(int x, int y) => throw null; - Diagnostic(ErrorCode.ERR_BadBinaryOperatorSignature, "<=").WithLocation(25, 31) + Diagnostic(ErrorCode.ERR_BadBinaryOperatorSignature, "<=").WithLocation(25, 31), + // (26,31): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int + // public static I1 operator >>>(int x, int y) => throw null; + Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>>").WithLocation(26, 31) ); } @@ -43932,8 +43960,8 @@ public interface I1 { public static I1 operator <<(I1 x, I1 y) => throw null; public static I1 operator >>(I1 x, I1 y) => throw null; + public static I1 operator >>>(I1 x, I1 y) => throw null; } - public interface I2 { public static bool operator true(I2 x) => throw null; @@ -43952,7 +43980,7 @@ public interface I4 "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); + parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,31): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int @@ -43961,6 +43989,9 @@ public interface I4 // (5,31): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int // public static I1 operator >>(I1 x, I1 y) => throw null; Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>").WithLocation(5, 31), + // (6,31): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int + // public static I1 operator >>>(I1 x, I1 y) => throw null; + Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>>").WithLocation(6, 31), // (10,33): error CS0216: The operator 'I2.operator true(I2)' requires a matching operator 'false' to also be defined // public static bool operator true(I2 x) => throw null; Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "true").WithArguments("I2.operator true(I2)", "false").WithLocation(10, 33), @@ -44191,6 +44222,12 @@ static bool operator false(I1 x) System.Console.WriteLine(""<=""); return x; } + + static I1 operator >>>(I1 x, int y) + { + System.Console.WriteLine("">>>""); + return x; + } } "; @@ -44224,6 +44261,8 @@ static void Main() x = x < y; x = x >= y; x = x <= y; + + x = x >>> 3; } } "; @@ -44252,11 +44291,12 @@ static void Main() < >= <= +>>> "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); var i1 = compilation1.GlobalNamespace.GetTypeMember("I1"); @@ -44272,12 +44312,12 @@ static void Main() var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr).VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular); + parseOptions: TestOptions.RegularPreview); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr).VerifyDiagnostics(); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 28e5a750d7088..4e3cae08714dc 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -10548,6 +10548,10 @@ class C { return 0; } + public static int operator >>>(int c1, int c2) // CS0564 + { + return 0; + } static void Main() { } @@ -10558,10 +10562,12 @@ static void Main() // (4,32): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int // public static int operator <<(C c1, C c2) // CS0564 Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, "<<"), - // (8,32): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int // public static int operator >>(int c1, int c2) // CS0564 - Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>") + Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>"), + // (12,32): error CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int + // public static int operator >>>(int c1, int c2) // CS0564 + Diagnostic(ErrorCode.ERR_BadShiftOperatorSignature, ">>>").WithLocation(12, 32) ); } @@ -10957,6 +10963,7 @@ public class C public static implicit operator void(C c1) { } public static void operator +(C c) { } public static void operator >>(C c, int x) { } + public static void operator >>>(C c, int x) { } } "; var comp = CreateCompilation(text); @@ -10967,15 +10974,18 @@ public static implicit operator void(C c1) { } // (5,33): error CS0590: User-defined operators cannot return void // public static implicit operator void(C c1) { } Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "void"), -// (5,46): error CS1547: Keyword 'void' cannot be used in this context -// public static implicit operator void(C c1) { } -Diagnostic(ErrorCode.ERR_NoVoidHere, "void"), + // (5,46): error CS1547: Keyword 'void' cannot be used in this context + // public static implicit operator void(C c1) { } + Diagnostic(ErrorCode.ERR_NoVoidHere, "void"), // (6,33): error CS0590: User-defined operators cannot return void // public static void operator +(C c) { } Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "+"), // (73): error CS0590: User-defined operators cannot return void // public static void operator >>(C c, int x) { } - Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, ">>") + Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, ">>"), + // (74): error CS0590: User-defined operators cannot return void + // public static void operator >>>(C c, int x) { } + Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, ">>>") ); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/UnsignedRightShiftTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/UnsignedRightShiftTests.cs index 0fb69be1b0132..b917946ec0fb9 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/UnsignedRightShiftTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/UnsignedRightShiftTests.cs @@ -2264,6 +2264,45 @@ static void Main() Assert.Equal(MethodKind.UserDefinedOperator, compilation3.GetMember("C1.op_UnsignedRightShift").MethodKind); } + [Fact] + public void UserDefined_06() + { + var source0 = @" +public class C1 +{ + public static C1 op_UnsignedRightShift(C1 x, int y) + { + return x; + } +} +"; + + var source1 = +@" +class C +{ + static C1 Test1(C1 x, int y) => x >>> y; +} +"; + var compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll); + + var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, references: new[] { compilation0.ToMetadataReference() }, + parseOptions: TestOptions.RegularPreview); + compilation2.VerifyDiagnostics( + // (4,37): error CS0019: Operator '>>>' cannot be applied to operands of type 'C1' and 'int' + // static C1 Test1(C1 x, int y) => x >>> y; + Diagnostic(ErrorCode.ERR_BadBinaryOps, "x >>> y").WithArguments(">>>", "C1", "int").WithLocation(4, 37) + ); + + var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, references: new[] { compilation0.EmitToImageReference() }, + parseOptions: TestOptions.RegularPreview); + compilation3.VerifyDiagnostics( + // (4,37): error CS0019: Operator '>>>' cannot be applied to operands of type 'C1' and 'int' + // static C1 Test1(C1 x, int y) => x >>> y; + Diagnostic(ErrorCode.ERR_BadBinaryOps, "x >>> y").WithArguments(">>>", "C1", "int").WithLocation(4, 37) + ); + } + [Fact] public void UserDefined_ExpressionTree_01() { @@ -3582,6 +3621,50 @@ class C } } + [Fact] + public void TestGenericArgWithGreaterThan_05() + { + var source1 = @" +class C +{ + void M() + { + var added = ImmutableDictionary>> + + ProjectChange = projectChange; + } +} +"; + var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.RegularPreview); + compilation1.VerifyDiagnostics( + // (6,21): error CS0103: The name 'ImmutableDictionary' does not exist in the current context + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_NameNotInContext, "ImmutableDictionary").WithArguments("ImmutableDictionary").WithLocation(6, 21), + // (6,41): error CS0103: The name 'T' does not exist in the current context + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_NameNotInContext, "T").WithArguments("T").WithLocation(6, 41), + // (6,44): error CS0246: The type or namespace name 'S' could not be found (are you missing a using directive or an assembly reference?) + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "S").WithArguments("S").WithLocation(6, 44), + // (6,44): error CS8185: A declaration is not allowed in this context. + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "S a").WithLocation(6, 44), + // (6,49): error CS0246: The type or namespace name 'U' could not be found (are you missing a using directive or an assembly reference?) + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "U").WithArguments("U").WithLocation(6, 49), + // (6,49): error CS8185: A declaration is not allowed in this context. + // var added = ImmutableDictionary>> + Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "U b").WithLocation(6, 49), + // (8,9): error CS0103: The name 'ProjectChange' does not exist in the current context + // ProjectChange = projectChange; + Diagnostic(ErrorCode.ERR_NameNotInContext, "ProjectChange").WithArguments("ProjectChange").WithLocation(8, 9), + // (8,25): error CS0103: The name 'projectChange' does not exist in the current context + // ProjectChange = projectChange; + Diagnostic(ErrorCode.ERR_NameNotInContext, "projectChange").WithArguments("projectChange").WithLocation(8, 25) + ); + } + [Fact] public void CanBeValidAttributeArgument() { diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/UserDefinedOperatorErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/UserDefinedOperatorErrorTests.cs index e1bb171219fb6..702bfd922ff69 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/UserDefinedOperatorErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/UserDefinedOperatorErrorTests.cs @@ -184,6 +184,7 @@ partial class C public public public static int operator & (C c1, C c2) { return 0; } extern static public int operator ^ (C c1, C c2) { return 1; } static public int operator + (C c1); + new public static int operator >>> (C c1, int c2) { return 0; } } "; @@ -241,7 +242,10 @@ partial class C Diagnostic(ErrorCode.ERR_ExternHasBody, "^").WithArguments("C.operator ^(C, C)").WithLocation(13, 39), // (14,32): error CS0501: 'C.operator +(C)' must declare a body because it is not marked abstract, extern, or partial // static public int operator + (C c1); - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "+").WithArguments("C.operator +(C)").WithLocation(14, 32) + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "+").WithArguments("C.operator +(C)").WithLocation(14, 32), + // (15,36): error CS0106: The modifier 'new' is not valid for this item + // new public static int operator >>> (C c1, int c2) { return 0; } + Diagnostic(ErrorCode.ERR_BadMemberFlag, ">>>").WithArguments("new").WithLocation(15, 36) ); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs index 2361c74e61ed4..7ddda6f9fd317 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs @@ -2477,5 +2477,255 @@ void M() } EOF(); } + + [Fact] + public void TestGenericArgWithGreaterThan_04() + { + UsingTree(@" +class C +{ + void M() + { + var added = ImmutableDictionary>> + + ProjectChange = projectChange; + } +} +"); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ImmutableDictionary"); + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.UnsignedRightShiftExpression); + { + N(SyntaxKind.TupleExpression); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "U"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ProjectChange"); + } + } + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "projectChange"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericArgWithGreaterThan_05() + { + UsingTree(@" +class C +{ + void M() + { + var added = ImmutableDictionary>> + + ProjectChange = projectChange; + } +} +"); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ImmutableDictionary"); + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.UnsignedRightShiftExpression); + { + N(SyntaxKind.TupleExpression); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.DeclarationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.DeclarationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "U"); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ProjectChange"); + } + } + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "projectChange"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 2fac5f8cfcf56..f2b63f3899ef0 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -606,6 +606,11 @@ public void TestNormalizeDeclaration1() TestNormalizeDeclaration("class a{ implicit I1 . operator checked b(c d){}}", "class a\r\n{\r\n implicit I1.operator checked b(c d)\r\n {\r\n }\r\n}"); TestNormalizeDeclaration("class a{ explicit I1 . operator checked b(c d){}}", "class a\r\n{\r\n explicit I1.operator checked b(c d)\r\n {\r\n }\r\n}"); + TestNormalizeDeclaration("class a{b operator >>> ( c d , e f ){}}", "class a\r\n{\r\n b operator >>>(c d, e f)\r\n {\r\n }\r\n}"); + TestNormalizeDeclaration("class a{b I1 . operator >>> ( c d , e f ){}}", "class a\r\n{\r\n b I1.operator >>>(c d, e f)\r\n {\r\n }\r\n}"); + TestNormalizeDeclaration("class a{b operator>>> ( c d , e f ){}}", "class a\r\n{\r\n b operator >>>(c d, e f)\r\n {\r\n }\r\n}"); + TestNormalizeDeclaration("class a{b I1 . operator>>> ( c d , e f ){}}", "class a\r\n{\r\n b I1.operator >>>(c d, e f)\r\n {\r\n }\r\n}"); + // properties TestNormalizeDeclaration("class a{b c{get;}}", "class a\r\n{\r\n b c { get; }\r\n}"); TestNormalizeDeclaration("class a {\r\nint X{get;set;}= 2;\r\n}\r\n", "class a\r\n{\r\n int X { get; set; } = 2;\r\n}"); diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs index ce2330c1d7593..e1c947a75c290 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxTests.cs @@ -239,5 +239,14 @@ public void TestGetLiteralExpression(SyntaxKind tokenKind, SyntaxKind expression { Assert.Equal(expressionKind, SyntaxFacts.GetLiteralExpression(tokenKind)); } + + [Fact] + public void Punctuation() + { + foreach (var kind in SyntaxFacts.GetPunctuationKinds()) + { + Assert.True(SyntaxFacts.IsPunctuation(kind)); + } + } } } diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnsignedRightShiftTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnsignedRightShiftTests.vb new file mode 100644 index 0000000000000..a1fcea40c7585 --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/UnsignedRightShiftTests.vb @@ -0,0 +1,88 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Symbols +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests + + Public Class UnsignedRightShiftTests + Inherits BasicTestBase + + + Public Sub Consume_01() + + Dim csSource = +" +public class C1 +{ + public static C1 operator >>>(C1 x, int y) + { + System.Console.WriteLine("">>>""); + return x; + } +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + referencedAssemblies:=TargetFrameworkUtil.GetReferences(TargetFramework.Standard)).EmitToImageReference() + + Dim source1 = + + > 1 + End Sub +End Class +]]> + + + Dim comp1 = CreateCompilation(source1, targetFramework:=TargetFramework.Standard, references:={csCompilation}, options:=TestOptions.DebugExe) + CompileAndVerify(comp1, expectedOutput:=">>>").VerifyDiagnostics() + End Sub + + + Public Sub Consume_02() + + Dim csSource = +" +public class C1 +{ + public static C1 operator >>>(C1 x, int y) + { + System.Console.WriteLine("">>>""); + return x; + } + public static C1 operator >>(C1 x, int y) + { + System.Console.WriteLine("">>""); + return x; + } +} +" + + Dim csCompilation = CreateCSharpCompilation(csSource, + parseOptions:=CSharp.CSharpParseOptions.Default.WithLanguageVersion(CSharp.LanguageVersion.Preview), + referencedAssemblies:=TargetFrameworkUtil.GetReferences(TargetFramework.Standard)).EmitToImageReference() + + Dim source1 = + + > 1 + End Sub +End Class +]]> + + + Dim comp1 = CreateCompilation(source1, targetFramework:=TargetFramework.Standard, references:={csCompilation}, options:=TestOptions.DebugExe) + CompileAndVerify(comp1, expectedOutput:=">>").VerifyDiagnostics() + End Sub + + End Class +End Namespace diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs index 0d711f9e7a648..d77e90f40d090 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs @@ -3493,6 +3493,7 @@ public void method() b = true && false || true; i << 5; i >> 5; + i >>> 5; b = i == i && i != i && i <= i && i >= i; i += 5.0; i -= i; @@ -3504,6 +3505,7 @@ public void method() i ^= i; i <<= i; i >>= i; + i >>>= i; i ??= i; object s = x => x + 1; Point point; @@ -3681,6 +3683,10 @@ public void method() Operators.GreaterThanGreaterThan, Number("5"), Punctuation.Semicolon, + Identifier("i"), + Operators.GreaterThanGreaterThanGreaterThan, + Number("5"), + Punctuation.Semicolon, Identifier("b"), Operators.Equals, Identifier("i"), @@ -3740,6 +3746,10 @@ public void method() Identifier("i"), Punctuation.Semicolon, Identifier("i"), + Operators.GreaterThanGreaterThanGreaterThanEquals, + Identifier("i"), + Punctuation.Semicolon, + Identifier("i"), Operators.QuestionQuestionEquals, Identifier("i"), Punctuation.Semicolon, @@ -6348,5 +6358,85 @@ static explicit I1.operator checked T(T a) Punctuation.OpenCurly, Punctuation.CloseCurly); } + + [Theory] + [CombinatorialData] + public async Task UnsignedRightShift_01(TestHost testHost) + { + await TestInClassAsync( +@" +static T operator >>>(T a, int b) +{ +}", + testHost, + Keyword("static"), + Identifier("T"), + Keyword("operator"), + Operators.GreaterThanGreaterThanGreaterThan, + Punctuation.OpenParen, + Identifier("T"), + Parameter("a"), + Punctuation.Comma, + Keyword("int"), + Parameter("b"), + Punctuation.CloseParen, + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Theory] + [CombinatorialData] + public async Task UnsignedRightShift_02(TestHost testHost) + { + await TestInClassAsync( +@" +static T I1.operator checked >>>(T a, T b) +{ +}", + testHost, + Keyword("static"), + Identifier("T"), + Identifier("I1"), + Operators.Dot, + Keyword("operator"), + Keyword("checked"), + Operators.GreaterThanGreaterThanGreaterThan, + Punctuation.OpenParen, + Identifier("T"), + Parameter("a"), + Punctuation.Comma, + Identifier("T"), + Parameter("b"), + Punctuation.CloseParen, + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Theory] + [CombinatorialData] + public async Task TestExclamationExclamation(TestHost testHost) + { + await TestAsync( +@"class C +{ + void M(string v!!) + { + } +}", + testHost, + Keyword("class"), + Class("C"), + Punctuation.OpenCurly, + Keyword("void"), + Method("M"), + Punctuation.OpenParen, + Keyword("string"), + Parameter("v"), + Punctuation.ExclamationExclamation, + Punctuation.CloseParen, + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OperatorCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OperatorCompletionProviderTests.cs index 54716fc2b49fa..5c152dae8f270 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OperatorCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OperatorCompletionProviderTests.cs @@ -33,6 +33,7 @@ private static IEnumerable BinaryArithmeticAndLogicalOperators() yield return new[] { "%" }; yield return new[] { "*" }; yield return new[] { ">>" }; + yield return new[] { ">>>" }; yield return new[] { "<<" }; yield return new[] { "-" }; } @@ -214,6 +215,7 @@ public class C public static C operator ^(C a, C b) => null; public static C operator <<(C a, int b) => null; public static C operator >>(C a, int b) => null; + public static C operator >>>(C a, int b) => null; public static C operator ~(C a) => null; } @@ -249,6 +251,7 @@ public static void Main() i => Assert.Equal("^", i.DisplayText), i => Assert.Equal("<<", i.DisplayText), i => Assert.Equal(">>", i.DisplayText), + i => Assert.Equal(">>>", i.DisplayText), i => Assert.Equal("~", i.DisplayText) ); } diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs index e3dd25381fb9c..c7e7b44242547 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs @@ -2523,6 +2523,45 @@ interface I1 where T : I1 AssertFormatAfterTypeChar(code, expected, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview)); } + [WpfFact] + public void FormatUnsignedRightShift() + { + var code = @"$$ +class C +{ + public static C operator>>> ( C x, C y){ + } +}"; + + var expected = @"$$ +class C +{ + public static C operator >>>(C x, C y) + { + } +}"; + + AssertFormatWithView(expected, code); + } + + [WpfFact] + public void FormatUnsignedRightShiftOnType() + { + var code = @" +interface I1 +{ + abstract static I1 operator >>> ( I1 x, I1 y);$$ +}"; + + var expected = @" +interface I1 +{ + abstract static I1 operator >>>(I1 x, I1 y); +}"; + + AssertFormatAfterTypeChar(code, expected); + } + private static void AssertFormatAfterTypeChar(string code, string expected, Dictionary changedOptionSet = null, ParseOptions parseOptions = null) { using var workspace = TestWorkspace.CreateCSharp(code, parseOptions: parseOptions); diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs index 0b700630c28c2..b18390aa604ad 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs @@ -3155,6 +3155,47 @@ public static explicit operator checked Class(int x) options: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview)); } + [WpfFact] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void UnsignedRightShift() + { + var code = @"using System; + +namespace NS +{ + class Class + { + public static Class operator >>>(Class x, Class y) + +"; + + AssertSmartIndent( + code, + indentationLine: 7, + expectedIndentation: 12); + } + + [WpfFact] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void UnsignedRightShiftBody() + { + var code = @"using System; + +namespace NS +{ + class Class + { + public static Class operator >>>(Class x, Class y) + { + +"; + + AssertSmartIndent( + code, + indentationLine: 8, + expectedIndentation: 12); + } + private static void AssertSmartIndentInProjection( string markup, int expectedIndentation, diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs index f3380570364e8..764677294dfdc 100644 --- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs @@ -10083,6 +10083,41 @@ class C : ITest }.RunAsync(); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestStaticAbstractInterfaceUnsigneRightShiftOperator_OnlyExplicitlyImplementable() + { + await new VerifyCS.Test + { + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + LanguageVersion = LanguageVersion.Preview, + TestCode = @" +interface ITest +{ + static abstract int operator >>>(ITest x, int y); +} +class C : {|CS0535:ITest|} +{ +} +", + FixedCode = @" +interface ITest +{ + static abstract int operator >>>(ITest x, int y); +} +class C : ITest +{ + static int ITest.operator >>>(ITest x, int y) + { + throw new System.NotImplementedException(); + } +} +", + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(FeaturesResources.Implement_all_members_explicitly, codeAction.Title), + CodeActionEquivalenceKey = "True;False;False:global::ITest;TestProject;Microsoft.CodeAnalysis.ImplementInterface.AbstractImplementInterfaceService+ImplementInterfaceCodeAction;", + CodeActionIndex = 0, + }.RunAsync(); + } + [WorkItem(53927, "https://github.com/dotnet/roslyn/issues/53927")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/56171"), Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestStaticAbstractInterfaceOperator_ImplementImplicitly() @@ -10126,6 +10161,41 @@ class C : ITest }.RunAsync(); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestStaticAbstractInterfaceUnsignedRightShiftOperator_ImplementImplicitly() + { + await new VerifyCS.Test + { + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + LanguageVersion = LanguageVersion.Preview, + TestCode = @" +interface ITest where T : ITest +{ + static abstract int operator >>>(T x, int y); +} +class C : {|CS0535:ITest|} +{ +} +", + FixedCode = @" +interface ITest where T : ITest +{ + static abstract int operator >>>(T x, int y); +} +class C : ITest +{ + public static int operator >>>(C x, int y) + { + throw new System.NotImplementedException(); + } +} +", + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(FeaturesResources.Implement_interface, codeAction.Title), + CodeActionEquivalenceKey = "False;False;True:global::ITest;TestProject;Microsoft.CodeAnalysis.ImplementInterface.AbstractImplementInterfaceService+ImplementInterfaceCodeAction;", + CodeActionIndex = 0, + }.RunAsync(); + } + [WorkItem(53927, "https://github.com/dotnet/roslyn/issues/53927")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/56171"), Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestStaticAbstractInterfaceOperator_ImplementExplicitly() diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index 38fc0e11453c9..3068af158087f 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -1102,7 +1102,27 @@ await TestInMethodAsync( } [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] - public async Task TestOperatorCustomTypeBuiltIn() + public async Task TestOperatorBuiltIn12() + { + await TestInMethodAsync( +@"int x; + +x = x >>>$$ x;", + MainDescription("int int.operator >>>(int left, int right)")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestOperatorBuiltIn13() + { + await TestInMethodAsync( +@"int x; + +x >>>=$$ x;", + MainDescription("int int.operator >>>(int left, int right)")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestOperatorCustomTypeBuiltIn_01() { var markup = @"class C @@ -1113,6 +1133,18 @@ public async Task TestOperatorCustomTypeBuiltIn() await TestAsync(markup); } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestOperatorCustomTypeBuiltIn_02() + { + var markup = +@"class C +{ + static void M() { C c; c = c >>>$$ c; } +}"; + + await TestAsync(markup); + } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] public async Task TestOperatorCustomTypeOverload_01() { @@ -1229,6 +1261,34 @@ await TestAsync(markup, MainDescription("C C.operator checked -(C a)")); } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestOperatorCustomTypeOverload_09() + { + var markup = +@"class C +{ + static void M() { C c; c = c >>>$$ c; } + static C operator>>>(C a, C b) { return a; } +}"; + + await TestAsync(markup, + MainDescription("C C.operator >>>(C a, C b)")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task TestOperatorCustomTypeOverload_10() + { + var markup = +@"class C +{ + static void M() { C c; c >>>=$$ c; } + static C operator>>>(C a, C b) { return a; } +}"; + + await TestAsync(markup, + MainDescription("C C.operator >>>(C a, C b)")); + } + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] public async Task TestFieldInMethodMinimal() { diff --git a/src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs b/src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs index f9b2bb79947a6..48a9498bb2836 100644 --- a/src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs +++ b/src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs @@ -198,6 +198,13 @@ await TestInMethodAsync( @"var q = x >> [|Goo()|];", "global::System.Int32", mode); } + [Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)] + public async Task TestBinaryOperator3(TestMode mode) + { + await TestInMethodAsync( +@"var q = x >>> [|Goo()|];", "global::System.Int32", mode); + } + [Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.TypeInferenceService)] public async Task TestAssignmentOperator3(TestMode mode) { diff --git a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs index 8e30c8285a1a0..c2a76d198217c 100644 --- a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs +++ b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.CSharp.cs @@ -555,6 +555,51 @@ public R() await GenerateAndVerifySourceAsync(metadataSource, symbolName, LanguageNames.CSharp, expected: expected, signaturesOnly: signaturesOnly); } + + [Theory, CombinatorialData, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] + public async Task UnsignedRightShift(bool signaturesOnly) + { + var metadataSource = "public class C { public static C operator >>>(C x, int y) => x; }"; + var symbolName = "C.op_UnsignedRightShift"; + + var expected = signaturesOnly switch + { + true => $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// {CodeAnalysisResources.InMemoryAssembly} +#endregion + +public class C +{{ + public C(); + + public static C operator [|>>>|](C x, int y); +}}", + false => $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// {CodeAnalysisResources.InMemoryAssembly} +// Decompiled with ICSharpCode.Decompiler {ICSharpCodeDecompilerVersion} +#endregion + +using System.Runtime.CompilerServices; + +public class C +{{ + [SpecialName] + public static C [|op_UnsignedRightShift|](C x, int y) + {{ + return x; + }} +}} +#if false // {CSharpEditorResources.Decompilation_log} +{string.Format(CSharpEditorResources._0_items_in_cache, 6)} +------------------ +{string.Format(CSharpEditorResources.Resolve_0, "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")} +{string.Format(CSharpEditorResources.Found_single_assembly_0, "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")} +{string.Format(CSharpEditorResources.Load_from_0, "mscorlib.v4_6_1038_0.dll")} +#endif", + }; + + await GenerateAndVerifySourceAsync(metadataSource, symbolName, LanguageNames.CSharp, expected: expected, signaturesOnly: signaturesOnly, languageVersion: "Preview", metadataLanguageVersion: "Preview"); + } } } } diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OperatorSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OperatorSymbols.vb index 847bd34707da8..7c5d400e11490 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OperatorSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OperatorSymbols.vb @@ -68,7 +68,7 @@ class A End Function - Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverload(kind As TestKind, host As TestHost) As Task + Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverload_01(kind As TestKind, host As TestHost) As Task Dim input = @@ -88,7 +88,27 @@ class A End Function - Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverloadFromDefinition(kind As TestKind, host As TestHost) As Task + Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverload_02(kind As TestKind, host As TestHost) As Task + Dim input = + + + +class A +{ + void Goo() + { + var x = new A() [|$$>>>|] 1; + } + public static A operator {|Definition:>>>|}(A a, int b) { return a; } +} + + + + Await TestAPIAndFeature(input, kind, host) + End Function + + + Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverloadFromDefinition_01(kind As TestKind, host As TestHost) As Task Dim input = @@ -107,6 +127,26 @@ class A Await TestAPIAndFeature(input, kind, host) End Function + + Public Async Function TestCSharpFindReferencesOnBinaryOperatorOverloadFromDefinition_02(kind As TestKind, host As TestHost) As Task + Dim input = + + + +class A +{ + void Goo() + { + var x = new A() [|>>>|] 1; + } + public static A operator {|Definition:$$>>>|}(A a, int b) { return a; } +} + + + + Await TestAPIAndFeature(input, kind, host) + End Function + Public Async Function TestCSharpFindReferencesOnEqualsOperator(kind As TestKind, host As TestHost) As Task @@ -435,7 +475,7 @@ end class - Public Async Function TestOperatorReferenceInGlobalSuppression(kind As TestKind, host As TestHost) As Task + Public Async Function TestOperatorReferenceInGlobalSuppression_01(kind As TestKind, host As TestHost) As Task Dim input = @@ -457,6 +497,29 @@ class A Await TestAPIAndFeature(input, kind, host) End Function + + Public Async Function TestOperatorReferenceInGlobalSuppression_02(kind As TestKind, host As TestHost) As Task + Dim input = + + + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Category", "RuleId", Scope = "member", Target = "~M:A.[|op_UnsignedRightShift|](A,System.Int32)~A")] + +class A +{ + void Goo() + { + var x = new A() [|$$>>>|] 1; + } + + public static A operator {|Definition:>>>|}(A a, int b) { return a; } +} + + + + Await TestAPIAndFeature(input, kind, host) + End Function + Public Async Function TestCSharpFindOperatorUsedInSourceGeneratedDocument(kind As TestKind, host As TestHost) As Task Dim input = @@ -619,7 +682,7 @@ class C5_2 : I5 End Function - Public Async Function TestCSharpStaticAbstractOperatorInInterface(kind As TestKind, host As TestHost) As Task + Public Async Function TestCSharpStaticAbstractOperatorInInterface_01(kind As TestKind, host As TestHost) As Task Dim input = @@ -645,6 +708,33 @@ class C4_2 : I4 Await TestAPIAndFeature(input, kind, host) End Function + + Public Async Function TestCSharpStaticAbstractOperatorInInterface_02(kind As TestKind, host As TestHost) As Task + Dim input = + + + + where T : I4 +{ + abstract static int operator {|Definition:>>>$$|}(T x, int y); +} + +class C4_1 : I4 +{ + public static int operator {|Definition:>>>|}(C4_1 x, int y) => default; +} + +class C4_2 : I4 +{ + static int I4.operator {|Definition:>>>|}(C4_2 x, int y) => default; +}]]> + + + + Await TestAPIAndFeature(input, kind, host) + End Function + Public Async Function TestCSharpStaticAbstractOperatorViaApi1(host As TestHost) As Task Dim input = @@ -673,7 +763,7 @@ class C4_2 : I4 End Function - Public Async Function TestCSharpStaticAbstractOperatorViaApi2(host As TestHost) As Task + Public Async Function TestCSharpStaticAbstractOperatorViaApi2_01(host As TestHost) As Task Dim input = @@ -700,7 +790,34 @@ class C4_2 : I4 End Function - Public Async Function TestCSharpStaticAbstractOperatorViaFeature1(host As TestHost) As Task + Public Async Function TestCSharpStaticAbstractOperatorViaApi2_02(host As TestHost) As Task + Dim input = + + + + where T : I4 +{ + abstract static int operator {|Definition:>>>|}(T x, int y); +} + +class C4_1 : I4 +{ + public static int operator {|Definition:>>>|}(C4_1 x, int y) => default; +} + +class C4_2 : I4 +{ + static int I4.operator {|Definition:$$>>>|}(C4_2 x, int y) => default; +}]]> + + + + Await TestAPI(input, host) + End Function + + + Public Async Function TestCSharpStaticAbstractOperatorViaFeature1_01(host As TestHost) As Task Dim input = @@ -727,7 +844,34 @@ class C4_2 : I4 End Function - Public Async Function TestCSharpStaticAbstractOperatorViaFeature2(host As TestHost) As Task + Public Async Function TestCSharpStaticAbstractOperatorViaFeature1_02(host As TestHost) As Task + Dim input = + + + + where T : I4 +{ + abstract static int operator {|Definition:>>>|}(T x, int y); +} + +class C4_1 : I4 +{ + public static int operator {|Definition:$$>>>|}(C4_1 x, int y) => default; +} + +class C4_2 : I4 +{ + static int I4.operator >>>(C4_2 x, int y) => default; +}]]> + + + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestCSharpStaticAbstractOperatorViaFeature2_01(host As TestHost) As Task Dim input = @@ -749,6 +893,33 @@ class C4_2 : I4 }]]> + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestCSharpStaticAbstractOperatorViaFeature2_02(host As TestHost) As Task + Dim input = + + + + where T : I4 +{ + abstract static int operator {|Definition:>>>|}(T x, int y); +} + +class C4_1 : I4 +{ + public static int operator >>>(C4_1 x, int y) => default; +} + +class C4_2 : I4 +{ + static int I4.operator {|Definition:$$>>>|}(C4_2 x, int y) => default; +}]]> + + Await TestStreamingFeature(input, host) End Function diff --git a/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb b/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb index 8b48e6fc1831e..a415d9c7f58f0 100644 --- a/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb +++ b/src/EditorFeatures/Test2/GoToImplementation/GoToImplementationTests.vb @@ -702,5 +702,35 @@ interface I { void $$M(); } Await TestAsync(workspace, host) End Function + + + Public Async Function TestUnsignedRightShiftImplementation_01(host As TestHost) As Task + Dim workspace = + + + +class C : I<C> { public static C operator [|>>>|](C x, int y) { return x; } } +interface I<T> { static abstract T operator $$>>>(T x, int y); } + + + + + Await TestAsync(workspace, host) + End Function + + + Public Async Function TestUnsignedRightShiftImplementation_02(host As TestHost) As Task + Dim workspace = + + + +class C : I<C> { static C I<C>.operator [|>>>|](C x, int y) { return x; } } +interface I<T> { static abstract T operator $$>>>(T x, int y); } + + + + + Await TestAsync(workspace, host) + End Function End Class End Namespace diff --git a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Operators.cs b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Operators.cs index ec19d014d32ab..9a187c382904e 100644 --- a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Operators.cs +++ b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Operators.cs @@ -39,7 +39,9 @@ private static FormattedClassification New(string text) public static FormattedClassification GreaterThan { get; } = New(">"); public static FormattedClassification GreaterThanEquals { get; } = New(">="); public static FormattedClassification GreaterThanGreaterThan { get; } = New(">>"); + public static FormattedClassification GreaterThanGreaterThanGreaterThan { get; } = New(">>>"); public static FormattedClassification GreaterThanGreaterThanEquals { get; } = New(">>="); + public static FormattedClassification GreaterThanGreaterThanGreaterThanEquals { get; } = New(">>>="); public static FormattedClassification LessThan { get; } = New("<"); public static FormattedClassification LessThanEquals { get; } = New("<="); public static FormattedClassification LessThanGreaterThan { get; } = New("<>"); diff --git a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.OverloadedOperators.cs b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.OverloadedOperators.cs index ffa1b94956a08..12d8b51c5e8a4 100644 --- a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.OverloadedOperators.cs +++ b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.OverloadedOperators.cs @@ -32,7 +32,9 @@ private static FormattedClassification New(string text) public static FormattedClassification GreaterThan { get; } = New(">"); public static FormattedClassification GreaterThanEquals { get; } = New(">="); public static FormattedClassification GreaterThanGreaterThan { get; } = New(">>"); + public static FormattedClassification GreaterThanGreaterThanGreaterThan { get; } = New(">>>"); public static FormattedClassification GreaterThanGreaterThanEquals { get; } = New(">>="); + public static FormattedClassification GreaterThanGreaterThanGreaterThanEquals { get; } = New(">>>="); public static FormattedClassification LessThan { get; } = New("<"); public static FormattedClassification LessThanEquals { get; } = New("<="); public static FormattedClassification LessThanGreaterThan { get; } = New("<>"); diff --git a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Punctuation.cs b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Punctuation.cs index f7c7ab259ef17..43bffcb16dd56 100644 --- a/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Punctuation.cs +++ b/src/EditorFeatures/TestUtilities/Classification/FormattedClassifications.Punctuation.cs @@ -29,6 +29,7 @@ private static FormattedClassification New(string text) public static FormattedClassification Semicolon { get; } = New(";"); public static FormattedClassification Colon { get; } = New(":"); public static FormattedClassification DotDot { get; } = New(".."); + public static FormattedClassification ExclamationExclamation { get; } = New("!!"); [DebuggerStepThrough] public static FormattedClassification Text(string text) => New(text); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs index 9c5daf79c62e9..d2dd526a52be7 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs @@ -61,6 +61,7 @@ private enum OperatorPosition (WellKnownMemberNames.ExclusiveOrOperatorName, OperatorPosition.Infix), (WellKnownMemberNames.LeftShiftOperatorName, OperatorPosition.Infix), (WellKnownMemberNames.RightShiftOperatorName, OperatorPosition.Infix), + (WellKnownMemberNames.UnsignedRightShiftOperatorName, OperatorPosition.Infix), (WellKnownMemberNames.OnesComplementOperatorName, OperatorPosition.Prefix)); /// diff --git a/src/VisualStudio/CSharp/Test/F1Help/F1HelpTests.cs b/src/VisualStudio/CSharp/Test/F1Help/F1HelpTests.cs index e2b8609e5555d..4fa4de62fa422 100644 --- a/src/VisualStudio/CSharp/Test/F1Help/F1HelpTests.cs +++ b/src/VisualStudio/CSharp/Test/F1Help/F1HelpTests.cs @@ -328,6 +328,7 @@ void goo(T t, U u, V v) [InlineData("<=")] [InlineData("<<")] [InlineData(">>")] + [InlineData(">>>")] [InlineData("*")] [InlineData("%")] [InlineData("&&")] @@ -359,6 +360,7 @@ void goo() [InlineData("^=")] [InlineData("<<=")] [InlineData(">>=")] + [InlineData(">>>=")] public async Task TestCompoundOperator(string operatorText) { await TestAsync( diff --git a/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs b/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs index dc8c1553c22dc..2a257cdc16f8a 100644 --- a/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs +++ b/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs @@ -445,7 +445,9 @@ private static bool IsOperator(this SyntaxKind kind) case SyntaxKind.LessThanLessThanEqualsToken: case SyntaxKind.GreaterThanEqualsToken: case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: case SyntaxKind.SlashEqualsToken: case SyntaxKind.AsteriskEqualsToken: case SyntaxKind.BarEqualsToken: diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpDeclarationComparer.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpDeclarationComparer.cs index f755b96f241e4..826285ca8292e 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpDeclarationComparer.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpDeclarationComparer.cs @@ -57,6 +57,7 @@ internal class CSharpDeclarationComparer : IComparer { SyntaxKind.GreaterThanEqualsToken, 19 }, { SyntaxKind.TrueKeyword, 20 }, { SyntaxKind.FalseKeyword, 21 }, + { SyntaxKind.GreaterThanGreaterThanGreaterThanToken, 22 }, }; public static readonly CSharpDeclarationComparer WithNamesInstance = new(includeName: true); diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index e7c63ae6fd375..4341cdafc55c1 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -292,6 +292,7 @@ private static SyntaxKind GetTokenKind(OperatorKind kind) OperatorKind.Multiply => SyntaxKind.AsteriskToken, OperatorKind.OnesComplement => SyntaxKind.TildeToken, OperatorKind.RightShift => SyntaxKind.GreaterThanGreaterThanToken, + OperatorKind.UnsignedRightShift => SyntaxKind.GreaterThanGreaterThanGreaterThanToken, OperatorKind.Subtraction => SyntaxKind.MinusToken, OperatorKind.True => SyntaxKind.TrueKeyword, OperatorKind.UnaryNegation => SyntaxKind.MinusToken, diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs index 125d13e82fd86..9967a73c78dc0 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs @@ -81,6 +81,7 @@ private static bool IsLiftableOperator(IMethodSymbol symbol) case WellKnownMemberNames.ExclusiveOrOperatorName: case WellKnownMemberNames.LeftShiftOperatorName: case WellKnownMemberNames.RightShiftOperatorName: + case WellKnownMemberNames.UnsignedRightShiftOperatorName: return symbol.Parameters.Length == 2 && symbol.ReturnType.IsValueType; // Equality + Relational diff --git a/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs index 5b60a15647e83..1d8dd06a567fc 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs @@ -923,6 +923,10 @@ public void TestOperatorDeclaration() Generator.OperatorDeclaration(OperatorKind.RightShift, parameters, returnType), "bool operator >>(global::System.Int32 p0, global::System.String p1)\r\n{\r\n}"); + VerifySyntax( + Generator.OperatorDeclaration(OperatorKind.UnsignedRightShift, parameters, returnType), + "bool operator >>>(global::System.Int32 p0, global::System.String p1)\r\n{\r\n}"); + VerifySyntax( Generator.OperatorDeclaration(OperatorKind.Subtraction, parameters, returnType), "bool operator -(global::System.Int32 p0, global::System.String p1)\r\n{\r\n}"); diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOperatorKind.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOperatorKind.cs index e8307df440c70..48e61c2af3a7e 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOperatorKind.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOperatorKind.cs @@ -33,6 +33,7 @@ internal enum CodeGenerationOperatorKind Subtraction = 24, True = 25, UnaryPlus = 26, - UnaryNegation = 27 + UnaryNegation = 27, + UnsignedRightShift = 28, } } diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationOperatorSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationOperatorSymbol.cs index 2e99829026b52..7b82a6a656964 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationOperatorSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationOperatorSymbol.cs @@ -62,6 +62,7 @@ public static int GetParameterCount(CodeGenerationOperatorKind operatorKind) case CodeGenerationOperatorKind.Modulus: case CodeGenerationOperatorKind.Multiplication: case CodeGenerationOperatorKind.RightShift: + case CodeGenerationOperatorKind.UnsignedRightShift: case CodeGenerationOperatorKind.Subtraction: return 2; case CodeGenerationOperatorKind.Increment: @@ -105,6 +106,7 @@ private static string GetMetadataName(CodeGenerationOperatorKind operatorKind) CodeGenerationOperatorKind.Multiplication => WellKnownMemberNames.MultiplyOperatorName, CodeGenerationOperatorKind.OnesComplement => WellKnownMemberNames.OnesComplementOperatorName, CodeGenerationOperatorKind.RightShift => WellKnownMemberNames.RightShiftOperatorName, + CodeGenerationOperatorKind.UnsignedRightShift => WellKnownMemberNames.UnsignedRightShiftOperatorName, CodeGenerationOperatorKind.Subtraction => WellKnownMemberNames.SubtractionOperatorName, CodeGenerationOperatorKind.True => WellKnownMemberNames.TrueOperatorName, CodeGenerationOperatorKind.UnaryPlus => WellKnownMemberNames.UnaryPlusOperatorName, diff --git a/src/Workspaces/Core/Portable/Editing/OperatorKind.cs b/src/Workspaces/Core/Portable/Editing/OperatorKind.cs index caf1c1c26d987..6d6f1a360ce8c 100644 --- a/src/Workspaces/Core/Portable/Editing/OperatorKind.cs +++ b/src/Workspaces/Core/Portable/Editing/OperatorKind.cs @@ -137,5 +137,10 @@ public enum OperatorKind /// The name assigned to the UnaryPlus operator. /// UnaryPlus, + + /// + /// The name assigned to the UnsignedRightShift operator. + /// + UnsignedRightShift, } } diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs index 7d5663897dfb3..6a7f130a0d5c0 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs @@ -247,6 +247,7 @@ private static OperatorKind GetOperatorKind(IMethodSymbol method) WellKnownMemberNames.MultiplyOperatorName => OperatorKind.Multiply, WellKnownMemberNames.OnesComplementOperatorName => OperatorKind.OnesComplement, WellKnownMemberNames.RightShiftOperatorName => OperatorKind.RightShift, + WellKnownMemberNames.UnsignedRightShiftOperatorName => OperatorKind.UnsignedRightShift, WellKnownMemberNames.SubtractionOperatorName => OperatorKind.Subtraction, WellKnownMemberNames.TrueOperatorName => OperatorKind.True, WellKnownMemberNames.UnaryNegationOperatorName => OperatorKind.UnaryNegation, diff --git a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt index 2bada5d42e0b8..c7fb6cb5bd09d 100644 --- a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt @@ -21,3 +21,5 @@ Microsoft.CodeAnalysis.Rename.DocumentRenameOptions.RenameMatchingTypeInStrings. Microsoft.CodeAnalysis.Rename.DocumentRenameOptions.RenameMatchingTypeInComments.init -> void static Microsoft.CodeAnalysis.Rename.Renamer.RenameDocumentAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Rename.DocumentRenameOptions options, string newDocumentName, System.Collections.Generic.IReadOnlyList newDocumentFolders = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task static Microsoft.CodeAnalysis.Rename.Renamer.RenameSymbolAsync(Microsoft.CodeAnalysis.Solution solution, Microsoft.CodeAnalysis.ISymbol symbol, Microsoft.CodeAnalysis.Rename.SymbolRenameOptions options, string newName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task + +Microsoft.CodeAnalysis.Editing.OperatorKind.UnsignedRightShift = 26 -> Microsoft.CodeAnalysis.Editing.OperatorKind \ No newline at end of file diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs index e68ab8512438f..7bda19e61764b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs @@ -432,6 +432,10 @@ private static PredefinedOperator GetPredefinedOperator(SyntaxToken token) case SyntaxKind.GreaterThanGreaterThanToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: return PredefinedOperator.RightShift; + + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + return PredefinedOperator.UnsignedRightShift; } return PredefinedOperator.None; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/IMethodSymbolExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/IMethodSymbolExtensions.cs index 923f603901323..985ca667263ab 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/IMethodSymbolExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/IMethodSymbolExtensions.cs @@ -93,6 +93,7 @@ public static PredefinedOperator GetPredefinedOperator(this IMethodSymbol symbol "op_Modulus" => PredefinedOperator.Modulus, "op_Multiply" => PredefinedOperator.Multiplication, "op_RightShift" => PredefinedOperator.RightShift, + "op_UnsignedRightShift" => PredefinedOperator.UnsignedRightShift, "op_Subtraction" or "op_UnaryNegation" => PredefinedOperator.Subtraction, _ => PredefinedOperator.None, }; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/PredefinedOperator.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/PredefinedOperator.cs index 815a0497b83a6..9467f535d36a2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/PredefinedOperator.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/PredefinedOperator.cs @@ -30,5 +30,6 @@ internal enum PredefinedOperator Multiplication = 1 << 20, RightShift = 1 << 21, Subtraction = 1 << 22, + UnsignedRightShift = 1 << 23, } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs index f765d3f284a83..76cbdc72da5e1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs @@ -2146,6 +2146,7 @@ public static bool IsExpressionContext( // q |= | // q <<= | // q >>= | + // q >>>= | // q ??= | if (token.IsKind(SyntaxKind.EqualsToken) || token.IsKind(SyntaxKind.MinusEqualsToken) || @@ -2159,6 +2160,7 @@ public static bool IsExpressionContext( token.IsKind(SyntaxKind.PercentEqualsToken) || token.IsKind(SyntaxKind.LessThanLessThanEqualsToken) || token.IsKind(SyntaxKind.GreaterThanGreaterThanEqualsToken) || + token.IsKind(SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken) || token.IsKind(SyntaxKind.QuestionQuestionEqualsToken)) { return true; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs index a5e6ff3cf0277..732c0cbf9873f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs @@ -937,12 +937,14 @@ private IEnumerable InferTypeInBinaryOrAssignmentExpression(E { case SyntaxKind.LessThanLessThanToken: case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: case SyntaxKind.LessThanLessThanEqualsToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: if (onRightOfToken) { - // x << Goo(), x >> Goo(), x <<= Goo(), x >>= Goo() + // x << Goo(), x >> Goo(), x >>> Goo(), x <<= Goo(), x >>= Goo(), x >>>= Goo() return CreateResult(this.Compilation.GetSpecialType(SpecialType.System_Int32)); } @@ -1037,8 +1039,10 @@ SyntaxKind.CaretToken or case SyntaxKind.PercentEqualsToken: case SyntaxKind.LessThanLessThanToken: case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: case SyntaxKind.LessThanLessThanEqualsToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return CreateResult(this.Compilation.GetSpecialType(SpecialType.System_Int32)); case SyntaxKind.BarEqualsToken: