// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Editor.Implementation.Classification; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Editor.UnitTests; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Tagging; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; using static Microsoft.CodeAnalysis.Editor.UnitTests.Classification.FormattedClassifications; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification { public partial class SemanticClassifierTests : AbstractCSharpClassifierTests { protected override Task> GetClassificationSpansAsync(string code, TextSpan span, ParseOptions options) { using (var workspace = TestWorkspace.CreateCSharp(code, options)) { var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); return GetSemanticClassificationsAsync(document, span); } } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericClassDeclaration() { await TestInMethodAsync( className: "Class", methodName: "M", code: @"new Class();", expected: Class("Class")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task RefVar() { await TestInMethodAsync( code: @"int i = 0; ref var x = ref i;", expected: Classifications(Keyword("var"), Local("i"))); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task UsingAlias1() { await TestAsync( @"using M = System.Math;", Class("M"), Namespace("System"), Class("Math"), Static("Math")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsTypeArgument() { await TestInMethodAsync( className: "Class", methodName: "M", code: @"new Class();", expected: Classifications(Class("Class"), Keyword("dynamic"))); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task UsingTypeAliases() { var code = @"using Alias = Test; class Test { void M() { Test a = new Test(); Alias b = new Alias(); } }"; await TestAsync(code, code, Class("Alias"), Class("Test"), Class("Test"), Class("Test"), Class("Alias"), Class("Alias")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicTypeAlias() { await TestAsync( @"using dynamic = System.EventArgs; class C { dynamic d = new dynamic(); }", Class("dynamic"), Namespace("System"), Class("EventArgs"), Class("dynamic"), Class("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsDelegateName() { await TestAsync( @"delegate void dynamic(); class C { void M() { dynamic d; } }", Delegate("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsInterfaceName() { await TestAsync( @"interface dynamic { } class C { dynamic d; }", Interface("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsEnumName() { await TestAsync( @"enum dynamic { } class C { dynamic d; }", Enum("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsClassName() { await TestAsync( @"class dynamic { } class C { dynamic d; }", Class("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsClassNameAndLocalVariableName() { await TestAsync( @"class dynamic { dynamic() { dynamic dynamic; } }", Class("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsStructName() { await TestAsync( @"struct dynamic { } class C { dynamic d; }", Struct("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsGenericClassName() { await TestAsync( @"class dynamic { } class C { dynamic d; }", Class("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsGenericClassNameButOtherArity() { await TestAsync( @"class dynamic { } class C { dynamic d; }", Keyword("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsUndefinedGenericType() { await TestAsync( @"class dynamic { } class C { dynamic d; }"); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsExternAlias() { await TestAsync( @"extern alias dynamic; class C { dynamic::Goo a; }", Namespace("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericClassNameButOtherArity() { await TestAsync( @"class A { } class C { A d; }", Class("A")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericTypeParameter() { await TestAsync( @"class C { void M() { default(T) } }", TypeParameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericMethodTypeParameter() { await TestAsync( @"class C { T M(T t) { return default(T); } }", TypeParameter("T"), TypeParameter("T"), TypeParameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericMethodTypeParameterInLocalVariableDeclaration() { await TestAsync( @"class C { void M() { T t; } }", TypeParameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ParameterOfLambda1() { await TestAsync( @"class C { C() { Action a = (C p) => { }; } }", Class("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ParameterOfAnonymousMethod() { await TestAsync( @"class C { C() { Action a = delegate (C p) { }; } }", Class("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GenericTypeParameterAfterWhere() { await TestAsync( @"class C where A : B { }", TypeParameter("A"), TypeParameter("B")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task BaseClass() { await TestAsync( @"class C { } class C2 : C { }", Class("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task BaseInterfaceOnInterface() { await TestAsync( @"interface T { } interface T2 : T { }", Interface("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task BaseInterfaceOnClass() { await TestAsync( @"interface T { } class T2 : T { }", Interface("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InterfaceColorColor() { await TestAsync( @"interface T { } class T2 : T { T T; }", Interface("T"), Interface("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DelegateColorColor() { await TestAsync( @"delegate void T(); class T2 { T T; }", Delegate("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DelegateReturnsItself() { await TestAsync( @"delegate T T(); class C { T T(T t); }", Delegate("T"), Delegate("T"), Delegate("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task StructColorColor() { await TestAsync( @"struct T { T T; }", Struct("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task EnumColorColor() { await TestAsync( @"enum T { T, T } class C { T T; }", Enum("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsGenericTypeParameter() { await TestAsync( @"class C { dynamic d; }", TypeParameter("dynamic")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DynamicAsGenericFieldName() { await TestAsync( @"class A { T dynamic; }", TypeParameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task PropertySameNameAsClass() { await TestAsync( @"class N { N N { get; set; } void M() { N n = N; N = n; N = N; } }", Class("N"), Class("N"), Property("N"), Property("N"), Local("n"), Property("N"), Property("N")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AttributeWithoutAttributeSuffix() { await TestAsync( @"using System; [Obsolete] class C { }", Namespace("System"), Class("Obsolete")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AttributeOnNonExistingMember() { await TestAsync( @"using System; class A { [Obsolete] }", Namespace("System"), Class("Obsolete")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AttributeWithoutAttributeSuffixOnAssembly() { await TestAsync( @"using System; [assembly: My] class MyAttribute : Attribute { }", Namespace("System"), Class("My"), Class("Attribute")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AttributeViaNestedClassOrDerivedClass() { await TestAsync( @"using System; [Base.My] [Derived.My] class Base { public class MyAttribute : Attribute { } } class Derived : Base { }", Namespace("System"), Class("Base"), Class("My"), Class("Derived"), Class("My"), Class("Attribute"), Class("Base")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NamedAndOptional() { await TestAsync( @"class C { void B(C C = null) { } void M() { B(C: null); } }", Class("C"), Method("B"), Parameter("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task PartiallyWrittenGenericName1() { await TestInMethodAsync( className: "Class", methodName: "M", code: @"Class", methodName: "M", code: @"Class /// Instance field should be preferred to type /// §7.5.4.1 /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor4() { await TestAsync( @"class T { T T; void M() { T.T = null; } }", Class("T"), Field("T"), Field("T")); } /// /// Type should be preferred to a static field /// §7.5.4.1 /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor5() { await TestAsync( @"class T { static T T; void M() { T.T = null; } }", Class("T"), Class("T"), Field("T"), Static("T")); } /// /// Needs to prefer the local /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor6() { await TestAsync( @"class T { int field; void M() { T T = new T(); T.field = 0; } }", Class("T"), Class("T"), Local("T"), Field("field")); } /// /// Needs to prefer the type /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor7() { await TestAsync( @"class T { static int field; void M() { T T = new T(); T.field = 0; } }", Class("T"), Class("T"), Class("T"), Field("field"), Static("field")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor8() { await TestAsync( @"class T { void M(T T) { } void M2() { T T = new T(); M(T); } }", Class("T"), Class("T"), Class("T"), Method("M"), Local("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor9() { await TestAsync( @"class T { T M(T T) { T = new T(); return T; } }", Class("T"), Class("T"), Parameter("T"), Class("T"), Parameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor10() { // note: 'var' now binds to the type of the local. await TestAsync( @"class T { void M() { var T = new object(); T temp = T as T; } }", Keyword("var"), Class("T"), Local("T"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor11() { await TestAsync( @"class T { void M() { var T = new object(); bool b = T is T; } }", Keyword("var"), Local("T"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor12() { await TestAsync( @"class T { void M() { T T = new T(); var t = typeof(T); } }", Class("T"), Class("T"), Keyword("var"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor13() { await TestAsync( @"class T { void M() { T T = new T(); T t = default(T); } }", Class("T"), Class("T"), Class("T"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ColorColor14() { await TestAsync( @"class T { void M() { object T = new T(); T t = (T)T; } }", Class("T"), Class("T"), Class("T"), Local("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NamespaceNameSameAsTypeName1() { await TestAsync( @"namespace T { class T { void M() { T.T T = new T.T(); } } }", Namespace("T"), Class("T"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NamespaceNameSameAsTypeNameWithGlobal() { await TestAsync( @"namespace T { class T { void M() { global::T.T T = new global::T.T(); } } }", Namespace("T"), Namespace("T"), Class("T"), Namespace("T"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AmbiguityTypeAsGenericMethodArgumentVsLocal() { await TestAsync( @"class T { void M() { T T; M(); } }", TypeParameter("T"), Method("M"), TypeParameter("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AmbiguityTypeAsGenericArgumentVsLocal() { await TestAsync( @"class T { class G { } void M() { T T; G g = new G(); } }", Class("T"), Class("G"), Class("T"), Class("G"), Class("T")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AmbiguityTypeAsGenericArgumentVsField() { await TestAsync( @"class T { class H { public static int f; } void M() { T T; int i = H.f; } }", Class("T"), Class("H"), Class("T"), Field("f"), Static("f")); } /// /// §7.5.4.2 /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task GrammarAmbiguity_7_5_4_2() { await TestAsync( @"class M { void m() { int A = 2; int B = 3; F(G(7)); } void F(bool b) { } bool G(int a) { return true; } class A { } class B { } }", Method("F"), Method("G"), Class("A"), Class("B")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AnonymousTypePropertyName() { await TestAsync( @"using System; class C { void M() { var x = new { String = "" }; } }", Namespace("System"), Keyword("var"), Property("String")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task YieldAsATypeName() { await TestAsync( @"using System.Collections.Generic; class yield { IEnumerable M() { yield yield = new yield(); yield return yield; } }", Namespace("System"), Namespace("Collections"), Namespace("Generic"), Interface("IEnumerable"), Class("yield"), Class("yield"), Class("yield"), Local("yield")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TypeNameDottedNames() { await TestAsync( @"class C { class Nested { } C.Nested f; }", Class("C"), Class("Nested")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task BindingTypeNameFromBCLViaGlobalAlias() { await TestAsync( @"using System; class C { global::System.String f; }", Namespace("System"), Namespace("System"), Class("String")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task BindingTypeNames() { string code = @"using System; using Str = System.String; class C { class Nested { } Str UsingAlias; Nested NestedClass; String BCL; C ClassDeclaration; C.Nested FCNested; global::C FCN; global::System.String FCNBCL; global::Str GlobalUsingAlias; }"; await TestAsync(code, code, Options.Regular, Namespace("System"), Class("Str"), Namespace("System"), Class("String"), Class("Str"), Class("Nested"), Class("String"), Class("C"), Class("C"), Class("Nested"), Class("C"), Namespace("System"), Class("String")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task Constructors() { await TestAsync( @"struct S { public int i; public S(int i) { this.i = i; } } class C { public C() { var s = new S(1); var c = new C(); } }", Field("i"), Parameter("i"), Keyword("var"), Struct("S"), Keyword("var"), Class("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TypesOfClassMembers() { await TestAsync( @"class Type { public Type() { } static Type() { } ~Type() { } Type Property { get; set; } Type Method() { } event Type Event; Type this[Type index] { get; set; } Type field; const Type constant = null; static operator Type(Type other) { } static operator +(Type other) { } static operator int(Type other) { } static operator Type(int other) { } }", Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type"), Class("Type")); } /// /// NAQ = Namespace Alias Qualifier (?) /// [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQTypeNameCtor() { await TestInMethodAsync( @"System.IO.BufferedStream b = new global::System.IO.BufferedStream();", Namespace("System"), Namespace("IO"), Class("BufferedStream"), Namespace("System"), Namespace("IO"), Class("BufferedStream")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQEnum() { await TestAsync( @"class C { void M() { global::System.IO.DriveType d; } }", Namespace("System"), Namespace("IO"), Enum("DriveType")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQDelegate() { await TestAsync( @"class C { void M() { global::System.AssemblyLoadEventHandler d; } }", Namespace("System"), Delegate("AssemblyLoadEventHandler")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQTypeNameMethodCall() { await TestInMethodAsync(@"global::System.String.Clone("");", Namespace("System"), Class("String")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQEventSubscription() { await TestInMethodAsync( @"global::System.AppDomain.CurrentDomain.AssemblyLoad += delegate (object sender, System.AssemblyLoadEventArgs args) {};", Namespace("System"), Class("AppDomain"), Property("CurrentDomain"), Static("CurrentDomain"), Event("AssemblyLoad"), Namespace("System"), Class("AssemblyLoadEventArgs")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AnonymousDelegateParameterType() { await TestAsync( @"class C { void M() { System.Action a = delegate (System.EventArgs e) { }; } }", Namespace("System"), Delegate("Action"), Namespace("System"), Class("EventArgs"), Namespace("System"), Class("EventArgs")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQCtor() { await TestInMethodAsync( @"global::System.Collections.DictionaryEntry de = new global::System.Collections.DictionaryEntry();", Namespace("System"), Namespace("Collections"), Struct("DictionaryEntry"), Namespace("System"), Namespace("Collections"), Struct("DictionaryEntry")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQSameFileClass() { var code = @"class C { static void M() { global::C.M(); } }"; await TestAsync(code, ParseOptions(Options.Regular), Class("C"), Static("M"), Method("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InteractiveNAQSameFileClass() { var code = @"class C { static void M() { global::Script.C.M(); } }"; await TestAsync(code, ParseOptions(Options.Script), Class("Script"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQSameFileClassWithNamespace() { await TestAsync( @"using @global = N; namespace N { class C { static void M() { global::N.C.M(); } } }", Namespace("@global"), Namespace("N"), Namespace("N"), Namespace("N"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQSameFileClassWithNamespaceAndEscapedKeyword() { await TestAsync( @"using @global = N; namespace N { class C { static void M() { @global.C.M(); } } }", Namespace("@global"), Namespace("N"), Namespace("N"), Namespace("@global"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQGlobalWarning() { await TestAsync( @"using global = N; namespace N { class C { static void M() { global.C.M(); } } }", Namespace("global"), Namespace("N"), Namespace("N"), Namespace("global"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedNAQNamespace() { await TestAsync( @"using goo = N; namespace N { class C { static void M() { goo.C.M(); } } }", Namespace("goo"), Namespace("N"), Namespace("N"), Namespace("goo"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedNAQNamespaceDoubleColon() { await TestAsync( @"using goo = N; namespace N { class C { static void M() { goo::C.M(); } } }", Namespace("goo"), Namespace("N"), Namespace("N"), Namespace("goo"), Class("C"), Method("M"), Static("M")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedNamespace1() { await TestAsync( @"class C { void M() { A.B.D d; } } namespace A { namespace B { class D { } } }", Namespace("A"), Namespace("B"), Class("D"), Namespace("A"), Namespace("B")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedNamespaceWithGlobal() { await TestAsync( @"class C { void M() { global::A.B.D d; } } namespace A { namespace B { class D { } } }", Namespace("A"), Namespace("B"), Class("D"), Namespace("A"), Namespace("B")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedNAQForClass() { await TestAsync( @"using IO = global::System.IO; class C { void M() { IO::BinaryReader b; } }", Namespace("IO"), Namespace("System"), Namespace("IO"), Namespace("IO"), Class("BinaryReader")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NAQUserDefinedTypes() { await TestAsync( @"using rabbit = MyNameSpace; class C { void M() { rabbit::MyClass2.method(); new rabbit::MyClass2().myEvent += null; rabbit::MyEnum Enum; rabbit::MyStruct strUct; object o2 = rabbit::MyClass2.MyProp; object o3 = rabbit::MyClass2.myField; rabbit::MyClass2.MyDelegate del = null; } } namespace MyNameSpace { namespace OtherNamespace { class A { } } public class MyClass2 { public static int myField; public delegate void MyDelegate(); public event MyDelegate myEvent; public static void method() { } public static int MyProp { get { return 0; } } } struct MyStruct { } enum MyEnum { } }", Namespace("rabbit"), Namespace("MyNameSpace"), Namespace("rabbit"), Class("MyClass2"), Static("method"), Method("method"), Namespace("rabbit"), Class("MyClass2"), Event("myEvent"), Namespace("rabbit"), Enum("MyEnum"), Namespace("rabbit"), Struct("MyStruct"), Namespace("rabbit"), Class("MyClass2"), Static("MyProp"), Property("MyProp"), Namespace("rabbit"), Class("MyClass2"), Static("myField"), Field("myField"), Namespace("rabbit"), Class("MyClass2"), Delegate("MyDelegate"), Namespace("MyNameSpace"), Namespace("OtherNamespace"), Delegate("MyDelegate")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task PreferPropertyOverNestedClass() { await TestAsync( @"class Outer { class A { public int B; } class B { void M() { A a = new A(); a.B = 10; } } }", Class("A"), Class("A"), Local("a"), Field("B")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TypeNameInsideNestedClass() { await TestAsync( @"using System; class Outer { class C { void M() { Console.WriteLine(); Console.WriteLine(); } } }", Namespace("System"), Class("Console"), Static("Console"), Method("WriteLine"), Static("WriteLine"), Class("Console"), Static("Console"), Method("WriteLine"), Static("WriteLine")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task StructEnumTypeNames() { await TestAsync( @"using System; class C { enum MyEnum { } struct MyStruct { } static void Main() { ConsoleColor c; Int32 i; } }", Namespace("System"), Enum("ConsoleColor"), Struct("Int32")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task PreferFieldOverClassWithSameName() { await TestAsync( @"class C { public int C; void M() { C = 0; } }", Field("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task AttributeBinding() { await TestAsync( @"using System; [Serializable] // Binds to System.SerializableAttribute; colorized class Serializable { } [SerializableAttribute] // Binds to System.SerializableAttribute; colorized class Serializable { } [NonSerialized] // Binds to global::NonSerializedAttribute; not colorized class NonSerializedAttribute { } [NonSerializedAttribute] // Binds to global::NonSerializedAttribute; not colorized class NonSerializedAttribute { } [Obsolete] // Binds to global::Obsolete; colorized class Obsolete : Attribute { } [ObsoleteAttribute] // Binds to global::Obsolete; colorized class ObsoleteAttribute : Attribute { }", Namespace("System"), Class("Serializable"), Class("SerializableAttribute"), Class("Obsolete"), Class("Attribute"), Class("ObsoleteAttribute"), Class("Attribute")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task ShouldNotClassifyNamespacesAsTypes() { await TestAsync( @"using System; namespace Roslyn.Compilers.Internal { }", Namespace("System"), Namespace("Roslyn"), Namespace("Compilers"), Namespace("Internal")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NestedTypeCantHaveSameNameAsParentType() { await TestAsync( @"class Program { class Program { } static void Main(Program p) { } Program.Program p2; }", Class("Program"), Class("Program")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NestedTypeCantHaveSameNameAsParentTypeWithGlobalNamespaceAlias() { var code = @"class Program { class Program { } static void Main(Program p) { } global::Program.Program p; }"; await TestAsync(code, ParseOptions(Options.Regular), Class("Program"), Class("Program"), Class("Program")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InteractiveNestedTypeCantHaveSameNameAsParentTypeWithGlobalNamespaceAlias() { var code = @"class Program { class Program { } static void Main(Program p) { } global::Script.Program.Program p; }"; await TestAsync(code, ParseOptions(Options.Script), Class("Program"), Class("Script"), Class("Program"), Class("Program")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task EnumFieldWithSameNameShouldBePreferredToType() { await TestAsync( @"enum E { E, F = E }", EnumMember("E")); } [WorkItem(541150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541150")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestGenericVarClassification() { await TestAsync( @"using System; static class Program { static void Main() { var x = 1; } } class var { }", Namespace("System"), Keyword("var")); } [WorkItem(541154, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541154")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestInaccessibleVarClassification() { await TestAsync( @"using System; class A { private class var { } } class B : A { static void Main() { var x = 1; } }", Namespace("System"), Class("A"), Keyword("var")); } [WorkItem(541154, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541154")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestVarNamedTypeClassification() { await TestAsync( @"class var { static void Main() { var x; } }", Class("var")); } [WorkItem(9513, "DevDiv_Projects/Roslyn")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task RegressionFor9513() { await TestAsync( @"enum E { A, B } class C { void M() { switch (new E()) { case E.A: goto case E.B; case E.B: goto default; default: goto case E.A; } } }", Enum("E"), Enum("E"), EnumMember("A"), Enum("E"), EnumMember("B"), Enum("E"), EnumMember("B"), Enum("E"), EnumMember("A")); } [WorkItem(542368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542368")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task RegressionFor9572() { await TestAsync( @"class A where T : A.I, A.I { public interface I { } }", TypeParameter("T"), Class("A"), TypeParameter("T"), TypeParameter("S"), Interface("I"), Class("A"), TypeParameter("T"), TypeParameter("T"), Interface("I")); } [WorkItem(542368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542368")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task RegressionFor9831() { await TestAsync(@"F : A", @"public class B { public class A { } } public class X : B { public class F : A { } }", Class("A")); } [WorkItem(542432, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542432")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestVar() { await TestAsync( @"class Program { class var { } static var GetVarT() { return null; } static void Main() { var x = GetVarT(); var y = new var(); } }", Class("var"), Keyword("var"), Method("GetVarT"), Static("GetVarT"), Keyword("var"), Class("var")); } [WorkItem(543123, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543123")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestVar2() { await TestAsync( @"class Program { void Main(string[] args) { foreach (var v in args) { } } }", Keyword("var"), Parameter("args")); } [WorkItem(542778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542778")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestDuplicateTypeParamWithConstraint() { await TestAsync(@"where U : IEnumerable", @"using System.Collections.Generic; class C { public void Goo(U arg) where S : T where U : IEnumerable { } }", TypeParameter("U"), Interface("IEnumerable")); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task OptimisticallyColorFromInDeclaration() { await TestInExpressionAsync("from ", Keyword("from")); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task OptimisticallyColorFromInAssignment() { await TestInMethodAsync( @"var q = 3; q = from", Keyword("var"), Local("q"), Keyword("from")); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DontColorThingsOtherThanFromInDeclaration() { await TestInExpressionAsync("fro "); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DontColorThingsOtherThanFromInAssignment() { await TestInMethodAsync( @"var q = 3; q = fro", Keyword("var"), Local("q")); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DontColorFromWhenBoundInDeclaration() { await TestInMethodAsync( @"var from = 3; var q = from", Keyword("var"), Keyword("var"), Local("from")); } [WorkItem(542685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task DontColorFromWhenBoundInAssignment() { await TestInMethodAsync( @"var q = 3; var from = 3; q = from", Keyword("var"), Keyword("var"), Local("q"), Local("from")); } [WorkItem(543404, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543404")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NewOfClassWithOnlyPrivateConstructor() { await TestAsync( @"class X { private X() { } } class Program { static void Main(string[] args) { new X(); } }", Class("X")); } [WorkItem(544179, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544179")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestNullableVersusConditionalAmbiguity1() { await TestAsync( @"class Program { static void Main(string[] args) { C1 ? } } public class C1 { }", Class("C1")); } [WorkItem(544179, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544179")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestPointerVersusMultiplyAmbiguity1() { await TestAsync( @"class Program { static void Main(string[] args) { C1 * } } public class C1 { }", Class("C1")); } [WorkItem(544302, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544302")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task EnumTypeAssignedToNamedPropertyOfSameNameInAttributeCtor() { await TestAsync( @"using System; using System.Runtime.InteropServices; class C { [DllImport(""abc"", CallingConvention = CallingConvention)] static extern void M(); }", Namespace("System"), Namespace("System"), Namespace("Runtime"), Namespace("InteropServices"), Class("DllImport"), Field("CallingConvention"), Enum("CallingConvention")); } [WorkItem(531119, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531119")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task OnlyClassifyGenericNameOnce() { await TestAsync( @"enum Type { } struct Type { Type f; }", Struct("Type")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NameOf1() { await TestAsync( @"class C { void goo() { var x = nameof } }", Keyword("var"), Keyword("nameof")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task NameOf2() { await TestAsync( @"class C { void goo() { var x = nameof(C); } }", Keyword("var"), Keyword("nameof"), Class("C")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task MethodCalledNameOfInScope() { await TestAsync( @"class C { void nameof(int i) { } void goo() { int y = 3; var x = nameof(); } }", Keyword("var")); } [WorkItem(744813, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/744813")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestCreateWithBufferNotInWorkspace() { // don't crash using (var workspace = TestWorkspace.CreateCSharp("")) { var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); var contentTypeService = document.GetLanguageService(); var contentType = contentTypeService.GetDefaultContentType(); var extraBuffer = workspace.ExportProvider.GetExportedValue().CreateTextBuffer("", contentType); WpfTestRunner.RequireWpfFact($"Creates an {nameof(IWpfTextView)} explicitly with an unrelated buffer"); using (var disposableView = workspace.ExportProvider.GetExportedValue().CreateDisposableTextView(extraBuffer)) { var listenerProvider = workspace.ExportProvider.GetExportedValue(); var provider = new SemanticClassificationViewTaggerProvider( workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), listenerProvider); using (var tagger = (IDisposable)provider.CreateTagger(disposableView.TextView, extraBuffer)) { using (var edit = extraBuffer.CreateEdit()) { edit.Insert(0, "class A { }"); edit.Apply(); } var waiter = listenerProvider.GetWaiter(FeatureAttribute.Classification); await waiter.CreateWaitTask(); } } } } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestGetTagsOnBufferTagger() { // don't crash using (var workspace = TestWorkspace.CreateCSharp("class C { C c; }")) { var document = workspace.Documents.First(); var listenerProvider = workspace.ExportProvider.GetExportedValue(); var provider = new SemanticClassificationBufferTaggerProvider( workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), workspace.ExportProvider.GetExportedValue(), listenerProvider); var tagger = provider.CreateTagger(document.TextBuffer); using (var disposable = (IDisposable)tagger) { var waiter = listenerProvider.GetWaiter(FeatureAttribute.Classification); await waiter.CreateWaitTask(); var tags = tagger.GetTags(document.TextBuffer.CurrentSnapshot.GetSnapshotSpanCollection()); var allTags = tagger.GetAllTags(document.TextBuffer.CurrentSnapshot.GetSnapshotSpanCollection(), CancellationToken.None); Assert.Empty(tags); Assert.NotEmpty(allTags); Assert.Equal(allTags.Count(), 1); } } } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task Tuples() { await TestAsync( @"class C { (int a, int b) x; }", ParseOptions(TestOptions.Regular, Options.Script)); } [Fact] [WorkItem(261049, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/261049")] public async Task DevDiv261049RegressionTest() { var source = @" var (a,b) = Get(out int x, out int y); Console.WriteLine($""({a.first}, {a.second})"");"; await TestInMethodAsync( source, Keyword("var"), Local("a"), Local("a")); } [WorkItem(633, "https://github.com/dotnet/roslyn/issues/633")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InXmlDocCref_WhenTypeOnlyIsSpecified_ItIsClassified() { await TestAsync( @"/// /// /// class MyClass { public MyClass(int x) { } }", Class("MyClass")); } [WorkItem(633, "https://github.com/dotnet/roslyn/issues/633")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InXmlDocCref_WhenConstructorOnlyIsSpecified_NothingIsClassified() { await TestAsync( @"/// /// /// class MyClass { public MyClass(int x) { } }", Class("MyClass")); } [WorkItem(633, "https://github.com/dotnet/roslyn/issues/633")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task InXmlDocCref_WhenTypeAndConstructorSpecified_OnlyTypeIsClassified() { await TestAsync( @"/// /// /// class MyClass { public MyClass(int x) { } }", Class("MyClass"), Class("MyClass")); } [WorkItem(13174, "https://github.com/dotnet/roslyn/issues/13174")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestMemberBindingThatLooksGeneric() { await TestAsync( @"using System.Diagnostics; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Debug.Assert(args?.Length < 2); } } }", Namespace("System"), Namespace("Diagnostics"), Namespace("System"), Namespace("Threading"), Namespace("Tasks"), Namespace("ConsoleApplication1"), Class("Debug"), Static("Debug"), Method("Assert"), Static("Assert"), Parameter("args"), Property("Length")); } [WorkItem(18956, "https://github.com/dotnet/roslyn/issues/18956")] [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/30855"), Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestVarInPattern1() { await TestAsync( @" class Program { void Main(string s) { if (s is var v) { } } }", Parameter("s"), Keyword("var")); } [WorkItem(18956, "https://github.com/dotnet/roslyn/issues/18956")] [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/30855"), Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestVarInPattern2() { await TestAsync( @" class Program { void Main(string s) { switch (s) { case var v: } } }", Parameter("s"), Keyword("var")); } [WorkItem(23940, "https://github.com/dotnet/roslyn/issues/23940")] [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestAliasQualifiedClass() { await TestAsync( @" using System; using Col = System.Collections.Generic; namespace AliasTest { class Program { static void Main(string[] args) { var list1 = new Col::List } } }", Namespace("System"), Namespace("Col"), Namespace("System"), Namespace("Collections"), Namespace("Generic"), Namespace("AliasTest"), Keyword("var"), Namespace("Col"), Class("List")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_InsideMethod() { // Asserts no Keyword("unmanaged") because it is an identifier. await TestInMethodAsync(@" var unmanaged = 0; unmanaged++;", Keyword("var"), Local("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Type_Keyword() { await TestAsync( "class X where T : unmanaged { }", TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Type_ExistingInterface() { await TestAsync(@" interface unmanaged {} class X where T : unmanaged { }", TypeParameter("T"), Interface("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope() { await TestAsync(@" namespace OtherScope { interface unmanaged {} } class X where T : unmanaged { }", Namespace("OtherScope"), TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Method_Keyword() { await TestAsync(@" class X { void M() where T : unmanaged { } }", TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Method_ExistingInterface() { await TestAsync(@" interface unmanaged {} class X { void M() where T : unmanaged { } }", TypeParameter("T"), Interface("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope() { await TestAsync(@" namespace OtherScope { interface unmanaged {} } class X { void M() where T : unmanaged { } }", Namespace("OtherScope"), TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Delegate_Keyword() { await TestAsync( "delegate void D() where T : unmanaged;", TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Delegate_ExistingInterface() { await TestAsync(@" interface unmanaged {} delegate void D() where T : unmanaged;", TypeParameter("T"), Interface("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope() { await TestAsync(@" namespace OtherScope { interface unmanaged {} } delegate void D() where T : unmanaged;", Namespace("OtherScope"), TypeParameter("T"), Keyword("unmanaged")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex1() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = new Regex(@""$(\a\t\u0020)|[^\p{Lu}-a\w\sa-z-[m-p]]+?(?#comment)|(\b\G\z)|(?sub){0,5}?^""); } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Class("Regex"), Regex.Anchor("$"), Regex.Grouping("("), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.OtherEscape("\\"), Regex.OtherEscape("t"), Regex.OtherEscape("\\"), Regex.OtherEscape("u"), Regex.OtherEscape("0020"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.CharacterClass("["), Regex.CharacterClass("^"), Regex.CharacterClass("\\"), Regex.CharacterClass("p"), Regex.CharacterClass("{"), Regex.CharacterClass("Lu"), Regex.CharacterClass("}"), Regex.Text("-a"), Regex.CharacterClass("\\"), Regex.CharacterClass("w"), Regex.CharacterClass("\\"), Regex.CharacterClass("s"), Regex.Text("a"), Regex.CharacterClass("-"), Regex.Text("z"), Regex.CharacterClass("-"), Regex.CharacterClass("["), Regex.Text("m"), Regex.CharacterClass("-"), Regex.Text("p"), Regex.CharacterClass("]"), Regex.CharacterClass("]"), Regex.Quantifier("+"), Regex.Quantifier("?"), Regex.Comment("(?#comment)"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Anchor("\\"), Regex.Anchor("b"), Regex.Anchor("\\"), Regex.Anchor("G"), Regex.Anchor("\\"), Regex.Anchor("z"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Grouping("?"), Regex.Grouping("<"), Regex.Grouping("name"), Regex.Grouping(">"), Regex.Text("sub"), Regex.Grouping(")"), Regex.Quantifier("{"), Regex.Quantifier("0"), Regex.Quantifier(","), Regex.Quantifier("5"), Regex.Quantifier("}"), Regex.Quantifier("?"), Regex.Anchor("^")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex2() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { // language=regex var r = @""$(\a\t\u0020)|[^\p{Lu}-a\w\sa-z-[m-p]]+?(?#comment)|(\b\G\z)|(?sub){0,5}?^""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.Grouping("("), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.OtherEscape("\\"), Regex.OtherEscape("t"), Regex.OtherEscape("\\"), Regex.OtherEscape("u"), Regex.OtherEscape("0020"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.CharacterClass("["), Regex.CharacterClass("^"), Regex.CharacterClass("\\"), Regex.CharacterClass("p"), Regex.CharacterClass("{"), Regex.CharacterClass("Lu"), Regex.CharacterClass("}"), Regex.Text("-a"), Regex.CharacterClass("\\"), Regex.CharacterClass("w"), Regex.CharacterClass("\\"), Regex.CharacterClass("s"), Regex.Text("a"), Regex.CharacterClass("-"), Regex.Text("z"), Regex.CharacterClass("-"), Regex.CharacterClass("["), Regex.Text("m"), Regex.CharacterClass("-"), Regex.Text("p"), Regex.CharacterClass("]"), Regex.CharacterClass("]"), Regex.Quantifier("+"), Regex.Quantifier("?"), Regex.Comment("(?#comment)"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Anchor("\\"), Regex.Anchor("b"), Regex.Anchor("\\"), Regex.Anchor("G"), Regex.Anchor("\\"), Regex.Anchor("z"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Grouping("?"), Regex.Grouping("<"), Regex.Grouping("name"), Regex.Grouping(">"), Regex.Text("sub"), Regex.Grouping(")"), Regex.Quantifier("{"), Regex.Quantifier("0"), Regex.Quantifier(","), Regex.Quantifier("5"), Regex.Quantifier("}"), Regex.Quantifier("?"), Regex.Anchor("^")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex3() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* language=regex */@""$(\a\t\u0020\\)|[^\p{Lu}-a\w\sa-z-[m-p]]+?(?#comment)|(\b\G\z)|(?sub){0,5}?^""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.Grouping("("), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.OtherEscape("\\"), Regex.OtherEscape("t"), Regex.OtherEscape("\\"), Regex.OtherEscape("u"), Regex.OtherEscape("0020"), Regex.SelfEscapedCharacter("\\"), Regex.SelfEscapedCharacter("\\"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.CharacterClass("["), Regex.CharacterClass("^"), Regex.CharacterClass("\\"), Regex.CharacterClass("p"), Regex.CharacterClass("{"), Regex.CharacterClass("Lu"), Regex.CharacterClass("}"), Regex.Text("-a"), Regex.CharacterClass("\\"), Regex.CharacterClass("w"), Regex.CharacterClass("\\"), Regex.CharacterClass("s"), Regex.Text("a"), Regex.CharacterClass("-"), Regex.Text("z"), Regex.CharacterClass("-"), Regex.CharacterClass("["), Regex.Text("m"), Regex.CharacterClass("-"), Regex.Text("p"), Regex.CharacterClass("]"), Regex.CharacterClass("]"), Regex.Quantifier("+"), Regex.Quantifier("?"), Regex.Comment("(?#comment)"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Anchor("\\"), Regex.Anchor("b"), Regex.Anchor("\\"), Regex.Anchor("G"), Regex.Anchor("\\"), Regex.Anchor("z"), Regex.Grouping(")"), Regex.Alternation("|"), Regex.Grouping("("), Regex.Grouping("?"), Regex.Grouping("<"), Regex.Grouping("name"), Regex.Grouping(">"), Regex.Text("sub"), Regex.Grouping(")"), Regex.Quantifier("{"), Regex.Quantifier("0"), Regex.Quantifier(","), Regex.Quantifier("5"), Regex.Quantifier("}"), Regex.Quantifier("?"), Regex.Anchor("^")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex4() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* lang=regex */@""$\a(?#comment)""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex5() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* lang=regexp */@""$\a(?#comment)""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex6() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* lang=regexp */@""$\a(?#comment) # not end of line comment""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)"), Regex.Text(" # not end of line comment")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex7() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* lang=regexp,ignorepatternwhitespace */@""$\a(?#comment) # is end of line comment""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)"), Regex.Comment("# is end of line comment")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex8() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = /* lang = regexp , ignorepatternwhitespace */@""$\a(?#comment) # is end of line comment""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)"), Regex.Comment("# is end of line comment")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex9() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = new Regex(@""$\a(?#comment) # is end of line comment"", RegexOptions.IgnorePatternWhitespace); } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Class("Regex"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)"), Regex.Comment("# is end of line comment"), Enum("RegexOptions"), EnumMember("IgnorePatternWhitespace")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex10() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void Goo() { var r = new Regex(@""$\a(?#comment) # is not end of line comment""); } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Class("Regex"), Regex.Anchor("$"), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.Comment("(?#comment)"), Regex.Text(" # is not end of line comment")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestRegex11() { await TestAsync( @" using System.Text.RegularExpressions; class Program { // language=regex private static string myRegex = @""$(\a\t\u0020)""; }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Regex.Anchor("$"), Regex.Grouping("("), Regex.OtherEscape("\\"), Regex.OtherEscape("a"), Regex.OtherEscape("\\"), Regex.OtherEscape("t"), Regex.OtherEscape("\\"), Regex.OtherEscape("u"), Regex.OtherEscape("0020"), Regex.Grouping(")")); } [WpfFact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestIncompleteRegexLeadingToStringInsideSkippedTokensInsideADirective() { await TestAsync( @" using System.Text.RegularExpressions; class Program { void M() { // not terminating this string caused us to eat up to the quote on the next line. // we then treated #comment as a directive with a lot of skipped tokens on it, including // a skipped token for ""; // // Because it's a comment on a directive, special lexing rules apply (i.e. no escape // characters are supposed, and we want our system to bail there and not try to validate // it. var r = new Regex(@""$; var s = /* language=regex */ @""(?#comment)|(\b\G\z)|(?sub){0,5}?^""; } }", Namespace("System"), Namespace("Text"), Namespace("RegularExpressions"), Keyword("var"), Class("Regex")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_LocalFunction_Keyword() { await TestAsync(@" class X { void N() { void M() where T : unmanaged { } } }", TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterface() { await TestAsync(@" interface unmanaged {} class X { void N() { void M() where T : unmanaged { } } }", TypeParameter("T"), Interface("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterfaceButOutOfScope() { await TestAsync(@" namespace OtherScope { interface unmanaged {} } class X { void N() { void M() where T : unmanaged { } } }", Namespace("OtherScope"), TypeParameter("T"), Keyword("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape1() { await TestInMethodAsync(@"var goo = ""goo\r\nbar"";", Keyword("var"), Escape(@"\r"), Escape(@"\n")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape2() { await TestInMethodAsync(@"var goo = @""goo\r\nbar"";", Keyword("var")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape3() { await TestInMethodAsync(@"var goo = $""goo{{1}}bar"";", Keyword("var"), Escape(@"{{"), Escape(@"}}")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape4() { await TestInMethodAsync(@"var goo = $@""goo{{1}}bar"";", Keyword("var"), Escape(@"{{"), Escape(@"}}")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape5() { await TestInMethodAsync(@"var goo = $""goo\r{{1}}\nbar"";", Keyword("var"), Escape(@"\r"), Escape(@"{{"), Escape(@"}}"), Escape(@"\n")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape6() { await TestInMethodAsync(@"var goo = $@""goo\r{{1}}\nbar"";", Keyword("var"), Escape(@"{{"), Escape(@"}}")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape7() { await TestInMethodAsync(@"var goo = $""goo\r{1}\nbar"";", Keyword("var"), Escape(@"\r"), Escape(@"\n")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestStringEscape8() { await TestInMethodAsync(@"var goo = $@""{{goo{1}bar}}"";", Keyword("var"), Escape(@"{{"), Escape(@"}}")); } [WorkItem(29451, "https://github.com/dotnet/roslyn/issues/29451")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestDirectiveStringLiteral() { await TestInMethodAsync(@"#line 1 ""a\b"""); } [WorkItem(30378, "https://github.com/dotnet/roslyn/issues/30378")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestFormatSpecifierInInterpolation() { await TestInMethodAsync(@"var goo = $""goo{{1:0000}}bar"";", Keyword("var"), Escape(@"{{"), Escape(@"}}")); } [WorkItem(29492, "https://github.com/dotnet/roslyn/issues/29492")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestOverloadedOperator_BinaryExpression() { await TestAsync(@" class C { void M() { var a = 1 + 1; var b = new True() + new True(); } } class True { public static True operator +(True a, True b) { return new True(); } }", Keyword("var"), Keyword("var"), Class("True"), OverloadedOperators.Plus, Class("True"), Class("True"), Class("True"), Class("True"), Class("True")); } [WorkItem(29492, "https://github.com/dotnet/roslyn/issues/29492")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestOverloadedOperator_PrefixUnaryExpression() { await TestAsync(@" class C { void M() { var a = !false; var b = !new True(); } } class True { public static bool operator !(True a) { return false; } }", Keyword("var"), Keyword("var"), OverloadedOperators.Exclamation, Class("True"), Class("True")); } [WorkItem(29492, "https://github.com/dotnet/roslyn/issues/29492")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestOverloadedOperator_PostfixUnaryExpression() { await TestAsync(@" class C { void M() { var a = 1; a++; var b = new True(); b++; } } class True { public static True operator ++(True a) { return new True(); } }", Keyword("var"), Local("a"), Keyword("var"), Class("True"), Local("b"), OverloadedOperators.PlusPlus, Class("True"), Class("True"), Class("True")); } [WorkItem(29492, "https://github.com/dotnet/roslyn/issues/29492")] [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestOverloadedOperator_ConditionalExpression() { await TestAsync(@" class C { void M() { var a = 1 == 1; var b = new True() == new True(); } } class True { public static bool operator ==(True a, True b) { return true; } }", Keyword("var"), Keyword("var"), Class("True"), OverloadedOperators.EqualsEquals, Class("True"), Class("True"), Class("True")); } } }