diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs index 2b49151f496e..189f967f5396 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs @@ -366,6 +366,16 @@ private BoundExpression BindNamedAttributeArgument(AttributeArgumentSyntax named ReportDiagnosticsIfObsolete(diagnostics, namedArgumentNameSymbol, namedArgument, hasBaseReceiver: false); + if (namedArgumentNameSymbol.Kind == SymbolKind.Property) + { + var propertySymbol = (PropertySymbol)namedArgumentNameSymbol; + var setMethod = propertySymbol.GetOwnOrInheritedSetMethod(); + if (setMethod != null) + { + ReportDiagnosticsIfObsolete(diagnostics, setMethod, namedArgument, hasBaseReceiver: false); + } + } + Debug.Assert(resultKind == LookupResultKind.Viable || wasError); TypeSymbol namedArgumentType; diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index bf04ada56393..6cc22a48e117 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -762,6 +762,15 @@ internal static string ERR_AttributeNotOnAccessor { } } + /// + /// Looks up a localized string similar to Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations.. + /// + internal static string ERR_AttributeNotOnEventAccessor { + get { + return ResourceManager.GetString("ERR_AttributeNotOnEventAccessor", resourceCulture); + } + } + /// /// Looks up a localized string similar to Attribute '{0}' is not valid on this declaration type. It is only valid on '{1}' declarations.. /// @@ -11401,6 +11410,15 @@ internal static string IDS_FeatureObjectInitializer { } } + /// + /// Looks up a localized string similar to obsolete on property accessor. + /// + internal static string IDS_FeatureObsoleteOnPropertyAccessor { + get { + return ResourceManager.GetString("IDS_FeatureObsoleteOnPropertyAccessor", resourceCulture); + } + } + /// /// Looks up a localized string similar to optional parameter. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 580bc1a872df..753c3d637005 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5829,4 +5829,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The switch expression does not handle some null inputs. - + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + + obsolete on property accessor + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 4d6432b45a6e..f957c0169c2c 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1598,7 +1598,7 @@ internal enum ErrorCode ERR_PossibleAsyncIteratorWithoutYieldOrAwait = 8420, ERR_StaticLocalFunctionCannotCaptureVariable = 8421, ERR_StaticLocalFunctionCannotCaptureThis = 8422, - + ERR_AttributeNotOnEventAccessor = 8423, #region diagnostics introduced for recursive patterns // 8501, // available ERR_WrongNumberOfSubpatterns = 8502, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index e9641a389ea8..497446b361b3 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -175,7 +175,8 @@ internal enum MessageID IDS_FeatureStaticLocalFunctions = MessageBase + 12755, IDS_FeatureNameShadowingInNestedFunctions = MessageBase + 12756, IDS_FeatureUnmanagedConstructedTypes = MessageBase + 12757, - + IDS_FeatureObsoleteOnPropertyAccessor = MessageBase + 12758, + IDS_DefaultInterfaceImplementation = MessageBase + 12800, IDS_BaseTypeInBaseExpression = MessageBase + 12801, } @@ -282,6 +283,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureStaticLocalFunctions: case MessageID.IDS_FeatureNameShadowingInNestedFunctions: case MessageID.IDS_FeatureUnmanagedConstructedTypes: // semantic check + case MessageID.IDS_FeatureObsoleteOnPropertyAccessor: case MessageID.IDS_DefaultInterfaceImplementation: // semantic check case MessageID.IDS_BaseTypeInBaseExpression: return LanguageVersion.CSharp8; diff --git a/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs index 9afb5890dd69..708f55bec99b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs @@ -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; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 100567532c26..d6c40705439d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -1222,9 +1222,16 @@ private bool VerifyObsoleteAttributeAppliedToMethod( { if (this.IsAccessor()) { - // CS1667: Attribute '{0}' is not valid on property or event accessors. It is only valid on '{1}' declarations. - AttributeUsageInfo attributeUsage = arguments.Attribute.AttributeClass.GetAttributeUsageInfo(); - arguments.Diagnostics.Add(ErrorCode.ERR_AttributeNotOnAccessor, arguments.AttributeSyntaxOpt.Name.Location, description.FullName, attributeUsage.GetValidTargetsErrorArgument()); + if (this is SourceEventAccessorSymbol) + { + // CS1667: Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + AttributeUsageInfo attributeUsage = arguments.Attribute.AttributeClass.GetAttributeUsageInfo(); + arguments.Diagnostics.Add(ErrorCode.ERR_AttributeNotOnEventAccessor, arguments.AttributeSyntaxOpt.Name.Location, description.FullName, attributeUsage.GetValidTargetsErrorArgument()); + } + else + { + MessageID.IDS_FeatureObsoleteOnPropertyAccessor.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt.Location); + } } return true; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 59399e45e0f5..7be309c9865d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -32,6 +32,11 @@ Ve výrazu as se nepovoluje použití typu odkazu s možnou hodnotou null {0}?; místo toho použijte základní typ {0}. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchronní příkaz foreach nejde použít pro proměnné typu {0}, protože {0} neobsahuje vhodnou veřejnou definici instance pro {1}. @@ -742,6 +747,11 @@ omezení obecného typu objektu + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly akce varování enable nebo safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index e9923fef4563..4c1b6cb5b016 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -32,6 +32,11 @@ Es ist unzulässig, den Nullable-Verweistyp "{0}?" in einem as-Ausdruck zu verwenden. Verwenden Sie stattdessen den zugrunde liegenden Typ "{0}". + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Eine asynchrone foreach-Anweisung kann nicht für Variablen vom Typ "{0}" verwendet werden, weil "{0}" keine geeignete öffentliche Instanzdefinition für "{1}" enthält. @@ -742,6 +747,11 @@ Einschränkung eines generischen Objekttyps + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly Warnaktion: "enable" oder "safeonly" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 719b47e8e812..669dc1258090 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -32,6 +32,11 @@ No se puede usar el tipo "{0}?" que acepta valores NULL en una expresión as; use en su lugar el tipo "{0}" subyacente. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Una instrucción foreach asincrónica no puede funcionar en variables de tipo "{0}", porque "{0}" no contiene una definición de instancia pública adecuada para "{1}". @@ -744,6 +749,11 @@ restricción de tipo genérico de objeto + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly acción de advertencia "enable" o "safeonly" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index a59a42976381..4b59fac9300f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -32,6 +32,11 @@ Il n'est pas correct d'utiliser le type de référence Nullable '{0}?' dans une expression as. Utilisez le type sous-jacent '{0}' à la place. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' L'instruction foreach asynchrone ne peut pas fonctionner sur des variables de type '{0}', car '{0}' ne contient aucune définition d'instance publique appropriée pour '{1}' @@ -743,6 +748,11 @@ contrainte de type générique d'objet + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly action d'avertissement enable ou safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 38f7e570dd83..917e74101552 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -32,6 +32,11 @@ Non è consentito usare il tipo riferimento nullable '{0}?' in un'espressione as. Usare il tipo sottostante '{0}'. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' L'istruzione foreach asincrona non può funzionare con variabili di tipo '{0}' perché '{0}' non contiene una definizione di istanza pubblica idonea per '{1}' @@ -742,6 +747,11 @@ vincolo di tipo generico object + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly azione di avviso enable o safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 10970e8496c9..ea4843ffba13 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -32,6 +32,11 @@ as 式で Null 許容参照型 '{0}?' を使用することはできません。代わりに基になる型 '{0}' をご使用ください。 + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' '{0}' は '{1}' の適切なパブリック インスタンス定義を含んでいないため、型 '{0}' の変数に対して非同期 foreach ステートメントを使用することはできません @@ -742,6 +747,11 @@ オブジェクト ジェネリック型の制約 + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly 警告アクション enable または safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 0c62b51a4d31..3db8d4ce3c86 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -32,6 +32,11 @@ 식에 nullable 참조 형식 '{0}'을(를) 사용하는 것은 올바르지 않습니다. 대신 기본 형식 '{0}'을(를) 사용하세요. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' '{0}' 형식 변수에서 비동기 foreach 문을 수행할 수 없습니다. '{0}'에는 '{1}'의 적합한 공용 인스턴스 정의가 없기 때문입니다. @@ -742,6 +747,11 @@ 개체 제네릭 형식 제약 조건 + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly 경고 작업 enable 또는 safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1a3723a177ec..1d30ff57c00e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -32,6 +32,11 @@ Użycie typu odwołania dopuszczającego wartość null „{0}?” w wyrażeniu „as” jest niedozwolone. Zamiast tego użyj bazowego typu „{0}”. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Asynchroniczna instrukcja foreach nie może operować na zmiennych typu „{0}”, ponieważ typ „{0}” nie zawiera odpowiedniej publicznej definicji wystąpienia elementu „{1}” @@ -742,6 +747,11 @@ ogólne ograniczenie typu obiektu + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly akcja warning: enable lub safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index badcf494e342..797d8c6698a4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -32,6 +32,11 @@ É ilegal usar o tipo de referência anulável '{0}?' em uma expressão as; use o tipo subjacente '{0}' em seu lugar. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' A instrução foreach assíncrona não pode operar em variáveis do tipo '{0}' porque '{0}' não contém uma definição da instância pública adequada para '{1}' @@ -742,6 +747,11 @@ restrição de tipo genérico de objeto + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly ação de aviso enable ou safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index d4d31024571b..31e09eb6bdf7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -32,6 +32,11 @@ Недопустимо использовать ссылочный тип "{0}", допускающий значения NULL, в выражении "as". Используйте вместо него базовый тип "{0}". + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' Асинхронный оператор foreach не работает с переменными типа "{0}", так как "{0}" не содержит подходящее открытое определение экземпляра для "{1}". @@ -742,6 +747,11 @@ ограничение универсального типа для объекта + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly действие warning с enable или safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index bd1f3442b862..0a566e39b070 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -32,6 +32,11 @@ Boş değer atanabilir '{0}?' başvuru türünün bir as ifadesinde kullanılması yasaktır; bunun yerine temel alınan '{0}' türünü kullanın. + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' '{0}', '{1}' için uygun bir genel örnek tanımı içermediğinden zaman uyumsuz foreach deyimi '{0}' türündeki değişkenlerle çalışmaz @@ -743,6 +748,11 @@ nesne genel tür kısıtlamaları + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly enable veya safeonly uyarı eylemi diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index ab24e5403f17..b0c4fa9aaaba 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -32,6 +32,11 @@ 在 as 表达式中使用可以为 null 的引用类型“{0}?”是非法的;请改用基础类型“{0}”。 + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' “{0}”不包含“{1}”的适当公共实例定义,因此异步 foreach 语句不能作用于“{0}”类型的变量 @@ -783,6 +788,11 @@ 对象泛型类型约束 + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly 警告操作 enable 或 safeonly diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 87365bfbf484..28e3dffe9a29 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -32,6 +32,11 @@ 在運算式中使用可為 Null 的參考型別 '{0}?' 不合法,請改用基礎類型 '{0}'。 + + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + Attribute '{0}' is not valid on event accessors. It is only valid on '{1}' declarations. + + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}' 因為 '{0}' 不包含適用於 '{1}' 的公用執行個體定義,所以非同步的 foreach 陳述式無法在類型為 '{0}' 的變數上運作 @@ -742,6 +747,11 @@ 物件泛型型別條件約束 + + obsolete on property accessor + obsolete on property accessor + + warning action enable or safeonly 警告動作 enable 或 safeonly diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs index 7d0b9f71b931..18a6d67834ea 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs @@ -5678,7 +5678,7 @@ class SelfReferenceInBase1 : IGoo {} } [Fact] - public void TestObsoleteAttributeOnMembers() + public void TestObsoleteAttributeOnMembersAndAccessors() { var source = @" using System; @@ -5698,6 +5698,16 @@ public static void Main() var f = t.field1; var p1 = t.Property1; var p2 = t.Property2; + + var p3 = t.Prop2; + t.Prop2 = p3; + + var p4 = t.Prop3; + t.Prop3 = p4; + + var p5 = t.Prop4; + t.Prop4 = p5; + t.event1(); t.event1 += () => { }; @@ -5750,6 +5760,7 @@ public static void ObsoleteMethod5() { } public int Prop2 { [Obsolete] get { return 10; } + set {} } public int Prop3 @@ -5758,6 +5769,12 @@ public int Prop3 [Obsolete] set { } } + public int Prop4 + { + [Obsolete] get { return 10; } + [Obsolete] set { } + } + public event Action event2 { [Obsolete] add {} @@ -5793,78 +5810,84 @@ public static void ObsoleteExtensionMethod1(this Test t) { } } "; CreateCompilationWithMscorlib40(source, new[] { ExtensionAssemblyRef }).VerifyDiagnostics( - // (65,10): error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. - // [Obsolete] get { return 10; } - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate"), - // (71,10): error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. - // [Obsolete] set { } - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate"), - // (76,10): error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. + // (98,10): error CS8423: Attribute 'System.ObsoleteAttribute' is not valid on event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. // [Obsolete] add {} - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate"), - // (77,10): error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(98, 10), + // (99,10): error CS8423: Attribute 'System.ObsoleteAttribute' is not valid on event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. // [Obsolete("Don't use remove accessor")] remove {} - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate"), + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(99, 10), // (8,9): warning CS0612: 'Test.ObsoleteMethod1()' is obsolete // ObsoleteMethod1(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "ObsoleteMethod1()").WithArguments("Test.ObsoleteMethod1()"), + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "ObsoleteMethod1()").WithArguments("Test.ObsoleteMethod1()").WithLocation(8, 9), // (9,9): warning CS0618: 'Test.ObsoleteMethod2()' is obsolete: 'Do not call this method' // ObsoleteMethod2(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "ObsoleteMethod2()").WithArguments("Test.ObsoleteMethod2()", "Do not call this method"), + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "ObsoleteMethod2()").WithArguments("Test.ObsoleteMethod2()", "Do not call this method").WithLocation(9, 9), // (10,9): error CS0619: 'Test.ObsoleteMethod3()' is obsolete: '' // ObsoleteMethod3(); - Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "ObsoleteMethod3()").WithArguments("Test.ObsoleteMethod3()", ""), + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "ObsoleteMethod3()").WithArguments("Test.ObsoleteMethod3()", "").WithLocation(10, 9), // (11,9): warning CS0612: 'Test.ObsoleteMethod5()' is obsolete // ObsoleteMethod5(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "ObsoleteMethod5()").WithArguments("Test.ObsoleteMethod5()"), - // (14,9): warning CS0618: 'Test.ObsoleteMethod4()' is obsolete: 'Do not call this method' + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "ObsoleteMethod5()").WithArguments("Test.ObsoleteMethod5()").WithLocation(11, 9), + // (15,9): warning CS0618: 'Test.ObsoleteMethod4()' is obsolete: 'Do not call this method' // t.ObsoleteMethod4(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4()").WithArguments("Test.ObsoleteMethod4()", "Do not call this method"), - // (15,17): warning CS0618: 'Test.field1' is obsolete: 'Do not use this field' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4()").WithArguments("Test.ObsoleteMethod4()", "Do not call this method").WithLocation(15, 9), + // (16,17): warning CS0618: 'Test.field1' is obsolete: 'Do not use this field' // var f = t.field1; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.field1").WithArguments("Test.field1", "Do not use this field"), - // (16,18): warning CS0618: 'Test.Property1' is obsolete: 'Do not use this property' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.field1").WithArguments("Test.field1", "Do not use this field").WithLocation(16, 17), + // (17,18): warning CS0618: 'Test.Property1' is obsolete: 'Do not use this property' // var p1 = t.Property1; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.Property1").WithArguments("Test.Property1", "Do not use this property"), - // (17,18): warning CS0618: 'Test.Property2' is obsolete: 'Do not use this property' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.Property1").WithArguments("Test.Property1", "Do not use this property").WithLocation(17, 18), + // (18,18): warning CS0618: 'Test.Property2' is obsolete: 'Do not use this property' // var p2 = t.Property2; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.Property2").WithArguments("Test.Property2", "Do not use this property"), - // (19,9): warning CS0618: 'Test.event1' is obsolete: 'Do not use this event' - // t.event1 += () => { }; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.event1").WithArguments("Test.event1", "Do not use this event"), - // (21,9): warning CS0618: 'TestExtension.ObsoleteExtensionMethod1(Test)' is obsolete: 'Do not call this extension method' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.Property2").WithArguments("Test.Property2", "Do not use this property").WithLocation(18, 18), + // (20,18): warning CS0612: 'Test.Prop2.get' is obsolete + // var p3 = t.Prop2; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t.Prop2").WithArguments("Test.Prop2.get").WithLocation(20, 18), + // (24,9): warning CS0612: 'Test.Prop3.set' is obsolete + // t.Prop3 = p4; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t.Prop3").WithArguments("Test.Prop3.set").WithLocation(24, 9), + // (26,18): warning CS0612: 'Test.Prop4.get' is obsolete + // var p5 = t.Prop4; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t.Prop4").WithArguments("Test.Prop4.get").WithLocation(26, 18), + // (27,9): warning CS0612: 'Test.Prop4.set' is obsolete + // t.Prop4 = p5; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t.Prop4").WithArguments("Test.Prop4.set").WithLocation(27, 9), + // (32,9): warning CS0618: 'TestExtension.ObsoleteExtensionMethod1(Test)' is obsolete: 'Do not call this extension method' // t.ObsoleteExtensionMethod1(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteExtensionMethod1()").WithArguments("TestExtension.ObsoleteExtensionMethod1(Test)", "Do not call this extension method"), - // (23,28): warning CS0618: 'Test.ObsoleteMethod4(int)' is obsolete: 'Do not call this method' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteExtensionMethod1()").WithArguments("TestExtension.ObsoleteExtensionMethod1(Test)", "Do not call this extension method").WithLocation(32, 9), + // (34,28): warning CS0618: 'Test.ObsoleteMethod4(int)' is obsolete: 'Do not call this method' // Action func = t.ObsoleteMethod4; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4").WithArguments("Test.ObsoleteMethod4(int)", "Do not call this method"), - // (25,24): warning CS0618: 'Test.ObsoleteMethod4()' is obsolete: 'Do not call this method' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4").WithArguments("Test.ObsoleteMethod4(int)", "Do not call this method").WithLocation(34, 28), + // (36,24): warning CS0618: 'Test.ObsoleteMethod4()' is obsolete: 'Do not call this method' // Action func1 = t.ObsoleteMethod4; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4").WithArguments("Test.ObsoleteMethod4()", "Do not call this method"), - // (29,30): warning CS0618: 'Test.Property1' is obsolete: 'Do not use this property' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.ObsoleteMethod4").WithArguments("Test.ObsoleteMethod4()", "Do not call this method").WithLocation(36, 24), + // (38,30): warning CS0618: 'Test.Property1' is obsolete: 'Do not use this property' // Test t1 = new Test { Property1 = 10, Property2 =20}; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "Property1").WithArguments("Test.Property1", "Do not use this property"), - // (29,46): warning CS0618: 'Test.Property2' is obsolete: 'Do not use this property' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "Property1").WithArguments("Test.Property1", "Do not use this property").WithLocation(38, 30), + // (38,46): warning CS0618: 'Test.Property2' is obsolete: 'Do not use this property' // Test t1 = new Test { Property1 = 10, Property2 =20}; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "Property2").WithArguments("Test.Property2", "Do not use this property"), - // (28,18): warning CS0612: 'Test.this[int]' is obsolete + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "Property2").WithArguments("Test.Property2", "Do not use this property").WithLocation(38, 46), + // (39,18): warning CS0612: 'Test.this[int]' is obsolete // var i1 = t1[10]; - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t1[10]").WithArguments("Test.this[int]"), - // (30,9): warning CS0612: 'GenericTest.ObsoleteMethod1()' is obsolete - // gt.ObsoleteMethod1(); - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "gt.ObsoleteMethod1()").WithArguments("GenericTest.ObsoleteMethod1()"), - // (31,18): warning CS0618: 'GenericTest.field1' is obsolete: 'Do not use this field' + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "t1[10]").WithArguments("Test.this[int]").WithLocation(39, 18), + // (42,9): warning CS0612: 'GenericTest.ObsoleteMethod1()' is obsolete + // gt.ObsoleteMethod1(); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "gt.ObsoleteMethod1()").WithArguments("GenericTest.ObsoleteMethod1()").WithLocation(42, 9), + // (43,18): warning CS0618: 'GenericTest.field1' is obsolete: 'Do not use this field' // var gf = gt.field1; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.field1").WithArguments("GenericTest.field1", "Do not use this field"), - // (32,19): warning CS0618: 'GenericTest.Property1' is obsolete: 'Do not use this property' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.field1").WithArguments("GenericTest.field1", "Do not use this field").WithLocation(43, 18), + // (44,19): warning CS0618: 'GenericTest.Property1' is obsolete: 'Do not use this property' // var gp1 = gt.Property1; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.Property1").WithArguments("GenericTest.Property1", "Do not use this property"), - // (33,9): warning CS0618: 'GenericTest.event1' is obsolete: 'Do not use this event' + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.Property1").WithArguments("GenericTest.Property1", "Do not use this property").WithLocation(44, 19), + // (30,9): warning CS0618: 'Test.event1' is obsolete: 'Do not use this event' + // t.event1 += () => { }; + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "t.event1").WithArguments("Test.event1", "Do not use this event").WithLocation(30, 9), + // (45,9): warning CS0618: 'GenericTest.event1' is obsolete: 'Do not use this event' // gt.event1 += (i) => { }; - Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.event1").WithArguments("GenericTest.event1", "Do not use this event"), - // (104,28): warning CS0067: The event 'GenericTest.event1' is never used + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "gt.event1").WithArguments("GenericTest.event1", "Do not use this event").WithLocation(45, 9), + // (121,28): warning CS0067: The event 'GenericTest.event1' is never used // public event Action event1; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "event1").WithArguments("GenericTest.event1")); + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "event1").WithArguments("GenericTest.event1").WithLocation(121, 28)); } [Fact] @@ -5968,6 +5991,10 @@ public void TestMethod() {} [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; @@ -5993,37 +6020,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] @@ -6086,20 +6123,145 @@ 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] + public void TestConsumptionOfObsoleteAttributeOnOverriddenAccessors() + { + var source = @" +using System; + +class Base +{ + public virtual int Boo { [Obsolete] get; set;} + public virtual int Goo { get; set; } + public virtual int Hoo { [Obsolete(""Base.Hoo is Obsolete"", true)] get; set; } + public virtual int Joo { [Obsolete(""Base.Joo is Obsolete"", false)] get; set; } + [Obsolete(""Base.Koo is Obsolete"")] public virtual int Koo { get; set; } +} +class Derived : Base +{ + public override int Boo { get; set; } + public override int Goo { [Obsolete] get; set; } + public override int Hoo { [Obsolete(""Derived.Hoo is Obsolete"", false)] get; set; } + public override int Joo { [Obsolete(""Derived.Joo is Obsolete"", true)] get; set; } + public override int Koo { [Obsolete(""Derived.Koo is Obsolete"")] get; set; } +} + +public class Program +{ + public void Main() + { + var derived = new Derived(); + _ = derived.Boo; + _ = derived.Goo; + _ = derived.Hoo; + _ = derived.Joo; + _ = derived.Koo; + } +} +"; + CreateCompilation(source).VerifyDiagnostics( + // (14,31): warning CS0672: Member 'Derived.Boo.get' overrides obsolete member 'Base.Boo.get'. Add the Obsolete attribute to 'Derived.Boo.get'. + // public override int Boo { get; set; } + Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "get").WithArguments("Derived.Boo.get", "Base.Boo.get").WithLocation(14, 31), + // (15,42): warning CS0809: Obsolete member 'Derived.Goo.get' overrides non-obsolete member 'Base.Goo.get' + // public override int Goo { [Obsolete] get; set; } + Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "get").WithArguments("Derived.Goo.get", "Base.Goo.get").WithLocation(15, 42), + // (18,25): warning CS0672: Member 'Derived.Koo' overrides obsolete member 'Base.Koo'. Add the Obsolete attribute to 'Derived.Koo'. + // public override int Koo { [Obsolete("Derived.Koo is Obsolete")] get; set; } + Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "Koo").WithArguments("Derived.Koo", "Base.Koo").WithLocation(18, 25), + // (18,69): warning CS0809: Obsolete member 'Derived.Koo.get' overrides non-obsolete member 'Base.Koo.get' + // public override int Koo { [Obsolete("Derived.Koo is Obsolete")] get; set; } + Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "get").WithArguments("Derived.Koo.get", "Base.Koo.get").WithLocation(18, 69), + // (26,7): warning CS0612: 'Base.Boo.get' is obsolete + // _ = derived.Boo; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "derived.Boo").WithArguments("Base.Boo.get").WithLocation(26, 7), + // (28,13): error CS0619: 'Base.Hoo.get' is obsolete: 'Base.Hoo is Obsolete' + // _ = derived.Hoo; + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "derived.Hoo").WithArguments("Base.Hoo.get", "Base.Hoo is Obsolete").WithLocation(28, 13), + // (29,13): warning CS0618: 'Base.Joo.get' is obsolete: 'Base.Joo is Obsolete' + // _ = derived.Joo; + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "derived.Joo").WithArguments("Base.Joo.get", "Base.Joo is Obsolete").WithLocation(29, 13), + // (30,13): warning CS0618: 'Base.Koo' is obsolete: 'Base.Koo is Obsolete' + // _ = derived.Koo; + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "derived.Koo").WithArguments("Base.Koo", "Base.Koo is Obsolete").WithLocation(30, 13)); } [Fact] @@ -6294,7 +6456,11 @@ public class Test event Action 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(); } + + public static SomeType someProp3 { [Obsolete] get => new SomeType(); } [Obsolete] SomeType this[int x] { get { SomeType y = new SomeType(); return y; } } @@ -6318,9 +6484,12 @@ public class Base {} public class Derived : Base> {} "; CreateCompilation(source).VerifyDiagnostics( + // (27,19): warning CS0612: 'SomeType' is obsolete + // public static SomeType someProp3 { [Obsolete] get => new SomeType(); } + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "SomeType").WithArguments("SomeType").WithLocation(27, 19), // (20,28): warning CS0067: The event 'Test.someEvent' is never used // event Action someEvent; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "someEvent").WithArguments("Test.someEvent")); + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "someEvent").WithArguments("Test.someEvent").WithLocation(20, 28)); } [Fact] @@ -6447,6 +6616,24 @@ public int Prop get { return 1; } set { } } + [Obsolete(""Property"", true)] + public int Prop2 + { + get; set; + } + public int Prop3 + { + get; [Obsolete(""setter"", true)]set; + } + [Obsolete(""Property"", true)] + public int Prop4 + { + get; [Obsolete(""setter"", true)]set; + } + public int Prop5 + { + [Obsolete(""setter"", true)]get; set; + } [Obsolete(""Field"", true)] public int Field; } @@ -6454,6 +6641,10 @@ public int Prop [Att] [Att(Field = 1)] [Att(Prop = 1)] +[Att(Prop2 = 1)] +[Att(Prop3 = 1)] +[Att(Prop4 = 1)] +[Att(Prop5 = 1)] public class Test { [Att()] @@ -6461,24 +6652,172 @@ public static void Main() { } } "; CreateCompilation(source).VerifyDiagnostics( - // (20,6): error CS0619: 'Att.Field' is obsolete: 'Field' + // (37,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor' + // [Att] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att").WithArguments("Att.Att()", "Constructor").WithLocation(37, 2), + // (38,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(38, 6), + // (38,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(38, 2), + // (39,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(39, 6), + // (39,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(39, 2), + // (40,6): error CS0619: 'Att.Prop2' is obsolete: 'Property' + // [Att(Prop2 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop2 = 1").WithArguments("Att.Prop2", "Property").WithLocation(40, 6), + // (40,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor' + // [Att(Prop2 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop2 = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(40, 2), + // (41,6): error CS0619: 'Att.Prop3.set' is obsolete: 'setter' + // [Att(Prop3 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop3 = 1").WithArguments("Att.Prop3.set", "setter").WithLocation(41, 6), + // (41,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor' + // [Att(Prop3 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop3 = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(41, 2), + // (42,6): error CS0619: 'Att.Prop4' is obsolete: 'Property' + // [Att(Prop4 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop4 = 1").WithArguments("Att.Prop4", "Property").WithLocation(42, 6), + // (42,6): error CS0619: 'Att.Prop4.set' is obsolete: 'setter' + // [Att(Prop4 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop4 = 1").WithArguments("Att.Prop4.set", "setter").WithLocation(42, 6), + // (42,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor' + // [Att(Prop4 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop4 = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(42, 2), + // (43,2): error CS0619: 'Att.Att()' is obsolete: 'Constructor' + // [Att(Prop5 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Att(Prop5 = 1)").WithArguments("Att.Att()", "Constructor").WithLocation(43, 2), + // (46,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(46, 6)); + } + + [Fact] + public void TestOverridenObsoleteSetterOnAttributes() + { + var source = @" +using System; + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +public class BaseAtt : Attribute +{ + public virtual int Prop + { + get { return 1; } + [Obsolete(""setter"", true)] set { } + } + + public virtual int Prop1 + { + get { return 1; } + [Obsolete(""setter"", true)] set { } + } + + public virtual int Prop2 + { + get { return 1; } + [Obsolete(""base setter"", true)] set { } + } + + public virtual int Prop3 + { + get { return 1; } + set { } + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +public class DerivedAtt : BaseAtt +{ + public override int Prop + { + get { return 1; } + } + + public override int Prop1 + { + get { return 1; } + set { } + } + + public override int Prop2 + { + get { return 1; } + [Obsolete(""derived setter"", true)] set { } + } + + public override int Prop3 + { + get { return 1; } + [Obsolete(""setter"", true)] set { } + } +} + +[DerivedAtt(Prop = 1)] +[DerivedAtt(Prop1 = 1)] +[DerivedAtt(Prop2 = 1)] +[DerivedAtt(Prop3 = 1)] +public class Test +{ + public static void Main() { } +} +"; + CreateCompilation(source).VerifyDiagnostics( + // (43,9): warning CS0672: Member 'DerivedAtt.Prop1.set' overrides obsolete member 'BaseAtt.Prop1.set'. Add the Obsolete attribute to 'DerivedAtt.Prop1.set'. + // set { } + Diagnostic(ErrorCode.WRN_NonObsoleteOverridingObsolete, "set").WithArguments("DerivedAtt.Prop1.set", "BaseAtt.Prop1.set").WithLocation(43, 9), + // (55,36): warning CS0809: Obsolete member 'DerivedAtt.Prop3.set' overrides non-obsolete member 'BaseAtt.Prop3.set' + // [Obsolete("setter", true)] set { } + Diagnostic(ErrorCode.WRN_ObsoleteOverridingNonObsolete, "set").WithArguments("DerivedAtt.Prop3.set", "BaseAtt.Prop3.set").WithLocation(55, 36), + // (59,13): error CS0619: 'BaseAtt.Prop.set' is obsolete: 'setter' + // [DerivedAtt(Prop = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop = 1").WithArguments("BaseAtt.Prop.set", "setter").WithLocation(59, 13), + // (60,13): error CS0619: 'BaseAtt.Prop1.set' is obsolete: 'setter' + // [DerivedAtt(Prop1 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop1 = 1").WithArguments("BaseAtt.Prop1.set", "setter").WithLocation(60, 13), + // (61,13): error CS0619: 'BaseAtt.Prop2.set' is obsolete: 'base setter' + // [DerivedAtt(Prop2 = 1)] + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Prop2 = 1").WithArguments("BaseAtt.Prop2.set", "base setter").WithLocation(61, 13)); + } + + [Fact] + public void TestObsoleteAttributeOnIndexerAccessors() + { + var source = @" +using System; + +class C1 +{ + public int this[int index] { [Obsolete] get => 1; set {} } +} + +class C2 +{ + public int this[int index] { get => 1; [Obsolete] set {} } +} + +public class Program +{ + public void Main() + { + var c1 = new C1(); + c1[0] = c1[0]; + var c2 = new C2(); + c2[0] = c2[0]; + } +} +"; + CreateCompilation(source).VerifyDiagnostics( + // (19,17): warning CS0612: 'C1.this[int].get' is obsolete + // c1[0] = c1[0]; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "c1[0]").WithArguments("C1.this[int].get").WithLocation(19, 17), + // (21,9): warning CS0612: 'C2.this[int].set' is obsolete + // c2[0] = c2[0]; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "c2[0]").WithArguments("C2.this[int].set").WithLocation(21, 9)); } [Fact] @@ -6771,15 +7110,9 @@ class D }"; var comp = CreateCompilation(new[] { Parse(source0), Parse(source1) }); comp.VerifyDiagnostics( - // (9,17): error CS1667: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on property or event accessors. It is only valid on 'assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter' declarations. - // object R { [Deprecated(null, DeprecationType.Deprecate, 0)] get { return new C(); } } - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter").WithLocation(9, 17), // (7,33): warning CS0612: 'A' is obsolete // object P { get { return new A(); } } - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "A").WithArguments("A").WithLocation(7, 33), - // (9,82): warning CS0612: 'C' is obsolete - // object R { [Deprecated(null, DeprecationType.Deprecate, 0)] get { return new C(); } } - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "C").WithArguments("C").WithLocation(9, 82)); + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "A").WithArguments("A").WithLocation(7, 33)); } [Fact] @@ -6828,15 +7161,12 @@ static void M(object o) { } }"; var comp = CreateCompilation(new[] { Parse(source0), Parse(source1) }); comp.VerifyDiagnostics( - // (21,10): error CS1667: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on property or event accessors. It is only valid on 'assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter' declarations. - // [Deprecated(null, DeprecationType.Deprecate, 0)] remove { M(new C()); } - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter"), // (11,24): warning CS0612: 'A' is obsolete // remove { M(new A()); } - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "A").WithArguments("A"), - // (21,73): warning CS0612: 'C' is obsolete + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "A").WithArguments("A").WithLocation(11, 24), + // (21,10): error CS8423: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on event accessors. It is only valid on 'assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter' declarations. // [Deprecated(null, DeprecationType.Deprecate, 0)] remove { M(new C()); } - Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "C").WithArguments("C").WithLocation(21, 73)); + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "assembly, module, class, struct, enum, constructor, method, property, indexer, field, event, interface, parameter, delegate, return, type parameter").WithLocation(21, 10)); } [Fact] @@ -7973,27 +8303,45 @@ void Test() Class2 x2 = null; Class3 x3 = null; Class4 x4 = null; + Class6 x6 = new Class6(); object x5; x5=x1; x5 = x2; x5 = x3; x5 = x4; + x5 = x6.P1; + x6.P1 = 1; + x5 = x6.P2; + x6.P2 = 1; + x6.E1 += null; + x6.E1 -= null; } } class Class6 { - int P1 + public int P1 { [Deprecated(""P1.get is deprecated."", DeprecationType.Remove, 1)] get { return 1; } + set {} } - event System.Action E1 + public int P2 + { + get + { + return 1; + } + [Deprecated(""P1.get is deprecated."", DeprecationType.Remove, 1)] + set {} + } + + public event System.Action E1 { [Deprecated(""E1.add is deprecated."", DeprecationType.Remove, 1)] add @@ -8008,12 +8356,6 @@ event System.Action E1 var compilation2 = CreateEmptyCompilation(source2, WinRtRefs.Concat(new[] { new CSharpCompilationReference(compilation1) }), TestOptions.ReleaseDll); var expected = new[] { - // (25,10): error CS1667: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. - // [Deprecated("P1.get is deprecated.", DeprecationType.Remove, 1)] - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(25, 10), - // (34,10): error CS1667: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. - // [Deprecated("E1.add is deprecated.", DeprecationType.Remove, 1)] - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(34, 10), // (8,9): warning CS0618: 'Class1' is obsolete: 'Class1 is deprecated.' // Class1 x1 = null; Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "Class1").WithArguments("Class1", "Class1 is deprecated.").WithLocation(8, 9), @@ -8025,7 +8367,16 @@ event System.Action E1 Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Class3").WithArguments("Class3", "Class3 is deprecated.").WithLocation(10, 9), // (11,9): error CS0619: 'Class4' is obsolete: 'Class4 is deprecated.' // Class4 x4 = null; - Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Class4").WithArguments("Class4", "Class4 is deprecated.").WithLocation(11, 9) + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "Class4").WithArguments("Class4", "Class4 is deprecated.").WithLocation(11, 9), + // (19,14): error CS0619: 'Class6.P1.get' is obsolete: 'P1.get is deprecated.' + // x5 = x6.P1; + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "x6.P1").WithArguments("Class6.P1.get", "P1.get is deprecated.").WithLocation(19, 14), + // (22,9): error CS0619: 'Class6.P2.set' is obsolete: 'P1.get is deprecated.' + // x6.P2 = 1; + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "x6.P2").WithArguments("Class6.P2.set", "P1.get is deprecated.").WithLocation(22, 9), + // (52,10): error CS8423: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. + // [Deprecated("E1.add is deprecated.", DeprecationType.Remove, 1)] + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(52, 10) }; compilation2.VerifyDiagnostics(expected); @@ -8970,5 +9321,139 @@ 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; +/// +/// +/// +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 +{ + public void M() => Prop = Prop; + + [Obsolete] + public int Prop { [Obsolete] get; [Obsolete] set; } +} +"; + + CreateCompilation(code).VerifyDiagnostics( + // (5,24): warning CS0612: 'C.Prop' is obsolete + // public void M() => Prop = Prop; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Prop").WithArguments("C.Prop").WithLocation(5, 24), + // (5,24): warning CS0612: 'C.Prop.set' is obsolete + // public void M() => Prop = Prop; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Prop").WithArguments("C.Prop.set").WithLocation(5, 24), + // (5,31): warning CS0612: 'C.Prop' is obsolete + // public void M() => Prop = Prop; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Prop").WithArguments("C.Prop").WithLocation(5, 31), + // (5,31): warning CS0612: 'C.Prop.get' is obsolete + // public void M() => Prop = Prop; + Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Prop").WithArguments("C.Prop.get").WithLocation(5, 31)); + } + + [Fact] + public void TestObsoleteOnPropertyAccessorCSharp7() + { + var code = @" +using System; +class C +{ + public int Prop { [Obsolete] get; set; } +} +"; + + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)).VerifyDiagnostics( + // (4,24): error CS8652: The feature 'obsolete on property accessor' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public int Prop { [Obsolete] get; set; } + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Obsolete").WithArguments("obsolete on property accessor").WithLocation(5, 24)); + } + + [Fact] + public void TestDeprecatedOnPropertyAccessorCSharp7() + { + var code = @" +using Windows.Foundation.Metadata; +class C +{ + public int Prop { [Deprecated(""don't use this"", DeprecationType.Remove, 50331648u)] get; set; } +} +"; + + CreateEmptyCompilation(code, references: WinRtRefs, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)).VerifyDiagnostics( + // (5,24): error CS8652: The feature 'obsolete on property accessor' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public int Prop { [Deprecated("don't use this", DeprecationType.Remove, 50331648u)] get; set; } + Diagnostic(ErrorCode.ERR_FeatureInPreview, @"Deprecated(""don't use this"", DeprecationType.Remove, 50331648u)").WithArguments("obsolete on property accessor").WithLocation(5, 24)); + } + + [Fact] + public void TestObsoleteOnEventAccessorCSharp7() + { + var code = @" +using System; +class C +{ + public event System.Action E + { + [Obsolete] + add + { + } + remove + { + } + } +} +"; + + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)).VerifyDiagnostics( + // (7,10): error CS8423: Attribute 'System.ObsoleteAttribute' is not valid on event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. + // [Obsolete] + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(7, 10)); + } + + [Fact] + public void TestDeprecatedOnEventAccessorCSharp7() + { + var code = @" +using Windows.Foundation.Metadata; +class C +{ + public event System.Action E + { + [Deprecated(""don't use this"", DeprecationType.Remove, 50331648u)] + add + { + } + remove + { + } + } +} +"; + + CreateEmptyCompilation(code, references: WinRtRefs, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)).VerifyDiagnostics( + // (7,10): error CS8423: Attribute 'Windows.Foundation.Metadata.DeprecatedAttribute' is not valid on event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. + // [Deprecated("don't use this", DeprecationType.Remove, 50331648u)] + Diagnostic(ErrorCode.ERR_AttributeNotOnEventAccessor, "Deprecated").WithArguments("Windows.Foundation.Metadata.DeprecatedAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate").WithLocation(7, 10)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 791aa464ef34..92f1443bb56e 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -15233,9 +15233,6 @@ public static void Main() } "; var comp = CreateCompilation(text).VerifyDiagnostics( - // (8,10): error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations. - // [Obsolete] // CS1667 - Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "Obsolete").WithArguments("System.ObsoleteAttribute", "class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate"), // (10,10): error CS1667: Attribute 'System.Diagnostics.Conditional' is not valid on property or event accessors. It is only valid on 'class, method' declarations. // [System.Diagnostics.Conditional("Bernard")] Diagnostic(ErrorCode.ERR_AttributeNotOnAccessor, "System.Diagnostics.Conditional").WithArguments("System.Diagnostics.Conditional", "class, method")