Skip to content

Commit

Permalink
Merge branch 'candidate-0.0.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
GordonSmith committed Dec 5, 2017
2 parents 803cb96 + 7323cb8 commit a5a8dbe
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 151 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This extension adds rich language support for the ECL language to VS Code, inclu
- Auto completion
- F7 Syntax check
- shift+F7 Syntax check all
- ctrl+F7 Syntax check clear all reported problems
- F12 "Goto definition"
- Basic workunit support
- Multi root workspaces ([vscode docs](https://code.visualstudio.com/docs/editor/multi-root-workspaces)): No need to manually include folders.
Expand Down Expand Up @@ -35,6 +36,12 @@ The following Visual Studio Code settings are available for the ECL extension.

// Add '-legacy' arguement to eclcc.
"ecl.legacyMode": false,

// Open workunits in external browser.
"ecl.WUOpenExternal": false

// Automatically open WU in browser on creation.
"ecl.WUAutoOpen": false
```

#### Launch Settings
Expand Down
28 changes: 24 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
},
"extensionDependencies": [],
"dependencies": {
"@hpcc-js/comms": "0.0.54",
"@hpcc-js/comms": "0.0.55",
"@hpcc-js/util": "0.0.49",
"console-stamp": "^0.2.5",
"es6-promise": "~4.1.1",
Expand Down Expand Up @@ -100,6 +100,11 @@
"title": "ECL: Check Syntax (all files)",
"description": "Save All + check syntax of all files."
},
{
"command": "ecl.syntaxCheckClear",
"title": "ECL: Clear all reported problems",
"description": "Clear all reported ECL problems."
},
{
"command": "ecl.showECLWatch",
"title": "ECL: Show Workunits",
Expand Down Expand Up @@ -139,6 +144,11 @@
"key": "shift+f7",
"mac": "shift+f7"
},
{
"command": "ecl.syntaxCheckClear",
"key": "ctrl+f7",
"mac": "ctrl+f7"
},
{
"command": "ecl.showECLWatch",
"key": "shift+f8",
Expand Down Expand Up @@ -332,18 +342,28 @@
"type": "string"
},
"default": [],
"description": "External folders use by IMPORT"
"description": "External folders use by IMPORT."
},
"ecl.eclccPath": {
"type": "string",
"default": "",
"description": "Override eclcc auto detection"
"description": "Override eclcc auto detection."
},
"ecl.legacyMode": {
"type": "boolean",
"default": false,
"description": "Add '-legacy' arguement to eclcc."
},
"ecl.WUOpenExternal": {
"type": "boolean",
"default": false,
"description": "Open WU in external browser."
},
"ecl.WUAutoOpen": {
"type": "boolean",
"default": false,
"description": "Automatically open WU on creation."
},
"ecl.defaultServer": {
"type": "string",
"description": "Default Server"
Expand Down Expand Up @@ -374,4 +394,4 @@
}
}
}
}
}
100 changes: 13 additions & 87 deletions src/debugger/ECLDebugSession.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { locateAllClientTools, locateClientTools, Workunit, WUUpdate } from "@hpcc-js/comms";
import { locateAllClientTools, locateClientTools, Workunit } from "@hpcc-js/comms";
import { Graph, IGraphItem, IObserverHandle, Level, logger, scopedLogger, ScopedLogging, Writer } from "@hpcc-js/util";
import os = require("os");
import path = require("path");
Expand All @@ -7,6 +7,7 @@ import {
StackFrame, StoppedEvent, TerminatedEvent, Thread, ThreadEvent, Variable
} from "vscode-debugadapter";
import { DebugProtocol } from "vscode-debugprotocol";
import { LaunchConfig, LaunchRequestArguments } from "./launchConfig";

class VSCodeServerWriter implements Writer {
private _owner: DebugSession;
Expand All @@ -22,46 +23,6 @@ class VSCodeServerWriter implements Writer {
// tslint:disable-next-line:no-var-requires
require("console-stamp")(console);

// This interface should always match the schema found in `package.json`.
export type LaunchMode = "submit" | "compile" | "debug";
export type LaunchProtocol = "http" | "https";
export type LaunchLegacyMode = "true" | "false";
export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
mode: LaunchMode;
program: string;
workspace: string;
protocol: LaunchProtocol;
serverAddress: string;
port: number;
rejectUnauthorized: boolean;
targetCluster: string;
eclccPath: string;
eclccArgs: string[];
includeFolders: string;
legacyMode: LaunchLegacyMode;
resultLimit: number;
user: string;
password: string;
}

export interface LaunchRequestArgumentsEx extends DebugProtocol.LaunchRequestArguments {
mode: WUUpdate.Action;
program: string;
workspace: string;
protocol: LaunchProtocol;
serverAddress: string;
port: number;
rejectUnauthorized: boolean;
targetCluster: string;
eclccPath: string;
eclccArgs: string[];
includeFolders: string[];
legacyMode: boolean;
resultLimit: number;
user: string;
password: string;
}

class WUStack {
graphItem: IGraphItem;

Expand All @@ -83,7 +44,7 @@ class WUScope {
export class ECLDebugSession extends DebugSession {
workunit: Workunit;
watchHandle: IObserverHandle;
launchRequestArgs: LaunchRequestArgumentsEx;
launchConfig: LaunchConfig;

private prevMonitorMessage: string;

Expand Down Expand Up @@ -128,69 +89,35 @@ export class ECLDebugSession extends DebugSession {

protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
this.logger.debug("launchRequest: " + JSON.stringify(args));
let _action: WUUpdate.Action;
switch (args.mode) {
case "compile":
_action = WUUpdate.Action.Compile;
break;
case "debug":
_action = WUUpdate.Action.Debug;
break;
case "submit":
default:
_action = WUUpdate.Action.Run;
break;
}
this.launchRequestArgs = {
mode: _action,
program: args.program,
workspace: args.workspace,
protocol: args.protocol || "http",
serverAddress: args.serverAddress,
port: args.port,
rejectUnauthorized: args.rejectUnauthorized || false,
targetCluster: args.targetCluster,
eclccPath: args.eclccPath ? args.eclccPath : "",
eclccArgs: args.eclccArgs ? args.eclccArgs : [],
includeFolders: args.includeFolders ? args.includeFolders.split(",") : [],
legacyMode: args.legacyMode === "true" ? true : false,
resultLimit: args.resultLimit || 100,
user: args.user || "",
password: args.password || ""
};
this.launchConfig = new LaunchConfig(args);
this.sendEvent(new OutputEvent("Locating Client Tools." + os.EOL));
locateClientTools(this.launchRequestArgs.eclccPath, this.launchRequestArgs.workspace, this.launchRequestArgs.includeFolders, this.launchRequestArgs.legacyMode).then((clientTools) => {
locateClientTools(this.launchConfig._config.eclccPath, this.launchConfig._config.workspace, this.launchConfig.includeFolders(), this.launchConfig.legacyMode()).then((clientTools) => {
this.sendEvent(new OutputEvent("Client Tools: " + clientTools.eclccPath + os.EOL));
this.sendEvent(new OutputEvent("Generating archive." + os.EOL));
return clientTools.createArchive(this.launchRequestArgs.program);
return clientTools.createArchive(this.launchConfig._config.program);
}).then((archive) => {
this.sendEvent(new OutputEvent("Creating workunit." + os.EOL));
return Workunit.create({
baseUrl: `${this.launchRequestArgs.protocol}://${this.launchRequestArgs.serverAddress}:${this.launchRequestArgs.port}`,
userID: this.launchRequestArgs.user,
password: this.launchRequestArgs.password,
rejectUnauthorized: this.launchRequestArgs.rejectUnauthorized
}).then((wu) => {
this.sendEvent(new Event("WUCreated", { ...this.launchRequestArgs, wuid: wu.Wuid }));
const pathParts = path.parse(this.launchRequestArgs.program);
return this.launchConfig.createWorkunit().then((wu) => {
this.sendEvent(new Event("WUCreated", { ...this.launchConfig._config, wuid: wu.Wuid }));
const pathParts = path.parse(this.launchConfig._config.program);
return wu.update({
Jobname: pathParts.name,
QueryText: archive.content,
ApplicationValues: {
ApplicationValue: [{
Application: "vscode-ecl",
Name: "filePath",
Value: this.launchRequestArgs.program
Value: this.launchConfig._config.program
}]
}
});
});
}).then((workunit) => {
this.workunit = workunit;
this.sendEvent(new OutputEvent("Submitting workunit: " + workunit.Wuid + os.EOL));
return workunit.submit(this.launchRequestArgs.targetCluster, this.launchRequestArgs.mode, this.launchRequestArgs.resultLimit);
return workunit.submit(this.launchConfig._config.targetCluster, this.launchConfig.action(), this.launchConfig._config.resultLimit);
}).then(() => {
this.sendEvent(new OutputEvent("Submitted: " + this.launchRequestArgs.protocol + "://" + this.launchRequestArgs.serverAddress + ":" + this.launchRequestArgs.port + "/?Widget=WUDetailsWidget&Wuid=" + this.workunit.Wuid + os.EOL));
this.sendEvent(new OutputEvent("Submitted: " + this.launchConfig.wuDetailsUrl(this.workunit.Wuid) + os.EOL));
}).then(() => {
this.workunit.watchUntilRunning().then(() => {
this.sendEvent(new InitializedEvent());
Expand Down Expand Up @@ -248,7 +175,6 @@ export class ECLDebugSession extends DebugSession {
if (this.prevMonitorMessage !== monitorMsg) {
this.prevMonitorMessage = monitorMsg;
this.sendEvent(new OutputEvent(monitorMsg));
this.sendEvent(new Event("WUWatched", { ...this.launchRequestArgs, wuid: this.workunit.Wuid }));
}
if (this.workunit.isComplete()) {
this.sendEvent(new TerminatedEvent());
Expand Down Expand Up @@ -367,7 +293,7 @@ export class ECLDebugSession extends DebugSession {
}
break;
case "workunit":
this.pushStackFrame(stackFrames, graph, { file: this.launchRequestArgs.program, col: debugState.state === "finished" ? Number.MAX_SAFE_INTEGER : 0 });
this.pushStackFrame(stackFrames, graph, { file: this.launchConfig._config.program, col: debugState.state === "finished" ? Number.MAX_SAFE_INTEGER : 0 });
break;
default:
}
Expand Down
119 changes: 119 additions & 0 deletions src/debugger/launchConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { Workunit, WUQuery, WUUpdate } from "@hpcc-js/comms";
import { setTimeout } from "timers";
import { DebugProtocol } from "vscode-debugprotocol";

// This interface should always match the schema found in `package.json`.
export type LaunchMode = "submit" | "compile" | "debug";
export type LaunchProtocol = "http" | "https";
export type LaunchLegacyMode = "true" | "false" | "";

export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
mode?: LaunchMode;
program: string;
workspace: string;
protocol: LaunchProtocol;
serverAddress: string;
port: number;
rejectUnauthorized?: boolean;
targetCluster: string;
eclccPath?: string;
eclccArgs?: string[];
includeFolders?: string;
legacyMode?: LaunchLegacyMode;
resultLimit?: number;
user?: string;
password?: string;
}

export class LaunchConfig {
_config: LaunchRequestArguments;
constructor(args: any) {
this._config = {
...args,
protocol: args.protocol || "http",
rejectUnauthorized: args.rejectUnauthorized || false,
eclccPath: args.eclccPath ? args.eclccPath : "",
eclccArgs: args.eclccArgs ? args.eclccArgs : [],
includeFolders: args.includeFolders ? args.includeFolders : "",
legacyMode: args.legacyMode || "",
resultLimit: args.resultLimit || 100,
user: args.user || "",
password: args.password || ""
};
}

action(): WUUpdate.Action {
switch (this._config.mode) {
case "compile":
return WUUpdate.Action.Compile;
case "debug":
return WUUpdate.Action.Debug;
case "submit":
default:
return WUUpdate.Action.Run;
}
}

legacyMode(): boolean | undefined {
switch (this._config.legacyMode) {
case "true":
return true;
case "false":
return false;
case "":
default:
return undefined;
}
}

includeFolders(): string[] {
return this._config.includeFolders!.split(",");
}

ping(timeout: number = 5000): Promise<boolean> {
const timeoutPrommise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Ping timeout");
}, timeout);
});
const queryPromise = Workunit.query({
baseUrl: this.espUrl(),
userID: this._config.user,
password: this._config.password,
rejectUnauthorized: this._config.rejectUnauthorized
}, { Count: 1 });

return Promise.race([timeoutPrommise, queryPromise])
.then(r => {
return true;
}).catch(e => {
return false;
});
}

createWorkunit() {
return Workunit.create({
baseUrl: this.espUrl(),
userID: this._config.user,
password: this._config.password,
rejectUnauthorized: this._config.rejectUnauthorized
});
}

query(opts: WUQuery.Request): Promise<Workunit[]> {
return Workunit.query({
baseUrl: this.espUrl(),
userID: this._config.user,
password: this._config.password,
rejectUnauthorized: this._config.rejectUnauthorized
}, opts);
}

espUrl() {
return `${this._config.protocol}://${this._config.serverAddress}:${this._config.port}`;
}

wuDetailsUrl(wuid: string) {
return `${this.espUrl()}/?Widget=WUDetailsWidget&Wuid=${wuid}`;
}
}
Loading

0 comments on commit a5a8dbe

Please sign in to comment.