diff --git a/.vscode/launch.json b/.vscode/launch.json index 6f1b5b5..6ecaca6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}/extension", - "${workspaceFolder}\\example-project" + "${workspaceFolder}\\demo" ], "env": { "HOT_RELOAD": "true", @@ -24,7 +24,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}/extension", - "${workspaceFolder}\\example-project" + "${workspaceFolder}\\demo" ], "env": { "HOT_RELOAD": "true", @@ -40,7 +40,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}/extension", - "${workspaceFolder}\\example-project" + "${workspaceFolder}\\demo" ], "env": { "HOT_RELOAD": "", @@ -55,7 +55,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}/extension", - "${workspaceFolder}\\example-project" + "${workspaceFolder}\\demo" ], "env": { "HOT_RELOAD": "", diff --git a/data-extraction/src/CommonDataTypes.ts b/data-extraction/src/CommonDataTypes.ts index 5efa9d1..857f62d 100644 --- a/data-extraction/src/CommonDataTypes.ts +++ b/data-extraction/src/CommonDataTypes.ts @@ -82,7 +82,7 @@ export interface TreeNode { export interface NodeGraphData { id: string; - label: string; + label?: string; color?: string; shape?: "ellipse" | "box"; } @@ -90,7 +90,7 @@ export interface NodeGraphData { export interface EdgeGraphData { from: string; to: string; - label: string; + label?: string; id?: string; color?: string; dashes?: boolean; diff --git a/data-extraction/src/js/api/default-extractors/TypeScriptDataExtractors.ts b/data-extraction/src/js/api/default-extractors/TypeScriptDataExtractors.ts index 59a5e8e..fd1b5e4 100644 --- a/data-extraction/src/js/api/default-extractors/TypeScriptDataExtractors.ts +++ b/data-extraction/src/js/api/default-extractors/TypeScriptDataExtractors.ts @@ -24,6 +24,7 @@ export class TypeScriptAstDataExtractor if (typeof data === "object" && "typescript" in (data as object)) { return (data as any).typescript; } else { + // This might refer to global.require which uses CWD for resolution! const require = evalFn<(request: string) => unknown>("require"); return require("typescript") as typeof ts; } diff --git a/demo/.vscode/launch.json b/demo/.vscode/launch.json new file mode 100644 index 0000000..6b00a5c --- /dev/null +++ b/demo/.vscode/launch.json @@ -0,0 +1,69 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "TypeScript - Demo: Custom Data Extractor", + "program": "${workspaceFolder}/js/dist/demo_custom-data-extractor", + "skipFiles": ["/**"], + "preLaunchTask": "typescript-watch" + }, + { + "type": "node", + "request": "launch", + "name": "TypeScript - Demo: Doubly Linked List", + "program": "${workspaceFolder}/js/dist/demo-doubly-linked-list", + "skipFiles": ["/**"], + "preLaunchTask": "typescript-watch" + }, + { + "type": "node", + "request": "launch", + "name": "TypeScript - Demo: Random Walks", + "program": "${workspaceFolder}/js/dist/demo_random-walks", + "skipFiles": ["/**"], + "preLaunchTask": "typescript-watch" + }, + { + "type": "node", + "request": "launch", + "name": "TypeScript - Demo: TypeScript ASTs", + "program": "${workspaceFolder}/js/dist/demo_typescript-asts", + "skipFiles": ["/**"], + "preLaunchTask": "typescript-watch", + "cwd": "${workspaceFolder}/js" + }, + { + "type": "node", + "request": "launch", + "name": "JavaScript - Demo: Singly Linked List", + "program": "${workspaceFolder}/js/src/demo_singly-linked-list", + "skipFiles": ["/**"], + "preLaunchTask": "typescript-watch" + }, + { + "name": "C# - Demo: Linked List", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "csharp-build", + "program": "${workspaceFolder}/csharp/bin/Debug/netcoreapp3.1/demo.dll", + "args": [], + "cwd": "${workspaceFolder}/csharp", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": "PHP - Demo", + "type": "php", + "request": "launch", + "program": "${workspaceFolder}/php/demo.php", + "xdebugSettings": { + "max_data": -1 + } + } + ] +} diff --git a/example-project/.vscode/settings.json b/demo/.vscode/settings.json similarity index 100% rename from example-project/.vscode/settings.json rename to demo/.vscode/settings.json diff --git a/demo/.vscode/tasks.json b/demo/.vscode/tasks.json new file mode 100644 index 0000000..b045f8c --- /dev/null +++ b/demo/.vscode/tasks.json @@ -0,0 +1,32 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "label": "typescript-watch", + "script": "dev", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "path": "js/", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "csharp-build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/csharp/demo.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} diff --git a/demo/csharp/.gitignore b/demo/csharp/.gitignore new file mode 100644 index 0000000..a57fdbb --- /dev/null +++ b/demo/csharp/.gitignore @@ -0,0 +1,353 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ \ No newline at end of file diff --git a/demo/csharp/ExtractedData.cs b/demo/csharp/ExtractedData.cs new file mode 100644 index 0000000..f1e1a56 --- /dev/null +++ b/demo/csharp/ExtractedData.cs @@ -0,0 +1,186 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Hediet.DebugVisualizer.ExtractedData +{ + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public abstract class ExtractedData + { + [JsonProperty("kind")] + public Dictionary Kind + { + get + { + var d = new Dictionary(); + foreach (var tag in Tags) + { + d.Add(tag, true); + } + return d; + } + } + + [JsonIgnore] + public abstract string[] Tags { get; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } + + public class TextData : ExtractedData + { + public override string[] Tags => new string[] { "text" }; + + [JsonProperty("text")] + public string TextValue { get; set; } + + public TextData(string text) + { + this.TextValue = text; + } + } + + public class GraphData : ExtractedData + { + public override string[] Tags => new string[] { "graph" }; + + [JsonProperty("nodes")] + public IList Nodes { get; set; } = new List(); + + [JsonProperty("edges")] + public IList Edges { get; set; } = new List(); + + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public class NodeData + { + public NodeData(string id) + { + Id = id; + } + + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("label")] + public string? Label { get; set; } + + [JsonProperty("color")] + public string? Color { get; set; } + + [JsonProperty("shape")] + public string? Shape { get; set; } + } + + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + + public class EdgeData + { + public EdgeData(string from, string to) + { + From = from; + To = to; + } + + [JsonProperty("from")] + public string From { get; set; } + + [JsonProperty("to")] + public string To { get; set; } + + [JsonProperty("label")] + public string? Label { get; set; } + + [JsonProperty("id")] + public string? Id { get; set; } + + [JsonProperty("color")] + public string? Color { get; set; } + + [JsonProperty("dashes")] + public bool? Dashes { get; set; } + } + + public static GraphData From(IEnumerable items, Func, NodeInfo> f) where T : notnull + { + var d = new GraphData(); + var q = new Queue(items); + var i = 0; + var infos = new Dictionary>(); + + string GetId(NodeInfo item) + { + if (item.Id == null) + item.Id = "hediet.de/" + (i++); + return item.Id; + } + + NodeInfo GetNodeInfo(T item) + { + if (infos.ContainsKey(item)) + return infos[item]; + + var info = f(item, new NodeInfo()); + infos.Add(item, info); + return info; + } + + while (q.Count > 0) + { + var nodeInfo = GetNodeInfo(q.Dequeue()); + var nd = new NodeData(GetId(nodeInfo)); + d.Nodes.Add(nd); + + nd.Label = nodeInfo.Label; + nd.Color = nodeInfo.Color; + + foreach (var e in nodeInfo.Edges) + { + var ed = new EdgeData(nd.Id, GetId(GetNodeInfo(e.To))); + d.Edges.Add(ed); + + ed.Label = e.Label; + ed.Id = e.Id; + + q.Enqueue(e.To); + } + } + + return d; + } + + public class NodeInfo + { + public IList> Edges { get; set; } = new List>(); + public string? Label { get; set; } + public string? Id { get; set; } + public string? Color { get; set; } + + public NodeInfo AddEdge(T to, string? id = null, string? label = null) + { + var e = new EdgeInfo(to); + e.Id = id; + e.Label = label; + Edges.Add(e); + return this; + } + } + + public class EdgeInfo + { + public T To { get; set; } + public string? Label { get; set; } + public string? Id { get; set; } + + public EdgeInfo(T to) + { + To = to; + } + } + } +} + diff --git a/demo/csharp/Program.cs b/demo/csharp/Program.cs new file mode 100644 index 0000000..9a6e96b --- /dev/null +++ b/demo/csharp/Program.cs @@ -0,0 +1,65 @@ +#nullable enable + +using System.Linq; +using Hediet.DebugVisualizer.ExtractedData; + +namespace Demo +{ + class Program + { + static void Main(string[] args) + { + var list = new LinkedList(); + // visualize `list.Visualize()` here! + list.Append(1); + list.Append(2); + list.Append(3); + list.Append(4); + } + } + + class LinkedList + { + class Node + { + public Node(T value) { Value = value; } + public T Value { get; set; } + public Node? Next { get; set; } + } + + private Node? Head { get; set; } + + public void Append(T item) + { + if (this.Head == null) + { + this.Head = new Node(item); + } + else + { + var cur = this.Head; + while (cur.Next != null) + { + cur = cur.Next; + } + cur.Next = new Node(item); + } + } + + public ExtractedData Visualize() + { + var list = new Node(default(T)!) { Next = this.Head }; + return GraphData.From(new[] { list }.Where(i => i != null), (item, info) => + { + info.Id = item == list ? "List" : string.Format("{0}", item.Value); + if (item == list) + { + info.Color = "orange"; + } + if (item.Next != null) + info.AddEdge(item.Next!, label: item == list ? "head" : "next"); + return info; + }); + } + } +} diff --git a/demo/csharp/demo.csproj b/demo/csharp/demo.csproj new file mode 100644 index 0000000..29fba83 --- /dev/null +++ b/demo/csharp/demo.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/demo/js/README.md b/demo/js/README.md new file mode 100644 index 0000000..f01e39f --- /dev/null +++ b/demo/js/README.md @@ -0,0 +1,3 @@ +# JS Demos + +Simply run `yarn` and select the launch target you want to debug in the debugger pane of VS Code. diff --git a/example-project/package.json b/demo/js/package.json similarity index 100% rename from example-project/package.json rename to demo/js/package.json diff --git a/example-project/src/MockLanguageServiceHost.ts b/demo/js/src/MockLanguageServiceHost.ts similarity index 100% rename from example-project/src/MockLanguageServiceHost.ts rename to demo/js/src/MockLanguageServiceHost.ts diff --git a/example-project/src/demo_custom-data-extractor.ts b/demo/js/src/demo_custom-data-extractor.ts similarity index 96% rename from example-project/src/demo_custom-data-extractor.ts rename to demo/js/src/demo_custom-data-extractor.ts index e98170a..eb8ba6e 100644 --- a/example-project/src/demo_custom-data-extractor.ts +++ b/demo/js/src/demo_custom-data-extractor.ts @@ -26,6 +26,7 @@ class Foo {} class Main { run() { const f = new Foo(); + // visualize `f` here! debugger; } } diff --git a/example-project/src/demo_doubly-linked-list.ts b/demo/js/src/demo_doubly-linked-list.ts similarity index 94% rename from example-project/src/demo_doubly-linked-list.ts rename to demo/js/src/demo_doubly-linked-list.ts index 36c3d7b..0a63cc9 100644 --- a/example-project/src/demo_doubly-linked-list.ts +++ b/demo/js/src/demo_doubly-linked-list.ts @@ -16,6 +16,7 @@ class Main { list.next!.setNext(new DoublyLinkedList("3")); list.next!.next!.setNext(new DoublyLinkedList("4")); + // Use `visualize()` as expression to visualize in the Debug Visualizer! const visualize = () => createGraphFromPointers({ list, last, cur }, i => ({ id: i.id, diff --git a/example-project/src/demo_random_walks.ts b/demo/js/src/demo_random-walks.ts similarity index 91% rename from example-project/src/demo_random_walks.ts rename to demo/js/src/demo_random-walks.ts index c374efb..7a2bca8 100644 --- a/example-project/src/demo_random_walks.ts +++ b/demo/js/src/demo_random-walks.ts @@ -1,4 +1,5 @@ while (true) { + // visualize data const data = new Array(); let value = 0; for (let i = 0; i < 10000; i++) { diff --git a/example-project/src/demo_singly-linked-list.js b/demo/js/src/demo_singly-linked-list.js similarity index 99% rename from example-project/src/demo_singly-linked-list.js rename to demo/js/src/demo_singly-linked-list.js index 4643c0d..5d9a699 100644 --- a/example-project/src/demo_singly-linked-list.js +++ b/demo/js/src/demo_singly-linked-list.js @@ -19,7 +19,7 @@ hedietDbgVis.createGraphFromPointers( label: `${n.data}`, edges: [{ to: n.next, label: "next" }].filter(i => !!i.to), }) -); +) ``` */ diff --git a/example-project/src/demo_typescript.ts b/demo/js/src/demo_typescript-asts.ts similarity index 93% rename from example-project/src/demo_typescript.ts rename to demo/js/src/demo_typescript-asts.ts index cc6d897..9938e7e 100644 --- a/example-project/src/demo_typescript.ts +++ b/demo/js/src/demo_typescript-asts.ts @@ -20,6 +20,9 @@ class Test1 { } `, }; + + //console.log(ts, require("typescript")); + const files = new Map([ [mainFile.name, mainFile.content], ]); @@ -38,10 +41,11 @@ class Test1 { traverse(prog.getSourceFiles()[0]); const c = prog.getTypeChecker(); - let myValue = undefined; + let myValue = undefined; // Visualize `myValue` here! const sourceFileAst = prog.getSourceFiles()[0]; myValue = sourceFileAst.getText(); console.log("myValue is the source code of the AST"); + debugger; myValue = { sf: sourceFileAst, @@ -55,6 +59,7 @@ class Test1 { }, }; console.log("myValue is AST, annotated with type information"); + debugger; myValue = { sf: sourceFileAst, @@ -68,10 +73,12 @@ class Test1 { }, }; console.log("myValue is AST, annotated with symbol information"); + debugger; for (const ident of identifiers) { myValue = ident; console.log("myValue is an identifier"); + debugger; } } } diff --git a/example-project/src/playground.ts b/demo/js/src/playground.ts similarity index 100% rename from example-project/src/playground.ts rename to demo/js/src/playground.ts diff --git a/example-project/tsconfig.json b/demo/js/tsconfig.json similarity index 100% rename from example-project/tsconfig.json rename to demo/js/tsconfig.json diff --git a/example-project/yarn.lock b/demo/js/yarn.lock similarity index 100% rename from example-project/yarn.lock rename to demo/js/yarn.lock diff --git a/demo/php/demo.php b/demo/php/demo.php new file mode 100644 index 0000000..978993f --- /dev/null +++ b/demo/php/demo.php @@ -0,0 +1,26 @@ + ["graph" => true], + "nodes" => [ + ["id" => "1", "label" => "1"] + ], + "edges" => [] +]; + +// Visualize "$visualize()" +$visualize = function () use (&$graph) { + return json_encode($graph); +}; + +for ($i = 2; $i < 100; $i++) { + $targetId = "" . random_int(1, $i - 1); + $id = "" . $i; + + array_push($graph["nodes"], ["id" => $id, "label" => $id]); + array_push($graph["edges"], ["from" => $id, "to" => "" . $targetId]); + + xdebug_break(); +} + +echo "finished"; diff --git a/example-project/.vscode/launch.json b/example-project/.vscode/launch.json deleted file mode 100644 index caa23fb..0000000 --- a/example-project/.vscode/launch.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Listen for XDebug", - "type": "php", - "request": "launch", - "port": 9000 - }, - { - "name": "Launch currently open script", - "type": "php", - "request": "launch", - "program": "${file}", - "cwd": "${fileDirname}", - "port": 9000 - } - ] -} diff --git a/example-project/.vscode/tasks.json b/example-project/.vscode/tasks.json deleted file mode 100644 index 1b7be82..0000000 --- a/example-project/.vscode/tasks.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "label": "npm: dev", - "script": "dev", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/example-project/src/demo.php b/example-project/src/demo.php deleted file mode 100644 index 246c3db..0000000 --- a/example-project/src/demo.php +++ /dev/null @@ -1,18 +0,0 @@ - array("graph" => true), - "nodes" => [ - array("id" => "1", "label" => "1"), - array("id" => "2", "label" => "2"), - ], - "edges" => [ - array("from" => "1", "to" => "2", "label" => "edge") - ] - )); - - echo "test" . $i; -} diff --git a/extension/src/VsCodeDebugger.ts b/extension/src/VsCodeDebugger.ts index cf5a08a..c35a046 100644 --- a/extension/src/VsCodeDebugger.ts +++ b/extension/src/VsCodeDebugger.ts @@ -34,6 +34,9 @@ export class VsCodeDebugger { this.sessions.set(session, extendedSession); return { + onWillReceiveMessage: msg => { + console.log(msg.type, msg.event, msg); + }, onDidSendMessage: async msg => { type Message = | StoppedEvent @@ -79,6 +82,7 @@ export class VsCodeDebugger { "getStackTrace" ]({ threadId, + startFrame: 0, levels: 1, }); extendedSession["activeStackFrame"] = @@ -106,23 +110,32 @@ export class VsCodeDebugger { } } +interface StackFrame { + id: number; + name: string; +} + export class VsCodeDebugSession { @observable protected activeStackFrame: number | undefined; constructor(public readonly session: DebugSession) {} - protected async getStackTrace(args: { threadId: number; levels?: number }) { - interface StackFrame { - id: number; - name: string; + protected async getStackTrace(args: { + threadId: number; + startFrame?: number; + levels?: number; + }): Promise<{ totalFrames?: number; stackFrames: StackFrame[] }> { + try { + const reply = (await this.session.customRequest("stackTrace", { + threadId: args.threadId, + levels: args.levels, + startFrame: args.startFrame || 0, + })) as { totalFrames?: number; stackFrames: StackFrame[] }; + return reply; + } catch (e) { + console.error(e); + throw e; } - - const reply = (await this.session.customRequest("stackTrace", { - threadId: args.threadId, - levels: args.levels, - })) as { totalFrames?: number; stackFrames: StackFrame[] }; - - return reply; } public async getCompletions(args: { diff --git a/extension/ui/src/Visualizers/GraphVisualizer/VisJsGraphVisualizer.tsx b/extension/ui/src/Visualizers/GraphVisualizer/VisJsGraphVisualizer.tsx index 096ceef..910273c 100644 --- a/extension/ui/src/Visualizers/GraphVisualizer/VisJsGraphVisualizer.tsx +++ b/extension/ui/src/Visualizers/GraphVisualizer/VisJsGraphVisualizer.tsx @@ -44,15 +44,15 @@ export class VisJsGraphViewer extends React.Component<{ private readonly divRef = React.createRef(); private readonly nodes = new DataSet<{ id: string; - label: string; + label?: string; color?: string; shape?: string; }>(); private readonly edges = new DataSet<{ id: string; - label: string; from: string; to: string; + label?: string; color?: string; dashes?: boolean; shape?: boolean; @@ -68,7 +68,7 @@ export class VisJsGraphViewer extends React.Component<{ newNodes.add(n.id); this.nodes.update({ id: n.id, - label: n.label, + label: n.label !== undefined ? n.label : n.id, color: n.color, shape: n.shape, }); @@ -92,7 +92,7 @@ export class VisJsGraphViewer extends React.Component<{ newEdges.add(id); this.edges.update({ id: id, - label: n.label, + label: n.label !== undefined ? n.label : "", from: n.from, to: n.to, color: n.color,