private static void AddCapturedLocalVariables(List <DebugLocalVariableInfo> vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType) { if (captureClassType.IsDisplayClass || captureClassType.IsYieldEnumerator) { foreach (DebugFieldInfo fieldInfo in captureClassType.GetFields()) { DebugFieldInfo fieldInfoCopy = fieldInfo; if (fieldInfo.Name.StartsWith("CS$")) { continue; // Ignore } DebugLocalVariableInfo locVar = new DebugLocalVariableInfo( fieldInfo.Name, -1, scopeStartOffset, scopeEndOffset, (DebugType)fieldInfo.FieldType, delegate(StackFrame context) { return(getCaptureClass(context).GetFieldValue(fieldInfoCopy)); } ); locVar.IsCaptured = true; if (locVar.Name.StartsWith("<>")) { bool hasThis = false; foreach (DebugLocalVariableInfo l in vars) { if (l.IsThis) { hasThis = true; break; } } if (!hasThis && locVar.Name.EndsWith("__this")) { locVar.Name = "this"; locVar.IsThis = true; } else { continue; // Ignore } } if (locVar.Name.StartsWith("<")) { int endIndex = locVar.Name.IndexOf('>'); if (endIndex == -1) { continue; // Ignore } locVar.Name = fieldInfo.Name.Substring(1, endIndex - 1); } vars.Add(locVar); } } }
private List <DebugLocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope) { List <DebugLocalVariableInfo> vars = new List <DebugLocalVariableInfo>(); foreach (ISymUnmanagedVariable symVar in symScope.GetLocals()) { ISymUnmanagedVariable symVarCopy = symVar; int start; SignatureReader sigReader = new SignatureReader(symVar.GetSignature()); LocalVarSig.LocalVariable locVarSig = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start); DebugType locVarType = DebugType.CreateFromSignature(this.DebugModule, locVarSig.Type, declaringType); // Compiler generated? // NB: Display class does not have the compiler-generated flag if ((symVar.GetAttributes() & 1) == 1 || symVar.GetName().StartsWith("CS$")) { // Get display class from local variable if (locVarType.IsDisplayClass) { AddCapturedLocalVariables( vars, (int)symScope.GetStartOffset(), (int)symScope.GetEndOffset(), delegate(StackFrame context) { return(GetLocalVariableValue(context, symVarCopy)); }, locVarType ); } } else { DebugLocalVariableInfo locVar = new DebugLocalVariableInfo( symVar.GetName(), (int)symVar.GetAddressField1(), // symVar also has Get*Offset methods, but the are not implemented (int)symScope.GetStartOffset(), (int)symScope.GetEndOffset(), locVarType, delegate(StackFrame context) { return(GetLocalVariableValue(context, symVarCopy)); } ); vars.Add(locVar); } } foreach (ISymUnmanagedScope childScope in symScope.GetChildren()) { vars.AddRange(GetLocalVariablesInScope(childScope)); } return(vars); }
public List <DebugLocalVariableInfo> GetLocalVariables() { if (localVariables != null) { return(localVariables); } // Generated constructor may not have any symbols if (this.SymMethod == null) { return(new List <DebugLocalVariableInfo>()); } localVariables = GetLocalVariablesInScope(this.SymMethod.GetRootScope()); if (declaringType.IsDisplayClass || declaringType.IsYieldEnumerator) { // Get display class from self AddCapturedLocalVariables( localVariables, 0, int.MaxValue, delegate(StackFrame context) { return(context.GetThisValue()); }, declaringType ); // Get dispaly classes from fields foreach (DebugFieldInfo fieldInfo in this.DeclaringType.GetFields()) { DebugFieldInfo fieldInfoCopy = fieldInfo; if (fieldInfo.Name.StartsWith("CS$")) { AddCapturedLocalVariables( localVariables, 0, int.MaxValue, delegate(StackFrame context) { return(context.GetThisValue().GetFieldValue(fieldInfoCopy)); }, (DebugType)fieldInfo.FieldType ); } } } else { // Add this if (!this.IsStatic) { DebugLocalVariableInfo thisVar = new DebugLocalVariableInfo( "this", -1, 0, int.MaxValue, declaringType, delegate(StackFrame context) { return(context.GetThisValue()); } ); thisVar.IsThis = true; localVariables.Add(thisVar); } } return(localVariables); }