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;
59 private ArrayList _blocks;
60 private Stack _block_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 if (_block_stack == null)
91 _block_stack = new Stack ();
92 _block_stack.Push (block);
94 _blocks = new ArrayList ();
98 public void EndBlock (int endOffset)
100 LexicalBlockEntry block = (LexicalBlockEntry) _block_stack.Pop ();
102 block.Close (endOffset);
105 public LexicalBlockEntry[] Blocks {
108 return new LexicalBlockEntry [0];
110 LexicalBlockEntry[] retval = new LexicalBlockEntry [_blocks.Count];
111 _blocks.CopyTo (retval, 0);
117 public LexicalBlockEntry CurrentBlock {
119 if ((_block_stack != null) && (_block_stack.Count > 0))
120 return (LexicalBlockEntry) _block_stack.Peek ();
122 return _implicit_block;
126 public LineNumberEntry[] Lines {
128 LineNumberEntry[] retval = new LineNumberEntry [_lines.Count];
129 _lines.CopyTo (retval);
134 public void AddLine (LineNumberEntry line)
139 public LocalVariableEntry[] Locals {
142 return new LocalVariableEntry [0];
144 LocalVariableEntry[] retval = new LocalVariableEntry [_locals.Count];
145 _locals.CopyTo (retval, 0);
151 public void AddLocal (string name, FieldAttributes attributes, byte[] signature)
154 _locals = new ArrayList ();
155 _locals.Add (new LocalVariableEntry (name, attributes, signature, CurrentBlock.Index));
158 public MethodBase MethodBase {
164 public string FullName {
166 return _method_base.DeclaringType.FullName + "." + _method_base.Name;
170 public Type ReturnType {
172 if (_method_base is MethodInfo)
173 return ((MethodInfo)_method_base).ReturnType;
174 else if (_method_base is ConstructorInfo)
175 return _method_base.DeclaringType;
177 throw new NotSupportedException ();
181 public ParameterInfo[] Parameters {
183 if (_method_base == null)
184 return new ParameterInfo [0];
186 ParameterInfo [] retval = _method_base.GetParameters ();
188 return new ParameterInfo [0];
194 public SourceFile SourceFile {
205 throw new NotSupportedException ();
209 public bool HasSource {
211 return _source_file != null;
215 public LineNumberEntry Start {
221 public LineNumberEntry End {
227 public int NamespaceID {
229 return _namespace_id;
234 public class MonoSymbolWriter : IMonoSymbolWriter
236 protected ModuleBuilder module_builder;
237 protected ArrayList locals = null;
238 protected ArrayList orphant_methods = null;
239 protected ArrayList methods = null;
240 protected Hashtable sources = null;
241 private MonoSymbolFile file = null;
243 internal SourceMethod[] Methods {
245 SourceMethod[] retval = new SourceMethod [methods.Count];
246 methods.CopyTo (retval);
251 internal SourceFile[] Sources {
253 SourceFile[] retval = new SourceFile [sources.Count];
254 sources.Values.CopyTo (retval, 0);
259 private SourceMethod current_method = null;
262 // Interface IMonoSymbolWriter
265 public MonoSymbolWriter (ModuleBuilder mb)
267 this.module_builder = mb;
268 this.methods = new ArrayList ();
269 this.sources = new Hashtable ();
270 this.orphant_methods = new ArrayList ();
271 this.locals = new ArrayList ();
272 this.file = new MonoSymbolFile ();
277 throw new InvalidOperationException ();
280 public byte[] CreateSymbolFile (AssemblyBuilder assembly_builder)
282 DoFixups (assembly_builder);
284 return CreateOutput (assembly_builder);
287 public void CloseNamespace () {
290 // Create and return a new IMonoSymbolDocumentWriter.
291 public ISymbolDocumentWriter DefineDocument (string url,
296 if (sources.ContainsKey (url))
297 return (ISymbolDocumentWriter)sources [url];
298 SourceFile source_info = new SourceFile (file, url);
299 sources.Add (url, source_info);
303 public void DefineField (
306 FieldAttributes attributes,
308 SymAddressKind addrKind,
313 throw new NotSupportedException ();
316 public void DefineGlobalVariable (
318 FieldAttributes attributes,
320 SymAddressKind addrKind,
325 throw new NotSupportedException ();
328 public void DefineLocalVariable (string name,
329 FieldAttributes attributes,
331 SymAddressKind addrKind,
338 if (current_method == null)
341 current_method.AddLocal (name, attributes, signature);
344 public void DefineParameter (string name,
345 ParameterAttributes attributes,
347 SymAddressKind addrKind,
352 throw new NotSupportedException ();
355 public void DefineSequencePoints (ISymbolDocumentWriter document,
362 throw new NotSupportedException ();
365 public void MarkSequencePoint (int offset, int line, int column)
367 if (current_method == null)
370 LineNumberEntry source_line = new LineNumberEntry (line, offset);
371 current_method.AddLine (source_line);
374 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
376 throw new NotSupportedException ();
379 public void OpenMethod (SymbolToken symbol_token)
381 throw new NotSupportedException ();
384 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
385 int startLine, int startColumn,
386 ISymbolDocumentWriter endDoc,
387 int endLine, int endColumn)
389 throw new NotSupportedException ();
392 public void OpenMethod (ISymbolDocumentWriter document, int startLine, int startColumn,
393 int endLine, int endColumn, MethodBase method, int namespace_id)
395 SourceFile source_info = document as SourceFile;
397 if ((source_info == null) || (method == null))
398 throw new NullReferenceException ();
400 current_method = new SourceMethod (file, source_info, startLine, startColumn,
401 endLine, endColumn, method, namespace_id);
403 methods.Add (current_method);
404 source_info.AddMethod (current_method);
407 public void CloseMethod ()
409 current_method = null;
412 public int DefineNamespace (string name, ISymbolDocumentWriter document,
413 string[] using_clauses, int parent)
415 if ((document == null) || (using_clauses == null))
416 throw new NullReferenceException ();
417 if (!(document is SourceFile))
418 throw new ArgumentException ();
420 SourceFile source_info = (SourceFile) document;
422 return source_info.DefineNamespace (name, using_clauses, parent);
425 public void OpenNamespace (string name)
427 throw new NotSupportedException ();
430 public int OpenScope (int startOffset)
432 if (current_method == null)
435 current_method.StartBlock (startOffset);
439 public void CloseScope (int endOffset)
441 if (current_method == null)
444 current_method.EndBlock (endOffset);
447 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
449 throw new NotSupportedException ();
452 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
454 throw new NotSupportedException ();
457 public void SetUnderlyingWriter (IntPtr underlyingWriter)
459 throw new NotSupportedException ();
462 public void SetUserEntryPoint (SymbolToken entryMethod)
464 throw new NotSupportedException ();
467 public void UsingNamespace (string fullName)
469 throw new NotSupportedException ();
473 // MonoSymbolWriter implementation
475 protected void DoFixups (Assembly assembly)
477 foreach (SourceMethod method in methods) {
478 if (method._method_base is MethodBuilder) {
479 MethodBuilder mb = (MethodBuilder) method._method_base;
480 method._token = mb.GetToken ().Token;
481 } else if (method._method_base is ConstructorBuilder) {
482 ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
483 method._token = cb.GetToken ().Token;
485 throw new NotSupportedException ();
487 if (method.SourceFile == null)
488 orphant_methods.Add (method);
492 protected byte[] CreateOutput (Assembly assembly)
494 foreach (SourceMethod method in Methods) {
495 if (!method.HasSource) {
496 Console.WriteLine ("INGORING METHOD: {0}", method);
500 method.SourceFile.DefineMethod (
501 method.MethodBase, method.Token, method.Locals,
502 method.Lines, method.Blocks, method.Start.Row, method.End.Row,
506 return file.CreateSymbolFile ();