提交 0af9dcf7 编写于 作者: Y yair halberstadt

Add further unit tests, and fix bug with suppression of obolete inside accessor declared obsolete.

上级 38179e34
......@@ -55,12 +55,7 @@ private static ThreeState GetObsoleteContextState(Symbol symbol, bool forceCompl
{
while ((object)symbol != null)
{
// For property or event accessors, check the associated property or event instead.
if (symbol.IsAccessor())
{
symbol = ((MethodSymbol)symbol).AssociatedSymbol;
}
else if (symbol.Kind == SymbolKind.Field)
if (symbol.Kind == SymbolKind.Field)
{
// If this is the backing field of an event, look at the event instead.
var associatedSymbol = ((FieldSymbol)symbol).AssociatedSymbol;
......@@ -81,7 +76,15 @@ private static ThreeState GetObsoleteContextState(Symbol symbol, bool forceCompl
return state;
}
symbol = symbol.ContainingSymbol;
// For property or event accessors, check the associated property or event next.
if (symbol.IsAccessor())
{
symbol = ((MethodSymbol)symbol).AssociatedSymbol;
}
else
{
symbol = symbol.ContainingSymbol;
}
}
return ThreeState.False;
......
......@@ -5881,7 +5881,7 @@ public static class TestExtension
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.event1").WithArguments("GenericTest<int>.event1", "Do not use this event").WithLocation(45, 9),
// (121,28): warning CS0067: The event 'GenericTest<T>.event1' is never used
// public event Action<T> event1;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "event1").WithArguments("GenericTest<T>.event1").WithLocation(121, 28)
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "event1").WithArguments("GenericTest<T>.event1").WithLocation(121, 28));
}
[Fact]
......@@ -5985,6 +5985,10 @@ public class TestClass
[Obsolete(""Do not use Prop1"", false)]
public int Prop1 { get; set; }
public int Prop2 { [Obsolete(""Do not use Prop2.Get"")] get; set; }
public int Prop3 { get; [Obsolete(""Do not use Prop3.Get"", true)] set; }
[Obsolete(""Do not use field1"", true)]
public TestClass field1;
......@@ -6010,37 +6014,47 @@ public static void Main()
c = c.field1;
c.event1();
c.event1 += () => {};
c.Prop2 = 42;
i = c.Prop2;
c.Prop3 = 42;
i = c.Prop3;
}
}
";
CreateCompilation(source, new[] { peReference }).VerifyDiagnostics(
// (4,29): warning CS0612: 'TestClass1' is obsolete
// public static void goo1(TestClass1 c) {}
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "TestClass1").WithArguments("TestClass1"),
// (5,29): warning CS0618: 'TestClass2' is obsolete: 'TestClass2 is obsolete'
// public static void goo2(TestClass2 c) {}
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "TestClass2").WithArguments("TestClass2", "TestClass2 is obsolete"),
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "TestClass2").WithArguments("TestClass2", "TestClass2 is obsolete").WithLocation(5, 29),
// (6,29): error CS0619: 'TestClass3' is obsolete: 'Do not use TestClass3'
// public static void goo3(TestClass3 c) {}
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "TestClass3").WithArguments("TestClass3", "Do not use TestClass3"),
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "TestClass3").WithArguments("TestClass3", "Do not use TestClass3").WithLocation(6, 29),
// (7,29): warning CS0618: 'TestClass4' is obsolete: 'TestClass4 is obsolete'
// public static void goo4(TestClass4 c) {}
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "TestClass4").WithArguments("TestClass4", "TestClass4 is obsolete"),
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "TestClass4").WithArguments("TestClass4", "TestClass4 is obsolete").WithLocation(7, 29),
// (4,29): warning CS0612: 'TestClass1' is obsolete
// public static void goo1(TestClass1 c) {}
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "TestClass1").WithArguments("TestClass1").WithLocation(4, 29),
// (12,9): warning CS0618: 'TestClass.TestMethod()' is obsolete: 'Do not use TestMethod'
// c.TestMethod();
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "c.TestMethod()").WithArguments("TestClass.TestMethod()", "Do not use TestMethod"),
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "c.TestMethod()").WithArguments("TestClass.TestMethod()", "Do not use TestMethod").WithLocation(12, 9),
// (13,17): warning CS0618: 'TestClass.Prop1' is obsolete: 'Do not use Prop1'
// var i = c.Prop1;
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "c.Prop1").WithArguments("TestClass.Prop1", "Do not use Prop1"),
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "c.Prop1").WithArguments("TestClass.Prop1", "Do not use Prop1").WithLocation(13, 17),
// (14,13): error CS0619: 'TestClass.field1' is obsolete: 'Do not use field1'
// c = c.field1;
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.field1").WithArguments("TestClass.field1", "Do not use field1"),
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.field1").WithArguments("TestClass.field1", "Do not use field1").WithLocation(14, 13),
// (15,9): error CS0619: 'TestClass.event1' is obsolete: 'Do not use event'
// c.event1();
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.event1").WithArguments("TestClass.event1", "Do not use event"),
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.event1").WithArguments("TestClass.event1", "Do not use event").WithLocation(15, 9),
// (16,9): error CS0619: 'TestClass.event1' is obsolete: 'Do not use event'
// c.event1 += () => {};
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.event1").WithArguments("TestClass.event1", "Do not use event"));
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.event1").WithArguments("TestClass.event1", "Do not use event").WithLocation(16, 9),
// (18,13): warning CS0618: 'TestClass.Prop2.get' is obsolete: 'Do not use Prop2.Get'
// i = c.Prop2;
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "c.Prop2").WithArguments("TestClass.Prop2.get", "Do not use Prop2.Get").WithLocation(18, 13),
// (19,9): error CS0619: 'TestClass.Prop3.set' is obsolete: 'Do not use Prop3.Get'
// c.Prop3 = 42;
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "c.Prop3").WithArguments("TestClass.Prop3.set", "Do not use Prop3.Get").WithLocation(19, 9));
}
[Fact]
......@@ -6103,20 +6117,82 @@ class D6 : D5
[Obsolete]
public override void goo() {}
}
class E1
{
public virtual int Goo {get; set;}
}
class E2 : E1
{
public override int Goo { [Obsolete] get; set;}
}
class E3 : E1
{
public new int Goo { [Obsolete] get; set;}
}
class E4 : E1
{
public override int Goo {get; set;}
}
class E5 : E4
{
public override int Goo { [Obsolete] get; set;}
}
class E6 : E5
{
public override int Goo {get; set;}
}
class F1
{
public virtual int Goo { [Obsolete] get; set;}
}
class F2 : F1
{
public override int Goo {get; set;}
}
class F3 : F1
{
public new int Goo {get; set;}
}
class F4 : F1
{
public override int Goo { [Obsolete] get; set;}
}
class F5 : F4
{
public override int Goo {get; set;}
}
class F6 : F5
{
public override int Goo { [Obsolete] get; set;}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (10,26): warning CS0809: Obsolete member 'C2.goo()' overrides non-obsolete member 'C1.goo()'
// public override void goo() {}
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "goo").WithArguments("C2.goo()", "C1.goo()"),
// (24,26): warning CS0809: Obsolete member 'C5.goo()' overrides non-obsolete member 'C1.goo()'
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "goo").WithArguments("C2.goo()", "C1.goo()").WithLocation(10, 26),
// (90,30): warning CS0672: Member 'F2.Goo.get' overrides obsolete member 'F1.Goo.get'. Add the Obsolete attribute to 'F2.Goo.get'.
// public override int Goo {get; set;}
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "get").WithArguments("F2.Goo.get", "F1.Goo.get").WithLocation(90, 30),
// (77,42): warning CS0809: Obsolete member 'E5.Goo.get' overrides non-obsolete member 'E1.Goo.get'
// public override int Goo { [Obsolete] get; set;}
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "get").WithArguments("E5.Goo.get", "E1.Goo.get").WithLocation(77, 42),
// (51,26): warning CS0672: Member 'D5.goo()' overrides obsolete member 'D1.goo()'. Add the Obsolete attribute to 'D5.goo()'.
// public override void goo() {}
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "goo").WithArguments("C5.goo()", "C1.goo()"),
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "goo").WithArguments("D5.goo()", "D1.goo()").WithLocation(51, 26),
// (38,26): warning CS0672: Member 'D2.goo()' overrides obsolete member 'D1.goo()'. Add the Obsolete attribute to 'D2.goo()'.
// public override void goo() {}
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "goo").WithArguments("D2.goo()", "D1.goo()"),
// (51,26): warning CS0672: Member 'D5.goo()' overrides obsolete member 'D1.goo()'. Add the Obsolete attribute to 'D5.goo()'.
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "goo").WithArguments("D2.goo()", "D1.goo()").WithLocation(38, 26),
// (24,26): warning CS0809: Obsolete member 'C5.goo()' overrides non-obsolete member 'C1.goo()'
// public override void goo() {}
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "goo").WithArguments("D5.goo()", "D1.goo()"));
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "goo").WithArguments("C5.goo()", "C1.goo()").WithLocation(24, 26),
// (102,30): warning CS0672: Member 'F5.Goo.get' overrides obsolete member 'F1.Goo.get'. Add the Obsolete attribute to 'F5.Goo.get'.
// public override int Goo {get; set;}
Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "get").WithArguments("F5.Goo.get", "F1.Goo.get").WithLocation(102, 30),
// (65,42): warning CS0809: Obsolete member 'E2.Goo.get' overrides non-obsolete member 'E1.Goo.get'
// public override int Goo { [Obsolete] get; set;}
Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "get").WithArguments("E2.Goo.get", "E1.Goo.get").WithLocation(65, 42));
}
[Fact]
......@@ -6311,7 +6387,9 @@ public class Test
event Action<SomeType> someEvent;
[Obsolete]
public static SomeType someProp { get; set; }
public static SomeType someProp { get => new SomeType(); set {} }
public static string someProp2 { [Obsolete] get => new SomeType().ToString(); }
[Obsolete]
SomeType this[int x] { get { SomeType y = new SomeType(); return y; } }
......@@ -6464,6 +6542,11 @@ public int Prop
get { return 1; }
set { }
}
[Obsolete(""Property"", true)]
public int Prop2
{
get ; [Obsolete] set;
}
[Obsolete(""Field"", true)]
public int Field;
}
......@@ -6471,6 +6554,7 @@ public int Prop
[Att]
[Att(Field = 1)]
[Att(Prop = 1)]
[Att(Prop2 = 1)]
public class Test
{
[Att()]
......@@ -6478,24 +6562,30 @@ public class Test
}
";
CreateCompilation(source).VerifyDiagnostics(
// (20,6): error CS0619: 'Att.Field' is obsolete: 'Field'
// (24,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att").WithArguments("Att.Att()", "Constructor").WithLocation(24, 2),
// (25,6): error CS0619: 'Att.Field' is obsolete: 'Field'
// [Att(Field = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Field = 1").WithArguments("Att.Field", "Field"),
// (20,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Field = 1").WithArguments("Att.Field", "Field").WithLocation(25, 6),
// (25,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att(Field = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Field = 1)").WithArguments("Att.Att()", "Constructor"),
// (21,6): error CS0619: 'Att.Prop' is obsolete: 'Property'
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Field = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(25, 2),
// (26,6): error CS0619: 'Att.Prop' is obsolete: 'Property'
// [Att(Prop = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop = 1").WithArguments("Att.Prop", "Property"),
// (21,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop = 1").WithArguments("Att.Prop", "Property").WithLocation(26, 6),
// (26,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att(Prop = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop = 1)").WithArguments("Att.Att()", "Constructor"),
// (24,6): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(26, 2),
// (27,6): error CS0619: 'Att.Prop2' is obsolete: 'Property'
// [Att(Prop2 = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop2 = 1").WithArguments("Att.Prop2", "Property").WithLocation(27, 6),
// (27,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att(Prop2 = 1)]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop2 = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(27, 2),
// (30,6): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att()]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att()").WithArguments("Att.Att()", "Constructor"),
// (19,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor'
// [Att]
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att").WithArguments("Att.Att()", "Constructor"));
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att()").WithArguments("Att.Att()", "Constructor").WithLocation(30, 6));
}
[Fact]
......@@ -8987,5 +9077,39 @@ void M(in int x)
// error CS0616: 'IsReadOnlyAttribute' is not an attribute class
Diagnostic(ErrorCode.ERR_NotAnAttributeClass).WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(1, 1));
}
[Fact]
public void TestObsoleteOnPropertyAccessorUsedInNameofAndXmlDocComment()
{
var code = @"
using System;
/// <summary>
/// <see cref=""Prop""/>
/// </summary>
class C
{
const string str = nameof(Prop);
public int Prop { [Obsolete] get; [Obsolete] set; }
}
";
CreateCompilation(code).VerifyDiagnostics().VerifyEmitDiagnostics();
}
[Fact]
public void TestObsoleteOnPropertyAndAccessors()
{
var code = @"
using System;
class C
{
[Obsolete]
public int Prop { [Obsolete] get; [Obsolete] set; }
}
";
CreateCompilation(code).VerifyDiagnostics().VerifyEmitDiagnostics();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册