提交 1b6bac5b 编写于 作者: C Charles Stoner

Do not suppress warnings within [Experimental] member

上级 03b5f4c3
......@@ -559,52 +559,41 @@ internal static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag dia
{
Debug.Assert(diagnostics != null);
if (symbol.ObsoleteState == ThreeState.False)
{
return ThreeState.False;
}
var data = symbol.ObsoleteAttributeData;
if (data == null)
{
// Obsolete attribute has errors.
return ThreeState.False;
}
// If we haven't cracked attributes on the symbol at all or we haven't
// cracked attribute arguments enough to be able to report diagnostics for
// ObsoleteAttribute, store the symbol so that we can report diagnostics at a
// later stage.
if (symbol.ObsoleteState == ThreeState.Unknown)
{
diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation());
return ThreeState.Unknown;
}
// After this point, always return True.
var inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(containingMember);
// If we are in a context that is already obsolete, there is no point reporting
// more obsolete diagnostics.
if (inObsoleteContext == ThreeState.True)
{
return ThreeState.True;
}
// If the context is unknown, then store the symbol so that we can do this check at a
// later stage
else if (inObsoleteContext == ThreeState.Unknown)
{
diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation());
return ThreeState.True;
}
// We have all the information we need to report diagnostics right now. So do it.
var diagInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location);
if (diagInfo != null)
{
diagnostics.Add(diagInfo, node.GetLocation());
return ThreeState.True;
var kind = symbol.ObsoleteKind;
switch (kind)
{
case ObsoleteAttributeKind.None:
return ThreeState.False;
case ObsoleteAttributeKind.Uninitialized:
// If we haven't cracked attributes on the symbol at all or we haven't
// cracked attribute arguments enough to be able to report diagnostics for
// ObsoleteAttribute, store the symbol so that we can report diagnostics at a
// later stage.
diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation());
return ThreeState.Unknown;
}
kind = containingMember.GetObsoleteContextKind();
switch (kind)
{
case ObsoleteAttributeKind.None:
case ObsoleteAttributeKind.Experimental:
// We have all the information we need to report diagnostics right now. So do it.
var diagInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location);
if (diagInfo != null)
{
diagnostics.Add(diagInfo, node.GetLocation());
}
break;
case ObsoleteAttributeKind.Uninitialized:
// If the context is unknown, then store the symbol so that we can do this check at a
// later stage
diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation());
break;
default:
// If we are in a context that is already obsolete, there is no point reporting
// more obsolete diagnostics.
break;
}
return ThreeState.True;
......
......@@ -33,10 +33,10 @@ internal override DiagnosticInfo GetResolvedInfo()
if (_symbol.ObsoleteState == ThreeState.True)
{
var inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(_containingSymbol, forceComplete: true);
Debug.Assert(inObsoleteContext != ThreeState.Unknown);
var kind = _containingSymbol.GetObsoleteContextKind(forceComplete: true);
Debug.Assert(kind != ObsoleteAttributeKind.Uninitialized);
if (inObsoleteContext == ThreeState.False)
if (kind == ObsoleteAttributeKind.None)
{
DiagnosticInfo info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(_symbol, _binderFlags);
if (info != null)
......
......@@ -39,37 +39,42 @@ internal static ObsoleteAttributeData GetObsoleteDataFromMetadata(EntityHandle t
/// This method checks to see if the given symbol is Obsolete or if any symbol in the parent hierarchy is Obsolete.
/// </summary>
/// <returns>
/// True if some symbol in the parent hierarchy is known to be Obsolete. Unknown if any
/// symbol's Obsoleteness is Unknown. False, if we are certain that no symbol in the parent
/// hierarchy is Obsolete.
/// Uninitialized if attributes have not been cracked yet.
/// </returns>
internal static ThreeState GetObsoleteContextState(Symbol symbol, bool forceComplete = false)
internal static ObsoleteAttributeKind GetObsoleteContextKind(this Symbol symbol, bool forceComplete = false)
{
if ((object)symbol == null)
return ThreeState.False;
// For Property or Event accessors, check the associated property or event instead.
if (symbol.IsAccessor())
{
symbol = ((MethodSymbol)symbol).AssociatedSymbol;
}
// If this is the backing field of an event, look at the event instead.
else if (symbol.Kind == SymbolKind.Field && (object)((FieldSymbol)symbol).AssociatedSymbol != null)
while ((object)symbol != null)
{
symbol = ((FieldSymbol)symbol).AssociatedSymbol;
}
// 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 this is the backing field of an event, look at the event instead.
var associatedSymbol = ((FieldSymbol)symbol).AssociatedSymbol;
if ((object)associatedSymbol != null)
{
symbol = associatedSymbol;
}
}
if (forceComplete)
{
symbol.ForceCompleteObsoleteAttribute();
}
if (forceComplete)
{
symbol.ForceCompleteObsoleteAttribute();
}
if (symbol.ObsoleteState != ThreeState.False)
{
return symbol.ObsoleteState;
var kind = symbol.ObsoleteKind;
if (kind != ObsoleteAttributeKind.None)
{
return kind;
}
symbol = symbol.ContainingSymbol;
}
return GetObsoleteContextState(symbol.ContainingSymbol, forceComplete);
return ObsoleteAttributeKind.None;
}
/// <summary>
......@@ -79,10 +84,10 @@ internal static ThreeState GetObsoleteContextState(Symbol symbol, bool forceComp
internal static DiagnosticInfo CreateObsoleteDiagnostic(Symbol symbol, BinderFlags location)
{
var data = symbol.ObsoleteAttributeData;
Debug.Assert(data != null);
if (data == null)
{
// ObsoleteAttribute had errors.
return null;
}
......
......@@ -1018,22 +1018,28 @@ internal ThreeState ObsoleteState
{
get
{
var data = this.ObsoleteAttributeData;
if (data == null)
{
return ThreeState.False;
}
else if (data.IsUninitialized)
switch (ObsoleteKind)
{
return ThreeState.Unknown;
}
else
{
return ThreeState.True;
case ObsoleteAttributeKind.None:
return ThreeState.False;
case ObsoleteAttributeKind.Uninitialized:
return ThreeState.Unknown;
default:
return ThreeState.True;
}
}
}
internal ObsoleteAttributeKind ObsoleteKind
{
get
{
var data = this.ObsoleteAttributeData;
return (data == null) ? ObsoleteAttributeKind.None : data.Kind;
}
}
/// <summary>
/// Returns data decoded from <see cref="ObsoleteAttribute"/> attribute or null if there is no <see cref="ObsoleteAttribute"/> attribute.
/// This property returns <see cref="Microsoft.CodeAnalysis.ObsoleteAttributeData.Uninitialized"/> if attribute arguments haven't been decoded yet.
......
......@@ -167,8 +167,6 @@ static void Main()
Diagnostic(ErrorCode.WRN_Experimental, "((I)o).F()").WithArguments("I.F()").WithLocation(11, 9));
}
// [Obsolete] and [Deprecated] diagnostics are not
// suppressed inside [Experimental] type.
[Fact]
public void TestExperimentalTypeWithDeprecatedAndObsoleteMembers()
{
......@@ -227,8 +225,62 @@ static void F(A a)
Diagnostic(ErrorCode.WRN_Experimental, "A.B").WithArguments("A.B").WithLocation(27, 14));
}
// Diagnostics for [Obsolete] members
// are not suppressed in [Experimental] types.
[Fact]
public void TestObsoleteMembersInExperimentalType()
{
var source =
@"using System;
using Windows.Foundation.Metadata;
class A
{
internal void F0() { }
[Deprecated("""", DeprecationType.Deprecate, 0)]
internal void F1() { }
[Deprecated("""", DeprecationType.Remove, 0)]
internal void F2() { }
[Obsolete("""", false)]
internal void F3() { }
[Obsolete("""", true)]
internal void F4() { }
[Experimental]
internal class B { }
}
[Experimental]
class C
{
static void F(A a)
{
a.F0();
a.F1();
a.F2();
a.F3();
a.F4();
(new A.B()).ToString();
}
}";
var comp = CreateCompilationWithMscorlibAndSystemCore(new[] { Parse(DeprecatedAttributeSource), Parse(ExperimentalAttributeSource), Parse(source) });
comp.VerifyDiagnostics(
// (23,9): warning CS0618: 'A.F1()' is obsolete: ''
// a.F1();
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "a.F1()").WithArguments("A.F1()", "").WithLocation(23, 9),
// (24,9): error CS0619: 'A.F2()' is obsolete: ''
// a.F2();
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "a.F2()").WithArguments("A.F2()", "").WithLocation(24, 9),
// (25,9): warning CS0618: 'A.F3()' is obsolete: ''
// a.F3();
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "a.F3()").WithArguments("A.F3()", "").WithLocation(25, 9),
// (26,9): error CS0619: 'A.F4()' is obsolete: ''
// a.F4();
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "a.F4()").WithArguments("A.F4()", "").WithLocation(26, 9),
// (27,14): warning CS8305: 'A.B' is for evaluation purposes only and is subject to change or removal in future updates.
// (new A.B()).ToString();
Diagnostic(ErrorCode.WRN_Experimental, "A.B").WithArguments("A.B").WithLocation(27, 14));
}
// Diagnostics for [Experimental] types
// are suppressed in [Obsolete] members.
// are not suppressed in [Obsolete] members.
[Fact]
public void TestExperimentalTypeInObsoleteMember()
{
......
......@@ -7,6 +7,7 @@ namespace Microsoft.CodeAnalysis
internal enum ObsoleteAttributeKind
{
None,
Uninitialized,
Obsolete,
Deprecated,
Experimental,
......@@ -17,7 +18,7 @@ internal enum ObsoleteAttributeKind
/// </summary>
internal sealed class ObsoleteAttributeData
{
public static readonly ObsoleteAttributeData Uninitialized = new ObsoleteAttributeData(ObsoleteAttributeKind.None, null, false);
public static readonly ObsoleteAttributeData Uninitialized = new ObsoleteAttributeData(ObsoleteAttributeKind.Uninitialized, null, false);
public static readonly ObsoleteAttributeData Experimental = new ObsoleteAttributeData(ObsoleteAttributeKind.Experimental, null, false);
public ObsoleteAttributeData(ObsoleteAttributeKind kind, string message, bool isError)
......
......@@ -895,43 +895,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(context IsNot Nothing)
Debug.Assert(symbol IsNot Nothing)
If symbol.ObsoleteState = ThreeState.False Then
Return
End If
Dim data = symbol.ObsoleteAttributeData
If data Is Nothing Then
' Obsolete attribute has errors.
Return
End If
' If we haven't cracked attributes on the symbol at all or we haven't
' cracked attribute arguments enough to be able to report diagnostics for
' ObsoleteAttribute, store the symbol so that we can report diagnostics at a
' later stage.
If symbol.ObsoleteState = ThreeState.Unknown OrElse data.IsUninitialized Then
diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation())
Return
End If
Dim inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(context)
' If we are in a context that is already obsolete, there is no point reporting
' more obsolete diagnostics.
If inObsoleteContext = ThreeState.True Then
Return
ElseIf inObsoleteContext = ThreeState.Unknown Then
' If the context is unknown, then store the symbol so that we can do this check at a
' later stage
diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation())
Return
End If
' We have all the information we need to report diagnostics right now. So do it.
Dim info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol)
If info IsNot Nothing Then
diagnostics.Add(info, node.GetLocation())
End If
Dim kind = symbol.ObsoleteKind
Select Case kind
Case ObsoleteAttributeKind.None
Return
Case ObsoleteAttributeKind.Uninitialized
' If we haven't cracked attributes on the symbol at all or we haven't
' cracked attribute arguments enough to be able to report diagnostics for
' ObsoleteAttribute, store the symbol so that we can report diagnostics at a
' later stage.
diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation())
Return
End Select
kind = ObsoleteAttributeHelpers.GetObsoleteContextKind(context)
Select Case kind
Case ObsoleteAttributeKind.None, ObsoleteAttributeKind.Experimental
' We have all the information we need to report diagnostics right now. So do it.
Dim info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol)
If info IsNot Nothing Then
diagnostics.Add(info, node.GetLocation())
End If
Case ObsoleteAttributeKind.Uninitialized
' If the context is unknown, then store the symbol so that we can do this check at a
' later stage
diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation())
Case Else
' If we are in a context that is already obsolete, there is no point reporting
' more obsolete diagnostics.
End Select
End Sub
Friend Overridable ReadOnly Property SuppressObsoleteDiagnostics As Boolean
......
......@@ -26,10 +26,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
_symbol.ForceCompleteObsoleteAttribute()
If _symbol.ObsoleteState = ThreeState.True Then
Dim inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(_containingSymbol, forceComplete:=True)
Debug.Assert(inObsoleteContext <> ThreeState.Unknown)
Dim kind = ObsoleteAttributeHelpers.GetObsoleteContextKind(_containingSymbol, forceComplete:=True)
Debug.Assert(kind <> ObsoleteAttributeKind.Uninitialized)
If inObsoleteContext = ThreeState.False Then
If kind = ObsoleteAttributeKind.None Then
Dim info As DiagnosticInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(_symbol)
If info IsNot Nothing Then
Interlocked.CompareExchange(Me._lazyActualObsoleteDiagnostic, info, Nothing)
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Diagnostics
Imports System.Threading
Imports System.Reflection.Metadata
Imports System.Threading
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
......@@ -32,50 +32,39 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' This method checks to see if the given symbol is Obsolete or if any symbol in the parent hierarchy is Obsolete.
''' </summary>
''' <returns>
''' True if some symbol in the parent hierarchy is known to be Obsolete. Unknown if any
''' symbol's Obsoleteness is Unknown. False, if we are certain that no symbol in the parent
''' hierarchy is Obsolete.
''' Uninitialized if attributes have not been cracked yet.
''' </returns>
Friend Shared Function GetObsoleteContextState(symbol As Symbol, Optional forceComplete As Boolean = False) As ThreeState
If symbol Is Nothing Then
Return ThreeState.False
End If
If forceComplete Then
symbol.ForceCompleteObsoleteAttribute()
End If
Friend Shared Function GetObsoleteContextKind(symbol As Symbol, Optional forceComplete As Boolean = False) As ObsoleteAttributeKind
While symbol IsNot Nothing
' For property or event accessors, check the associated property or event instead.
If symbol.IsAccessor() Then
symbol = DirectCast(symbol, MethodSymbol).AssociatedSymbol
End If
Dim associatedPropertyOrEvent = If(symbol.IsAccessor(), DirectCast(symbol, MethodSymbol).AssociatedSymbol, Nothing)
If forceComplete Then
symbol.ForceCompleteObsoleteAttribute()
End If
' If this is an event accessor, then consider the event itself for context since
' event accessors cannot be marked obsolete.
If associatedPropertyOrEvent IsNot Nothing AndAlso associatedPropertyOrEvent.Kind = SymbolKind.Event Then
symbol = DirectCast(symbol, MethodSymbol).AssociatedSymbol
End If
Dim kind = symbol.ObsoleteKind
If kind <> ObsoleteAttributeKind.None Then
Return kind
End If
If symbol.ObsoleteState <> ThreeState.False Then
Return symbol.ObsoleteState
End If
symbol = symbol.ContainingSymbol
End While
' If this is a property accessor then check the property for obsoleteness as well so that we suppress
' obsolete diagnostics anywhere inside a property.
If associatedPropertyOrEvent IsNot Nothing AndAlso associatedPropertyOrEvent.Kind = SymbolKind.Property Then
Return GetObsoleteContextState(associatedPropertyOrEvent, forceComplete)
Else
Return GetObsoleteContextState(symbol.ContainingSymbol, forceComplete)
End If
Return ObsoleteAttributeKind.None
End Function
''' <summary>
''' Create a diagnostic for the given symbol. This could be an error or a warning based on
''' the ObsoleteAttribute's arguments.
''' </summary>
Friend Shared Function CreateObsoleteDiagnostic(symbol As Symbol) As DiagnosticInfo
Dim data = symbol.ObsoleteAttributeData
Debug.Assert(data IsNot Nothing)
If data Is Nothing Then
' ObsoleteAttribute had errors.
Return Nothing
End If
......
......@@ -423,15 +423,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' This property returns Unknown if the Obsolete Attribute hasn't been cracked yet.
''' </summary>
Friend ReadOnly Property ObsoleteState As ThreeState
Get
Select Case ObsoleteKind
Case ObsoleteAttributeKind.None
Return ThreeState.False
Case ObsoleteAttributeKind.Uninitialized
Return ThreeState.Unknown
Case Else
Return ThreeState.True
End Select
End Get
End Property
Friend ReadOnly Property ObsoleteKind As ObsoleteAttributeKind
Get
Dim data = Me.ObsoleteAttributeData
If data Is Nothing Then
Return ThreeState.False
ElseIf data Is ObsoleteAttributeData.Uninitialized Then
Return ThreeState.Unknown
Else
Return ThreeState.True
End If
Return If(data Is Nothing, ObsoleteAttributeKind.None, data.Kind)
End Get
End Property
......
......@@ -210,8 +210,6 @@ End Class
</compilation>
End Sub
' <Obsolete> and <Deprecated> diagnostics are not
' suppressed inside <Experimental> type.
<Fact()>
Public Sub TestExperimentalTypeWithDeprecatedAndObsoleteMembers()
Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource)
......@@ -282,8 +280,74 @@ BC42380: 'A.B' is for evaluation purposes only and is subject to change or remov
</errors>)
End Sub
' Diagnostics for <Obsolete> members
' are not suppressed in <Experimental> types.
<Fact()>
Public Sub TestObsoleteMembersInExperimentalType()
Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource)
comp0.AssertNoDiagnostics()
Dim ref0 = comp0.EmitToImageReference()
Dim source =
<compilation>
<file><![CDATA[
Imports System
Imports Windows.Foundation.Metadata
Class A
Friend Sub F0()
End Sub
<Deprecated("", DeprecationType.Deprecate, 0)>
Friend Sub F1()
End Sub
<Deprecated("", DeprecationType.Remove, 0)>
Friend Sub F2()
End Sub
<Obsolete("", False)>
Friend Sub F3()
End Sub
<Obsolete("", True)>
Friend Sub F4()
End Sub
<Experimental>
Friend Class B
End Class
End Class
<Experimental>
Class C
Shared Sub F(a As A)
a.F0()
a.F1()
a.F2()
a.F3()
a.F4()
Dim b = New A.B()
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CreateCompilationWithMscorlib(source, references:={ref0})
comp.AssertTheseDiagnostics(<errors>
BC40008: 'Friend Sub F1()' is obsolete.
a.F1()
~~~~~~
BC31075: 'Friend Sub F2()' is obsolete.
a.F2()
~~~~~~
BC40008: 'Friend Sub F3()' is obsolete.
a.F3()
~~~~~~
BC31075: 'Friend Sub F4()' is obsolete.
a.F4()
~~~~~~
BC42380: 'A.B' is for evaluation purposes only and is subject to change or removal in future updates.
Dim b = New A.B()
~~~
</errors>)
End Sub
' Diagnostics for <Experimental> types
' are suppressed in [Obsolete] members.
' are not suppressed in <Obsolete> members.
<Fact()>
Public Sub TestExperimentalTypeInObsoleteMember()
Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册