提交 f6d61adf 编写于 作者: N nmgafter

667579-DebuggerHidden iterator methods should hide MoveNext (changeset 1310286)

上级 253a92f2
...@@ -90,13 +90,13 @@ protected override void GenerateMethodImplementations() ...@@ -90,13 +90,13 @@ protected override void GenerateMethodImplementations()
var IAsyncStateMachine_SetStateMachine = F.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_SetStateMachine); var IAsyncStateMachine_SetStateMachine = F.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_SetStateMachine);
// Add IAsyncStateMachine.MoveNext() // Add IAsyncStateMachine.MoveNext()
var moveNextMethod = OpenMethodImplementation(IAsyncStateMachine_MoveNext, "MoveNext", asyncKickoffMethod: this.method, hasMethodBodyDependency: true); var moveNextMethod = OpenMethodImplementation(IAsyncStateMachine_MoveNext, "MoveNext", asyncKickoffMethod: this.method, hasMethodBodyDependency: true, debuggerHidden: IsDebuggerHidden(this.method), generateDebugInfo: true);
GenerateMoveNext(moveNextMethod); GenerateMoveNext(moveNextMethod);
// Add IAsyncStateMachine.SetStateMachine() // Add IAsyncStateMachine.SetStateMachine()
OpenMethodImplementation(IAsyncStateMachine_SetStateMachine, "SetStateMachine", debuggerHidden: true, hasMethodBodyDependency: false); OpenMethodImplementation(IAsyncStateMachine_SetStateMachine, "SetStateMachine", debuggerHidden: true, generateDebugInfo: false, hasMethodBodyDependency: false);
// SetStateMachine is used to initialize the underlying AsyncMethodBuilder's reference to the boxed copy of the state machine. // SetStateMachine is used to initialize the underlying AsyncMethodBuilder's reference to the boxed copy of the state machine.
// If the state machine is a class there is no copy made and thus the initialization is not necessary. // If the state machine is a class there is no copy made and thus the initialization is not necessary.
......
...@@ -134,8 +134,8 @@ private void GenerateEnumeratorImplementation() ...@@ -134,8 +134,8 @@ private void GenerateEnumeratorImplementation()
// Add bool IEnumerator.MoveNext() and void IDisposable.Dispose() // Add bool IEnumerator.MoveNext() and void IDisposable.Dispose()
{ {
var disposeMethod = OpenMethodImplementation(IDisposable_Dispose, debuggerHidden: true, hasMethodBodyDependency: true); var disposeMethod = OpenMethodImplementation(IDisposable_Dispose, debuggerHidden: true, generateDebugInfo: false, hasMethodBodyDependency: true);
var moveNextMethod = OpenMethodImplementation(IEnumerator_MoveNext, methodName: WellKnownMemberNames.MoveNextMethodName, hasMethodBodyDependency: true); var moveNextMethod = OpenMethodImplementation(IEnumerator_MoveNext, methodName: WellKnownMemberNames.MoveNextMethodName, hasMethodBodyDependency: true, debuggerHidden: IsDebuggerHidden(this.method));
GenerateMoveNextAndDispose(moveNextMethod, disposeMethod); GenerateMoveNextAndDispose(moveNextMethod, disposeMethod);
} }
...@@ -147,7 +147,7 @@ private void GenerateEnumeratorImplementation() ...@@ -147,7 +147,7 @@ private void GenerateEnumeratorImplementation()
// Add void IEnumerator.Reset() // Add void IEnumerator.Reset()
{ {
OpenMethodImplementation(IEnumerator_Reset, debuggerHidden: true, hasMethodBodyDependency: false); OpenMethodImplementation(IEnumerator_Reset, debuggerHidden: true, generateDebugInfo: false, hasMethodBodyDependency: false);
F.CloseMethod(F.Throw(F.New(F.WellKnownType(WellKnownType.System_NotSupportedException)))); F.CloseMethod(F.Throw(F.New(F.WellKnownType(WellKnownType.System_NotSupportedException))));
} }
...@@ -184,7 +184,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI ...@@ -184,7 +184,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
// The implementation doesn't depend on the method body of the iterator method. // The implementation doesn't depend on the method body of the iterator method.
// Only on it's parameters and staticness. // Only on it's parameters and staticness.
var getEnumeratorGeneric = OpenMethodImplementation(IEnumerableOfElementType_GetEnumerator, debuggerHidden: true, hasMethodBodyDependency: false); var getEnumeratorGeneric = OpenMethodImplementation(IEnumerableOfElementType_GetEnumerator, debuggerHidden: true, generateDebugInfo: false, hasMethodBodyDependency: false);
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance(); var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();
var resultVariable = F.SynthesizedLocal(stateMachineClass, null); // iteratorClass result; var resultVariable = F.SynthesizedLocal(stateMachineClass, null); // iteratorClass result;
...@@ -263,7 +263,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI ...@@ -263,7 +263,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree())); F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree()));
// Generate IEnumerable.GetEnumerator // Generate IEnumerable.GetEnumerator
var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator, debuggerHidden: true); var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator, debuggerHidden: true, generateDebugInfo: false);
F.CloseMethod(F.Return(F.Call(F.This(), getEnumeratorGeneric))); F.CloseMethod(F.Return(F.Call(F.This(), getEnumeratorGeneric)));
} }
......
...@@ -247,11 +247,12 @@ private BoundStatement ReplaceOriginalMethod() ...@@ -247,11 +247,12 @@ private BoundStatement ReplaceOriginalMethod()
protected SynthesizedImplementationMethod OpenMethodImplementation( protected SynthesizedImplementationMethod OpenMethodImplementation(
MethodSymbol methodToImplement, MethodSymbol methodToImplement,
string methodName = null, string methodName = null,
bool debuggerHidden = false, bool debuggerHidden = false,
bool generateDebugInfo = true,
bool hasMethodBodyDependency = false, bool hasMethodBodyDependency = false,
MethodSymbol asyncKickoffMethod = null) MethodSymbol asyncKickoffMethod = null)
{ {
var result = new SynthesizedStateMachineMethod(methodName, methodToImplement, F.CurrentClass, asyncKickoffMethod, null, debuggerHidden, hasMethodBodyDependency); var result = new SynthesizedStateMachineMethod(methodName, methodToImplement, F.CurrentClass, asyncKickoffMethod, null, debuggerHidden, generateDebugInfo, hasMethodBodyDependency);
F.ModuleBuilderOpt.AddSynthesizedDefinition(F.CurrentClass, result); F.ModuleBuilderOpt.AddSynthesizedDefinition(F.CurrentClass, result);
F.CurrentMethod = result; F.CurrentMethod = result;
return result; return result;
...@@ -271,5 +272,16 @@ private BoundStatement ReplaceOriginalMethod() ...@@ -271,5 +272,16 @@ private BoundStatement ReplaceOriginalMethod()
F.CurrentMethod = getter; F.CurrentMethod = getter;
return getter; return getter;
} }
protected bool IsDebuggerHidden(MethodSymbol method)
{
var debuggerHiddenAttribute = this.compilationState.Compilation.GetWellKnownType(WellKnownType.System_Diagnostics_DebuggerHiddenAttribute);
foreach (var a in this.method.GetAttributes())
{
if (a.AttributeClass == debuggerHiddenAttribute) return true;
}
return false;
}
} }
} }
\ No newline at end of file
...@@ -19,8 +19,9 @@ internal sealed class SynthesizedStateMachineMethod : SynthesizedImplementationM ...@@ -19,8 +19,9 @@ internal sealed class SynthesizedStateMachineMethod : SynthesizedImplementationM
MethodSymbol asyncKickoffMethod, MethodSymbol asyncKickoffMethod,
PropertySymbol associatedProperty, PropertySymbol associatedProperty,
bool debuggerHidden, bool debuggerHidden,
bool generateDebugInfo,
bool hasMethodBodyDependency) bool hasMethodBodyDependency)
: base(interfaceMethod, implementingType, name, debuggerHidden, associatedProperty, asyncKickoffMethod) : base(interfaceMethod, implementingType, name, debuggerHidden, generateDebugInfo, associatedProperty, asyncKickoffMethod)
{ {
this.hasMethodBodyDependency = hasMethodBodyDependency; this.hasMethodBodyDependency = hasMethodBodyDependency;
} }
......
...@@ -29,6 +29,7 @@ internal class SynthesizedStateMachineProperty : PropertySymbol, ISynthesizedMet ...@@ -29,6 +29,7 @@ internal class SynthesizedStateMachineProperty : PropertySymbol, ISynthesizedMet
asyncKickoffMethod: null, asyncKickoffMethod: null,
associatedProperty: this, associatedProperty: this,
debuggerHidden: debuggerHidden, debuggerHidden: debuggerHidden,
generateDebugInfo: !debuggerHidden,
hasMethodBodyDependency: hasMethodBodyDependency); hasMethodBodyDependency: hasMethodBodyDependency);
} }
......
...@@ -14,6 +14,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol ...@@ -14,6 +14,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
private readonly MethodSymbol interfaceMethod; private readonly MethodSymbol interfaceMethod;
private readonly NamedTypeSymbol implementingType; private readonly NamedTypeSymbol implementingType;
private readonly bool debuggerHidden; private readonly bool debuggerHidden;
private readonly bool generateDebugInfo;
private readonly PropertySymbol associatedProperty; private readonly PropertySymbol associatedProperty;
private readonly MethodSymbol asyncKickoffMethod; private readonly MethodSymbol asyncKickoffMethod;
...@@ -29,6 +30,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol ...@@ -29,6 +30,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
NamedTypeSymbol implementingType, NamedTypeSymbol implementingType,
string name = null, string name = null,
bool debuggerHidden = false, bool debuggerHidden = false,
bool generateDebugInfo = true,
PropertySymbol associatedProperty = null, PropertySymbol associatedProperty = null,
MethodSymbol asyncKickoffMethod = null) MethodSymbol asyncKickoffMethod = null)
{ {
...@@ -39,6 +41,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol ...@@ -39,6 +41,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
this.interfaceMethod = interfaceMethod; this.interfaceMethod = interfaceMethod;
this.implementingType = implementingType; this.implementingType = implementingType;
this.debuggerHidden = debuggerHidden; this.debuggerHidden = debuggerHidden;
this.generateDebugInfo = generateDebugInfo;
this.associatedProperty = associatedProperty; this.associatedProperty = associatedProperty;
this.explicitInterfaceImplementations = ImmutableArray.Create<MethodSymbol>(interfaceMethod); this.explicitInterfaceImplementations = ImmutableArray.Create<MethodSymbol>(interfaceMethod);
this.asyncKickoffMethod = asyncKickoffMethod; this.asyncKickoffMethod = asyncKickoffMethod;
...@@ -100,7 +103,7 @@ internal sealed override void AddSynthesizedAttributes(ModuleCompilationState co ...@@ -100,7 +103,7 @@ internal sealed override void AddSynthesizedAttributes(ModuleCompilationState co
internal override bool GenerateDebugInfo internal override bool GenerateDebugInfo
{ {
get { return !debuggerHidden; } get { return generateDebugInfo; }
} }
public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters
......
...@@ -1009,6 +1009,54 @@ static IEnumerable<int> M() ...@@ -1009,6 +1009,54 @@ static IEnumerable<int> M()
</scope> </scope>
</method> </method>
</methods> </methods>
</symbols>";
AssertXmlEqual(expected, actual);
}
[Fact, WorkItem(667579, "DevDiv")]
public void DebuggerHiddenIterator()
{
var text = @"
using System;
using System.Collections.Generic;
using System.Diagnostics;
class C
{
static void Main(string[] args)
{
foreach (var x in F()) ;
}
[DebuggerHidden]
static IEnumerable<int> F()
{
throw new Exception();
yield break;
}
}";
string actual = GetPdbXml(text, TestOptions.DebugDll, "C+<F>d__0.MoveNext");
string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<symbols>
<methods>
<method containingType=""C+&lt;F&gt;d__0"" name=""MoveNext"" parameterNames="""">
<customDebugInfo version=""4"" count=""1"">
<forward version=""4"" kind=""ForwardInfo"" size=""12"" declaringType=""C"" methodName=""Main"" parameterNames=""args"" />
</customDebugInfo>
<sequencepoints total=""3"">
<entry il_offset=""0x0"" hidden=""true"" start_row=""16707566"" start_column=""0"" end_row=""16707566"" end_column=""0"" file_ref=""0"" />
<entry il_offset=""0x19"" start_row=""15"" start_column=""5"" end_row=""15"" end_column=""6"" file_ref=""0"" />
<entry il_offset=""0x1a"" start_row=""16"" start_column=""9"" end_row=""16"" end_column=""31"" file_ref=""0"" />
</sequencepoints>
<locals>
<local name=""CS$524$0000"" il_index=""0"" il_start=""0x0"" il_end=""0x20"" attributes=""1"" />
</locals>
<scope startOffset=""0x0"" endOffset=""0x20"">
<local name=""CS$524$0000"" il_index=""0"" il_start=""0x0"" il_end=""0x20"" attributes=""1"" />
</scope>
</method>
</methods>
</symbols>"; </symbols>";
AssertXmlEqual(expected, actual); AssertXmlEqual(expected, actual);
} }
......
...@@ -30,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -30,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
asyncKind As AsyncMethodKind, asyncKind As AsyncMethodKind,
compilationState As TypeCompilationState, compilationState As TypeCompilationState,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
generateDebugInfo As boolean) generateDebugInfo As Boolean)
MyBase.New(body, method, compilationState, diagnostics, generateDebugInfo) MyBase.New(body, method, compilationState, diagnostics, generateDebugInfo)
...@@ -62,10 +62,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -62,10 +62,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Sub End Sub
Friend Shared Function CreateAsyncStateMachine(method As MethodSymbol, Friend Shared Function CreateAsyncStateMachine(method As MethodSymbol,
typeIndex As Integer, typeIndex As Integer,
typeKind As TypeKind, typeKind As TypeKind,
valueTypeSymbol As NamedTypeSymbol, valueTypeSymbol As NamedTypeSymbol,
iAsyncStateMachine As NamedTypeSymbol) As NamedTypeSymbol iAsyncStateMachine As NamedTypeSymbol) As NamedTypeSymbol
Return New AsyncStateMachine(method, typeIndex, typeKind, valueTypeSymbol, iAsyncStateMachine) Return New AsyncStateMachine(method, typeIndex, typeKind, valueTypeSymbol, iAsyncStateMachine)
End Function End Function
...@@ -133,14 +133,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -133,14 +133,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
method As MethodSymbol, method As MethodSymbol,
compilationState As TypeCompilationState, compilationState As TypeCompilationState,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
generateDebugInfo As boolean) As BoundBlock generateDebugInfo As Boolean) As BoundBlock
If body.HasErrors Then If body.HasErrors Then
Return body Return body
End If End If
Dim asyncMethodKind As AsyncMethodKind = GetAsyncMethodKind(method) Dim asyncMethodKind As AsyncMethodKind = GetAsyncMethodKind(method)
If asyncMethodKind = asyncMethodKind.None Then If asyncMethodKind = AsyncMethodKind.None Then
Return body Return body
End If End If
...@@ -156,10 +156,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -156,10 +156,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Protected Overrides Sub GenerateMethodImplementations() Protected Overrides Sub GenerateMethodImplementations()
' Add IAsyncStateMachine.MoveNext() ' Add IAsyncStateMachine.MoveNext()
Dim debuggerHidden = IsDebuggerHidden(Me.Method)
Dim moveNextAttrs As DebugAttributes = DebugAttributes.CompilerGeneratedAttribute
If debuggerHidden Then moveNextAttrs = moveNextAttrs Or DebugAttributes.DebuggerHiddenAttribute
GenerateMoveNext(Me.StartMethodImplementation( GenerateMoveNext(Me.StartMethodImplementation(
WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_MoveNext, WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_MoveNext,
"MoveNext", "MoveNext",
DebugAttributes.CompilerGeneratedAttribute, Accessibility.Friend, True, asyncKickoffMethod:=Me.Method)) moveNextAttrs, Accessibility.Friend, True, asyncKickoffMethod:=Me.Method))
'Add IAsyncStateMachine.SetStateMachine() 'Add IAsyncStateMachine.SetStateMachine()
Me.StartMethodImplementation( Me.StartMethodImplementation(
......
...@@ -144,9 +144,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -144,9 +144,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Accessibility.Private, Accessibility.Private,
False) False)
Dim debuggerHidden = IsDebuggerHidden(Me.Method)
Dim moveNextAttrs As DebugAttributes = DebugAttributes.CompilerGeneratedAttribute
If debuggerHidden Then moveNextAttrs = moveNextAttrs Or DebugAttributes.DebuggerHiddenAttribute
Dim moveNextMethod = Me.StartMethodImplementation(SpecialMember.System_Collections_IEnumerator__MoveNext, Dim moveNextMethod = Me.StartMethodImplementation(SpecialMember.System_Collections_IEnumerator__MoveNext,
"MoveNext", "MoveNext",
DebugAttributes.CompilerGeneratedAttribute, moveNextAttrs,
Accessibility.Private, Accessibility.Private,
True) True)
......
...@@ -435,6 +435,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -435,6 +435,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return body Return body
End Function End Function
Protected Function IsDebuggerHidden(method As MethodSymbol) As Boolean
Dim debuggerHiddenAttribute = Me.CompilationState.Compilation.GetWellKnownType(WellKnownType.System_Diagnostics_DebuggerHiddenAttribute)
For Each a In Me.Method.GetAttributes()
If a.AttributeClass = debuggerHiddenAttribute Then Return True
Next
Return False
End Function
End Class End Class
End Namespace End Namespace
...@@ -410,5 +410,69 @@ End Class ...@@ -410,5 +410,69 @@ End Class
PDBTests.AssertXmlEqual(expected, actual) PDBTests.AssertXmlEqual(expected, actual)
End Sub End Sub
<Fact, WorkItem(667579, "DevDiv")>
Public Sub DebuggerHiddenIterator()
Dim source =
<compilation>
<file>
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Module Module1
Sub Main()
For Each i In Foo
Console.Write(i)
Next
End Sub
&lt;DebuggerHidden&gt;
Iterator Function Foo() As IEnumerable(Of Integer)
Yield 1
Yield 2
End Function
End Module
</file>
</compilation>
Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(
source,
OptionsExe.WithOptimizations(False))
Dim actual = PDBTests.GetPdbXml(compilation, "Module1+VB$StateMachine_1_Foo.MoveNext")
Dim expected =
<symbols>
<entryPoint declaringType="Module1" methodName="Main" parameterNames=""/>
<methods>
<method containingType="Module1+VB$StateMachine_1_Foo" name="MoveNext" parameterNames="">
<sequencepoints total="6">
<entry il_offset="0x0" hidden="true" start_row="16707566" start_column="0" end_row="16707566" end_column="0" file_ref="0"/>
<entry il_offset="0x2c" start_row="12" start_column="5" end_row="13" end_column="55" file_ref="0"/>
<entry il_offset="0x2d" start_row="13" start_column="5" end_row="13" end_column="55" file_ref="0"/>
<entry il_offset="0x2e" start_row="14" start_column="9" end_row="14" end_column="16" file_ref="0"/>
<entry il_offset="0x49" start_row="15" start_column="9" end_row="15" end_column="16" file_ref="0"/>
<entry il_offset="0x64" start_row="16" start_column="5" end_row="16" end_column="17" file_ref="0"/>
</sequencepoints>
<locals>
<local name="VB$returnTemp" il_index="0" il_start="0x0" il_end="0x66" attributes="1"/>
<local name="VB$cachedState" il_index="1" il_start="0x0" il_end="0x66" attributes="1"/>
<local name="MoveNext" il_index="2" il_start="0x2d" il_end="0x65" attributes="0"/>
</locals>
<scope startOffset="0x0" endOffset="0x66">
<importsforward declaringType="Module1" methodName="Main" parameterNames=""/>
<local name="VB$returnTemp" il_index="0" il_start="0x0" il_end="0x66" attributes="1"/>
<local name="VB$cachedState" il_index="1" il_start="0x0" il_end="0x66" attributes="1"/>
<scope startOffset="0x2d" endOffset="0x65">
<local name="MoveNext" il_index="2" il_start="0x2d" il_end="0x65" attributes="0"/>
</scope>
</scope>
</method>
</methods>
</symbols>
PDBTests.AssertXmlEqual(expected, actual)
End Sub
End Class End Class
End Namespace End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册