/// <summary> /// Helper function for /// <see cref="GetAllFunctions(Rhino.Debug.DebuggableScript)">GetAllFunctions(Rhino.Debug.DebuggableScript)</see> /// . /// </summary> private static void CollectFunctions_r(DebuggableScript function, ObjArray array) { array.Add(function); for (int i = 0; i != function.GetFunctionCount(); ++i) { CollectFunctions_r(function.GetFunction(i), array); } }
/// <summary>Returns the source URL for the given script or function.</summary> /// <remarks>Returns the source URL for the given script or function.</remarks> private string GetNormalizedUrl(DebuggableScript fnOrScript) { string url = fnOrScript.GetSourceName(); if (url == null) { url = "<stdin>"; } else { // Not to produce window for eval from different lines, // strip line numbers, i.e. replace all #[0-9]+\(eval\) by // (eval) // Option: similar teatment for Function? char evalSeparator = '#'; StringBuilder sb = null; int urlLength = url.Length; int cursor = 0; for (; ; ) { int searchStart = url.IndexOf(evalSeparator, cursor); if (searchStart < 0) { break; } string replace = null; int i = searchStart + 1; while (i != urlLength) { int c = url[i]; if (!('0' <= c && c <= '9')) { break; } ++i; } if (i != searchStart + 1) { // i points after #[0-9]+ if ("(eval)".RegionMatches(0, url, i, 6)) { cursor = i + 6; replace = "(eval)"; } } if (replace == null) { break; } if (sb == null) { sb = new StringBuilder(); sb.Append(Sharpen.Runtime.Substring(url, 0, searchStart)); } sb.Append(replace); } if (sb != null) { if (cursor != urlLength) { sb.Append(Sharpen.Runtime.Substring(url, cursor)); } url = sb.ToString(); } } return url; }
/// <summary>Returns an array of all functions in the given script.</summary> /// <remarks>Returns an array of all functions in the given script.</remarks> private static DebuggableScript[] GetAllFunctions(DebuggableScript function) { ObjArray functions = new ObjArray(); CollectFunctions_r(function, functions); DebuggableScript[] result = new DebuggableScript[functions.Size()]; functions.ToArray(result); return result; }
/// <summary>Registers the given script as a top-level script in the debugger.</summary> /// <remarks>Registers the given script as a top-level script in the debugger.</remarks> private void RegisterTopScript(DebuggableScript topScript, string source) { if (!topScript.IsTopLevel()) { throw new ArgumentException(); } string url = GetNormalizedUrl(topScript); DebuggableScript[] functions = GetAllFunctions(topScript); if (sourceProvider != null) { string providedSource = sourceProvider.GetSource(topScript); if (providedSource != null) { source = providedSource; } } Dim.SourceInfo sourceInfo = new Dim.SourceInfo(source, functions, url); lock (urlToSourceInfo) { Dim.SourceInfo old = urlToSourceInfo.Get(url); if (old != null) { sourceInfo.CopyBreakpointsFrom(old); } urlToSourceInfo.Put(url, sourceInfo); for (int i = 0; i != sourceInfo.FunctionSourcesTop(); ++i) { Dim.FunctionSource fsource = sourceInfo.FunctionSource(i); string name = fsource.Name(); if (name.Length != 0) { functionNames.Put(name, fsource); } } } lock (functionToSource) { for (int i = 0; i != functions.Length; ++i) { Dim.FunctionSource fsource = sourceInfo.FunctionSource(i); functionToSource.Put(functions[i], fsource); } } callback.UpdateSourceText(sourceInfo); }
/// <summary>Returns the FunctionSource object for the given function or script.</summary> /// <remarks>Returns the FunctionSource object for the given function or script.</remarks> private Dim.FunctionSource FunctionSource(DebuggableScript fnOrScript) { return functionToSource.Get(fnOrScript); }
/// <summary>Returns the FunctionSource object for the given script or function.</summary> /// <remarks>Returns the FunctionSource object for the given script or function.</remarks> private Dim.FunctionSource GetFunctionSource(DebuggableScript fnOrScript) { Dim.FunctionSource fsource = FunctionSource(fnOrScript); if (fsource == null) { string url = GetNormalizedUrl(fnOrScript); Dim.SourceInfo si = SourceInfo(url); if (si == null) { if (!fnOrScript.IsGeneratedScript()) { // Not eval or Function, try to load it from URL string source = LoadSource(url); if (source != null) { DebuggableScript top = fnOrScript; for (; ; ) { DebuggableScript parent = top.GetParent(); if (parent == null) { break; } top = parent; } RegisterTopScript(top, source); fsource = FunctionSource(fnOrScript); } } } } return fsource; }
/// <summary>Creates a new SourceInfo object.</summary> /// <remarks>Creates a new SourceInfo object.</remarks> private SourceInfo(string source, DebuggableScript[] functions, string normilizedUrl) { this.source = source; this.url = normilizedUrl; int N = functions.Length; int[][] lineArrays = new int[N][]; for (int i = 0; i != N; ++i) { lineArrays[i] = functions[i].GetLineNumbers(); } int minAll = 0; int maxAll = -1; int[] firstLines = new int[N]; for (int i_1 = 0; i_1 != N; ++i_1) { int[] lines = lineArrays[i_1]; if (lines == null || lines.Length == 0) { firstLines[i_1] = -1; } else { int min; int max; min = max = lines[0]; for (int j = 1; j != lines.Length; ++j) { int line = lines[j]; if (line < min) { min = line; } else { if (line > max) { max = line; } } } firstLines[i_1] = min; if (minAll > maxAll) { minAll = min; maxAll = max; } else { if (min < minAll) { minAll = min; } if (max > maxAll) { maxAll = max; } } } } if (minAll > maxAll) { // No line information this.breakableLines = EMPTY_BOOLEAN_ARRAY; this.breakpoints = EMPTY_BOOLEAN_ARRAY; } else { if (minAll < 0) { // Line numbers can not be negative throw new InvalidOperationException(minAll.ToString()); } int linesTop = maxAll + 1; this.breakableLines = new bool[linesTop]; this.breakpoints = new bool[linesTop]; for (int i_2 = 0; i_2 != N; ++i_2) { int[] lines = lineArrays[i_2]; if (lines != null && lines.Length != 0) { for (int j = 0; j != lines.Length; ++j) { int line = lines[j]; this.breakableLines[line] = true; } } } } this.functionSources = new Dim.FunctionSource[N]; for (int i_3 = 0; i_3 != N; ++i_3) { string name = functions[i_3].GetFunctionName(); if (name == null) { name = string.Empty; } this.functionSources[i_3] = new Dim.FunctionSource(this, firstLines[i_3], name); } }
/// <summary>Called when compilation is finished.</summary> /// <remarks>Called when compilation is finished.</remarks> public virtual void HandleCompilationDone(Context cx, DebuggableScript fnOrScript, string source) { if (type != IPROXY_DEBUG) { Kit.CodeBug(); } if (!fnOrScript.IsTopLevel()) { return; } dim.RegisterTopScript(fnOrScript, source); }
// Debugger /// <summary>Returns a StackFrame for the given function or script.</summary> /// <remarks>Returns a StackFrame for the given function or script.</remarks> public virtual DebugFrame GetFrame(Context cx, DebuggableScript fnOrScript) { if (type != IPROXY_DEBUG) { Kit.CodeBug(); } Dim.FunctionSource item = dim.GetFunctionSource(fnOrScript); if (item == null) { // Can not debug if source is not available return null; } return new Dim.StackFrame(cx, dim, item); }
private static void NotifyDebugger(Context cx, DebuggableScript dscript, string debugSource) { cx.m_Debugger.HandleCompilationDone (cx, dscript, debugSource); for (int i = 0; i != dscript.FunctionCount; ++i) { NotifyDebugger (cx, dscript.GetFunction (i), debugSource); } }