From bc4e7823bc36bbc52ea40785eb0b1e00cc5bea81 Mon Sep 17 00:00:00 2001
From: Josh Johnson <josh@fyrelogic.com>
Date: Mon, 18 Jan 2016 15:43:10 -0500
Subject: [PATCH 1/2] Fix #21

---
 package.json                 |   3 +-
 src/providers/Execution.ts   | 107 ++++++++++++++++++++++++++++-------
 src/providers/XPath.ts       |  12 +++-
 src/services/ChildProcess.ts |  11 +++-
 4 files changed, 111 insertions(+), 22 deletions(-)

diff --git a/package.json b/package.json
index c468db8..68650b1 100644
--- a/package.json
+++ b/package.json
@@ -125,7 +125,8 @@
 	"dependencies": {
 		"xmldom": "DotJoshJohnson/xmldom#2794915",
 		"xpath": "^0.0.9",
-        "xqlint": "^0.2.9"
+        "xqlint": "^0.2.9",
+        "opener": "^1.4.1"
 	},
     "scripts": {
         "vscode:prepublish": "tsc"
diff --git a/src/providers/Execution.ts b/src/providers/Execution.ts
index 5c81f97..a403f4f 100644
--- a/src/providers/Execution.ts
+++ b/src/providers/Execution.ts
@@ -9,6 +9,9 @@ const CFG_XQARGS: string = 'xqueryExecutionArguments';
 
 export class XQueryExecutionProvider {
     static async executeXQueryAsync(editor: vsc.TextEditor): Promise<void> {
+        // this disposable will be used for creating status bar messages
+        let disposable: vsc.Disposable;
+        
         if (editor.document.languageId !== 'xquery') {
             vsc.window.showErrorMessage('This action can only be performed on an XQuery file.');
             return;
@@ -27,33 +30,99 @@ export class XQueryExecutionProvider {
             return;
         }
         
+        let inputFile: vsc.Uri;
+        disposable = vsc.window.setStatusBarMessage('Searching for XML files in folder...');
         let files: vsc.Uri[] = await vsc.workspace.findFiles('**/*.xml', '', 100);
+        disposable.dispose();
         
-        let qpItems: any[] = new Array<any>();
-        
-        files.forEach((file) => {
-            let filename: string = file.fsPath.replace('\\', '/');
-            
-            qpItems.push({ // must implement vscode.QuickPickItem
-                label: filename.substring(filename.lastIndexOf('/') + 1),
-                description: file.fsPath,
-                file: file
-            });
-        });
-        
-        let selection = await vsc.window.showQuickPick(qpItems, { placeHolder: 'Please select an input file.' });
-        
-        if (!selection) {
+        // user does not have a folder open - prompt for file name
+        if (typeof files === 'undefined') {
+            vsc.window.showErrorMessage('You must have a folder opened in VS Code to use this feature.');
             return;
         }
         
-        let disposable: vsc.Disposable = vsc.window.setStatusBarMessage('Executing XQuery Script...');
+        // if there is only one XML file, default it
+        // otherwise, prompt the user to select one from the open folder
+        if (files.length > 1) {
+            let qpItems: any[] = new Array<any>();
+            
+            files.forEach((file) => {
+                let filename: string = file.fsPath.replace('\\', '/');
+            
+                qpItems.push({ // must implement vscode.QuickPickItem
+                    label: filename.substring(filename.lastIndexOf('/') + 1),
+                    description: file.fsPath,
+                    file: file
+                });
+            });
+            
+            let selection = await vsc.window.showQuickPick(qpItems, { placeHolder: 'Please select an input file.' });
+        
+            if (!selection) {
+                return;
+            }
+            
+            inputFile = selection.file;
+        }
+        
+        else {
+            inputFile = files[0];
+        }
+        
+        // prompt for output file name
+        let outputPath: string = null;
+        let outputPathPos: number = -1;
+        
+        for (let i = 0; i < args.length; i++) {
+            if (i > 0) {
+                if (args[i - 1].search(/out|result/)) {
+                    outputPath = args[i];
+                    outputPathPos = i;
+                }
+            }
+        }
+        
+        if (outputPath) {
+            outputPath = await vsc.window.showInputBox({
+                placeHolder: 'ex. C:\\TEMP\XQueryOutput\\MyOutputFile.xml',
+                prompt: 'Please specify the output file path. Existing file behavior is determined by the execution engine you have specified.',
+                value: outputPath
+            });
+            
+            args[outputPathPos] = outputPath;
+        }
+        
+        // call out to the execution engine
+        disposable = vsc.window.setStatusBarMessage('Executing XQuery Script...');
         args = args.map<string>((value: string) => {
             return value
                 .replace('$(script)', editor.document.uri.fsPath)
-                .replace('$(input)', selection.file.fsPath);
+                .replace('$(input)', inputFile.fsPath);
         });
-        await ChildProcess.spawnAsync(executable, args);
-        disposable.dispose();
+        
+        try {
+            await ChildProcess.spawnAsync(executable, args);
+        }
+        
+        catch (error) {            
+            if (error.message.search(/[Ll]ine:?\s*\d+/gm) > -1) {
+                let match: RegExpExecArray = /[Ll]ine:?\s*\d+/gm.exec(error.message);
+                let line: number = (Number.parseInt(match[0].replace(/([Ll]ine:?\s*)|\s/, '')) - 1);
+                
+                let selection: string = await vsc.window.showErrorMessage(error.message, `Go to Line ${line}`);
+                
+                if (selection == `Go to Line ${line}`) {
+                    editor.revealRange(new vsc.Range(line, 0, line, 0));
+                }
+            }
+            
+            else {
+                vsc.window.showErrorMessage(error.message);
+            }
+        }
+        
+        finally {
+            disposable.dispose();
+        }
     }
 }
\ No newline at end of file
diff --git a/src/providers/XPath.ts b/src/providers/XPath.ts
index 374268f..168deec 100644
--- a/src/providers/XPath.ts
+++ b/src/providers/XPath.ts
@@ -59,7 +59,17 @@ export class XPathFeatureProvider {
             
             // run the query
             let xml: string = editor.document.getText();
-            let nodes: Node[] = XPathEvaluator.evaluate(query, xml, ignoreDefaultNamespace);
+            let nodes: Node[];
+            
+            try {
+                nodes = XPathEvaluator.evaluate(query, xml, ignoreDefaultNamespace);
+            }
+            
+            catch (error) {
+                console.error(error);
+                vsc.window.showErrorMessage(`Something went wrong while evaluating the XPath: ${error}`);
+                return;
+            }
             
             // show the results to the user
             let outputChannel: vsc.OutputChannel = vsc.window.createOutputChannel(OUTPUT_CHANNEL);
diff --git a/src/services/ChildProcess.ts b/src/services/ChildProcess.ts
index 6991eca..1290a06 100644
--- a/src/services/ChildProcess.ts
+++ b/src/services/ChildProcess.ts
@@ -6,15 +6,24 @@ export class ChildProcess {
     static async spawnAsync(executable: string, args: string[]): Promise<void> {
         return new Promise<void>((resolve, reject) => {
            
+           let output: string = '';
            let handle = child_process.spawn(executable, args);
            
+           handle.stdout.on('data', (data: string) => {
+               output += data;
+           });
+           
+           handle.stderr.on('data', (data: string) => {
+               output += data;
+           });
+           
            handle.on('close', (code: string) => {
                if (code == '0') {
                    resolve();
                }
                
                else {
-                   reject(code);
+                   reject({ code: code, message: output });
                }
            });
             

From 9c10e7a271a8ef1948628e2c0ee84b6c59d91c77 Mon Sep 17 00:00:00 2001
From: Josh Johnson <josh@fyrelogic.com>
Date: Mon, 18 Jan 2016 15:44:15 -0500
Subject: [PATCH 2/2] Remove opener Dependency

---
 package.json | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 68650b1..c468db8 100644
--- a/package.json
+++ b/package.json
@@ -125,8 +125,7 @@
 	"dependencies": {
 		"xmldom": "DotJoshJohnson/xmldom#2794915",
 		"xpath": "^0.0.9",
-        "xqlint": "^0.2.9",
-        "opener": "^1.4.1"
+        "xqlint": "^0.2.9"
 	},
     "scripts": {
         "vscode:prepublish": "tsc"