提交 f6d61adf 编写于 作者: N nmgafter

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

上级 253a92f2
......@@ -91,12 +91,12 @@ protected override void GenerateMethodImplementations()
// 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);
// 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.
// 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()
// Add bool IEnumerator.MoveNext() and void IDisposable.Dispose()
{
var disposeMethod = OpenMethodImplementation(IDisposable_Dispose, debuggerHidden: true, hasMethodBodyDependency: true);
var moveNextMethod = OpenMethodImplementation(IEnumerator_MoveNext, methodName: WellKnownMemberNames.MoveNextMethodName, hasMethodBodyDependency: true);
var disposeMethod = OpenMethodImplementation(IDisposable_Dispose, debuggerHidden: true, generateDebugInfo: false, hasMethodBodyDependency: true);
var moveNextMethod = OpenMethodImplementation(IEnumerator_MoveNext, methodName: WellKnownMemberNames.MoveNextMethodName, hasMethodBodyDependency: true, debuggerHidden: IsDebuggerHidden(this.method));
GenerateMoveNextAndDispose(moveNextMethod, disposeMethod);
}
......@@ -147,7 +147,7 @@ private void GenerateEnumeratorImplementation()
// 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))));
}
......@@ -184,7 +184,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
// The implementation doesn't depend on the method body of the iterator method.
// 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 resultVariable = F.SynthesizedLocal(stateMachineClass, null); // iteratorClass result;
......@@ -263,7 +263,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree()));
// 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)));
}
......
......@@ -248,10 +248,11 @@ private BoundStatement ReplaceOriginalMethod()
MethodSymbol methodToImplement,
string methodName = null,
bool debuggerHidden = false,
bool generateDebugInfo = true,
bool hasMethodBodyDependency = false,
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.CurrentMethod = result;
return result;
......@@ -271,5 +272,16 @@ private BoundStatement ReplaceOriginalMethod()
F.CurrentMethod = 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
MethodSymbol asyncKickoffMethod,
PropertySymbol associatedProperty,
bool debuggerHidden,
bool generateDebugInfo,
bool hasMethodBodyDependency)
: base(interfaceMethod, implementingType, name, debuggerHidden, associatedProperty, asyncKickoffMethod)
: base(interfaceMethod, implementingType, name, debuggerHidden, generateDebugInfo, associatedProperty, asyncKickoffMethod)
{
this.hasMethodBodyDependency = hasMethodBodyDependency;
}
......
......@@ -29,6 +29,7 @@ internal class SynthesizedStateMachineProperty : PropertySymbol, ISynthesizedMet
asyncKickoffMethod: null,
associatedProperty: this,
debuggerHidden: debuggerHidden,
generateDebugInfo: !debuggerHidden,
hasMethodBodyDependency: hasMethodBodyDependency);
}
......
......@@ -14,6 +14,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
private readonly MethodSymbol interfaceMethod;
private readonly NamedTypeSymbol implementingType;
private readonly bool debuggerHidden;
private readonly bool generateDebugInfo;
private readonly PropertySymbol associatedProperty;
private readonly MethodSymbol asyncKickoffMethod;
......@@ -29,6 +30,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
NamedTypeSymbol implementingType,
string name = null,
bool debuggerHidden = false,
bool generateDebugInfo = true,
PropertySymbol associatedProperty = null,
MethodSymbol asyncKickoffMethod = null)
{
......@@ -39,6 +41,7 @@ internal class SynthesizedImplementationMethod : SynthesizedInstanceMethodSymbol
this.interfaceMethod = interfaceMethod;
this.implementingType = implementingType;
this.debuggerHidden = debuggerHidden;
this.generateDebugInfo = generateDebugInfo;
this.associatedProperty = associatedProperty;
this.explicitInterfaceImplementations = ImmutableArray.Create<MethodSymbol>(interfaceMethod);
this.asyncKickoffMethod = asyncKickoffMethod;
......@@ -100,7 +103,7 @@ internal sealed override void AddSynthesizedAttributes(ModuleCompilationState co
internal override bool GenerateDebugInfo
{
get { return !debuggerHidden; }
get { return generateDebugInfo; }
}
public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters
......
......@@ -1009,6 +1009,54 @@ static IEnumerable<int> M()
</scope>
</method>
</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>";
AssertXmlEqual(expected, actual);
}
......
......@@ -30,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
asyncKind As AsyncMethodKind,
compilationState As TypeCompilationState,
diagnostics As DiagnosticBag,
generateDebugInfo As boolean)
generateDebugInfo As Boolean)
MyBase.New(body, method, compilationState, diagnostics, generateDebugInfo)
......@@ -133,14 +133,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
method As MethodSymbol,
compilationState As TypeCompilationState,
diagnostics As DiagnosticBag,
generateDebugInfo As boolean) As BoundBlock
generateDebugInfo As Boolean) As BoundBlock
If body.HasErrors Then
Return body
End If
Dim asyncMethodKind As AsyncMethodKind = GetAsyncMethodKind(method)
If asyncMethodKind = asyncMethodKind.None Then
If asyncMethodKind = AsyncMethodKind.None Then
Return body
End If
......@@ -156,10 +156,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Protected Overrides Sub GenerateMethodImplementations()
' 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(
WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_MoveNext,
"MoveNext",
DebugAttributes.CompilerGeneratedAttribute, Accessibility.Friend, True, asyncKickoffMethod:=Me.Method))
moveNextAttrs, Accessibility.Friend, True, asyncKickoffMethod:=Me.Method))
'Add IAsyncStateMachine.SetStateMachine()
Me.StartMethodImplementation(
......
......@@ -144,9 +144,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Accessibility.Private,
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,
"MoveNext",
DebugAttributes.CompilerGeneratedAttribute,
moveNextAttrs,
Accessibility.Private,
True)
......
......@@ -435,6 +435,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return body
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 Namespace
......@@ -410,5 +410,69 @@ End Class
PDBTests.AssertXmlEqual(expected, actual)
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 Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册