This is an automated email from the ASF dual-hosted git repository.
hdalsania pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git
The following commit(s) were added to refs/heads/main by this push:
new 52ddf25b Added support for Daffodil 4.1.0 and 4.2.0, including support
for Scala 3.3.7
52ddf25b is described below
commit 52ddf25bae02f9015f66d0ab9d0e8a95247609bb
Author: Hitesh Dalsania <[email protected]>
AuthorDate: Mon Jul 27 23:09:46 2026 -0400
Added support for Daffodil 4.1.0 and 4.2.0, including support for Scala
3.3.7
update daffodilDebug.ts
Added error handling
---
CHANGELOG.md | 7 +
README.md | 16 +++
build.sbt | 2 +-
.../org.apache.daffodil.debugger.dap/Parse.scala | 142 +++++++++++++++++++--
.../org.apache.daffodil.debugger/ParseSuite.scala | 4 +
package.json | 10 +-
src/adapter/daffodilDebug.ts | 127 +++++++++++++++++-
src/daffodilDebugger/daffodilJars.ts | 20 ++-
src/launchWizard/launchWizard.ts | 26 +++-
src/launchWizard/script.js | 23 +++-
src/tests/suite/daffodilDebugger.test.ts | 8 +-
src/tests/suite/version.test.ts | 27 ++++
src/utils.ts | 2 +-
13 files changed, 385 insertions(+), 29 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b9b2d84..f54067b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,13 @@
This file outlines the release notes and known issues for the
"daffodil-vscode" extension.
+## 1.6.0
+ ### Debugger:
+ - Updated Scala 3 debugger compatibility for Apache Daffodil 4.x runtimes.
+ - Added support for Daffodil 4.0.0, 4.1.0, and 4.2.0 infoset runtime API
shapes.
+ - Added runtime compatibility regression coverage for infoset walker API
detection on Scala 3.
+ - Aligned Scala 3 target to 3.3.7 based on Daffodil release notes guidance.
+
## 1.5.0
### Debugger:
- Added support for multiple versions of the Daffodil parser (i.e., Daffodil
3.10.0, 3.11.0, and 4.0.0).
diff --git a/README.md b/README.md
index cc62780c..928ad40a 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,22 @@ The Data Editor component can be configured to run alongside
and open the design
* [Install Java Runtime 8 or
greater](https://docs.oracle.com/goldengate/1212/gg-winux/GDRAD/java.htm#BGBFJHAB)
* On Linux, glibc 2.31 or greater is required
+# Debugger Compatibility
+
+The debugger backend is built for multiple Scala and Daffodil versions so the
extension can support a wider range of parser runtimes.
+
+| Debugger target | Scala version | Daffodil dependency |
+| --- | --- | --- |
+| `debugger2_12` | 2.12.20 | 3.10.0 |
+| `debugger` | 2.13.18 | 3.11.0 |
+| `debugger3` | 3.3.8 | 4.0.0, 4.1.0, 4.2.0 |
+
+Notes:
+
+* The Scala 3 debugger target requires Java 17 or later.
+* Daffodil 4.x runtime API differences are handled in the debugger backend so
infoset serialization remains compatible with Daffodil 4.0.0, 4.1.0, and 4.2.0.
+* For Daffodil library and CLI release information, see [Apache Daffodil
Library and CLI](https://daffodil.apache.org/libraryAndCLI/).
+
# Getting Help
If additional help or guidance on using Apache Daffodilâ„¢, Apache Daffodilâ„¢
Extension for Visual Studio Code, or DFDL development in general is needed,
please engage with the Daffodil user and developer communities on [mailing
lists](https://daffodil.apache.org/community/)
(https://daffodil.apache.org/community/) and/or review the [list
archives](https://lists.apache.org/[email protected])
(https://lists.apache.org/[email protected]).
diff --git a/build.sbt b/build.sbt
index 619a9e3d..b0787ba2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -247,7 +247,7 @@ def getPlatformSpecificLibraries(scalaBinaryVersion:
String) =
)
case "3" =>
Seq(
- "org.apache.daffodil" %% "daffodil-core" % "4.0.0" % "provided,test"
+ "org.apache.daffodil" %% "daffodil-core" % "4.2.0" % "provided,test"
)
}
diff --git
a/debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala
b/debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala
index f559f9b0..c6777f85 100644
--- a/debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala
+++ b/debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala
@@ -33,7 +33,7 @@ import java.net.URI
import java.nio.file._
import org.apache.commons.io.FileUtils
import org.apache.daffodil.debugger.dap.{BuildInfo => DAPBuildInfo}
-import org.apache.daffodil.runtime1.infoset.{DIDocument, DIElement,
InfosetWalker}
+import org.apache.daffodil.runtime1.infoset.{DIDocument, DIElement}
import org.apache.daffodil.runtime1.processors._
import org.apache.daffodil.runtime1.processors.dfa.DFADelimiter
import org.apache.daffodil.runtime1.processors.parsers._
@@ -1245,18 +1245,140 @@ object Parse {
private def infosetToString(format: String, ie: DIElement): String = {
val bos = new java.io.ByteArrayOutputStream()
-
- val iw = InfosetWalker(
- ie.asInstanceOf[DIElement],
- Support.getInfosetOutputter(format, bos),
- walkHidden = false,
- ignoreBlocks = true,
- releaseUnneededInfoset = false
- )
- iw.walk(lastWalk = true)
+ val outputter = Support.getInfosetOutputter(format, bos)
+
+ // Daffodil runtime walker APIs differ across 4.x releases.
+ // Use reflection to support older InfosetWalker companion, newer
streaming walker class APIs, and
+ // finally a non-streaming constructor fallback.
+ val walker = createInfosetWalker(ie, outputter)
+ val walkMethod = walker.getClass.getMethod("walk", classOf[Boolean])
+ walkMethod.invoke(walker, Boolean.box(true))
bos.toString("UTF-8")
}
+ private def createInfosetWalker(ie: DIElement, outputter: AnyRef): AnyRef
= {
+ createInfosetWalkerFromCompanion(ie, outputter)
+ .orElse(createInfosetWalkerFromStreamingClass(ie, outputter))
+ .orElse(createInfosetWalkerFromCtor(ie, outputter))
+ .getOrElse {
+ throw new IllegalStateException(
+ "Unable to create infoset walker. Unsupported Daffodil runtime API
for infoset serialization."
+ )
+ }
+ }
+
+ def isCompatibleRuntimeForInfosetSerialization(): Boolean =
+ hasCompatibleInfosetWalkerCompanionApi() ||
hasCompatibleStreamingInfosetWalkerApi() || hasCompatibleNonStreamingCtorApi()
+
+ private def hasCompatibleInfosetWalkerCompanionApi(): Boolean =
+ Try {
+ val companion =
Class.forName("org.apache.daffodil.runtime1.infoset.InfosetWalker$")
+ companion
+ .getMethods
+ .filter(m => m.getName == "apply")
+ .exists(m => isCompatibleApplyMethod(m, classOf[DIElement], None))
+ }.getOrElse(false)
+
+ private def hasCompatibleStreamingInfosetWalkerApi(): Boolean =
+ Try {
+ val clazz =
Class.forName("org.apache.daffodil.runtime1.infoset.StreamingInfosetWalker")
+ clazz
+ .getMethods
+ .filter(m => m.getName == "apply")
+ .exists(m => isCompatibleApplyMethod(m, classOf[DIElement], None))
+ }.getOrElse(false)
+
+ private def hasCompatibleNonStreamingCtorApi(): Boolean =
+ Try {
+ val clazz =
Class.forName("org.apache.daffodil.runtime1.infoset.NonStreamingInfosetWalker")
+ clazz.getConstructors.exists(_.getParameterCount == 2)
+ }.getOrElse(false)
+
+ private def createInfosetWalkerFromCompanion(ie: DIElement, outputter:
AnyRef): Option[AnyRef] =
+ Try {
+ val companion =
Class.forName("org.apache.daffodil.runtime1.infoset.InfosetWalker$")
+ val module = companion.getField("MODULE$").get(null)
+ val maybeMethod = companion
+ .getMethods
+ .filter(m => m.getName == "apply")
+ .find(m => isCompatibleApplyMethod(m, ie.getClass,
Some(outputter.getClass)))
+
+ val method = maybeMethod.getOrElse(
+ throw new NoSuchMethodException(
+ "InfosetWalker$.apply(...) with expected first five parameters was
not found"
+ )
+ )
+
+ val args = new Array[AnyRef](method.getParameterCount)
+ args(0) = ie
+ args(1) = outputter
+ args(2) = Boolean.box(false)
+ args(3) = Boolean.box(true)
+ args(4) = Boolean.box(false)
+
+ (5 until method.getParameterCount).foreach { i =>
+ val defaultMethodName = s"apply$$default$$${i + 1}"
+ val defaultValue =
companion.getMethod(defaultMethodName).invoke(module)
+ args(i) = defaultValue.asInstanceOf[AnyRef]
+ }
+
+ method.invoke(module, args: _*).asInstanceOf[AnyRef]
+ }.toOption
+
+ private def createInfosetWalkerFromStreamingClass(ie: DIElement,
outputter: AnyRef): Option[AnyRef] =
+ Try {
+ val clazz =
Class.forName("org.apache.daffodil.runtime1.infoset.StreamingInfosetWalker")
+ val maybeApply = clazz
+ .getMethods
+ .filter(m => m.getName == "apply")
+ .find(m => isCompatibleApplyMethod(m, ie.getClass,
Some(outputter.getClass)))
+
+ val method = maybeApply.getOrElse(
+ throw new NoSuchMethodException(
+ "StreamingInfosetWalker.apply(...) with expected first five
parameters was not found"
+ )
+ )
+
+ val args = new Array[AnyRef](method.getParameterCount)
+ args(0) = ie
+ args(1) = outputter
+ args(2) = Boolean.box(false)
+ args(3) = Boolean.box(true)
+ args(4) = Boolean.box(false)
+
+ (5 until method.getParameterCount).foreach { i =>
+ val defaultMethodName = s"apply$$default$$${i + 1}"
+ val defaultValue = clazz.getMethod(defaultMethodName).invoke(null)
+ args(i) = defaultValue.asInstanceOf[AnyRef]
+ }
+
+ method.invoke(null, args: _*).asInstanceOf[AnyRef]
+ }.toOption
+
+ private def createInfosetWalkerFromCtor(ie: DIElement, outputter: AnyRef):
Option[AnyRef] =
+ Try {
+ val clazz =
Class.forName("org.apache.daffodil.runtime1.infoset.NonStreamingInfosetWalker")
+ val ctor = clazz.getConstructors.find(_.getParameterCount ==
2).getOrElse(
+ throw new
NoSuchMethodException("NonStreamingInfosetWalker(DIElement, InfosetOutputter)")
+ )
+
+ ctor.newInstance(ie, outputter).asInstanceOf[AnyRef]
+ }.toOption
+
+ private def isCompatibleApplyMethod(
+ method: java.lang.reflect.Method,
+ rootClass: Class[?],
+ outputterClass: Option[Class[?]]
+ ): Boolean = {
+ val pts = method.getParameterTypes
+ pts.length >= 5 &&
+ pts(0).isAssignableFrom(rootClass) &&
+ outputterClass.fold(!pts(1).isPrimitive)(cls =>
pts(1).isAssignableFrom(cls)) &&
+ pts(2) == java.lang.Boolean.TYPE &&
+ pts(3) == java.lang.Boolean.TYPE &&
+ pts(4) == java.lang.Boolean.TYPE
+ }
+
}
/** Behavior of a stepping debugger that can be running or stopped. */
diff --git
a/debugger/src/test/scala/org.apache.daffodil.debugger/ParseSuite.scala
b/debugger/src/test/scala/org.apache.daffodil.debugger/ParseSuite.scala
index 7102e7c3..ecf53834 100644
--- a/debugger/src/test/scala/org.apache.daffodil.debugger/ParseSuite.scala
+++ b/debugger/src/test/scala/org.apache.daffodil.debugger/ParseSuite.scala
@@ -169,6 +169,10 @@ class ParseSuite extends FunSuite {
)
}
+ test("Infoset walker runtime API is compatible") {
+
assertEquals(Parse.InfosetEvent.isCompatibleRuntimeForInfosetSerialization(),
true)
+ }
+
def buildJson(): Unit = {
schema.addProperty("path", schemaPath)
diff --git a/package.json b/package.json
index d11a6ebf..d0e77be3 100644
--- a/package.json
+++ b/package.json
@@ -718,7 +718,7 @@
"properties": {
"daffodilVersion": {
"type": "string",
- "default": "3.11.0",
+ "default": "4.2.0",
"description": "Daffodil version to use."
},
"timeout": {
@@ -755,7 +755,7 @@
}
},
"default": {
- "daffodilVersion": "3.11.0",
+ "daffodilVersion": "4.2.0",
"timeout": "10s",
"logging": {
"level": "INFO",
@@ -801,7 +801,7 @@
}
},
"dfdlDebugger": {
- "daffodilVersion": "3.11.0",
+ "daffodilVersion": "4.2.0",
"timeout": "10s",
"logging": {
"level": "INFO",
@@ -849,7 +849,7 @@
}
},
"dfdlDebugger": {
- "daffodilVersion": "3.11.0",
+ "daffodilVersion": "4.2.0",
"timeout": "10s",
"logging": {
"level": "INFO",
@@ -973,7 +973,7 @@
"type": "object",
"description": "Configuration for debugger. Settings are
daffodilVersion, timeout and logging (level and file)",
"default": {
- "daffodilVersion": "3.11.0",
+ "daffodilVersion": "4.2.0",
"timeout": "10s",
"logging": {
"level": "INFO",
diff --git a/src/adapter/daffodilDebug.ts b/src/adapter/daffodilDebug.ts
index ec098cb5..87c7a310 100644
--- a/src/adapter/daffodilDebug.ts
+++ b/src/adapter/daffodilDebug.ts
@@ -24,7 +24,8 @@ import {
Breakpoint,
} from '@vscode/debugadapter'
import { DebugProtocol } from '@vscode/debugprotocol'
-import { basename } from 'path'
+import * as fs from 'fs'
+import * as path from 'path'
import {
DaffodilRuntime,
IDaffodilBreakpoint,
@@ -51,6 +52,12 @@ interface ILaunchRequestArguments extends
DebugProtocol.LaunchRequestArguments {
trace?: boolean
/** run without debugging */
noDebug?: boolean
+ /** debugger-specific settings used by the external Scala backend */
+ dfdlDebugger?: {
+ logging?: {
+ file?: string
+ }
+ }
}
export class DaffodilDebugSession extends LoggingDebugSession {
@@ -75,6 +82,11 @@ export class DaffodilDebugSession extends
LoggingDebugSession {
private _showHex = false
private _useInvalidatedEvent = false
+ private _debuggerLogFilePath: string | undefined
+ private _debuggerLogWatcher: fs.FSWatcher | undefined
+ private _debuggerLogOffset = 0
+ private _debuggerLogRemainder = ''
+
/**
* Creates a new debug adapter that is used for one debug session.
* We configure the default implementation of a debug adapter here.
@@ -141,6 +153,7 @@ export class DaffodilDebugSession extends
LoggingDebugSession {
this.sendEvent(e)
})
this._runtime.on('end', () => {
+ this.stopDebuggerLogStreaming()
this.sendEvent(new TerminatedEvent())
})
}
@@ -243,6 +256,8 @@ export class DaffodilDebugSession extends
LoggingDebugSession {
false
)
+ this.startDebuggerLogStreaming(args)
+
// wait until configuration has finished (and configurationDoneRequest has
been called)
await this._configurationDone.wait(1000)
@@ -252,6 +267,24 @@ export class DaffodilDebugSession extends
LoggingDebugSession {
this.sendResponse(response)
}
+ protected disconnectRequest(
+ response: DebugProtocol.DisconnectResponse,
+ args: DebugProtocol.DisconnectArguments,
+ request?: DebugProtocol.Request
+ ): void {
+ this.stopDebuggerLogStreaming()
+ super.disconnectRequest(response, args, request)
+ }
+
+ protected terminateRequest(
+ response: DebugProtocol.TerminateResponse,
+ args: DebugProtocol.TerminateArguments,
+ request?: DebugProtocol.Request
+ ): void {
+ this.stopDebuggerLogStreaming()
+ super.terminateRequest(response, args, request)
+ }
+
protected async setBreakPointsRequest(
response: DebugProtocol.SetBreakpointsResponse,
args: DebugProtocol.SetBreakpointsArguments
@@ -775,9 +808,99 @@ export class DaffodilDebugSession extends
LoggingDebugSession {
//---- helpers
+ private startDebuggerLogStreaming(args: ILaunchRequestArguments): void {
+ const configuredLogFile = args.dfdlDebugger?.logging?.file?.trim()
+
+ if (!configuredLogFile || configuredLogFile.includes('${')) {
+ return
+ }
+
+ this.stopDebuggerLogStreaming()
+
+ try {
+ fs.mkdirSync(path.dirname(configuredLogFile), { recursive: true })
+ if (!fs.existsSync(configuredLogFile)) {
+ fs.writeFileSync(configuredLogFile, '')
+ }
+
+ this._debuggerLogFilePath = configuredLogFile
+ this._debuggerLogOffset = fs.statSync(configuredLogFile).size
+
+ this._debuggerLogWatcher = fs.watch(configuredLogFile, (eventType) => {
+ if (eventType === 'change') {
+ this.readDebuggerLogDelta()
+ }
+ })
+ } catch (error) {
+ this.sendEvent(
+ new OutputEvent(
+ `Unable to stream debugger log file '${configuredLogFile}':
${error}\n`
+ )
+ )
+ this.stopDebuggerLogStreaming()
+ }
+ }
+
+ private stopDebuggerLogStreaming(): void {
+ if (this._debuggerLogWatcher) {
+ this._debuggerLogWatcher.close()
+ this._debuggerLogWatcher = undefined
+ }
+
+ this._debuggerLogFilePath = undefined
+ this._debuggerLogOffset = 0
+ this._debuggerLogRemainder = ''
+ }
+
+ private readDebuggerLogDelta(): void {
+ if (!this._debuggerLogFilePath) {
+ return
+ }
+
+ try {
+ const stats = fs.statSync(this._debuggerLogFilePath)
+
+ if (stats.size < this._debuggerLogOffset) {
+ this._debuggerLogOffset = 0
+ this._debuggerLogRemainder = ''
+ }
+
+ if (stats.size === this._debuggerLogOffset) {
+ return
+ }
+
+ const chunkLength = stats.size - this._debuggerLogOffset
+ const buffer = Buffer.alloc(chunkLength)
+ const fd = fs.openSync(this._debuggerLogFilePath, 'r')
+
+ try {
+ fs.readSync(fd, buffer, 0, chunkLength, this._debuggerLogOffset)
+ } finally {
+ fs.closeSync(fd)
+ }
+
+ this._debuggerLogOffset = stats.size
+ this.emitDebuggerLogChunk(buffer.toString('utf8'))
+ } catch {
+ // Ignore transient file access errors while the backend is writing.
+ }
+ }
+
+ private emitDebuggerLogChunk(chunk: string): void {
+ const combined = this._debuggerLogRemainder + chunk
+ const lines = combined.split(/\r?\n/)
+ this._debuggerLogRemainder = lines.pop() ?? ''
+
+ for (const line of lines) {
+ if (line.length > 0) {
+ this.sendEvent(new OutputEvent(`[daffodil-debugger] ${line}\n`))
+ }
+ }
+ }
+
private createSource(filePath: string): Source {
return new Source(
- basename(filePath),
+ path.basename(filePath),
this.convertDebuggerPathToClient(filePath),
undefined,
undefined,
diff --git a/src/daffodilDebugger/daffodilJars.ts
b/src/daffodilDebugger/daffodilJars.ts
index e6cee07e..0b89873a 100644
--- a/src/daffodilDebugger/daffodilJars.ts
+++ b/src/daffodilDebugger/daffodilJars.ts
@@ -56,7 +56,7 @@ export async function checkIfDaffodilJarsNeeded(
// If not a valid daffodil version provided and it doesn't exist already in
cache then throw error
if (!(await checkIfValidDaffodilVersion(daffodilVersion))) {
throw new Error(
- 'Invalid Daffodil Version provided. Make sure
dfdlDebugger.daffodilVersion is a valid version of Daffodil'
+ 'Unsupported or Invalid Daffodil Version provided. Make sure
dfdlDebugger.daffodilVersion is a valid version of Daffodil'
)
}
@@ -65,6 +65,15 @@ export async function checkIfDaffodilJarsNeeded(
return await downloadAndExtractToGlobalStorage(context, daffodilVersion)
}
+const allowedDaffodilVersions = [
+ '3.9.0',
+ '3.10.0',
+ '3.11.0',
+ '4.0.0',
+ '4.1.0',
+ '4.2.0',
+]
+
// Helper function to get the list of valid Daffodil versions
async function getValidDaffodilVersions(): Promise<string[]> {
const url = 'https://daffodil.apache.org/doap.rdf'
@@ -91,8 +100,13 @@ async function getValidDaffodilVersions():
Promise<string[]> {
// Helper function to check if the given daffodil version is a valid version
or not
const checkIfValidDaffodilVersion = async (
daffodilVersion: string
-): Promise<boolean> =>
- (await getValidDaffodilVersions()).includes(daffodilVersion)
+): Promise<boolean> => {
+ const validVersions = await getValidDaffodilVersions()
+ return (
+ allowedDaffodilVersions.includes(daffodilVersion) &&
+ validVersions.includes(daffodilVersion)
+ )
+}
export async function downloadAndExtractToGlobalStorage(
context: vscode.ExtensionContext,
diff --git a/src/launchWizard/launchWizard.ts b/src/launchWizard/launchWizard.ts
index 63ff2a19..b1515c2c 100644
--- a/src/launchWizard/launchWizard.ts
+++ b/src/launchWizard/launchWizard.ts
@@ -26,6 +26,28 @@ import * as path from 'path'
let launchWizard: LaunchWizard | undefined
+export const DEFAULT_DAFFODIL_VERSION = '4.2.0'
+export const SUPPORTED_DAFFODIL_VERSIONS = [
+ '3.9.0',
+ '3.10.0',
+ '3.11.0',
+ '4.0.0',
+ '4.1.0',
+ '4.2.0',
+]
+
+export function getDaffodilVersionOptions(selectedVersion?: string): string {
+ const effectiveVersion =
+ selectedVersion && SUPPORTED_DAFFODIL_VERSIONS.includes(selectedVersion)
+ ? selectedVersion
+ : DEFAULT_DAFFODIL_VERSION
+
+ return SUPPORTED_DAFFODIL_VERSIONS.map((version) => {
+ const isSelected = version === effectiveVersion
+ return `<option value="${version}"${isSelected ? ' selected' :
''}>${version}</option>`
+ }).join('')
+}
+
const defaultConf = getConfig({
name: 'Wizard Config',
request: 'launch',
@@ -662,7 +684,9 @@ class LaunchWizard {
<input class="file-input" value="${defaultValues.debugServer}"
id="debugServer"/>
<p id="dfdlDaffodilVersionLabel" style="margin-top: 10px;"
class="setting-description">Version (Daffodil Version):</p>
- <input class="file-input" value="${dfdlDebugger.daffodilVersion}"
id="dfdlDaffodilVersion">
+ <select class="file-input" style="width: 200px;"
id="dfdlDaffodilVersion">
+ ${getDaffodilVersionOptions(dfdlDebugger.daffodilVersion)}
+ </select>
<p id="dfdlDebuggerTimeoutLabel" style="margin-top: 10px;"
class="setting-description">Timeout (should end with s, m or h):</p>
<input class="file-input" value="${dfdlDebugger.timeout}"
id="dfdlDebuggerTimeout">
diff --git a/src/launchWizard/script.js b/src/launchWizard/script.js
index 366ae663..e2bcf707 100644
--- a/src/launchWizard/script.js
+++ b/src/launchWizard/script.js
@@ -17,6 +17,15 @@
// Retrieve vscode api - Doing this multiple times causes issues with the
scripts
const vscode = acquireVsCodeApi()
+const SUPPORTED_DAFFODIL_VERSIONS = [
+ '3.9.0',
+ '3.10.0',
+ '3.11.0',
+ '4.0.0',
+ '4.1.0',
+ '4.2.0',
+]
+const DEFAULT_DAFFODIL_VERSION = '4.2.0'
// Function to get config index
function getConfigIndex() {
@@ -681,8 +690,18 @@ async function updateConfigValues(config) {
document.getElementById('dataEditorLogLevel').value =
config.dataEditor.logging.level
- document.getElementById('dfdlDaffodilVersion').value =
- config.dfdlDebugger.daffodilVersion
+ const dfdlDaffodilVersionSelect = document.getElementById(
+ 'dfdlDaffodilVersion'
+ )
+ if (dfdlDaffodilVersionSelect) {
+ const currentVersion =
+ config.dfdlDebugger?.daffodilVersion &&
+ SUPPORTED_DAFFODIL_VERSIONS.includes(config.dfdlDebugger.daffodilVersion)
+ ? config.dfdlDebugger.daffodilVersion
+ : DEFAULT_DAFFODIL_VERSION
+
+ dfdlDaffodilVersionSelect.value = currentVersion
+ }
document.getElementById('dfdlDebuggerTimeout').value =
config.dfdlDebugger.timeout
document.getElementById('dfdlDebuggerLogFile').value =
diff --git a/src/tests/suite/daffodilDebugger.test.ts
b/src/tests/suite/daffodilDebugger.test.ts
index bf3b3855..eaf2b317 100644
--- a/src/tests/suite/daffodilDebugger.test.ts
+++ b/src/tests/suite/daffodilDebugger.test.ts
@@ -120,13 +120,13 @@ async function getDaffodilVersionsToTest():
Promise<Array<string>> {
const isAtLeastJdk17: boolean = parseFloat(javaHome?.version ?? '0') >= 17
const dfdlVersions = ['3.10.0', '3.11.0']
- if (isAtLeastJdk17) dfdlVersions.push('4.0.0')
+ if (isAtLeastJdk17) dfdlVersions.push('4.0.0', '4.1.0', '4.2.0')
return dfdlVersions
}
/**
* Populates the array of debugger configs with all debugger configs. If JDK
>= 17 there
- * should be 6 and if JDK < 17 there should be 4. Each version of the debugger
has two
+ * should be 10 and if JDK < 17 there should be 4. Each version of the
debugger has two
* configs, one for XML and one for JSON.
*/
async function getDebuggerConfigs() {
@@ -198,11 +198,11 @@ async function checkDebug(
/**
* This function adds a number of tests to the suite for connecting to the
debuggers.
- * Since we have 3 different versions of the debugger, each needs to be
connected to
+ * Since we have multiple versions of the debugger, each needs to be connected
to
* twice. Once for outputting XML and one for outputting JSON. Not sure if
this is
* a common way to add tests to a test suite but it seemed better and more
efficient
* than making a single separate test for each combination of the debugger
plus infoset
- * format. Especially since two of the combinations can only be ran if the JDK
version
+ * format. Especially since some of the combinations can only be ran if the
JDK version
* being used is >= 17.
*/
async function addDebuggerRunningTests(
diff --git a/src/tests/suite/version.test.ts b/src/tests/suite/version.test.ts
index b6cd9b6a..a628173a 100644
--- a/src/tests/suite/version.test.ts
+++ b/src/tests/suite/version.test.ts
@@ -20,6 +20,10 @@ import * as fs from 'fs'
import * as path from 'path'
import { PROJECT_ROOT } from './common'
import { parse as jsoncParse } from 'jsonc-parser'
+import {
+ DEFAULT_DAFFODIL_VERSION,
+ getDaffodilVersionOptions,
+} from '../../launchWizard/launchWizard'
suite('Daffodil Version', () => {
const versionFile = path.join(PROJECT_ROOT, 'src/version.ts')
@@ -40,5 +44,28 @@ suite('Daffodil Version', () => {
const version = require('../../version').LIB_VERSION
assert.strictEqual(version, packageMapped.version)
})
+
+ test('launch wizard exposes the supported Daffodil version options', () =>
{
+ const options = getDaffodilVersionOptions('4.1.0')
+
+ assert.ok(options.includes('value="3.9.0"'))
+ assert.ok(options.includes('value="3.10.0"'))
+ assert.ok(options.includes('value="3.11.0"'))
+ assert.ok(options.includes('value="4.0.0"'))
+ assert.ok(options.includes('value="4.1.0"'))
+ assert.ok(options.includes('value="4.2.0"'))
+ assert.ok(options.includes('selected'))
+ assert.ok(options.includes('>4.1.0<'))
+ })
+
+ test('launch wizard defaults the Daffodil version to 4.2.0', () => {
+ assert.strictEqual(DEFAULT_DAFFODIL_VERSION, '4.2.0')
+ assert.ok(
+ getDaffodilVersionOptions(undefined).includes('value="4.2.0" selected')
+ )
+ assert.ok(
+ getDaffodilVersionOptions('9.9.9').includes('value="4.2.0" selected')
+ )
+ })
})
})
diff --git a/src/utils.ts b/src/utils.ts
index ca66f66d..b3f0e630 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -190,7 +190,7 @@ export function getConfig(jsonArgs: object):
vscode.DebugConfiguration {
},
}),
dfdlDebugger: defaultConf.get('dfdlDebugger', {
- daffodilVersion: '3.11.0',
+ daffodilVersion: '4.2.0',
timeout: '10s',
logging: {
level: 'INFO',