2 // System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
5 // Martin Baulig (martin@gnome.org)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Diagnostics.SymbolStore;
18 using System.Collections;
21 namespace Mono.CSharp.Debugger
23 internal class SourceFile : SourceFileEntry, ISymbolDocumentWriter
25 private ArrayList _methods = new ArrayList ();
27 public SourceFile (MonoSymbolFile file, string filename)
28 : base (file, filename)
31 public new SourceMethod[] Methods {
33 SourceMethod[] retval = new SourceMethod [_methods.Count];
34 _methods.CopyTo (retval);
39 public void AddMethod (SourceMethod method)
41 _methods.Add (method);
44 void ISymbolDocumentWriter.SetCheckSum (Guid algorithmId, byte[] checkSum)
46 throw new NotSupportedException ();
49 void ISymbolDocumentWriter.SetSource (byte[] source)
51 throw new NotSupportedException ();
55 internal class SourceMethod
57 private ArrayList _lines = new ArrayList ();
58 private ArrayList _locals = new ArrayList ();
59 private ArrayList _blocks = new ArrayList ();
60 private Stack _block_stack = new Stack ();
61 private int next_block_id = 0;
63 internal readonly MethodBase _method_base;
64 internal SourceFile _source_file;
66 private int _namespace_id;
67 private LineNumberEntry _start, _end;
68 private MonoSymbolFile _file;
70 private LexicalBlockEntry _implicit_block;
72 internal SourceMethod (MonoSymbolFile file, SourceFile source_file,
73 int startLine, int startColumn, int endLine, int endColumn,
74 MethodBase method_base, int namespace_id)
77 this._method_base = method_base;
78 this._source_file = source_file;
79 this._namespace_id = namespace_id;
81 this._start = new LineNumberEntry (startLine, 0);
82 this._end = new LineNumberEntry (endLine, 0);
84 this._implicit_block = new LexicalBlockEntry (0, 0);
87 public void StartBlock (int startOffset)
89 LexicalBlockEntry block = new LexicalBlockEntry (++next_block_id, startOffset);
90 _block_stack.Push (block);
94 public void EndBlock (int endOffset)
96 LexicalBlockEntry block = (LexicalBlockEntry) _block_stack.Pop ();
98 block.Close (endOffset);
101 public LexicalBlockEntry[] Blocks {
103 LexicalBlockEntry[] retval = new LexicalBlockEntry [_blocks.Count];
104 _blocks.CopyTo (retval, 0);
109 public LexicalBlockEntry CurrentBlock {
111 if (_block_stack.Count > 0)
112 return (LexicalBlockEntry) _block_stack.Peek ();
114 return _implicit_block;
118 public LineNumberEntry[] Lines {
120 LineNumberEntry[] retval = new LineNumberEntry [_lines.Count];
121 _lines.CopyTo (retval);
126 public void AddLine (LineNumberEntry line)
131 public LocalVariableEntry[] Locals {
133 LocalVariableEntry[] retval = new LocalVariableEntry [_locals.Count];
134 _locals.CopyTo (retval, 0);
139 public void AddLocal (string name, FieldAttributes attributes, byte[] signature)
141 _locals.Add (new LocalVariableEntry (name, attributes, signature, CurrentBlock.Index));
144 public MethodBase MethodBase {
150 public string FullName {
152 return _method_base.DeclaringType.FullName + "." + _method_base.Name;
156 public Type ReturnType {
158 if (_method_base is MethodInfo)
159 return ((MethodInfo)_method_base).ReturnType;
160 else if (_method_base is ConstructorInfo)
161 return _method_base.DeclaringType;
163 throw new NotSupportedException ();
167 public ParameterInfo[] Parameters {
169 if (_method_base == null)
170 return new ParameterInfo [0];
172 ParameterInfo [] retval = _method_base.GetParameters ();
174 return new ParameterInfo [0];
180 public SourceFile SourceFile {
191 throw new NotSupportedException ();
195 public bool HasSource {
197 return _source_file != null;
201 public LineNumberEntry Start {
207 public LineNumberEntry End {
213 public int NamespaceID {
215 return _namespace_id;
220 public class MonoSymbolWriter : IMonoSymbolWriter
222 protected ModuleBuilder module_builder;
223 protected ArrayList locals = null;
224 protected ArrayList orphant_methods = null;
225 protected ArrayList methods = null;
226 protected Hashtable sources = null;
227 private MonoSymbolFile file = null;
229 internal SourceMethod[] Methods {
231 SourceMethod[] retval = new SourceMethod [methods.Count];
232 methods.CopyTo (retval);
237 internal SourceFile[] Sources {
239 SourceFile[] retval = new SourceFile [sources.Count];
240 sources.Values.CopyTo (retval, 0);
245 private SourceMethod current_method = null;
248 // Interface IMonoSymbolWriter
251 public MonoSymbolWriter (ModuleBuilder mb)
253 this.module_builder = mb;
254 this.methods = new ArrayList ();
255 this.sources = new Hashtable ();
256 this.orphant_methods = new ArrayList ();
257 this.locals = new ArrayList ();
258 this.file = new MonoSymbolFile ();
263 throw new InvalidOperationException ();
266 public byte[] CreateSymbolFile (AssemblyBuilder assembly_builder)
268 DoFixups (assembly_builder);
270 return CreateOutput (assembly_builder);
273 public void CloseNamespace () {
276 // Create and return a new IMonoSymbolDocumentWriter.
277 public ISymbolDocumentWriter DefineDocument (string url,
282 SourceFile source_info = new SourceFile (file, url);
283 sources.Add (url, source_info);
287 public void DefineField (
290 FieldAttributes attributes,
292 SymAddressKind addrKind,
297 throw new NotSupportedException ();
300 public void DefineGlobalVariable (
302 FieldAttributes attributes,
304 SymAddressKind addrKind,
309 throw new NotSupportedException ();
312 public void DefineLocalVariable (string name,
313 FieldAttributes attributes,
315 SymAddressKind addrKind,
322 if (current_method == null)
325 current_method.AddLocal (name, attributes, signature);
328 public void DefineParameter (string name,
329 ParameterAttributes attributes,
331 SymAddressKind addrKind,
336 throw new NotSupportedException ();
339 public void DefineSequencePoints (ISymbolDocumentWriter document,
346 throw new NotSupportedException ();
349 public void MarkSequencePoint (int offset, int line, int column)
351 if (current_method == null)
354 LineNumberEntry source_line = new LineNumberEntry (line, offset);
355 current_method.AddLine (source_line);
358 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
360 throw new NotSupportedException ();
363 public void OpenMethod (SymbolToken symbol_token)
365 throw new NotSupportedException ();
368 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
369 int startLine, int startColumn,
370 ISymbolDocumentWriter endDoc,
371 int endLine, int endColumn)
373 throw new NotSupportedException ();
376 public void OpenMethod (ISymbolDocumentWriter document, int startLine, int startColumn,
377 int endLine, int endColumn, MethodBase method, int namespace_id)
379 SourceFile source_info = document as SourceFile;
381 if ((source_info == null) || (method == null))
382 throw new NullReferenceException ();
384 current_method = new SourceMethod (file, source_info, startLine, startColumn,
385 endLine, endColumn, method, namespace_id);
387 methods.Add (current_method);
388 source_info.AddMethod (current_method);
391 public void CloseMethod ()
393 current_method = null;
396 public int DefineNamespace (string name, ISymbolDocumentWriter document,
397 string[] using_clauses, int parent)
399 if ((document == null) || (using_clauses == null))
400 throw new NullReferenceException ();
401 if (!(document is SourceFile))
402 throw new ArgumentException ();
404 SourceFile source_info = (SourceFile) document;
406 return source_info.DefineNamespace (name, using_clauses, parent);
409 public void OpenNamespace (string name)
411 throw new NotSupportedException ();
414 public int OpenScope (int startOffset)
416 if (current_method == null)
419 current_method.StartBlock (startOffset);
423 public void CloseScope (int endOffset)
425 if (current_method == null)
428 current_method.EndBlock (endOffset);
431 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
433 throw new NotSupportedException ();
436 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
438 throw new NotSupportedException ();
441 public void SetUnderlyingWriter (IntPtr underlyingWriter)
443 throw new NotSupportedException ();
446 public void SetUserEntryPoint (SymbolToken entryMethod)
448 throw new NotSupportedException ();
451 public void UsingNamespace (string fullName)
453 throw new NotSupportedException ();
457 // MonoSymbolWriter implementation
459 protected void DoFixups (Assembly assembly)
461 foreach (SourceMethod method in methods) {
462 if (method._method_base is MethodBuilder) {
463 MethodBuilder mb = (MethodBuilder) method._method_base;
464 method._token = mb.GetToken ().Token;
465 } else if (method._method_base is ConstructorBuilder) {
466 ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
467 method._token = cb.GetToken ().Token;
469 throw new NotSupportedException ();
471 if (method.SourceFile == null)
472 orphant_methods.Add (method);
476 protected byte[] CreateOutput (Assembly assembly)
478 foreach (SourceMethod method in Methods) {
479 if (!method.HasSource) {
480 Console.WriteLine ("INGORING METHOD: {0}", method);
484 method.SourceFile.DefineMethod (
485 method.MethodBase, method.Token, method.Locals,
486 method.Lines, method.Blocks, method.Start.Row, method.End.Row,
490 return file.CreateSymbolFile ();