Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
out
**/out/
dist
node_modules
.vscode-test/
Expand All @@ -13,6 +14,7 @@ obj/
*.log
*.tmp
*.out.xml
**/*.out.xml

# OS generated files
.DS_Store
Expand Down
10 changes: 10 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ src/**
.vscodeignore
.yarnrc
vsc-extension-quickstart.md
package.json.backup
TestData/**
docs/**
**/tsconfig.json
**/eslint.config.mjs
**/*.map
**/*.ts
**/*.sh
**/.vscode-test.*
.github/**

Expand Down Expand Up @@ -69,6 +73,9 @@ logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.out.xml
**/*.out.xml
TestData/**/out/**

# Node modules (should be handled by vsce, but just in case)
node_modules/**
Expand Down Expand Up @@ -116,3 +123,6 @@ VARIABLE-PRINT-GUIDE.md
# Packaging scripts
package-darwin.sh
package-win.sh
package-all.sh
test-debug-output.sh
test-namespace-support.sh
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

All notable changes to the XSLT Debugger extension will be documented in this file.

## [1.0.0] - 2025

### Added

- Shared XSLT 1.0 instrumentation helper used by both engines so Saxon can now debug XSLT 1.0 stylesheets that do not rely on `msxsl:script`.
- Version-aware Saxon pipeline that switches to the 1.0-safe probes while retaining the existing XSLT 2.0/3.0 instrumentation.
- Integration coverage for the new Saxon 1.0 path (`SaxonEngine_ShouldCaptureVariables_WhenRunningXslt1Stylesheet`) and console smoke tests for both engines.

### Changed

- Reorganised integration samples under `TestData/Integration/xslt/compiled/` and `TestData/Integration/xslt/saxon/` to mirror the engine split.
- XsltCompiledEngine now delegates all 1.0 probe insertion to the shared helper, keeping instrumentation logic in one place.
- Bumped the extension version to `1.0.0` and updated packaging docs to reference the new VSIX build numbers.
- `.gitignore` / `.vscodeignore` now filter generated `out/` folders and `*.out.xml` artifacts across the tree.

### Fixed

- Ensured Saxon 1.0 runs produce the same breakpoint and variable capture behaviour as the compiled engine by reusing the same probe shapes.

## [0.6.0] - 2025

### Added
Expand Down
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ A powerful Visual Studio Code extension that enables debugging support for XSLT
- **Variable Inspection**: Automatically materialises XSLT variables and context nodes inside VS Code’s VARIABLES pane
- **XPath Evaluation**: Evaluate XPath expressions in the current context
- **Inline C# Scripting**: Debug XSLT stylesheets with embedded C# code using Roslyn
- **Multiple Engines**: Support for compiled XSLT engine (XSLT 1.0) and Saxon engine (XSLT 2.0/3.0)
- **Multiple Engines**: Support for compiled XSLT engine (XSLT 1.0 + inline C#) and Saxon engine (XSLT 1.0 without `msxsl:script`, plus XSLT 2.0/3.0)
- **Cross-Platform**: Works on Windows, macOS, and Linux
- **Probe Tagging**: Instrumented breakpoints and trace messages are tagged with `dbg:probe="1"` so repeated runs stay idempotent

## XSLT Processing Engines

| Feature | Compiled Engine | Saxon .NET Engine |
| ----------------- | -------------------------------- | ------------------------------------ |
| **XSLT Version** | 1.0 | 2.0, 3.0 |
| **XPath Version** | 1.0 | 2.0, 3.0 |
| **Special Features** | Inline C# via `msxsl:script` | Full XSLT 2.0/3.0 features |
| **Best For** | XSLT 1.0 with inline C# | Modern XSLT 2.0/3.0 stylesheets |
| Feature | Compiled Engine | Saxon .NET Engine |
| ----------------- | -------------------------------- | ---------------------------------------------------- |
| **XSLT Version** | 1.0 | 1.0 (no inline C#), 2.0, 3.0 |
| **XPath Version** | 1.0 | 2.0, 3.0 |
| **Special Features** | Inline C# via `msxsl:script` | Full XSLT 2.0/3.0 features, version-aware probes |
| **Best For** | XSLT 1.0 with inline C# | XSLT 1.0 without `msxsl:script`, plus 2.0/3.0 stylesheets |

**Engine Selection**: Auto-detected based on XSLT version, or manually set with `"engine": "compiled"` or `"engine": "saxonnet"` in launch.json
**Engine Selection**: Auto-detected based on XSLT version and inline script usage, or manually set with `"engine": "compiled"` or `"engine": "saxonnet"` in launch.json

### ⚠️ Current Limitations

- Debugging focuses on basic XSLT structures (templates, loops, expressions); complex dynamic calls are not instrumented
- Cannot step into inline C# scripts
- Cannot step into inline C# scripts, though Roslyn instrumentation still logs entry parameters and return values to the console for visibility
- Variable inspection uses "falldown" approach: variables are auto-captured via instrumentation as execution progresses forward (cannot re-run or step back to previous lines)
- No support for: **step back**, goto targets, set variable, conditional breakpoints, or debug console autocomplete
- Variable capture limited to `@select`-based variables; complex variables with content children may not be fully captured
Expand All @@ -49,10 +49,10 @@ A powerful Visual Studio Code extension that enables debugging support for XSLT

```bash
# macOS
code --install-extension xsltdebugger-darwin-darwin-arm64-0.6.0.vsix
code --install-extension xsltdebugger-darwin-darwin-arm64-1.0.0.vsix

# Windows
code --install-extension xsltdebugger-windows-win32-x64-0.6.0.vsix
code --install-extension xsltdebugger-windows-win32-x64-1.0.0.vsix
```

2. **Create a debug configuration** in [.vscode/launch.json](#setting-up-a-debug-configuration)
Expand Down Expand Up @@ -81,19 +81,19 @@ A powerful Visual Studio Code extension that enables debugging support for XSLT

```bash
./package-all.sh
code --install-extension xsltdebugger-darwin-darwin-arm64-0.6.0.vsix
code --install-extension xsltdebugger-darwin-darwin-arm64-1.0.0.vsix
```

**Platform-specific packaging** (build individually):

```bash
# For macOS only
./package-darwin.sh
code --install-extension xsltdebugger-darwin-darwin-arm64-0.6.0.vsix
code --install-extension xsltdebugger-darwin-darwin-arm64-1.0.0.vsix

# For Windows only
./package-win.sh
code --install-extension xsltdebugger-windows-win32-x64-0.6.0.vsix
code --install-extension xsltdebugger-windows-win32-x64-1.0.0.vsix
```

## Usage
Expand Down Expand Up @@ -202,7 +202,8 @@ Create a `.vscode/launch.json` file in your project workspace:
- **Falldown Approach**: Variables appear in the Variables panel as execution flows forward past their declarations (not available before declaration)
- **No Step Back**: Since variables are captured via forward instrumentation, you cannot step backward to re-inspect previous values
- **XSLT 2.0/3.0**: Full support via Saxon engine with `@select`-based variable capture
- **XSLT 1.0**: Limited variable inspection via Compiled engine
- **XSLT 1.0 (no inline C#)**: Saxon engine reuses 1.0-safe probes (value-of/message) for equivalent capture behaviour
- **XSLT 1.0 + inline C#**: Limited variable inspection via Compiled engine only

### Log Levels

Expand Down Expand Up @@ -254,7 +255,7 @@ The debugger supports XSLT stylesheets with embedded C# code using `msxsl:script

- **Extension** ([src/extension.ts](src/extension.ts)): Registers debug type, resolves paths
- **Adapter** ([XsltDebugger.DebugAdapter/](XsltDebugger.DebugAdapter/)): DAP server, engine management, breakpoint/stepping logic
- **Engines**: `XsltCompiledEngine` (XSLT 1.0 + C#), `SaxonEngine` (XSLT 2.0/3.0)
- **Engines**: `XsltCompiledEngine` (XSLT 1.0 + C#), `SaxonEngine` (XSLT 1.0 without `msxsl:script`, plus 2.0/3.0)
- **Instrumentation**:
- Breakpoints: Both engines inject `dbg:break()` extension function calls at breakpoint lines
- Variables: Saxon engine injects `<xsl:message>` elements after variable declarations to auto-capture values
Expand Down
19 changes: 19 additions & 0 deletions TestData/Integration/xml/ShipmentConf-lml.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ShipmentConfirmation>
<Reference>REF-12345</Reference>
<Net>1500.50</Net>
<LicensePlate>ABC-123</LicensePlate>
<Orders>
<Number>ORD-001</Number>
<CustomerName>Acme Corporation</CustomerName>
<Date>2025-10-31 14:30:00</Date>
<OrderItems>
<Sequence>1</Sequence>
<OperationCode>SHIP</OperationCode>
</OrderItems>
<OrderItems>
<Sequence>2</Sequence>
<OperationCode>LOAD</OperationCode>
</OrderItems>
</Orders>
</ShipmentConfirmation>
50 changes: 50 additions & 0 deletions TestData/Integration/xml/ShipmentConf_ns.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<ns0:ShipmentConfirmation xmlns:ns0="http://www.example.com/ShipmentConfv2">
<ns0:TransportTypeCode>TRUCK</ns0:TransportTypeCode>
<ns0:TransportTypeDescription>Truck</ns0:TransportTypeDescription>
<ns0:TransportMode>Road</ns0:TransportMode>
<ns0:Direction>Outbound</ns0:Direction>
<ns0:Reference>REF-REDACTED</ns0:Reference>
<ns0:Arrival>2025-07-15T08:30:00Z</ns0:Arrival>
<ns0:Departure>2025-07-15T10:45:00+02:00</ns0:Departure>
<ns0:LicensePlate>PLATE-REDACTED</ns0:LicensePlate>
<ns0:Net Currency="USD">12500.756</ns0:Net>
<ns0:Status>Approved</ns0:Status>

<ns0:Orders>
<ns0:Number>ORD-XXXX</ns0:Number>
<ns0:Date>2025-07-15T00:00:00</ns0:Date>
<ns0:CustomerCode>CUST-XXXX</ns0:CustomerCode>
<ns0:CustomerName>LogicApps - iPaaS Tool Helper</ns0:CustomerName>
<ns0:OrderItems>
<ns0:Sequence>10</ns0:Sequence>
<ns0:OperationName>Load truck</ns0:OperationName>
<ns0:OperationCode>LD</ns0:OperationCode>
<ns0:OperationReports>
<ns0:ReportInfo>
<ns0:OperationReportDate>2025-07-14T12:00:00</ns0:OperationReportDate>
</ns0:ReportInfo>
<ns0:ReportInfo>
<ns0:OperationReportDate>2025-07-13T09:00:00</ns0:OperationReportDate>
</ns0:ReportInfo>
<ns0:ReportInfo>
<ns0:OperationReportDate>2025-06-15T06:30:00</ns0:OperationReportDate>
</ns0:ReportInfo>
</ns0:OperationReports>
</ns0:OrderItems>

<ns0:OrderItems>
<ns0:Sequence>20</ns0:Sequence>
<ns0:OperationName>Second load</ns0:OperationName>
<ns0:OperationCode>LD2</ns0:OperationCode>
<ns0:OperationReports>
<ns0:ReportInfo>
<ns0:OperationReportDate>2023-07-12</ns0:OperationReportDate>
</ns0:ReportInfo>
<ns0:ReportInfo>
<ns0:OperationReportDate>2025-07-16T00:00:00</ns0:OperationReportDate>
</ns0:ReportInfo>
</ns0:OperationReports>
</ns0:OrderItems>
</ns0:Orders>
</ns0:ShipmentConfirmation>
13 changes: 13 additions & 0 deletions TestData/Integration/xml/foreach-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
<items>
<item>First</item>
<item>Second</item>
<item>Third</item>
</items>
<sorted>
<item priority="1">Low</item>
<item priority="3">High</item>
<item priority="2">Medium</item>
</sorted>
</root>
4 changes: 4 additions & 0 deletions TestData/Integration/xml/sample-inline-cs-auto-instrument.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<data>
<test>Auto-instrumentation test data</test>
</data>
File renamed without changes.
98 changes: 98 additions & 0 deletions TestData/Integration/xslt/compiled/ShipmentConfv1.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:userCSharp="urn:userCSharp"
exclude-result-prefixes="msxsl userCSharp">

<xsl:output method="xml" indent="yes" encoding="UTF-8" />

<msxsl:script language="C#" implements-prefix="userCSharp">
<![CDATA[


public string Sum(string values)
{
double total = 0;
foreach (string s in values.Split(','))
{
double d;
if (double.TryParse(s, out d))
total += d;
}
return total.ToString("0.##");
}


public string RoundToTwoDecimals(string input)
{
try
{
double d = Convert.ToDouble(input);
return d.ToString("0.00");
}
catch
{
return "0.00";
}
}

public string MinDate(string values)
{
DateTime min = DateTime.MaxValue;
foreach (string s in values.Split(','))
{
DateTime dt;
if (DateTime.TryParse(s, out dt) && dt < min)
min = dt;
}
return min == DateTime.MaxValue ? "" : min.ToString("dd.MM.yyyy");
}
]]>
</msxsl:script>

<xsl:template match="/">
<TransportConfirmations>
<!-- Optional header/placeholder to mirror original shape -->
<Confirmation />

<xsl:for-each select="/ShipmentConfirmation/Orders/OrderItems">
<Confirmation>
<CompanyName>Logic App Tool Shipper</CompanyName>

<Reference>
<xsl:value-of select="/ShipmentConfirmation/Reference" />
</Reference>
<xsl:message>Hello</xsl:message>
<OrderNumber>
<xsl:value-of select="/ShipmentConfirmation/Orders/Number" />
<xsl:text>/</xsl:text>
<xsl:value-of select="Sequence" />
</OrderNumber>

<Quantity>
<xsl:value-of select="userCSharp:RoundToTwoDecimals(/ShipmentConfirmation/Net)" />
</Quantity>

<Unit>KG</Unit>

<!-- Earliest operation date across ReportInfo nodes -->
<Date>
<xsl:variable name="dateList">
<xsl:for-each select="OperationReports/ReportInfo/OperationReportDate">
<xsl:value-of select="normalize-space(.)" />
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="userCSharp:MinDate($dateList)" />
</Date>

<LicensePlate>
<xsl:value-of select="/ShipmentConfirmation/LicensePlate" />
</LicensePlate>
</Confirmation>
</xsl:for-each>
</TransportConfirmations>
</xsl:template>
</xsl:stylesheet>
26 changes: 26 additions & 0 deletions TestData/Integration/xslt/compiled/foreach-test.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" encoding="UTF-8" />

<xsl:template match="/">
<result>
<!-- Simple for-each without sort -->
<xsl:for-each select="/root/items/item">
<item>
<xsl:value-of select="." />
</item>
</xsl:for-each>

<!-- For-each with sort (to test insertion after sort) -->
<xsl:for-each select="/root/sorted/item">
<xsl:sort select="@priority" order="descending" />
<sorted-item>
<xsl:value-of select="." />
</sorted-item>
</xsl:for-each>
</result>
</xsl:template>

</xsl:stylesheet>
Loading
Loading