diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..f62874186f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "msjsdiag.debugger-for-chrome", + "ms-vscode.PowerShell", + "eg2.tslint", + "DavidAnson.vscode-markdownlint" + ] +} diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json index 64ffb7dd42..b0dfef11b6 100644 --- a/examples/.vscode/settings.json +++ b/examples/.vscode/settings.json @@ -3,4 +3,4 @@ // Relative paths for this setting are always relative to the workspace root dir. "powershell.scriptAnalysis.settingsPath": "./PSScriptAnalyzerSettings.psd1", "files.defaultLanguage": "powershell" -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index d8913c6785..6a0b1cceb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "PowerShell", - "version": "1.4.3", + "version": "1.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -127,6 +127,17 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -206,6 +217,12 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -282,6 +299,21 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -528,6 +560,12 @@ "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", "dev": true }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -1471,6 +1509,12 @@ } } }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -2021,6 +2065,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, "pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -2359,6 +2409,15 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -2641,6 +2700,112 @@ "punycode": "1.4.1" } }, + "tslib": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", + "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", + "dev": true + }, + "tslint": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", + "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "builtin-modules": "1.1.1", + "chalk": "2.3.0", + "commander": "2.12.2", + "diff": "3.4.0", + "glob": "7.1.2", + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.4.1", + "tslib": "1.8.1", + "tsutils": "2.13.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "tsutils": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz", + "integrity": "sha512-FuWzNJbMsp3gcZMbI3b5DomhW4Ia41vMxjN63nKWI0t7f+I3UmHfRl0TrXJTwI2LUduDG+eR1Mksp3pvtlyCFQ==", + "dev": true, + "requires": { + "tslib": "1.8.1" + } + }, "tunnel": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", diff --git a/package.json b/package.json index c53589f788..b6c946454b 100644 --- a/package.json +++ b/package.json @@ -40,12 +40,13 @@ "vscode-languageclient": "3.3.0" }, "devDependencies": { + "@types/mocha": "^2.2.32", "@types/node": "^6.0.40", + "mocha": "^2.3.3", + "tslint": "^5.8.0", "typescript": "2.3.x", "vsce": "^1.18.0", - "vscode": "^1.1.0", - "mocha": "^2.3.3", - "@types/mocha": "^2.2.32" + "vscode": "^1.1.0" }, "extensionDependencies": [ "vscode.powershell" diff --git a/src/controls/animatedStatusBar.ts b/src/controls/animatedStatusBar.ts index 4320bc9864..dc4709a56d 100644 --- a/src/controls/animatedStatusBar.ts +++ b/src/controls/animatedStatusBar.ts @@ -3,14 +3,14 @@ *--------------------------------------------------------*/ import { - StatusBarItem, + Disposable, StatusBarAlignment, + StatusBarItem, ThemeColor, - Disposable, window} from "vscode"; export function showAnimatedStatusBarMessage(text: string, hideWhenDone: Thenable): Disposable { - let animatedStatusBarItem: AnimatedStatusBarItem = new AnimatedStatusBarItem(text); + const animatedStatusBarItem: AnimatedStatusBarItem = new AnimatedStatusBarItem(text); animatedStatusBarItem.show(hideWhenDone); return animatedStatusBarItem; } @@ -73,7 +73,7 @@ class AnimatedStatusBarItem implements StatusBarItem { this.counter = 0; this.suffixStates = [" ", ". ", ".. ", "..."]; this.maxCount = this.suffixStates.length; - this.timerInterval = ((1/this.maxCount) * 1000) / this.animationRate; + this.timerInterval = ((1 / this.maxCount) * 1000) / this.animationRate; this.elapsedTime = 0; } @@ -121,4 +121,4 @@ class AnimatedStatusBarItem implements StatusBarItem { private stop(): void { clearInterval(this.intervalId); } -} \ No newline at end of file +} diff --git a/src/controls/checkboxQuickPick.ts b/src/controls/checkboxQuickPick.ts index 3babd238ad..2271cd95ed 100644 --- a/src/controls/checkboxQuickPick.ts +++ b/src/controls/checkboxQuickPick.ts @@ -4,67 +4,66 @@ import vscode = require("vscode"); -var confirmItemLabel: string = "$(checklist) Confirm"; -var checkedPrefix: string = "[ $(check) ]"; -var uncheckedPrefix: string = "[ ]"; -var defaultPlaceHolder: string = "Select 'Confirm' to confirm or press 'Esc' key to cancel"; +const confirmItemLabel: string = "$(checklist) Confirm"; +const checkedPrefix: string = "[ $(check) ]"; +const uncheckedPrefix: string = "[ ]"; +const defaultPlaceHolder: string = "Select 'Confirm' to confirm or press 'Esc' key to cancel"; -export interface CheckboxQuickPickItem { +export interface ICheckboxQuickPickItem { label: string; description?: string; isSelected: boolean; } -export interface CheckboxQuickPickOptions { +export interface ICheckboxQuickPickOptions { confirmPlaceHolder: string; } -var defaultOptions:CheckboxQuickPickOptions = { confirmPlaceHolder: defaultPlaceHolder}; +const defaultOptions: ICheckboxQuickPickOptions = { confirmPlaceHolder: defaultPlaceHolder}; export function showCheckboxQuickPick( - items: CheckboxQuickPickItem[], - options: CheckboxQuickPickOptions = defaultOptions): Thenable { + items: ICheckboxQuickPickItem[], + options: ICheckboxQuickPickOptions = defaultOptions): Thenable { return showInner(items, options).then( (selectedItem) => { // We're mutating the original item list so just return it for now. // If 'selectedItem' is undefined it means the user cancelled the // inner showQuickPick UI so pass the undefined along. - return selectedItem != undefined ? items : undefined; - }) + return selectedItem !== undefined ? items : undefined; + }); } -function getQuickPickItems(items: CheckboxQuickPickItem[]): vscode.QuickPickItem[] { +function getQuickPickItems(items: ICheckboxQuickPickItem[]): vscode.QuickPickItem[] { - let quickPickItems: vscode.QuickPickItem[] = []; + const quickPickItems: vscode.QuickPickItem[] = []; quickPickItems.push({ label: confirmItemLabel, description: "" }); - items.forEach(item => + items.forEach((item) => quickPickItems.push({ label: convertToCheckBox(item), - description: item.description + description: item.description, })); return quickPickItems; } function showInner( - items: CheckboxQuickPickItem[], - options: CheckboxQuickPickOptions): Thenable { + items: ICheckboxQuickPickItem[], + options: ICheckboxQuickPickOptions): Thenable { - var quickPickThenable: Thenable = + const quickPickThenable: Thenable = vscode.window.showQuickPick( getQuickPickItems(items), { ignoreFocusOut: true, matchOnDescription: true, - placeHolder: options.confirmPlaceHolder + placeHolder: options.confirmPlaceHolder, }); return quickPickThenable.then( (selection) => { if (!selection) { - //return Promise.reject("showCheckBoxQuickPick cancelled") return Promise.resolve(undefined); } @@ -72,12 +71,12 @@ function showInner( return selection; } - let index: number = getItemIndex(items, selection.label); + const index: number = getItemIndex(items, selection.label); if (index >= 0) { toggleSelection(items[index]); - } - else { + } else { + // tslint:disable-next-line:no-console console.log(`Couldn't find CheckboxQuickPickItem for label '${selection.label}'`); } @@ -85,15 +84,15 @@ function showInner( }); } -function getItemIndex(items: CheckboxQuickPickItem[], itemLabel: string): number { - var trimmedLabel = itemLabel.substr(itemLabel.indexOf("]") + 2); - return items.findIndex(item => item.label === trimmedLabel); +function getItemIndex(items: ICheckboxQuickPickItem[], itemLabel: string): number { + const trimmedLabel = itemLabel.substr(itemLabel.indexOf("]") + 2); + return items.findIndex((item) => item.label === trimmedLabel); } -function toggleSelection(item: CheckboxQuickPickItem): void { +function toggleSelection(item: ICheckboxQuickPickItem): void { item.isSelected = !item.isSelected; } -function convertToCheckBox(item: CheckboxQuickPickItem): string { +function convertToCheckBox(item: ICheckboxQuickPickItem): string { return `${item.isSelected ? checkedPrefix : uncheckedPrefix} ${item.label}`; -} \ No newline at end of file +} diff --git a/src/debugAdapter.ts b/src/debugAdapter.ts index 10940dec24..3886c30904 100644 --- a/src/debugAdapter.ts +++ b/src/debugAdapter.ts @@ -2,11 +2,11 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import fs = require('fs'); -import path = require('path'); -import net = require('net'); -import utils = require('./utils'); -import { Logger } from './logging'; +import fs = require("fs"); +import net = require("net"); +import path = require("path"); +import { Logger } from "./logging"; +import utils = require("./utils"); // NOTE: The purpose of this file is to serve as a bridge between // VS Code's debug adapter client (which communicates via stdio) and @@ -14,9 +14,9 @@ import { Logger } from './logging'; // named pipes or a network protocol). It is purely a naive data // relay between the two transports. -var logBasePath = path.resolve(__dirname, "../../logs"); +const logBasePath = path.resolve(__dirname, "../../logs"); -var debugAdapterLogWriter = +const debugAdapterLogWriter = fs.createWriteStream( path.resolve( logBasePath, @@ -26,13 +26,13 @@ var debugAdapterLogWriter = // debug server process.stdin.pause(); -var debugSessionFilePath = utils.getDebugSessionFilePath(); +const debugSessionFilePath = utils.getDebugSessionFilePath(); debugAdapterLogWriter.write("Session file path: " + debugSessionFilePath + ", pid: " + process.pid + " \r\n"); function startDebugging() { // Read the details of the current session to learn // the connection details for the debug service - let sessionDetails = utils.readSessionFile(debugSessionFilePath); + const sessionDetails = utils.readSessionFile(debugSessionFilePath); // Delete the session file after it has been read so that // it isn't used mistakenly by another debug session @@ -42,13 +42,13 @@ function startDebugging() { debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n"); let isConnected = false; - let debugServiceSocket = net.connect(sessionDetails.debugServicePort, '127.0.0.1'); + const debugServiceSocket = net.connect(sessionDetails.debugServicePort, "127.0.0.1"); // Write any errors to the log file debugServiceSocket.on( - 'error', + "error", (e) => { - debugAdapterLogWriter.write("Socket ERROR: " + e + "\r\n") + debugAdapterLogWriter.write("Socket ERROR: " + e + "\r\n"); debugAdapterLogWriter.close(); debugServiceSocket.destroy(); process.exit(0); @@ -56,19 +56,19 @@ function startDebugging() { // Route any output from the socket through stdout debugServiceSocket.on( - 'data', + "data", (data: Buffer) => process.stdout.write(data)); // Wait for the connection to complete debugServiceSocket.on( - 'connect', + "connect", () => { isConnected = true; debugAdapterLogWriter.write("Connected to socket!\r\n\r\n"); // When data comes on stdin, route it through the socket process.stdin.on( - 'data', + "data", (data: Buffer) => debugServiceSocket.write(data)); // Resume the stdin stream @@ -77,7 +77,7 @@ function startDebugging() { // When the socket closes, end the session debugServiceSocket.on( - 'close', + "close", () => { debugAdapterLogWriter.write("Socket closed, shutting down."); debugAdapterLogWriter.close(); @@ -88,17 +88,17 @@ function startDebugging() { setTimeout(() => { process.exit(0); }, 2000); - } - ) + }, + ); process.on( - 'exit', + "exit", (e) => { if (debugAdapterLogWriter) { debugAdapterLogWriter.write("Debug adapter process is exiting..."); } - } - ) + }, + ); } function waitForSessionFile(triesRemaining: number) { @@ -109,28 +109,26 @@ function waitForSessionFile(triesRemaining: number) { if (utils.checkIfFileExists(debugSessionFilePath)) { debugAdapterLogWriter.write(`Session file present, connecting to debug adapter...\r\n\r\n`); startDebugging(); - } - else { + } else { // Wait for a second and try again setTimeout( () => waitForSessionFile(triesRemaining - 1), 1000); } - } - else { + } else { debugAdapterLogWriter.write(`Timed out waiting for session file!\r\n`); - var errorJson = + const errorJson = JSON.stringify({ type: "response", request_seq: 1, command: "initialize", success: false, - message: "Timed out waiting for the PowerShell extension to start." + message: "Timed out waiting for the PowerShell extension to start.", }); process.stdout.write( - `Content-Length: ${Buffer.byteLength(errorJson, 'utf8')}\r\n\r\n${errorJson}`, - 'utf8'); + `Content-Length: ${Buffer.byteLength(errorJson, "utf8")}\r\n\r\n${errorJson}`, + "utf8"); } } diff --git a/src/feature.ts b/src/feature.ts index 596f0cc8ed..f946a8a482 100644 --- a/src/feature.ts +++ b/src/feature.ts @@ -2,9 +2,9 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { LanguageClient } from 'vscode-languageclient'; -export { LanguageClient } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient } from "vscode-languageclient"; +export { LanguageClient } from "vscode-languageclient"; export interface IFeature extends vscode.Disposable { setLanguageClient(languageclient: LanguageClient); diff --git a/src/features/CodeActions.ts b/src/features/CodeActions.ts index f6ca66beea..871773b64a 100644 --- a/src/features/CodeActions.ts +++ b/src/features/CodeActions.ts @@ -2,17 +2,17 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { LanguageClient } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient } from "vscode-languageclient"; import Window = vscode.window; -import { IFeature } from '../feature'; +import { IFeature } from "../feature"; export class CodeActionsFeature implements IFeature { private command: vscode.Disposable; private languageClient: LanguageClient; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.ApplyCodeActionEdits', (edit: any) => { + this.command = vscode.commands.registerCommand("PowerShell.ApplyCodeActionEdits", (edit: any) => { Window.activeTextEditor.edit((editBuilder) => { editBuilder.replace( new vscode.Range( @@ -25,11 +25,11 @@ export class CodeActionsFeature implements IFeature { }); } - public setLanguageClient(languageclient: LanguageClient) { - this.languageClient = languageclient; - } - public dispose() { this.command.dispose(); } -} \ No newline at end of file + + public setLanguageClient(languageclient: LanguageClient) { + this.languageClient = languageclient; + } +} diff --git a/src/features/Console.ts b/src/features/Console.ts index deb91eb0d7..ae1f6f87e6 100644 --- a/src/features/Console.ts +++ b/src/features/Console.ts @@ -2,91 +2,82 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { showCheckboxQuickPick, CheckboxQuickPickItem } from '../controls/checkboxQuickPick' -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { ICheckboxQuickPickItem, showCheckboxQuickPick } from "../controls/checkboxQuickPick"; +import { IFeature } from "../feature"; -export namespace EvaluateRequest { - export const type = new RequestType('evaluate'); -} +export const EvaluateRequestType = new RequestType("evaluate"); +export const OutputNotificationType = new NotificationType("output"); -export interface EvaluateRequestArguments { - expression: string; -} +export const ShowChoicePromptRequestType = + new RequestType("powerShell/showChoicePrompt"); + +export const ShowInputPromptRequestType = + new RequestType("powerShell/showInputPrompt"); -export namespace OutputNotification { - export const type = new NotificationType('output'); +export interface IEvaluateRequestArguments { + expression: string; } -export interface OutputNotificationBody { +export interface IOutputNotificationBody { category: string; output: string; } -export namespace ShowChoicePromptRequest { - export const type = - new RequestType('powerShell/showChoicePrompt'); -} - -export namespace ShowInputPromptRequest { - export const type = - new RequestType('powerShell/showInputPrompt'); -} - -interface ChoiceDetails { +interface IChoiceDetails { label: string; helpMessage: string; } -interface ShowInputPromptRequestArgs { +interface IShowInputPromptRequestArgs { name: string; label: string; } -interface ShowChoicePromptRequestArgs { +interface IShowChoicePromptRequestArgs { isMultiChoice: boolean; caption: string; message: string; - choices: ChoiceDetails[]; + choices: IChoiceDetails[]; defaultChoices: number[]; } -interface ShowChoicePromptResponseBody { +interface IShowChoicePromptResponseBody { responseText: string; promptCancelled: boolean; } -interface ShowInputPromptResponseBody { +interface IShowInputPromptResponseBody { responseText: string; promptCancelled: boolean; } function showChoicePrompt( - promptDetails: ShowChoicePromptRequestArgs, - client: LanguageClient) : Thenable { + promptDetails: IShowChoicePromptRequestArgs, + client: LanguageClient): Thenable { - var resultThenable: Thenable = undefined; + let resultThenable: Thenable; if (!promptDetails.isMultiChoice) { - var quickPickItems = - promptDetails.choices.map(choice => { + let quickPickItems = + promptDetails.choices.map((choice) => { return { label: choice.label, - description: choice.helpMessage - } + description: choice.helpMessage, + }; }); - if (promptDetails.defaultChoices && - promptDetails.defaultChoices.length > 0) { - + if (promptDetails.defaultChoices && promptDetails.defaultChoices.length > 0) { // Shift the default items to the front of the // array so that the user can select it easily - var defaultChoice = promptDetails.defaultChoices[0]; + const defaultChoice = promptDetails.defaultChoices[0]; if (defaultChoice > -1 && defaultChoice < promptDetails.choices.length) { - var defaultChoiceItem = quickPickItems[defaultChoice]; + const defaultChoiceItem = quickPickItems[defaultChoice]; quickPickItems.splice(defaultChoice, 1); // Add the default choice to the head of the array @@ -100,20 +91,19 @@ function showChoicePrompt( quickPickItems, { placeHolder: promptDetails.caption + " - " + promptDetails.message }) .then(onItemSelected); - } - else { - var checkboxQuickPickItems = - promptDetails.choices.map(choice => { + } else { + const checkboxQuickPickItems = + promptDetails.choices.map((choice) => { return { label: choice.label, description: choice.helpMessage, - isSelected: false - } + isSelected: false, + }; }); // Select the defaults - promptDetails.defaultChoices.forEach(choiceIndex => { - checkboxQuickPickItems[choiceIndex].isSelected = true + promptDetails.defaultChoices.forEach((choiceIndex) => { + checkboxQuickPickItems[choiceIndex].isSelected = true; }); resultThenable = @@ -127,61 +117,58 @@ function showChoicePrompt( } function showInputPrompt( - promptDetails: ShowInputPromptRequestArgs, - client: LanguageClient) : Thenable { + promptDetails: IShowInputPromptRequestArgs, + client: LanguageClient): Thenable { - var resultThenable = + const resultThenable = vscode.window.showInputBox({ - placeHolder: promptDetails.name + ": " - }).then(onInputEntered) + placeHolder: promptDetails.name + ": ", + }).then(onInputEntered); return resultThenable; } -function onItemsSelected(chosenItems: CheckboxQuickPickItem[]): ShowChoicePromptResponseBody { +function onItemsSelected(chosenItems: ICheckboxQuickPickItem[]): IShowChoicePromptResponseBody { if (chosenItems !== undefined) { return { promptCancelled: false, - responseText: chosenItems.filter(item => item.isSelected).map(item => item.label).join(", ") + responseText: chosenItems.filter((item) => item.isSelected).map((item) => item.label).join(", "), }; - } - else { + } else { // User cancelled the prompt, send the cancellation return { promptCancelled: true, - responseText: undefined + responseText: undefined, }; } } -function onItemSelected(chosenItem: vscode.QuickPickItem): ShowChoicePromptResponseBody { +function onItemSelected(chosenItem: vscode.QuickPickItem): IShowChoicePromptResponseBody { if (chosenItem !== undefined) { return { promptCancelled: false, - responseText: chosenItem.label + responseText: chosenItem.label, }; - } - else { + } else { // User cancelled the prompt, send the cancellation return { promptCancelled: true, - responseText: undefined + responseText: undefined, }; } } -function onInputEntered(responseText: string): ShowInputPromptResponseBody { +function onInputEntered(responseText: string): IShowInputPromptResponseBody { if (responseText !== undefined) { return { promptCancelled: false, - responseText: responseText - } - } - else { + responseText, + }; + } else { return { promptCancelled: true, - responseText: undefined - } + responseText: undefined, + }; } } @@ -191,48 +178,47 @@ export class ConsoleFeature implements IFeature { constructor() { this.commands = [ - vscode.commands.registerCommand('PowerShell.RunSelection', () => { + vscode.commands.registerCommand("PowerShell.RunSelection", () => { if (this.languageClient === undefined) { // TODO: Log error message return; } - var editor = vscode.window.activeTextEditor; - var selectionRange: vscode.Range = undefined; + const editor = vscode.window.activeTextEditor; + let selectionRange: vscode.Range; if (!editor.selection.isEmpty) { selectionRange = new vscode.Range( editor.selection.start, editor.selection.end); - } - else { + } else { selectionRange = editor.document.lineAt(editor.selection.start.line).range; } - this.languageClient.sendRequest(EvaluateRequest.type, { - expression: editor.document.getText(selectionRange) + this.languageClient.sendRequest(EvaluateRequestType, { + expression: editor.document.getText(selectionRange), }); // Show the integrated console if it isn't already visible vscode.commands.executeCommand("PowerShell.ShowSessionConsole", true); - }) + }), ]; } + public dispose() { + this.commands.forEach((command) => command.dispose()); + } + public setLanguageClient(languageClient: LanguageClient) { this.languageClient = languageClient; this.languageClient.onRequest( - ShowChoicePromptRequest.type, - promptDetails => showChoicePrompt(promptDetails, this.languageClient)); + ShowChoicePromptRequestType, + (promptDetails) => showChoicePrompt(promptDetails, this.languageClient)); this.languageClient.onRequest( - ShowInputPromptRequest.type, - promptDetails => showInputPrompt(promptDetails, this.languageClient)); - } - - public dispose() { - this.commands.forEach(command => command.dispose()); + ShowInputPromptRequestType, + (promptDetails) => showInputPrompt(promptDetails, this.languageClient)); } } diff --git a/src/features/CustomViews.ts b/src/features/CustomViews.ts index 97e9cd447f..336d097ead 100644 --- a/src/features/CustomViews.ts +++ b/src/features/CustomViews.ts @@ -2,9 +2,9 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; export class CustomViewsFeature implements IFeature { @@ -20,11 +20,15 @@ export class CustomViewsFeature implements IFeature { this.contentProvider)); } + public dispose() { + this.commands.forEach((d) => d.dispose()); + } + public setLanguageClient(languageClient: LanguageClient) { languageClient.onRequest( - NewCustomViewRequest.type, - args => { + NewCustomViewRequestType, + (args) => { this.contentProvider.createView( args.id, args.title, @@ -32,30 +36,30 @@ export class CustomViewsFeature implements IFeature { }); languageClient.onRequest( - ShowCustomViewRequest.type, - args => { + ShowCustomViewRequestType, + (args) => { this.contentProvider.showView( args.id, args.viewColumn); }); languageClient.onRequest( - CloseCustomViewRequest.type, - args => { + CloseCustomViewRequestType, + (args) => { this.contentProvider.closeView(args.id); }); languageClient.onRequest( - SetHtmlContentViewRequest.type, - args => { + SetHtmlContentViewRequestType, + (args) => { this.contentProvider.setHtmlContentView( args.id, args.htmlContent); }); languageClient.onRequest( - AppendHtmlOutputViewRequest.type, - args => { + AppendHtmlOutputViewRequestType, + (args) => { this.contentProvider.appendHtmlOutputView( args.id, args.appendedHtmlBodyContent); @@ -63,10 +67,6 @@ export class CustomViewsFeature implements IFeature { this.languageClient = languageClient; } - - public dispose() { - this.commands.forEach(d => d.dispose()); - } } class PowerShellContentProvider implements vscode.TextDocumentContentProvider { @@ -75,23 +75,26 @@ class PowerShellContentProvider implements vscode.TextDocumentContentProvider { private viewIndex: { [id: string]: CustomView } = {}; private didChangeEvent: vscode.EventEmitter = new vscode.EventEmitter(); + // tslint:disable-next-line:member-ordering + public onDidChange: vscode.Event = this.didChangeEvent.event; + public provideTextDocumentContent(uri: vscode.Uri): string { return this.viewIndex[uri.toString()].getContent(); } public createView(id: string, title: string, viewType: CustomViewType) { - let view = undefined; + let view; switch (viewType) { case CustomViewType.HtmlContent: view = new HtmlContentView(id, title); - }; + } this.viewIndex[this.getUri(view.id)] = view; } public showView(id: string, viewColumn: vscode.ViewColumn) { - let uriString = this.getUri(id); - let view: CustomView = this.viewIndex[uriString]; + const uriString = this.getUri(id); + const view: CustomView = this.viewIndex[uriString]; vscode.commands.executeCommand( "vscode.previewHtml", @@ -101,40 +104,38 @@ class PowerShellContentProvider implements vscode.TextDocumentContentProvider { } public closeView(id: string) { - let uriString = this.getUri(id); - let view: CustomView = this.viewIndex[uriString]; + const uriString = this.getUri(id); + const view: CustomView = this.viewIndex[uriString]; - vscode.workspace.textDocuments.some( - doc => { - if (doc.uri.toString() === uriString) { - vscode.window - .showTextDocument(doc) - .then(editor => vscode.commands.executeCommand("workbench.action.closeActiveEditor")) + vscode.workspace.textDocuments.some((doc) => { + if (doc.uri.toString() === uriString) { + vscode.window + .showTextDocument(doc) + .then((editor) => vscode.commands.executeCommand("workbench.action.closeActiveEditor")); - return true; - } - - return false; + return true; } - ) + + return false; + }); } - public setHtmlContentView(id: string, content: HtmlContent) { - let uriString = this.getUri(id); - let view: CustomView = this.viewIndex[uriString]; + public setHtmlContentView(id: string, content: IHtmlContent) { + const uriString = this.getUri(id); + const view: CustomView = this.viewIndex[uriString]; if (view.viewType === CustomViewType.HtmlContent) { - (view).setContent(content); + (view as HtmlContentView).setContent(content); this.didChangeEvent.fire(vscode.Uri.parse(uriString)); } } public appendHtmlOutputView(id: string, content: string) { - let uriString = this.getUri(id); - let view: CustomView = this.viewIndex[uriString]; + const uriString = this.getUri(id); + const view: CustomView = this.viewIndex[uriString]; if (view.viewType === CustomViewType.HtmlContent) { - (view).appendContent(content); + (view as HtmlContentView).appendContent(content); this.didChangeEvent.fire(vscode.Uri.parse(uriString)); } } @@ -142,8 +143,6 @@ class PowerShellContentProvider implements vscode.TextDocumentContentProvider { private getUri(id: string) { return `powershell://views/${id}`; } - - public onDidChange: vscode.Event = this.didChangeEvent.event; } abstract class CustomView { @@ -151,39 +150,37 @@ abstract class CustomView { constructor( public id: string, public title: string, - public viewType: CustomViewType) - { + public viewType: CustomViewType) { } - abstract getContent(): string; + public abstract getContent(): string; } class HtmlContentView extends CustomView { - private htmlContent: HtmlContent = { + private htmlContent: IHtmlContent = { bodyContent: "", javaScriptPaths: [], - styleSheetPaths: [] + styleSheetPaths: [], }; constructor( id: string, - title: string) - { + title: string) { super(id, title, CustomViewType.HtmlContent); } - setContent(htmlContent: HtmlContent) { + public setContent(htmlContent: IHtmlContent) { this.htmlContent = htmlContent; } - appendContent(content: string) { + public appendContent(content: string) { this.htmlContent.bodyContent += content; } - getContent(): string { - var styleSrc = "none"; - var styleTags = ""; + public getContent(): string { + let styleSrc = "none"; + let styleTags = ""; function getNonce(): number { return Math.floor(Math.random() * 100000) + 100000; @@ -193,29 +190,31 @@ class HtmlContentView extends CustomView { this.htmlContent.styleSheetPaths.length > 0) { styleSrc = ""; this.htmlContent.styleSheetPaths.forEach( - p => { - var nonce = getNonce(); + (p) => { + const nonce = getNonce(); styleSrc += `'nonce-${nonce}' `; styleTags += `\n`; }); } - var scriptSrc = "none"; - var scriptTags = ""; + let scriptSrc = "none"; + let scriptTags = ""; if (this.htmlContent.javaScriptPaths && this.htmlContent.javaScriptPaths.length > 0) { scriptSrc = ""; this.htmlContent.javaScriptPaths.forEach( - p => { - var nonce = getNonce(); + (p) => { + const nonce = getNonce(); scriptSrc += `'nonce-${nonce}' `; scriptTags += `\n`; }); } // Return an HTML page with the specified content - return `${styleTags}\n${this.htmlContent.bodyContent}\n${scriptTags}`; + return `` + + `${styleTags}\n${this.htmlContent.bodyContent}\n${scriptTags}`; } } @@ -223,63 +222,53 @@ enum CustomViewType { HtmlContent = 1, } -namespace NewCustomViewRequest { - export const type = - new RequestType( - 'powerShell/newCustomView'); -} +export const NewCustomViewRequestType = + new RequestType( + "powerShell/newCustomView"); -interface NewCustomViewRequestArguments { +interface INewCustomViewRequestArguments { id: string; title: string; viewType: CustomViewType; } -namespace ShowCustomViewRequest { - export const type = - new RequestType( - 'powerShell/showCustomView'); -} +export const ShowCustomViewRequestType = + new RequestType( + "powerShell/showCustomView"); -interface ShowCustomViewRequestArguments { +interface IShowCustomViewRequestArguments { id: string; viewColumn: vscode.ViewColumn; } -namespace CloseCustomViewRequest { - export const type = - new RequestType( - 'powerShell/closeCustomView'); -} +export const CloseCustomViewRequestType = + new RequestType( + "powerShell/closeCustomView"); -interface CloseCustomViewRequestArguments { +interface ICloseCustomViewRequestArguments { id: string; } -namespace SetHtmlContentViewRequest { - export const type = - new RequestType( - 'powerShell/setHtmlViewContent'); -} +export const SetHtmlContentViewRequestType = + new RequestType( + "powerShell/setHtmlViewContent"); -interface HtmlContent { +interface IHtmlContent { bodyContent: string; javaScriptPaths: string[]; styleSheetPaths: string[]; } -interface SetHtmlContentViewRequestArguments { +interface ISetHtmlContentViewRequestArguments { id: string; - htmlContent: HtmlContent; + htmlContent: IHtmlContent; } -namespace AppendHtmlOutputViewRequest { - export const type = - new RequestType( - 'powerShell/appendHtmlViewContent'); -} +export const AppendHtmlOutputViewRequestType = + new RequestType( + "powerShell/appendHtmlViewContent"); -interface AppendHtmlOutputViewRequestArguments { +interface IAppendHtmlOutputViewRequestArguments { id: string; appendedHtmlBodyContent: string; } diff --git a/src/features/DebugSession.ts b/src/features/DebugSession.ts index 11a8bdbdb7..57399442ce 100644 --- a/src/features/DebugSession.ts +++ b/src/features/DebugSession.ts @@ -2,17 +2,17 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import utils = require('../utils'); -import Settings = require('../settings'); -import { dirname } from 'path'; -import { IFeature } from '../feature'; -import { SessionManager } from '../session'; -import { OperatingSystem, PlatformDetails, getPlatformDetails } from '../platform'; - -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import { dirname } from "path"; +import vscode = require("vscode"); import { CancellationToken, DebugConfiguration, DebugConfigurationProvider, - ExtensionContext, ProviderResult, WorkspaceFolder } from 'vscode'; + ExtensionContext, ProviderResult, WorkspaceFolder } from "vscode"; +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; +import { getPlatformDetails, IPlatformDetails, OperatingSystem } from "../platform"; +import { SessionManager } from "../session"; +import Settings = require("../settings"); +import utils = require("../utils"); +import { hostname } from "os"; export class DebugSessionFeature implements IFeature, DebugConfigurationProvider { @@ -22,38 +22,39 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider constructor(context: ExtensionContext, private sessionManager: SessionManager) { // Register a debug configuration provider - context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('PowerShell', this)); - } - - public setLanguageClient(languageClient: LanguageClient) { + context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("PowerShell", this)); } public dispose() { this.command.dispose(); } + public setLanguageClient(languageClient: LanguageClient) { + // There is no implementation for this IFeature method + } + // DebugConfigurationProvider method - resolveDebugConfiguration( + public resolveDebugConfiguration( folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { - let currentDocument = vscode.window.activeTextEditor.document; - let debugCurrentScript = (config.script === "${file}") || !config.request; - let generateLaunchConfig = !config.request; + const currentDocument = vscode.window.activeTextEditor.document; + const debugCurrentScript = (config.script === "${file}") || !config.request; + const generateLaunchConfig = !config.request; - var settings = Settings.load(); + const settings = Settings.load(); let createNewIntegratedConsole = settings.debugging.createTemporaryIntegratedConsole; if (config.request === "attach") { - let platformDetails = getPlatformDetails(); - let versionDetails = this.sessionManager.getPowerShellVersionDetails(); + const platformDetails = getPlatformDetails(); + const versionDetails = this.sessionManager.getPowerShellVersionDetails(); if (versionDetails.edition.toLowerCase() === "core" && platformDetails.operatingSystem !== OperatingSystem.Windows) { - let msg = "PowerShell Core only supports attaching to a host process on Windows."; - return vscode.window.showErrorMessage(msg).then(_ => { + const msg = "PowerShell Core only supports attaching to a host process on Windows."; + return vscode.window.showErrorMessage(msg).then((_) => { return undefined; }); } @@ -61,9 +62,9 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider if (generateLaunchConfig) { // No launch.json, create the default configuration for both unsaved (Untitled) and saved documents. - config.type = 'PowerShell'; - config.name = 'PowerShell Launch Current File'; - config.request = 'launch'; + config.type = "PowerShell"; + config.name = "PowerShell Launch Current File"; + config.request = "launch"; config.args = []; config.script = @@ -79,7 +80,7 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider : currentDocument.fileName; } - if (config.request === 'launch') { + if (config.request === "launch") { // For debug launch of "current script" (saved or unsaved), warn before starting the debugger if either // A) the unsaved document's language type is not PowerShell or @@ -87,37 +88,35 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider if (debugCurrentScript) { if (currentDocument.isUntitled) { - if (currentDocument.languageId === 'powershell') { + if (currentDocument.languageId === "powershell") { if (!generateLaunchConfig) { // Cover the case of existing launch.json but unsaved (Untitled) document. // In this case, vscode.workspace.rootPath will not be undefined. config.script = currentDocument.uri.toString(); - config.cwd = vscode.workspace.rootPath + config.cwd = vscode.workspace.rootPath; } - } - else { - let msg = "To debug '" + currentDocument.fileName + - "', change the document's language mode to PowerShell or save the file with a PowerShell extension."; + } else { + const msg = "To debug '" + currentDocument.fileName + "', change the document's " + + "language mode to PowerShell or save the file with a PowerShell extension."; vscode.window.showErrorMessage(msg); return; } - } - else { + } else { let isValidExtension = false; - let extIndex = currentDocument.fileName.lastIndexOf('.'); + const extIndex = currentDocument.fileName.lastIndexOf("."); if (extIndex !== -1) { - let ext = currentDocument.fileName.substr(extIndex + 1).toUpperCase(); + const ext = currentDocument.fileName.substr(extIndex + 1).toUpperCase(); isValidExtension = (ext === "PS1" || ext === "PSM1"); } - if ((currentDocument.languageId !== 'powershell') || !isValidExtension) { + if ((currentDocument.languageId !== "powershell") || !isValidExtension) { let path = currentDocument.fileName; - let workspaceRootPath = vscode.workspace.rootPath; + const workspaceRootPath = vscode.workspace.rootPath; if (currentDocument.fileName.startsWith(workspaceRootPath)) { path = currentDocument.fileName.substring(vscode.workspace.rootPath.length + 1); } - let msg = "'" + path + "' is a file type that cannot be debugged by the PowerShell debugger."; + const msg = "'" + path + "' is a file type that cannot be debugged by the PowerShell debugger."; vscode.window.showErrorMessage(msg); return; } @@ -141,24 +140,22 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider config.internalConsoleOptions = "neverOpen"; // Create or show the interactive console - vscode.commands.executeCommand('PowerShell.ShowSessionConsole', true); + vscode.commands.executeCommand("PowerShell.ShowSessionConsole", true); - var sessionFilePath = utils.getDebugSessionFilePath(); + const sessionFilePath = utils.getDebugSessionFilePath(); if (createNewIntegratedConsole) { - var debugProcess = + const debugProcess = this.sessionManager.createDebugSessionProcess( sessionFilePath, settings); debugProcess .start(`DebugSession-${this.sessionCount++}`) - .then( - sessionDetails => { + .then((sessionDetails) => { utils.writeSessionFile(sessionFilePath, sessionDetails); - }); - } - else { + }); + } else { utils.writeSessionFile(sessionFilePath, this.sessionManager.getSessionDetails()); } @@ -176,18 +173,18 @@ export class SpecifyScriptArgsFeature implements IFeature { constructor(context: vscode.ExtensionContext) { this.context = context; - let vscodeVersionArray = vscode.version.split('.'); - let editorVersion = { + const vscodeVersionArray = vscode.version.split("."); + const editorVersion = { major: Number(vscodeVersionArray[0]), minor: Number(vscodeVersionArray[1]), - } + }; this.emptyInputBoxBugFixed = ((editorVersion.major > 1) || - ((editorVersion.major == 1) && (editorVersion.minor > 12))); + ((editorVersion.major === 1) && (editorVersion.minor > 12))); this.command = - vscode.commands.registerCommand('PowerShell.SpecifyScriptArgs', () => { + vscode.commands.registerCommand("PowerShell.SpecifyScriptArgs", () => { return this.specifyScriptArguments(); }); } @@ -201,21 +198,21 @@ export class SpecifyScriptArgsFeature implements IFeature { } private specifyScriptArguments(): Thenable { - const powerShellDbgScriptArgsKey = 'powerShellDebugScriptArgs'; + const powerShellDbgScriptArgsKey = "powerShellDebugScriptArgs"; - let options: vscode.InputBoxOptions = { + const options: vscode.InputBoxOptions = { ignoreFocusOut: true, - placeHolder: "Enter script arguments or leave empty to pass no args" - } + placeHolder: "Enter script arguments or leave empty to pass no args", + }; if (this.emptyInputBoxBugFixed) { - let prevArgs = this.context.workspaceState.get(powerShellDbgScriptArgsKey, ''); + const prevArgs = this.context.workspaceState.get(powerShellDbgScriptArgsKey, ""); if (prevArgs.length > 0) { options.value = prevArgs; } } - return vscode.window.showInputBox(options).then(text => { + return vscode.window.showInputBox(options).then((text) => { // When user cancel's the input box (by pressing Esc), the text value is undefined. if (text !== undefined) { if (this.emptyInputBoxBugFixed) { @@ -230,24 +227,22 @@ export class SpecifyScriptArgsFeature implements IFeature { } } -interface ProcessItem extends vscode.QuickPickItem { - pid: string; // payload for the QuickPick UI +interface IProcessItem extends vscode.QuickPickItem { + pid: string; // payload for the QuickPick UI } -interface PSHostProcessInfo { +interface IPSHostProcessInfo { processName: string; processId: string; appDomainName: string; mainWindowTitle: string; } -namespace GetPSHostProcessesRequest { - export const type = - new RequestType('powerShell/getPSHostProcesses'); -} +export const GetPSHostProcessesRequestType = + new RequestType("powerShell/getPSHostProcesses"); -interface GetPSHostProcessesResponseBody { - hostProcesses: PSHostProcessInfo[]; +interface IGetPSHostProcessesResponseBody { + hostProcesses: IPSHostProcessInfo[]; } export class PickPSHostProcessFeature implements IFeature { @@ -260,9 +255,9 @@ export class PickPSHostProcessFeature implements IFeature { constructor() { this.command = - vscode.commands.registerCommand('PowerShell.PickPSHostProcess', () => { + vscode.commands.registerCommand("PowerShell.PickPSHostProcess", () => { return this.getLanguageClient() - .then(_ => this.pickPSHostProcess(), _ => undefined); + .then((_) => this.pickPSHostProcess(), (_) => undefined); }); } @@ -282,8 +277,7 @@ export class PickPSHostProcessFeature implements IFeature { private getLanguageClient(): Thenable { if (this.languageClient) { return Promise.resolve(this.languageClient); - } - else { + } else { // If PowerShell isn't finished loading yet, show a loading message // until the LanguageClient is passed on to us this.waitingForClientToken = new vscode.CancellationTokenSource(); @@ -297,7 +291,7 @@ export class PickPSHostProcessFeature implements IFeature { ["Cancel"], { placeHolder: "Attach to PowerShell host process: Please wait, starting PowerShell..." }, this.waitingForClientToken.token) - .then(response => { + .then((response) => { if (response === "Cancel") { this.clearWaitingToken(); reject(); @@ -306,51 +300,53 @@ export class PickPSHostProcessFeature implements IFeature { // Cancel the loading prompt after 60 seconds setTimeout(() => { - if (this.waitingForClientToken) { - this.clearWaitingToken(); - reject(); + if (this.waitingForClientToken) { + this.clearWaitingToken(); + reject(); - vscode.window.showErrorMessage( - "Attach to PowerShell host process: PowerShell session took too long to start."); - } - }, 60000); - } + vscode.window.showErrorMessage( + "Attach to PowerShell host process: PowerShell session took too long to start."); + } + }, 60000); + }, ); } } - private pickPSHostProcess(): Thenable { - return this.languageClient.sendRequest(GetPSHostProcessesRequest.type, null).then(hostProcesses => { - var items: ProcessItem[] = []; + private pickPSHostProcess(): Thenable { + return this.languageClient.sendRequest(GetPSHostProcessesRequestType, null).then((hostProcesses) => { + const items: IProcessItem[] = []; - for (var p in hostProcesses) { - var windowTitle = ""; - if (hostProcesses[p].mainWindowTitle) { - windowTitle = `, Title: ${hostProcesses[p].mainWindowTitle}`; - } + for (const p in hostProcesses) { + if (hostProcesses.hasOwnProperty(p)) { + let windowTitle = ""; + if (hostProcesses[p].mainWindowTitle) { + windowTitle = `, Title: ${hostProcesses[p].mainWindowTitle}`; + } - items.push({ - label: hostProcesses[p].processName, - description: `PID: ${hostProcesses[p].processId.toString()}${windowTitle}`, - pid: hostProcesses[p].processId - }); - }; + items.push({ + label: hostProcesses[p].processName, + description: `PID: ${hostProcesses[p].processId.toString()}${windowTitle}`, + pid: hostProcesses[p].processId, + }); + } + } if (items.length === 0) { return Promise.reject("There are no PowerShell host processes to attach to."); } - let options : vscode.QuickPickOptions = { + const options: vscode.QuickPickOptions = { placeHolder: "Select a PowerShell host process to attach to", matchOnDescription: true, - matchOnDetail: true + matchOnDetail: true, }; - return vscode.window.showQuickPick(items, options).then(item => { + return vscode.window.showQuickPick(items, options).then((item) => { return item ? item.pid : ""; }); }); - } + } private clearWaitingToken() { if (this.waitingForClientToken) { diff --git a/src/features/DocumentFormatter.ts b/src/features/DocumentFormatter.ts index 5a1d299161..623919eb30 100644 --- a/src/features/DocumentFormatter.ts +++ b/src/features/DocumentFormatter.ts @@ -3,51 +3,49 @@ *--------------------------------------------------------*/ import * as path from "path"; -import vscode = require('vscode'); +import vscode = require("vscode"); import { - TextDocument, - TextEdit, - FormattingOptions, CancellationToken, DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider, + FormattingOptions, OnTypeFormattingEditProvider, Position, Range, + TextDocument, + TextEdit, TextEditor, - TextLine -} from 'vscode'; + TextLine, +} from "vscode"; import { - LanguageClient, - RequestType, DocumentFormattingRequest, DocumentRangeFormattingParams, - DocumentRangeFormattingRequest -} from 'vscode-languageclient'; + DocumentRangeFormattingRequest, + LanguageClient, + RequestType, +} from "vscode-languageclient"; import { TextDocumentIdentifier } from "vscode-languageserver-types"; import Window = vscode.window; -import { Logger } from '../logging'; -import { IFeature } from '../feature'; -import * as Settings from '../settings'; -import * as Utils from '../utils'; -import * as AnimatedStatusBar from '../controls/animatedStatusBar'; - -export namespace ScriptRegionRequest { - export const type = new RequestType("powerShell/getScriptRegion"); -} +import * as AnimatedStatusBar from "../controls/animatedStatusBar"; +import { IFeature } from "../feature"; +import { Logger } from "../logging"; +import * as Settings from "../settings"; +import * as Utils from "../utils"; -interface ScriptRegionRequestParams { +export const ScriptRegionRequestType = new RequestType("powerShell/getScriptRegion"); + +interface IScriptRegionRequestParams { fileUri: string; character: string; line: number; column: number; } -interface ScriptRegionRequestResult { - scriptRegion: ScriptRegion; +interface IScriptRegionRequestResult { + scriptRegion: IScriptRegion; } -interface ScriptRegion { +interface IScriptRegion { file: string; text: string; startLineNumber: number; @@ -58,7 +56,7 @@ interface ScriptRegion { endOffset: number; } -function toRange(scriptRegion: ScriptRegion): vscode.Range { +function toRange(scriptRegion: IScriptRegion): vscode.Range { return new vscode.Range( scriptRegion.startLineNumber - 1, scriptRegion.startColumnNumber - 1, @@ -77,20 +75,20 @@ class DocumentLocker { this.lockedDocuments = new Object(); } - isLocked(document: TextDocument): boolean { + public isLocked(document: TextDocument): boolean { return this.isLockedInternal(this.getKey(document)); } - lock(document: TextDocument, unlockWhenDone?: Thenable): void { + public lock(document: TextDocument, unlockWhenDone?: Thenable): void { this.lockInternal(this.getKey(document), unlockWhenDone); } - unlock(document: TextDocument): void { + public unlock(document: TextDocument): void { this.unlockInternal(this.getKey(document)); } - unlockAll(): void { - Object.keys(this.lockedDocuments).slice().forEach(documentKey => this.unlockInternal(documentKey)); + public unlockAll(): void { + Object.keys(this.lockedDocuments).slice().forEach((documentKey) => this.unlockInternal(documentKey)); } private getKey(document: TextDocument): string { @@ -125,6 +123,27 @@ class PSDocumentFormattingEditProvider implements private static documentLocker = new DocumentLocker(); private static statusBarTracker = new Object(); + + private static showStatusBar(document: TextDocument, hideWhenDone: Thenable): void { + const statusBar = + AnimatedStatusBar.showAnimatedStatusBarMessage("Formatting PowerShell document", hideWhenDone); + this.statusBarTracker[document.uri.toString()] = statusBar; + hideWhenDone.then(() => { + this.disposeStatusBar(document.uri.toString()); + }); + } + + private static disposeStatusBar(documentUri: string) { + if (this.statusBarTracker.hasOwnProperty(documentUri)) { + this.statusBarTracker[documentUri].dispose(); + delete this.statusBarTracker[documentUri]; + } + } + + private static disposeAllStatusBars() { + Object.keys(this.statusBarTracker).slice().forEach((key) => this.disposeStatusBar(key)); + } + private languageClient: LanguageClient; private get emptyPromise(): Promise { @@ -134,35 +153,45 @@ class PSDocumentFormattingEditProvider implements constructor(private logger: Logger) { } - provideDocumentFormattingEdits( + public setLanguageClient(languageClient: LanguageClient): void { + this.languageClient = languageClient; + + // setLanguageClient is called while restarting a session, + // so this makes sure we clean up the document locker and + // any residual status bars + PSDocumentFormattingEditProvider.documentLocker.unlockAll(); + PSDocumentFormattingEditProvider.disposeAllStatusBars(); + } + + public provideDocumentFormattingEdits( document: TextDocument, options: FormattingOptions, token: CancellationToken): TextEdit[] | Thenable { - this.logger.writeVerbose(`Formatting entire document - ${document.uri}...`) + this.logger.writeVerbose(`Formatting entire document - ${document.uri}...`); return this.sendDocumentFormatRequest(document, null, options, token); } - provideDocumentRangeFormattingEdits( + public provideDocumentRangeFormattingEdits( document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): TextEdit[] | Thenable { - this.logger.writeVerbose(`Formatting document range ${JSON.stringify(range)} - ${document.uri}...`) + this.logger.writeVerbose(`Formatting document range ${JSON.stringify(range)} - ${document.uri}...`); return this.sendDocumentFormatRequest(document, range, options, token); } - provideOnTypeFormattingEdits( + public provideOnTypeFormattingEdits( document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): TextEdit[] | Thenable { - this.logger.writeVerbose(`Formatting on type at position ${JSON.stringify(position)} - ${document.uri}...`) + this.logger.writeVerbose(`Formatting on type at position ${JSON.stringify(position)} - ${document.uri}...`); - return this.getScriptRegion(document, position, ch).then(scriptRegion => { + return this.getScriptRegion(document, position, ch).then((scriptRegion) => { if (scriptRegion === null) { this.logger.writeVerbose("No formattable range returned."); return this.emptyPromise; @@ -175,7 +204,7 @@ class PSDocumentFormattingEditProvider implements token); }, (err) => { - this.logger.writeVerbose(`Error while requesting script region for formatting: ${err}`) + this.logger.writeVerbose(`Error while requesting script region for formatting: ${err}`); }); } @@ -185,7 +214,7 @@ class PSDocumentFormattingEditProvider implements options: FormattingOptions, token: CancellationToken): TextEdit[] | Thenable { - let editor: TextEditor = this.getEditor(document); + const editor: TextEditor = this.getEditor(document); if (editor === undefined) { return this.emptyPromise; } @@ -203,27 +232,27 @@ class PSDocumentFormattingEditProvider implements rangeParam = { start: { line: range.start.line, - character: range.start.character + character: range.start.character, }, end: { line: range.end.line, - character: range.end.character - } + character: range.end.character, + }, }; - }; + } - let requestParams: DocumentRangeFormattingParams = { + const requestParams: DocumentRangeFormattingParams = { textDocument: TextDocumentIdentifier.create(document.uri.toString()), range: rangeParam, - options: this.getEditorSettings() + options: this.getEditorSettings(), }; - let formattingStartTime = new Date().valueOf(); + const formattingStartTime = new Date().valueOf(); function getFormattingDuration() { return ((new Date().valueOf()) - formattingStartTime) / 1000; } - let textEdits = this.languageClient.sendRequest( + const textEdits = this.languageClient.sendRequest( DocumentRangeFormattingRequest.type, requestParams); this.lockDocument(document, textEdits); @@ -239,26 +268,16 @@ class PSDocumentFormattingEditProvider implements }); } - setLanguageClient(languageClient: LanguageClient): void { - this.languageClient = languageClient; - - // setLanguageClient is called while restarting a session, - // so this makes sure we clean up the document locker and - // any residual status bars - PSDocumentFormattingEditProvider.documentLocker.unlockAll(); - PSDocumentFormattingEditProvider.disposeAllStatusBars(); - } - - private getScriptRegion(document: TextDocument, position: Position, ch: string): Thenable { - let oneBasedPosition = toOneBasedPosition(position); + private getScriptRegion(document: TextDocument, position: Position, ch: string): Thenable { + const oneBasedPosition = toOneBasedPosition(position); return this.languageClient.sendRequest( - ScriptRegionRequest.type, + ScriptRegionRequestType, { fileUri: document.uri.toString(), character: ch, line: oneBasedPosition.line, - column: oneBasedPosition.character - }).then((result: ScriptRegionRequestResult) => { + column: oneBasedPosition.character, + }).then((result: IScriptRegionRequestResult) => { if (result === null) { return null; } @@ -268,7 +287,7 @@ class PSDocumentFormattingEditProvider implements } private getEditor(document: TextDocument): TextEditor { - return Window.visibleTextEditors.find((e, n, obj) => { return e.document === document; }); + return Window.visibleTextEditors.find((e, n, obj) => e.document === document); } private isDocumentLocked(document: TextDocument): boolean { @@ -280,31 +299,12 @@ class PSDocumentFormattingEditProvider implements } private getEditorSettings(): { insertSpaces: boolean, tabSize: number } { - let editorConfiguration = vscode.workspace.getConfiguration("editor"); + const editorConfiguration = vscode.workspace.getConfiguration("editor"); return { insertSpaces: editorConfiguration.get("insertSpaces"), - tabSize: editorConfiguration.get("tabSize") + tabSize: editorConfiguration.get("tabSize"), }; } - - private static showStatusBar(document: TextDocument, hideWhenDone: Thenable): void { - let statusBar = AnimatedStatusBar.showAnimatedStatusBarMessage("Formatting PowerShell document", hideWhenDone); - this.statusBarTracker[document.uri.toString()] = statusBar; - hideWhenDone.then(() => { - this.disposeStatusBar(document.uri.toString()); - }); - } - - private static disposeStatusBar(documentUri: string) { - if (this.statusBarTracker.hasOwnProperty(documentUri)) { - this.statusBarTracker[documentUri].dispose(); - delete this.statusBarTracker[documentUri]; - } - } - - private static disposeAllStatusBars() { - Object.keys(this.statusBarTracker).slice().forEach((key) => this.disposeStatusBar(key)); - } } export class DocumentFormatterFeature implements IFeature { @@ -331,14 +331,14 @@ export class DocumentFormatterFeature implements IFeature { ...this.moreTriggerCharacters); } - public setLanguageClient(languageclient: LanguageClient): void { - this.languageClient = languageclient; - this.documentFormattingEditProvider.setLanguageClient(languageclient); - } - public dispose(): any { this.formattingEditProvider.dispose(); this.rangeFormattingEditProvider.dispose(); this.onTypeFormattingEditProvider.dispose(); } + + public setLanguageClient(languageclient: LanguageClient): void { + this.languageClient = languageclient; + this.documentFormattingEditProvider.setLanguageClient(languageclient); + } } diff --git a/src/features/Examples.ts b/src/features/Examples.ts index 77862b6777..afedf8008a 100644 --- a/src/features/Examples.ts +++ b/src/features/Examples.ts @@ -2,10 +2,10 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import path = require('path'); -import { IFeature } from '../feature'; -import { LanguageClient } from 'vscode-languageclient'; +import path = require("path"); +import vscode = require("vscode"); +import { LanguageClient } from "vscode-languageclient"; +import { IFeature } from "../feature"; export class ExamplesFeature implements IFeature { private command: vscode.Disposable; @@ -13,7 +13,7 @@ export class ExamplesFeature implements IFeature { constructor() { this.examplesPath = path.resolve(__dirname, "../../../examples"); - this.command = vscode.commands.registerCommand('PowerShell.OpenExamplesFolder', () => { + this.command = vscode.commands.registerCommand("PowerShell.OpenExamplesFolder", () => { vscode.commands.executeCommand( "vscode.openFolder", vscode.Uri.file(this.examplesPath), @@ -22,9 +22,10 @@ export class ExamplesFeature implements IFeature { } public setLanguageClient(languageclient: LanguageClient) { + // Eliminate tslint warning } public dispose() { this.command.dispose(); } -} \ No newline at end of file +} diff --git a/src/features/ExpandAlias.ts b/src/features/ExpandAlias.ts index 64564262da..01fbe7366b 100644 --- a/src/features/ExpandAlias.ts +++ b/src/features/ExpandAlias.ts @@ -2,38 +2,34 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); +import vscode = require("vscode"); import Window = vscode.window; -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; -export namespace ExpandAliasRequest { - export const type = new RequestType('powerShell/expandAlias'); -} +export const ExpandAliasRequestType = new RequestType("powerShell/expandAlias"); export class ExpandAliasFeature implements IFeature { private command: vscode.Disposable; private languageClient: LanguageClient; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.ExpandAlias', () => { + this.command = vscode.commands.registerCommand("PowerShell.ExpandAlias", () => { if (this.languageClient === undefined) { // TODO: Log error message return; } - var editor = Window.activeTextEditor; - var document = editor.document; - var selection = editor.selection; - var text, range; + const editor = Window.activeTextEditor; + const document = editor.document; + const selection = editor.selection; + const sls = selection.start; + const sle = selection.end; - var sls = selection.start; - var sle = selection.end; + let text; + let range; - if ( - (sls.character === sle.character) && - (sls.line === sle.line) - ) { + if ((sls.character === sle.character) && (sls.line === sle.line)) { text = document.getText(); range = new vscode.Range(0, 0, document.lineCount, text.length); } else { @@ -41,7 +37,7 @@ export class ExpandAliasFeature implements IFeature { range = new vscode.Range(sls.line, sls.character, sle.line, sle.character); } - this.languageClient.sendRequest(ExpandAliasRequest.type, text).then((result) => { + this.languageClient.sendRequest(ExpandAliasRequestType, text).then((result) => { editor.edit((editBuilder) => { editBuilder.replace(range, result); }); @@ -49,11 +45,11 @@ export class ExpandAliasFeature implements IFeature { }); } - public setLanguageClient(languageclient: LanguageClient) { - this.languageClient = languageclient; - } - public dispose() { this.command.dispose(); } -} \ No newline at end of file + + public setLanguageClient(languageclient: LanguageClient) { + this.languageClient = languageclient; + } +} diff --git a/src/features/ExtensionCommands.ts b/src/features/ExtensionCommands.ts index 0032671825..ebd38fa9f3 100644 --- a/src/features/ExtensionCommands.ts +++ b/src/features/ExtensionCommands.ts @@ -2,28 +2,26 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import os = require('os'); -import path = require('path'); -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType, Range, Position } from 'vscode-languageclient'; +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); +import { LanguageClient, NotificationType, Position, Range, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; -export interface ExtensionCommand { +export interface IExtensionCommand { name: string; displayName: string; } -export interface ExtensionCommandQuickPickItem extends vscode.QuickPickItem { - command: ExtensionCommand; +export interface IExtensionCommandQuickPickItem extends vscode.QuickPickItem { + command: IExtensionCommand; } -export namespace InvokeExtensionCommandRequest { - export const type = - new RequestType( - 'powerShell/invokeExtensionCommand'); -} +export const InvokeExtensionCommandRequestType = + new RequestType( + "powerShell/invokeExtensionCommand"); -export interface EditorContext { +export interface IEditorContext { currentFilePath: string; cursorPosition: Position; selectionRange: Range; @@ -31,16 +29,14 @@ export interface EditorContext { export interface InvokeExtensionCommandRequestArguments { name: string; - context: EditorContext; + context: IEditorContext; } -export namespace ExtensionCommandAddedNotification { - export const type = - new NotificationType( - 'powerShell/extensionCommandAdded'); -} +export const ExtensionCommandAddedNotificationType = + new NotificationType( + "powerShell/extensionCommandAdded"); -export interface ExtensionCommandAddedNotificationBody { +export interface IExtensionCommandAddedNotificationBody { name: string; displayName: string; } @@ -49,134 +45,113 @@ export interface ExtensionCommandAddedNotificationBody { function asRange(value: vscode.Range): Range { - if (value === undefined) { - return undefined; - } else if (value === null) { - return null; - } - return { start: asPosition(value.start), end: asPosition(value.end) }; + if (value === undefined) { + return undefined; + } else if (value === null) { + return null; + } + return { start: asPosition(value.start), end: asPosition(value.end) }; } function asPosition(value: vscode.Position): Position { - if (value === undefined) { - return undefined; - } else if (value === null) { - return null; - } - return { line: value.line, character: value.character }; + if (value === undefined) { + return undefined; + } else if (value === null) { + return null; + } + return { line: value.line, character: value.character }; } function asCodeRange(value: Range): vscode.Range { - if (value === undefined) { - return undefined; - } else if (value === null) { - return null; - } - return new vscode.Range(asCodePosition(value.start), asCodePosition(value.end)); + if (value === undefined) { + return undefined; + } else if (value === null) { + return null; + } + return new vscode.Range(asCodePosition(value.start), asCodePosition(value.end)); } function asCodePosition(value: Position): vscode.Position { - if (value === undefined) { - return undefined; - } else if (value === null) { - return null; - } - return new vscode.Position(value.line, value.character); + if (value === undefined) { + return undefined; + } else if (value === null) { + return null; + } + return new vscode.Position(value.line, value.character); } -export namespace GetEditorContextRequest { - export const type = - new RequestType( - 'editor/getEditorContext'); -} +export const GetEditorContextRequestType = + new RequestType( + "editor/getEditorContext"); -export interface GetEditorContextRequestArguments { +// tslint:disable-next-line:no-empty-interface +export interface IGetEditorContextRequestArguments { } enum EditorOperationResponse { Unsupported = 0, - Completed + Completed, } -export namespace InsertTextRequest { - export const type = - new RequestType( - 'editor/insertText'); -} +export const InsertTextRequestType = + new RequestType( + "editor/insertText"); -export interface InsertTextRequestArguments { +export interface IInsertTextRequestArguments { filePath: string; insertText: string; - insertRange: Range + insertRange: Range; } -export namespace SetSelectionRequest { - export const type = - new RequestType( - 'editor/setSelection'); -} +export const SetSelectionRequestType = + new RequestType( + "editor/setSelection"); -export interface SetSelectionRequestArguments { - selectionRange: Range +export interface ISetSelectionRequestArguments { + selectionRange: Range; } -export namespace OpenFileRequest { - export const type = - new RequestType( - 'editor/openFile'); -} +export const OpenFileRequestType = + new RequestType( + "editor/openFile"); -export namespace NewFileRequest { - export const type = - new RequestType( - 'editor/newFile'); -} +export const NewFileRequestType = + new RequestType( + "editor/newFile"); -export namespace CloseFileRequest { - export const type = - new RequestType( - 'editor/closeFile'); -} +export const CloseFileRequestType = + new RequestType( + "editor/closeFile"); -export namespace SaveFileRequest { - export const type = - new RequestType( - 'editor/saveFile'); -} +export const SaveFileRequestType = + new RequestType( + "editor/saveFile"); -export namespace ShowErrorMessageRequest { - export const type = - new RequestType( - 'editor/showErrorMessage'); -} +export const ShowErrorMessageRequestType = + new RequestType( + "editor/showErrorMessage"); -export namespace ShowWarningMessageRequest { - export const type = - new RequestType( - 'editor/showWarningMessage'); -} +export const ShowWarningMessageRequestType = + new RequestType( + "editor/showWarningMessage"); -export namespace ShowInformationMessageRequest { - export const type = - new RequestType( - 'editor/showInformationMessage'); -} +export const ShowInformationMessageRequestType = + new RequestType( + "editor/showInformationMessage"); -export namespace SetStatusBarMessageRequest { - export const type = - new RequestType( - 'editor/setStatusBarMessage'); -} +export const SetStatusBarMessageRequestType = + new RequestType( + "editor/setStatusBarMessage"); -export interface StatusBarMessageDetails { +export interface IStatusBarMessageDetails { message: string; timeout?: number; } -interface InvokeRegisteredEditorCommandParameter{ - commandName : string +interface IInvokeRegisteredEditorCommandParameter { + commandName: string; } export class ExtensionCommandsFeature implements IFeature { @@ -184,34 +159,36 @@ export class ExtensionCommandsFeature implements IFeature { private command: vscode.Disposable; private command2: vscode.Disposable; private languageClient: LanguageClient; - private extensionCommands: ExtensionCommand[] = []; + private extensionCommands: IExtensionCommand[] = []; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.ShowAdditionalCommands', () => { + this.command = vscode.commands.registerCommand("PowerShell.ShowAdditionalCommands", () => { if (this.languageClient === undefined) { // TODO: Log error message return; } - let editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; let start = editor.selection.start; - let end = editor.selection.end; + const end = editor.selection.end; if (editor.selection.isEmpty) { - start = new vscode.Position(start.line, 0) + start = new vscode.Position(start.line, 0); } this.showExtensionCommands(this.languageClient); }); - this.command2 = vscode.commands.registerCommand('PowerShell.InvokeRegisteredEditorCommand',(param : InvokeRegisteredEditorCommandParameter) => { - if(this.extensionCommands.length == 0){ + + this.command2 = vscode.commands.registerCommand("PowerShell.InvokeRegisteredEditorCommand", + (param: IInvokeRegisteredEditorCommandParameter) => { + if (this.extensionCommands.length === 0) { return; } - let commandToExecute = this.extensionCommands.find(x => x.name === param.commandName); + const commandToExecute = this.extensionCommands.find((x) => x.name === param.commandName); - if(commandToExecute){ + if (commandToExecute) { this.languageClient.sendRequest( - InvokeExtensionCommandRequest.type, + InvokeExtensionCommandRequestType, { name: commandToExecute.name, context: this.getEditorContext() }); } @@ -227,52 +204,52 @@ export class ExtensionCommandsFeature implements IFeature { this.languageClient = languageclient; if (this.languageClient !== undefined) { this.languageClient.onNotification( - ExtensionCommandAddedNotification.type, - command => this.addExtensionCommand(command)); + ExtensionCommandAddedNotificationType, + (command) => this.addExtensionCommand(command)); this.languageClient.onRequest( - GetEditorContextRequest.type, - details => this.getEditorContext()); + GetEditorContextRequestType, + (details) => this.getEditorContext()); this.languageClient.onRequest( - InsertTextRequest.type, - details => this.insertText(details)); + InsertTextRequestType, + (details) => this.insertText(details)); this.languageClient.onRequest( - SetSelectionRequest.type, - details => this.setSelection(details)); + SetSelectionRequestType, + (details) => this.setSelection(details)); this.languageClient.onRequest( - NewFileRequest.type, - filePath => this.newFile()); + NewFileRequestType, + (filePath) => this.newFile()); this.languageClient.onRequest( - OpenFileRequest.type, - filePath => this.openFile(filePath)); + OpenFileRequestType, + (filePath) => this.openFile(filePath)); this.languageClient.onRequest( - CloseFileRequest.type, - filePath => this.closeFile(filePath)); + CloseFileRequestType, + (filePath) => this.closeFile(filePath)); this.languageClient.onRequest( - SaveFileRequest.type, - filePath => this.saveFile(filePath)); + SaveFileRequestType, + (filePath) => this.saveFile(filePath)); this.languageClient.onRequest( - ShowInformationMessageRequest.type, - message => this.showInformationMessage(message)); + ShowInformationMessageRequestType, + (message) => this.showInformationMessage(message)); this.languageClient.onRequest( - ShowErrorMessageRequest.type, - message => this.showErrorMessage(message)); + ShowErrorMessageRequestType, + (message) => this.showErrorMessage(message)); this.languageClient.onRequest( - ShowWarningMessageRequest.type, - message => this.showWarningMessage(message)); + ShowWarningMessageRequestType, + (message) => this.showWarningMessage(message)); this.languageClient.onRequest( - SetStatusBarMessageRequest.type, - messageDetails => this.setStatusBarMessage(messageDetails)); + SetStatusBarMessageRequestType, + (messageDetails) => this.setStatusBarMessage(messageDetails)); } } @@ -281,58 +258,58 @@ export class ExtensionCommandsFeature implements IFeature { this.command2.dispose(); } - private addExtensionCommand(command: ExtensionCommandAddedNotificationBody) { + private addExtensionCommand(command: IExtensionCommandAddedNotificationBody) { this.extensionCommands.push({ name: command.name, - displayName: command.displayName + displayName: command.displayName, }); this.extensionCommands.sort( - (a: ExtensionCommand, b: ExtensionCommand) => + (a: IExtensionCommand, b: IExtensionCommand) => a.name.localeCompare(b.name)); } - private showExtensionCommands(client: LanguageClient) : Thenable { + private showExtensionCommands(client: LanguageClient): Thenable { // If no extension commands are available, show a message - if (this.extensionCommands.length == 0) { + if (this.extensionCommands.length === 0) { vscode.window.showInformationMessage( "No extension commands have been loaded into the current session."); return; } - let quickPickItems = - this.extensionCommands.map(command => { + const quickPickItems = + this.extensionCommands.map((command) => { return { label: command.displayName, description: command.name, - command: command - } + command, + }; }); vscode.window .showQuickPick( quickPickItems, { placeHolder: "Select a command" }) - .then(command => this.onCommandSelected(command, client)); + .then((command) => this.onCommandSelected(command, client)); } private onCommandSelected( - chosenItem: ExtensionCommandQuickPickItem, + chosenItem: IExtensionCommandQuickPickItem, client: LanguageClient) { if (chosenItem !== undefined) { client.sendRequest( - InvokeExtensionCommandRequest.type, + InvokeExtensionCommandRequestType, { name: chosenItem.command.name, context: this.getEditorContext() }); } } - private insertText(details: InsertTextRequestArguments): EditorOperationResponse { - let edit = new vscode.WorkspaceEdit(); + private insertText(details: IInsertTextRequestArguments): EditorOperationResponse { + const edit = new vscode.WorkspaceEdit(); edit.set( vscode.Uri.parse(details.filePath), @@ -343,8 +320,8 @@ export class ExtensionCommandsFeature implements IFeature { details.insertRange.start.character, details.insertRange.end.line, details.insertRange.end.character), - details.insertText) - ] + details.insertText), + ], ); vscode.workspace.applyEdit(edit); @@ -352,7 +329,7 @@ export class ExtensionCommandsFeature implements IFeature { return EditorOperationResponse.Completed; } - private getEditorContext(): EditorContext { + private getEditorContext(): IEditorContext { return { currentFilePath: vscode.window.activeTextEditor.document.uri.toString(), cursorPosition: asPosition(vscode.window.activeTextEditor.selection.active), @@ -360,24 +337,24 @@ export class ExtensionCommandsFeature implements IFeature { asRange( new vscode.Range( vscode.window.activeTextEditor.selection.start, - vscode.window.activeTextEditor.selection.end)) - } + vscode.window.activeTextEditor.selection.end)), + }; } private newFile(): Thenable { - return vscode.workspace.openTextDocument({ content: ''}) - .then(doc => vscode.window.showTextDocument(doc)) - .then(_ => EditorOperationResponse.Completed); + return vscode.workspace.openTextDocument({ content: ""}) + .then((doc) => vscode.window.showTextDocument(doc)) + .then((_) => EditorOperationResponse.Completed); } private openFile(filePath: string): Thenable { filePath = this.normalizeFilePath(filePath); - let promise = + const promise = vscode.workspace.openTextDocument(filePath) - .then(doc => vscode.window.showTextDocument(doc)) - .then(_ => EditorOperationResponse.Completed); + .then((doc) => vscode.window.showTextDocument(doc)) + .then((_) => EditorOperationResponse.Completed); return promise; } @@ -385,16 +362,13 @@ export class ExtensionCommandsFeature implements IFeature { private closeFile(filePath: string): Thenable { let promise: Thenable; - if (this.findTextDocument(this.normalizeFilePath(filePath))) - { + if (this.findTextDocument(this.normalizeFilePath(filePath))) { promise = vscode.workspace.openTextDocument(filePath) - .then(doc => vscode.window.showTextDocument(doc)) - .then(editor => vscode.commands.executeCommand("workbench.action.closeActiveEditor")) - .then(_ => EditorOperationResponse.Completed); - } - else - { + .then((doc) => vscode.window.showTextDocument(doc)) + .then((editor) => vscode.commands.executeCommand("workbench.action.closeActiveEditor")) + .then((_) => EditorOperationResponse.Completed); + } else { promise = Promise.resolve(EditorOperationResponse.Completed); } @@ -404,8 +378,7 @@ export class ExtensionCommandsFeature implements IFeature { private saveFile(filePath: string): Thenable { let promise: Thenable; - if (this.findTextDocument(this.normalizeFilePath(filePath))) - { + if (this.findTextDocument(this.normalizeFilePath(filePath))) { promise = vscode.workspace.openTextDocument(filePath) .then((doc) => { @@ -413,10 +386,8 @@ export class ExtensionCommandsFeature implements IFeature { doc.save(); } }) - .then(_ => EditorOperationResponse.Completed); - } - else - { + .then((_) => EditorOperationResponse.Completed); + } else { promise = Promise.resolve(EditorOperationResponse.Completed); } @@ -424,11 +395,10 @@ export class ExtensionCommandsFeature implements IFeature { } private normalizeFilePath(filePath: string): string { - let platform = os.platform(); - if (platform == "win32") { + const platform = os.platform(); + if (platform === "win32") { // Make sure the file path is absolute - if (!path.win32.isAbsolute(filePath)) - { + if (!path.win32.isAbsolute(filePath)) { filePath = path.win32.resolve( vscode.workspace.rootPath, filePath); @@ -438,15 +408,14 @@ export class ExtensionCommandsFeature implements IFeature { return filePath.toLowerCase(); } else { // Make sure the file path is absolute - if (!path.isAbsolute(filePath)) - { + if (!path.isAbsolute(filePath)) { filePath = path.resolve( vscode.workspace.rootPath, filePath); } - //macOS is case-insensitive - if (platform == "darwin") { + // macOS is case-insensitive + if (platform === "darwin") { filePath = filePath.toLowerCase(); } @@ -456,9 +425,10 @@ export class ExtensionCommandsFeature implements IFeature { private findTextDocument(filePath: string): boolean { // since Windows and macOS are case-insensitive, we need to normalize them differently - let canFind = vscode.workspace.textDocuments.find(doc => { - let docPath, platform = os.platform(); - if (platform == "win32" || platform == "darwin") { + const canFind = vscode.workspace.textDocuments.find((doc) => { + let docPath; + const platform = os.platform(); + if (platform === "win32" || platform === "darwin") { // for Windows and macOS paths, they are normalized to be lowercase docPath = doc.fileName.toLowerCase(); } else { @@ -470,12 +440,12 @@ export class ExtensionCommandsFeature implements IFeature { return canFind != null; } - private setSelection(details: SetSelectionRequestArguments): EditorOperationResponse { + private setSelection(details: ISetSelectionRequestArguments): EditorOperationResponse { vscode.window.activeTextEditor.selections = [ new vscode.Selection( asCodePosition(details.selectionRange.start), - asCodePosition(details.selectionRange.end)) - ] + asCodePosition(details.selectionRange.end)), + ]; return EditorOperationResponse.Completed; } @@ -483,27 +453,26 @@ export class ExtensionCommandsFeature implements IFeature { private showInformationMessage(message: string): Thenable { return vscode.window .showInformationMessage(message) - .then(_ => EditorOperationResponse.Completed); + .then((_) => EditorOperationResponse.Completed); } private showErrorMessage(message: string): Thenable { return vscode.window .showErrorMessage(message) - .then(_ => EditorOperationResponse.Completed); + .then((_) => EditorOperationResponse.Completed); } private showWarningMessage(message: string): Thenable { return vscode.window .showWarningMessage(message) - .then(_ => EditorOperationResponse.Completed); + .then((_) => EditorOperationResponse.Completed); } - private setStatusBarMessage(messageDetails: StatusBarMessageDetails): EditorOperationResponse { + private setStatusBarMessage(messageDetails: IStatusBarMessageDetails): EditorOperationResponse { if (messageDetails.timeout) { vscode.window.setStatusBarMessage(messageDetails.message, messageDetails.timeout); - } - else { + } else { vscode.window.setStatusBarMessage(messageDetails.message); } diff --git a/src/features/GenerateBugReport.ts b/src/features/GenerateBugReport.ts index 33aeb96f69..38d52bc2fd 100644 --- a/src/features/GenerateBugReport.ts +++ b/src/features/GenerateBugReport.ts @@ -1,28 +1,33 @@ -import vscode = require('vscode'); -import { SessionManager } from '../session'; -import cp = require('child_process'); -import Settings = require('../settings'); - -const os = require("os"); - -import { IFeature, LanguageClient } from '../feature'; -// import { IExtensionManagementService, LocalExtensionType, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; - -const extensionId: string = 'ms-vscode.PowerShell'; +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ + +import cp = require("child_process"); +import os = require("os"); +import vscode = require("vscode"); +import { IFeature, LanguageClient } from "../feature"; +import { SessionManager } from "../session"; +import Settings = require("../settings"); + +const extensionId: string = "ms-vscode.PowerShell"; const extensionVersion: string = vscode.extensions.getExtension(extensionId).packageJSON.version; +const queryStringPrefix: string = "?"; -const queryStringPrefix: string = '?' - -var settings = Settings.load(); -let project = settings.bugReporting.project; - -const issuesUrl: string = `${project}/issues/new` +const settings = Settings.load(); +const project = settings.bugReporting.project; +const issuesUrl: string = `${project}/issues/new`; -var extensions = vscode.extensions.all.filter(element => element.packageJSON.isBuiltin == false).sort((leftside, rightside): number => { - if (leftside.packageJSON.name.toLowerCase() < rightside.packageJSON.name.toLowerCase()) return -1; - if (leftside.packageJSON.name.toLowerCase() > rightside.packageJSON.name.toLowerCase()) return 1; - return 0; -}) +const extensions = + vscode.extensions.all.filter((element) => element.packageJSON.isBuiltin === false) + .sort((leftside, rightside): number => { + if (leftside.packageJSON.name.toLowerCase() < rightside.packageJSON.name.toLowerCase()) { + return -1; + } + if (leftside.packageJSON.name.toLowerCase() > rightside.packageJSON.name.toLowerCase()) { + return 1; + } + return 0; + }); export class GenerateBugReportFeature implements IFeature { @@ -30,15 +35,16 @@ export class GenerateBugReportFeature implements IFeature { private powerShellProcess: cp.ChildProcess; constructor(private sessionManager: SessionManager) { - this.command = vscode.commands.registerCommand('PowerShell.GenerateBugReport', () => { + this.command = vscode.commands.registerCommand("PowerShell.GenerateBugReport", () => { - var body = encodeURIComponent(`## Issue Description ## + const body = encodeURIComponent(`## Issue Description ## I am experiencing a problem with... ## Attached Logs ## -Follow the instructions in the [README](https://github.com/PowerShell/vscode-powershell#reporting-problems) about capturing and sending logs. +Follow the instructions in the [README](https://github.com/PowerShell/vscode-powershell#reporting-problems) about +capturing and sending logs. ## Environment Information ## @@ -46,7 +52,7 @@ Follow the instructions in the [README](https://github.com/PowerShell/vscode-pow | Name | Version | | --- | --- | -| Operating System | ${os.type() + ' ' + os.arch() + ' ' + os.release()} | +| Operating System | ${os.type()} ${os.arch()} ${os.release()} | | VSCode | ${vscode.version}| | PowerShell Extension Version | ${extensionVersion} | @@ -63,36 +69,31 @@ ${this.generateExtensionTable(extensions)} `); - var encodedBody = encodeURIComponent(body); - var fullUrl = `${issuesUrl}${queryStringPrefix}body=${encodedBody}`; - vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(fullUrl)); - + const encodedBody = encodeURIComponent(body); + const fullUrl = `${issuesUrl}${queryStringPrefix}body=${encodedBody}`; + vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(fullUrl)); }); - - } - - - public setLanguageClient(LanguageClient: LanguageClient) { - // Not needed for this feature. } public dispose() { this.command.dispose(); } + public setLanguageClient(languageclient: LanguageClient) { + // Elimiinate tslint warning. + } - private generateExtensionTable(extensions): string { - if (!extensions.length) { - return 'none'; + private generateExtensionTable(installedExtensions): string { + if (!installedExtensions.length) { + return "none"; } - let tableHeader = `|Extension|Author|Version|\n|---|---|---|`; - const table = extensions.map(e => { - - if (e.packageJSON.isBuiltin == false) { + const tableHeader = `|Extension|Author|Version|\n|---|---|---|`; + const table = installedExtensions.map((e) => { + if (e.packageJSON.isBuiltin === false) { return `|${e.packageJSON.name}|${e.packageJSON.publisher}|${e.packageJSON.version}|`; } - }).join('\n'); + }).join("\n"); const extensionTable = ` ${tableHeader}\n${table}; @@ -108,19 +109,16 @@ ${tableHeader}\n${table}; private getRuntimeInfo() { - var psOutput; - var powerShellExePath = this.sessionManager.getPowerShellExePath(); - var powerShellArgs = [ + const powerShellExePath = this.sessionManager.getPowerShellExePath(); + const powerShellArgs = [ "-NoProfile", "-Command", - '$PSVersionString = "|Name|Value|\n"; $PSVersionString += "|---|---|\n"; $PSVersionTable.keys | ForEach-Object { $PSVersionString += "|$_|$($PSVersionTable.Item($_))|\n" }; $PSVersionString' - ] - - var spawn = require('child_process').spawnSync; - var child = spawn(powerShellExePath, powerShellArgs); - return child.stdout.toString().replace(';', ','); + '$PSVersionString = "|Name|Value|\n"; $PSVersionString += "|---|---|\n"; $PSVersionTable.keys | ' + + 'ForEach-Object { $PSVersionString += "|$_|$($PSVersionTable.Item($_))|\n" }; $PSVersionString', + ]; + const spawn = require("child_process").spawnSync; + const child = spawn(powerShellExePath, powerShellArgs); + return child.stdout.toString().replace(";", ","); } - } - diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index f2a5f14e51..997bf00593 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -2,25 +2,25 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import { IFeature } from "../feature"; -import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine, SnippetString, TextDocument } from "vscode"; +import { Disposable, EndOfLine, Position, Range, SnippetString, + TextDocument, TextDocumentChangeEvent, window, workspace } from "vscode"; import { LanguageClient, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; -export namespace CommentHelpRequest { - export const type = new RequestType("powerShell/getCommentHelp"); -} +export const CommentHelpRequestType = + new RequestType("powerShell/getCommentHelp"); -interface CommentHelpRequestParams { +interface ICommentHelpRequestParams { documentUri: string; triggerPosition: Position; blockComment: boolean; } -interface CommentHelpRequestResult { +interface ICommentHelpRequestResult { content: string[]; } -enum SearchState { Searching, Locked, Found }; +enum SearchState { Searching, Locked, Found } export class HelpCompletionFeature implements IFeature { private helpCompletionProvider: HelpCompletionProvider; @@ -29,21 +29,21 @@ export class HelpCompletionFeature implements IFeature { constructor() { this.helpCompletionProvider = new HelpCompletionProvider(); - let subscriptions = []; + const subscriptions = []; workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); this.disposable = Disposable.from(...subscriptions); } - setLanguageClient(languageClient: LanguageClient) { - this.languageClient = languageClient; - this.helpCompletionProvider.languageClient = languageClient; + public dispose() { + this.disposable.dispose(); } - dispose() { - this.disposable.dispose(); + public setLanguageClient(languageClient: LanguageClient) { + this.languageClient = languageClient; + this.helpCompletionProvider.languageClient = languageClient; } - onEvent(changeEvent: TextDocumentChangeEvent): void { + public onEvent(changeEvent: TextDocumentChangeEvent): void { this.helpCompletionProvider.updateState( changeEvent.document, changeEvent.contentChanges[0].text, @@ -53,7 +53,6 @@ export class HelpCompletionFeature implements IFeature { if (this.helpCompletionProvider.triggerFound) { this.helpCompletionProvider.complete().then(() => this.helpCompletionProvider.reset()); } - } } @@ -88,8 +87,7 @@ class TriggerFinder { if (this.count === this.triggerCharacters.length) { this.state = SearchState.Found; } - } - else { + } else { this.reset(); } break; @@ -145,28 +143,29 @@ class HelpCompletionProvider { return; } - let change = this.lastChangeText; - let triggerStartPos = this.lastChangeRange.start; - let triggerEndPos = this.lastChangeRange.end; - let doc = this.lastDocument; + const change = this.lastChangeText; + const triggerStartPos = this.lastChangeRange.start; + const triggerEndPos = this.lastChangeRange.end; + const doc = this.lastDocument; + return this.langClient.sendRequest( - CommentHelpRequest.type, + CommentHelpRequestType, { documentUri: doc.uri.toString(), triggerPosition: triggerStartPos, - blockComment: this.triggerFinderBlockComment.found - }).then(result => { + blockComment: this.triggerFinderBlockComment.found, + }).then((result) => { if (result == null || result.content == null) { return; } // todo add indentation level to the help content - let editor = window.activeTextEditor; - let replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); + const editor = window.activeTextEditor; + const replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); - // Trim the leading whitespace (used by the rule for indentation) as VSCode takes care of the indentation. + // Trim leading whitespace (used by the rule for indentation) as VSCode takes care of the indentation. // Trim the last empty line and join the strings. - let text = result.content.map(x => x.trimLeft()).slice(0, -1).join(this.getEOL(doc.eol)); + const text = result.content.map((x) => x.trimLeft()).slice(0, -1).join(this.getEOL(doc.eol)); editor.insertSnippet(new SnippetString(text), replaceRange); }); } diff --git a/src/features/NewFileOrProject.ts b/src/features/NewFileOrProject.ts index 34595bf6d1..e8e3e5efc1 100644 --- a/src/features/NewFileOrProject.ts +++ b/src/features/NewFileOrProject.ts @@ -2,9 +2,9 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; export class NewFileOrProjectFeature implements IFeature { @@ -15,7 +15,7 @@ export class NewFileOrProjectFeature implements IFeature { constructor() { this.command = - vscode.commands.registerCommand('PowerShell.NewProjectFromTemplate', () => { + vscode.commands.registerCommand("PowerShell.NewProjectFromTemplate", () => { if (!this.languageClient && !this.waitingForClientToken) { @@ -27,7 +27,11 @@ export class NewFileOrProjectFeature implements IFeature { ["Cancel"], { placeHolder: "New Project: Please wait, starting PowerShell..." }, this.waitingForClientToken.token) - .then(response => { if (response === "Cancel") { this.clearWaitingToken(); } }); + .then((response) => { + if (response === "Cancel") { + this.clearWaitingToken(); + } + }); // Cancel the loading prompt after 60 seconds setTimeout(() => { @@ -38,13 +42,16 @@ export class NewFileOrProjectFeature implements IFeature { "New Project: PowerShell session took too long to start."); } }, 60000); - } - else { + } else { this.showProjectTemplates(); } }); } + public dispose() { + this.command.dispose(); + } + public setLanguageClient(languageClient: LanguageClient) { this.languageClient = languageClient; @@ -54,57 +61,56 @@ export class NewFileOrProjectFeature implements IFeature { } } - public dispose() { - this.command.dispose(); - } - private showProjectTemplates(includeInstalledModules: boolean = false): void { vscode.window .showQuickPick( this.getProjectTemplates(includeInstalledModules), { placeHolder: "Choose a template to create a new project", ignoreFocusOut: true }) - .then(template => { + .then((template) => { if (template.label.startsWith(this.loadIcon)) { this.showProjectTemplates(true); - } - else { + } else { this.createProjectFromTemplate(template.template); } }); } - private getProjectTemplates(includeInstalledModules: boolean): Thenable { + private getProjectTemplates(includeInstalledModules: boolean): Thenable { return this.languageClient - .sendRequest( - GetProjectTemplatesRequest.type, - { includeInstalledModules: includeInstalledModules }) - .then(response => { + .sendRequest(GetProjectTemplatesRequestType, { includeInstalledModules }) + .then((response) => { if (response.needsModuleInstall) { // TODO: Offer to install Plaster vscode.window.showErrorMessage("Plaster is not installed!"); - return Promise.reject("Plaster needs to be installed"); - } - else { - var templates = response.templates.map( - template => { + return Promise.reject("Plaster needs to be installed"); + } else { + let templates = response.templates.map( + (template) => { return { label: template.title, description: `v${template.version} by ${template.author}, tags: ${template.tags}`, detail: template.description, - template: template - } + template, + }; }); if (!includeInstalledModules) { templates = - [{ label: this.loadIcon, description: "Load additional templates from installed modules", template: undefined }] - .concat(templates) - } - else { + [{ + label: this.loadIcon, + description: "Load additional templates from installed modules", + template: undefined, + }] + .concat(templates); + } else { templates = - [{ label: this.loadIcon, description: "Refresh template list", template: undefined }] - .concat(templates) + [{ + label: this.loadIcon, + description: "Refresh template list", + template: undefined, + }] + .concat(templates); } return templates; @@ -112,12 +118,12 @@ export class NewFileOrProjectFeature implements IFeature { }); } - private createProjectFromTemplate(template: TemplateDetails): void { + private createProjectFromTemplate(template: ITemplateDetails): void { vscode.window .showInputBox( { placeHolder: "Enter an absolute path to the folder where the project should be created", ignoreFocusOut: true }) - .then(destinationPath => { + .then((destinationPath) => { if (destinationPath) { // Show the PowerShell session output in case an error occurred @@ -125,29 +131,26 @@ export class NewFileOrProjectFeature implements IFeature { this.languageClient .sendRequest( - NewProjectFromTemplateRequest.type, - { templatePath: template.templatePath, destinationPath: destinationPath }) - .then(result => { + NewProjectFromTemplateRequestType, + { templatePath: template.templatePath, destinationPath }) + .then((result) => { if (result.creationSuccessful) { this.openWorkspacePath(destinationPath); - } - else { + } else { vscode.window.showErrorMessage( "Project creation failed, read the Output window for more details."); } }); - } - else { + } else { vscode.window .showErrorMessage( "New Project: You must enter an absolute folder path to continue. Try again?", "Yes", "No") - .then( - response => { - if (response === "Yes") { - this.createProjectFromTemplate(template); - } - }); + .then((response) => { + if (response === "Yes") { + this.createProjectFromTemplate(template); + } + }); } }); } @@ -168,11 +171,11 @@ export class NewFileOrProjectFeature implements IFeature { } } -interface TemplateQuickPickItem extends vscode.QuickPickItem { - template: TemplateDetails +interface ITemplateQuickPickItem extends vscode.QuickPickItem { + template: ITemplateDetails; } -interface TemplateDetails { +interface ITemplateDetails { title: string; version: string; author: string; @@ -181,32 +184,28 @@ interface TemplateDetails { templatePath: string; } -namespace GetProjectTemplatesRequest { - export const type = - new RequestType( - 'powerShell/getProjectTemplates'); -} +export const GetProjectTemplatesRequestType = + new RequestType( + "powerShell/getProjectTemplates"); -interface GetProjectTemplatesRequestArgs { +interface IGetProjectTemplatesRequestArgs { includeInstalledModules: boolean; } -interface GetProjectTemplatesResponseBody { +interface IGetProjectTemplatesResponseBody { needsModuleInstall: boolean; - templates: TemplateDetails[]; + templates: ITemplateDetails[]; } -namespace NewProjectFromTemplateRequest { - export const type = - new RequestType( - 'powerShell/newProjectFromTemplate'); -} +export const NewProjectFromTemplateRequestType = + new RequestType( + "powerShell/newProjectFromTemplate"); -interface NewProjectFromTemplateRequestArgs { +interface INewProjectFromTemplateRequestArgs { destinationPath: string; templatePath: string; } -interface NewProjectFromTemplateResponseBody { +interface INewProjectFromTemplateResponseBody { creationSuccessful: boolean; -} \ No newline at end of file +} diff --git a/src/features/OpenInISE.ts b/src/features/OpenInISE.ts index 6c7c36edcb..1a0f1007dd 100644 --- a/src/features/OpenInISE.ts +++ b/src/features/OpenInISE.ts @@ -2,36 +2,39 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import Window = vscode.window; -import ChildProcess = require('child_process'); -import { IFeature, LanguageClient } from '../feature'; +import ChildProcess = require("child_process"); +import vscode = require("vscode"); +import { IFeature, LanguageClient } from "../feature"; export class OpenInISEFeature implements IFeature { private command: vscode.Disposable; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.OpenInISE', () => { + this.command = vscode.commands.registerCommand("PowerShell.OpenInISE", () => { - var editor = Window.activeTextEditor; - var document = editor.document; - var uri = document.uri + const editor = vscode.window.activeTextEditor; + const document = editor.document; + const uri = document.uri; - if (process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')) { - var ISEPath = process.env.windir + '\\Sysnative\\WindowsPowerShell\\v1.0\\powershell_ise.exe'; + let ISEPath = process.env.windir; + + if (process.env.hasOwnProperty("PROCESSOR_ARCHITEW6432")) { + ISEPath += "\\Sysnative"; } else { - var ISEPath = process.env.windir + '\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe'; + ISEPath += "\\System32"; } - ChildProcess.exec(ISEPath + ' -File "' + uri.fsPath + '"').unref(); - }); - } + ISEPath += "\\WindowsPowerShell\\v1.0\\powershell_ise.exe"; - public setLanguageClient(languageClient: LanguageClient) { - // Not needed for this feature. + ChildProcess.exec(ISEPath + ` -File "${uri.fsPath}"`).unref(); + }); } public dispose() { this.command.dispose(); } -} \ No newline at end of file + + public setLanguageClient(languageClient: LanguageClient) { + // Not needed for this feature. + } +} diff --git a/src/features/PesterTests.ts b/src/features/PesterTests.ts index d0d141d6dc..7a20e91611 100644 --- a/src/features/PesterTests.ts +++ b/src/features/PesterTests.ts @@ -2,12 +2,12 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import utils = require('../utils'); +import ChildProcess = require("child_process"); +import vscode = require("vscode"); import Window = vscode.window; -import ChildProcess = require('child_process'); -import { SessionManager } from '../session'; -import { IFeature, LanguageClient } from '../feature'; +import { IFeature, LanguageClient } from "../feature"; +import { SessionManager } from "../session"; +import utils = require("../utils"); export class PesterTestsFeature implements IFeature { @@ -16,25 +16,25 @@ export class PesterTestsFeature implements IFeature { constructor(private sessionManager: SessionManager) { this.command = vscode.commands.registerCommand( - 'PowerShell.RunPesterTests', + "PowerShell.RunPesterTests", (uriString, runInDebugger, describeBlockName?) => { this.launchTests(uriString, runInDebugger, describeBlockName); }); } - public setLanguageClient(languageClient: LanguageClient) { - this.languageClient = languageClient; - } - public dispose() { this.command.dispose(); } + public setLanguageClient(languageClient: LanguageClient) { + this.languageClient = languageClient; + } + private launchTests(uriString, runInDebugger, describeBlockName?) { - var uri = vscode.Uri.parse(uriString); - let currentDocument = vscode.window.activeTextEditor.document; + const uri = vscode.Uri.parse(uriString); + const currentDocument = vscode.window.activeTextEditor.document; - let launchConfig = { + const launchConfig = { request: "launch", type: "PowerShell", name: "PowerShell Launch Pester Tests", @@ -43,19 +43,19 @@ export class PesterTestsFeature implements IFeature { `-Script "${uri.fsPath}"`, describeBlockName ? `-TestName '${describeBlockName}'` - : "" + : "", ], internalConsoleOptions: "neverOpen", noDebug: !runInDebugger, cwd: currentDocument.isUntitled ? vscode.workspace.rootPath - : currentDocument.fileName - } + : currentDocument.fileName, + }; // Create or show the interactive console // TODO #367: Check if "newSession" mode is configured - vscode.commands.executeCommand('PowerShell.ShowSessionConsole', true); + vscode.commands.executeCommand("PowerShell.ShowSessionConsole", true); // Write out temporary debug session file utils.writeSessionFile( diff --git a/src/features/PowerShellFindModule.ts b/src/features/PowerShellFindModule.ts index c1664a69d0..cb57f25994 100644 --- a/src/features/PowerShellFindModule.ts +++ b/src/features/PowerShellFindModule.ts @@ -2,19 +2,17 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; import Window = vscode.window; -import { IFeature } from '../feature'; +import { IFeature } from "../feature"; import QuickPickItem = vscode.QuickPickItem; -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; -export namespace FindModuleRequest { - export const type = new RequestType('powerShell/findModule'); -} +export const FindModuleRequestType = + new RequestType("powerShell/findModule"); -export namespace InstallModuleRequest { - export const type = new RequestType('powerShell/installModule'); -} +export const InstallModuleRequestType = + new RequestType("powerShell/installModule"); export class FindModuleFeature implements IFeature { @@ -23,7 +21,7 @@ export class FindModuleFeature implements IFeature { private cancelFindToken: vscode.CancellationTokenSource; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.PowerShellFindModule', () => { + this.command = vscode.commands.registerCommand("PowerShell.PowerShellFindModule", () => { // It takes a while to get the list of PowerShell modules, display some UI to let user know this.cancelFindToken = new vscode.CancellationTokenSource(); vscode.window @@ -31,7 +29,9 @@ export class FindModuleFeature implements IFeature { ["Cancel"], { placeHolder: "Please wait, retrieving list of PowerShell modules. This can take some time..." }, this.cancelFindToken.token) - .then(response => { if (response === "Cancel") { this.clearCancelFindToken(); } }); + .then((response) => { + if (response === "Cancel") { this.clearCancelFindToken(); } + }); // Cancel the loading prompt after 60 seconds setTimeout(() => { @@ -39,14 +39,15 @@ export class FindModuleFeature implements IFeature { this.clearCancelFindToken(); vscode.window.showErrorMessage( - "The online source for PowerShell modules is not responding. Cancelling Find/Install PowerShell command."); + "The online source for PowerShell modules is not responding. " + + "Cancelling Find/Install PowerShell command."); } }, 60000); this.pickPowerShellModule().then((moduleName) => { if (moduleName) { // vscode.window.setStatusBarMessage("Installing PowerShell Module " + moduleName, 1500); - this.languageClient.sendRequest(InstallModuleRequest.type, moduleName); + this.languageClient.sendRequest(InstallModuleRequestType, moduleName); } }); }); @@ -61,33 +62,34 @@ export class FindModuleFeature implements IFeature { } private pickPowerShellModule(): Thenable { - return this.languageClient.sendRequest(FindModuleRequest.type, null).then((modules) => { - var items: QuickPickItem[] = []; + return this.languageClient.sendRequest(FindModuleRequestType, null).then((modules) => { + const items: QuickPickItem[] = []; // We've got the modules info, let's cancel the timeout unless it's already been cancelled if (this.cancelFindToken) { this.clearCancelFindToken(); - } - else { + } else { // Already timed out, would be weird to dislay modules after we said it timed out. return Promise.resolve(""); } - for (var item in modules) { - items.push({ label: modules[item].name, description: modules[item].description }); - }; + for (const item in modules) { + if (modules.hasOwnProperty(item)) { + items.push({ label: modules[item].name, description: modules[item].description }); + } + } if (items.length === 0) { return Promise.reject("No PowerShell modules were found."); } - let options: vscode.QuickPickOptions = { + const options: vscode.QuickPickOptions = { placeHolder: "Select a PowerShell module to install", matchOnDescription: true, - matchOnDetail: true + matchOnDetail: true, }; - return vscode.window.showQuickPick(items, options).then(item => { + return vscode.window.showQuickPick(items, options).then((item) => { return item ? item.label : ""; }); }); diff --git a/src/features/RemoteFiles.ts b/src/features/RemoteFiles.ts index 39ab7bc3c2..19c74b5ad7 100644 --- a/src/features/RemoteFiles.ts +++ b/src/features/RemoteFiles.ts @@ -2,25 +2,25 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import os = require('os'); -import path = require('path'); -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType, TextDocumentIdentifier } from 'vscode-languageclient'; +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType, TextDocumentIdentifier } from "vscode-languageclient"; +import { IFeature } from "../feature"; // NOTE: The following two DidSaveTextDocument* types will // be removed when #593 gets fixed. -export interface DidSaveTextDocumentParams { - /** - * The document that was closed. - */ - textDocument: TextDocumentIdentifier; +export interface IDidSaveTextDocumentParams { + /** + * The document that was closed. + */ + textDocument: TextDocumentIdentifier; } -export namespace DidSaveTextDocumentNotification { - export const type = new NotificationType('textDocument/didSave'); -} +export const DidSaveTextDocumentNotificationType = + new NotificationType( + "textDocument/didSave"); export class RemoteFilesFeature implements IFeature { @@ -31,25 +31,21 @@ export class RemoteFilesFeature implements IFeature { // Get the common PowerShell Editor Services temporary file path // so that remote files from previous sessions can be closed. this.tempSessionPathPrefix = - path.join(os.tmpdir(), 'PSES-') + path.join(os.tmpdir(), "PSES-") .toLowerCase(); // At startup, close any lingering temporary remote files this.closeRemoteFiles(); - vscode.workspace.onDidSaveTextDocument(doc => { + vscode.workspace.onDidSaveTextDocument((doc) => { if (this.languageClient && this.isDocumentRemote(doc)) { this.languageClient.sendNotification( - DidSaveTextDocumentNotification.type, + DidSaveTextDocumentNotificationType, { - textDocument: TextDocumentIdentifier.create(doc.uri.toString()) + textDocument: TextDocumentIdentifier.create(doc.uri.toString()), }); } - }) - } - - public setLanguageClient(languageclient: LanguageClient) { - this.languageClient = languageclient; + }); } public dispose() { @@ -57,25 +53,28 @@ export class RemoteFilesFeature implements IFeature { this.closeRemoteFiles(); } + public setLanguageClient(languageclient: LanguageClient) { + this.languageClient = languageclient; + } + private isDocumentRemote(doc: vscode.TextDocument) { return doc.fileName.toLowerCase().startsWith(this.tempSessionPathPrefix); } private closeRemoteFiles() { - var remoteDocuments = - vscode.workspace.textDocuments.filter( - doc => this.isDocumentRemote(doc)); + const remoteDocuments = + vscode.workspace.textDocuments.filter((doc) => this.isDocumentRemote(doc)); function innerCloseFiles(): Thenable<{}> { if (remoteDocuments.length > 0) { - var doc = remoteDocuments.pop(); + const doc = remoteDocuments.pop(); return vscode.window .showTextDocument(doc) - .then(editor => vscode.commands.executeCommand("workbench.action.closeActiveEditor")) - .then(_ => innerCloseFiles()); + .then((editor) => vscode.commands.executeCommand("workbench.action.closeActiveEditor")) + .then((_) => innerCloseFiles()); } - }; + } innerCloseFiles(); } diff --git a/src/features/SelectPSSARules.ts b/src/features/SelectPSSARules.ts index 167c02eb19..04bb2f7618 100644 --- a/src/features/SelectPSSARules.ts +++ b/src/features/SelectPSSARules.ts @@ -3,21 +3,16 @@ *--------------------------------------------------------*/ import vscode = require("vscode"); -import { IFeature } from "../feature"; import { LanguageClient, RequestType } from "vscode-languageclient"; -import { CheckboxQuickPickItem, showCheckboxQuickPick } from "../controls/checkboxQuickPick"; - -export namespace GetPSSARulesRequest { - export const type = new RequestType("powerShell/getPSSARules"); -} +import { ICheckboxQuickPickItem, showCheckboxQuickPick } from "../controls/checkboxQuickPick"; +import { IFeature } from "../feature"; -export namespace SetPSSARulesRequest { - export const type = new RequestType("powerShell/setPSSARules"); -} +export const GetPSSARulesRequestType = new RequestType("powerShell/getPSSARules"); +export const SetPSSARulesRequestType = new RequestType("powerShell/setPSSARules"); class RuleInfo { - name: string; - isEnabled: boolean; + public name: string; + public isEnabled: boolean; } export class SelectPSSARulesFeature implements IFeature { @@ -31,40 +26,42 @@ export class SelectPSSARulesFeature implements IFeature { return; } - this.languageClient.sendRequest(GetPSSARulesRequest.type, null).then((returnedRules) => { + this.languageClient.sendRequest(GetPSSARulesRequestType, null).then((returnedRules) => { if (returnedRules == null) { vscode.window.showWarningMessage( "PowerShell extension uses PSScriptAnalyzer settings file - Cannot update rules."); return; } - let options: CheckboxQuickPickItem[] = returnedRules.map(function (rule: RuleInfo): CheckboxQuickPickItem { - return { label: rule.name, isSelected: rule.isEnabled }; + + const options: ICheckboxQuickPickItem[] = + returnedRules.map((rule: RuleInfo): ICheckboxQuickPickItem => { + return { label: rule.name, isSelected: rule.isEnabled }; }); showCheckboxQuickPick(options) - .then((updatedOptions: CheckboxQuickPickItem[]) => { + .then((updatedOptions: ICheckboxQuickPickItem[]) => { if (updatedOptions === undefined) { return; } + this.languageClient.sendRequest( - SetPSSARulesRequest.type, + SetPSSARulesRequestType, { filepath: vscode.window.activeTextEditor.document.uri.fsPath, - ruleInfos: updatedOptions.map( - function (option: CheckboxQuickPickItem): RuleInfo { - return { name: option.label, isEnabled: option.isSelected }; - }) + ruleInfos: updatedOptions.map((option: ICheckboxQuickPickItem): RuleInfo => { + return { name: option.label, isEnabled: option.isSelected }; + }), }); }); }); }); } - public setLanguageClient(languageclient: LanguageClient): void { - this.languageClient = languageclient; - } - public dispose(): void { this.command.dispose(); } + + public setLanguageClient(languageclient: LanguageClient): void { + this.languageClient = languageclient; + } } diff --git a/src/features/ShowOnlineHelp.ts b/src/features/ShowOnlineHelp.ts index f96c648c72..00dde83045 100644 --- a/src/features/ShowOnlineHelp.ts +++ b/src/features/ShowOnlineHelp.ts @@ -2,13 +2,12 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require('vscode'); -import { IFeature } from '../feature'; -import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient'; +import vscode = require("vscode"); +import { LanguageClient, NotificationType, RequestType } from "vscode-languageclient"; +import { IFeature } from "../feature"; -export namespace ShowOnlineHelpRequest { - export const type = new RequestType('powerShell/showOnlineHelp'); -} +export const ShowOnlineHelpRequestType = + new RequestType("powerShell/showOnlineHelp"); export class ShowHelpFeature implements IFeature { @@ -16,7 +15,7 @@ export class ShowHelpFeature implements IFeature { private languageClient: LanguageClient; constructor() { - this.command = vscode.commands.registerCommand('PowerShell.OnlineHelp', () => { + this.command = vscode.commands.registerCommand("PowerShell.OnlineHelp", () => { if (this.languageClient === undefined) { // TODO: Log error message return; @@ -24,20 +23,20 @@ export class ShowHelpFeature implements IFeature { const editor = vscode.window.activeTextEditor; - var selection = editor.selection; - var doc = editor.document; - var cwr = doc.getWordRangeAtPosition(selection.active) - var text = doc.getText(cwr); + const selection = editor.selection; + const doc = editor.document; + const cwr = doc.getWordRangeAtPosition(selection.active); + const text = doc.getText(cwr); - this.languageClient.sendRequest(ShowOnlineHelpRequest.type, text); + this.languageClient.sendRequest(ShowOnlineHelpRequestType, text); }); } - public setLanguageClient(languageclient: LanguageClient) { - this.languageClient = languageclient; - } - public dispose() { this.command.dispose(); } + + public setLanguageClient(languageclient: LanguageClient) { + this.languageClient = languageclient; + } } diff --git a/src/logging.ts b/src/logging.ts index 95ac427754..ff4076b09f 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -2,30 +2,29 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import fs = require('fs'); -import os = require('os'); -import path = require('path'); -import vscode = require('vscode'); -import utils = require('./utils'); -import jsonrpc = require('vscode-jsonrpc'); +import fs = require("fs"); +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); +import utils = require("./utils"); export enum LogLevel { Verbose, Normal, Warning, - Error + Error, } export class Logger { - private commands: vscode.Disposable[]; - private logChannel: vscode.OutputChannel; - private logFilePath: string; - public logBasePath: string; public logSessionPath: string; public MinimumLogLevel: LogLevel = LogLevel.Normal; + private commands: vscode.Disposable[]; + private logChannel: vscode.OutputChannel; + private logFilePath: string; + constructor() { this.logChannel = vscode.window.createOutputChannel("PowerShell Extension Logs"); @@ -34,13 +33,18 @@ export class Logger { this.commands = [ vscode.commands.registerCommand( - 'PowerShell.ShowLogs', + "PowerShell.ShowLogs", () => { this.showLogPanel(); }), vscode.commands.registerCommand( - 'PowerShell.OpenLogFolder', - () => { this.openLogFolder(); }) - ] + "PowerShell.OpenLogFolder", + () => { this.openLogFolder(); }), + ]; + } + + public dispose() { + this.commands.forEach((command) => { command.dispose(); }); + this.logChannel.dispose(); } public getLogFilePath(baseName: string): string { @@ -49,7 +53,7 @@ export class Logger { public writeAtLevel(logLevel: LogLevel, message: string, ...additionalMessages: string[]) { if (logLevel >= this.MinimumLogLevel) { - this.writeLine(message, logLevel) + this.writeLine(message, logLevel); additionalMessages.forEach((line) => { this.writeLine(line, logLevel); @@ -116,11 +120,6 @@ export class Logger { } } - public dispose() { - this.commands.forEach((command) => { command.dispose() }); - this.logChannel.dispose(); - } - private showLogPanel() { this.logChannel.show(); } @@ -130,47 +129,28 @@ export class Logger { // Open the folder in VS Code since there isn't an easy way to // open the folder in the platform's file browser vscode.commands.executeCommand( - 'vscode.openFolder', + "vscode.openFolder", vscode.Uri.file(this.logSessionPath), true); } } private writeLine(message: string, level: LogLevel = LogLevel.Normal) { - let now = new Date(); - let timestampedMessage = `${now.toLocaleDateString()} ${now.toLocaleTimeString()} [${LogLevel[level].toUpperCase()}] - ${message}` + const now = new Date(); + const timestampedMessage = + `${now.toLocaleDateString()} ${now.toLocaleTimeString()} [${LogLevel[level].toUpperCase()}] - ${message}`; this.logChannel.appendLine(timestampedMessage); if (this.logFilePath) { fs.appendFile( this.logFilePath, timestampedMessage + os.EOL, - err => { + (err) => { if (err) { - console.log(`Error writing to vscode-powershell log file: ${err}`) + // tslint:disable-next-line:no-console + console.log(`Error writing to vscode-powershell log file: ${err}`); } }); } } } - -export class LanguageClientLogger implements jsonrpc.Logger { - - constructor(private logger: Logger) { } - - public error(message: string) { - this.logger.writeError(message); - } - - public warn(message: string) { - this.logger.writeWarning(message); - } - - public info(message: string) { - this.logger.write(message); - } - - public log(message: string) { - this.logger.writeVerbose(message); - } -} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 8bfa1ed098..418288f4c6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,43 +2,43 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -'use strict'; - -import vscode = require('vscode'); -import utils = require('./utils'); -import path = require('path'); -import Settings = require('./settings'); -import { Logger, LogLevel } from './logging'; -import { IFeature } from './feature'; -import { SessionManager } from './session'; -import { PowerShellLanguageId } from './utils'; -import { ConsoleFeature } from './features/Console'; -import { ExamplesFeature } from './features/Examples'; -import { OpenInISEFeature } from './features/OpenInISE'; -import { GenerateBugReportFeature } from './features/GenerateBugReport'; -import { CustomViewsFeature } from './features/CustomViews'; -import { ExpandAliasFeature } from './features/ExpandAlias'; -import { ShowHelpFeature } from './features/ShowOnlineHelp'; -import { CodeActionsFeature } from './features/CodeActions'; -import { RemoteFilesFeature } from './features/RemoteFiles'; -import { PesterTestsFeature } from './features/PesterTests'; -import { DebugSessionFeature } from './features/DebugSession'; -import { PickPSHostProcessFeature } from './features/DebugSession'; -import { SpecifyScriptArgsFeature } from './features/DebugSession'; -import { SelectPSSARulesFeature } from './features/SelectPSSARules'; -import { FindModuleFeature } from './features/PowerShellFindModule'; -import { NewFileOrProjectFeature } from './features/NewFileOrProject'; -import { ExtensionCommandsFeature } from './features/ExtensionCommands'; -import { DocumentFormatterFeature } from './features/DocumentFormatter'; +"use strict"; + +import path = require("path"); +import vscode = require("vscode"); +import { IFeature } from "./feature"; +import { CodeActionsFeature } from "./features/CodeActions"; +import { ConsoleFeature } from "./features/Console"; +import { CustomViewsFeature } from "./features/CustomViews"; +import { DebugSessionFeature } from "./features/DebugSession"; +import { PickPSHostProcessFeature } from "./features/DebugSession"; +import { SpecifyScriptArgsFeature } from "./features/DebugSession"; +import { DocumentFormatterFeature } from "./features/DocumentFormatter"; +import { ExamplesFeature } from "./features/Examples"; +import { ExpandAliasFeature } from "./features/ExpandAlias"; +import { ExtensionCommandsFeature } from "./features/ExtensionCommands"; +import { GenerateBugReportFeature } from "./features/GenerateBugReport"; import { HelpCompletionFeature } from "./features/HelpCompletion"; +import { NewFileOrProjectFeature } from "./features/NewFileOrProject"; +import { OpenInISEFeature } from "./features/OpenInISE"; +import { PesterTestsFeature } from "./features/PesterTests"; +import { FindModuleFeature } from "./features/PowerShellFindModule"; +import { RemoteFilesFeature } from "./features/RemoteFiles"; +import { SelectPSSARulesFeature } from "./features/SelectPSSARules"; +import { ShowHelpFeature } from "./features/ShowOnlineHelp"; +import { Logger, LogLevel } from "./logging"; +import { SessionManager } from "./session"; +import Settings = require("./settings"); +import { PowerShellLanguageId } from "./utils"; +import utils = require("./utils"); // NOTE: We will need to find a better way to deal with the required // PS Editor Services version... -var requiredEditorServicesVersion = "1.5.1"; +const requiredEditorServicesVersion = "1.5.1"; -var logger: Logger = undefined; -var sessionManager: SessionManager = undefined; -var extensionFeatures: IFeature[] = []; +let logger: Logger; +let sessionManager: SessionManager; +let extensionFeatures: IFeature[] = []; export function activate(context: vscode.ExtensionContext): void { @@ -53,48 +53,48 @@ export function activate(context: vscode.ExtensionContext): void { // ^(.*\*/)?\s*\}.*$ decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/, // ^.*\{[^}"']*$ - increaseIndentPattern: /^.*\{[^}"']*$/ + increaseIndentPattern: /^.*\{[^}"']*$/, }, comments: { - lineComment: '#', - blockComment: ['<#', '#>'] + lineComment: "#", + blockComment: ["<#", "#>"], }, brackets: [ - ['{', '}'], - ['[', ']'], - ['(', ')'], + ["{", "}"], + ["[", "]"], + ["(", ")"], ], - onEnterRules: [ - { - // e.g. /** | */ - beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - afterText: /^\s*\*\/$/, - action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' } - }, - { - // e.g. /** ...| - beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: vscode.IndentAction.None, appendText: ' * ' } - }, - { - // e.g. * ...| - beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: vscode.IndentAction.None, appendText: '* ' } - }, - { - // e.g. */| - beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, - action: { indentAction: vscode.IndentAction.None, removeText: 1 } - }, - { - // e.g. *-----*/| - beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/, - action: { indentAction: vscode.IndentAction.None, removeText: 1 } - } - ] + onEnterRules: [ + { + // e.g. /** | */ + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: " * " }, + }, + { + // e.g. /** ...| + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { indentAction: vscode.IndentAction.None, appendText: " * " }, + }, + { + // e.g. * ...| + beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { indentAction: vscode.IndentAction.None, appendText: "* " }, + }, + { + // e.g. */| + beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, + action: { indentAction: vscode.IndentAction.None, removeText: 1 }, + }, + { + // e.g. *-----*/| + beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/, + action: { indentAction: vscode.IndentAction.None, removeText: 1 }, + }, + ], }); // Create the logger @@ -125,12 +125,12 @@ export function activate(context: vscode.ExtensionContext): void { new PickPSHostProcessFeature(), new SpecifyScriptArgsFeature(context), new HelpCompletionFeature(), - new CustomViewsFeature() + new CustomViewsFeature(), ]; sessionManager.setExtensionFeatures(extensionFeatures); - var extensionSettings = Settings.load(); + const extensionSettings = Settings.load(); if (extensionSettings.startAutomatically) { sessionManager.start(); } @@ -139,30 +139,29 @@ export function activate(context: vscode.ExtensionContext): void { function checkForUpdatedVersion(context: vscode.ExtensionContext) { const showReleaseNotes = "Show Release Notes"; - const powerShellExtensionVersionKey = 'powerShellExtensionVersion'; + const powerShellExtensionVersionKey = "powerShellExtensionVersion"; - var extensionVersion: string = + const extensionVersion: string = vscode .extensions .getExtension("ms-vscode.PowerShell") .packageJSON .version; - var storedVersion = context.globalState.get(powerShellExtensionVersionKey); + const storedVersion = context.globalState.get(powerShellExtensionVersionKey); if (!storedVersion) { // TODO: Prompt to show User Guide for first-time install - } - else if (extensionVersion !== storedVersion) { + } else if (extensionVersion !== storedVersion) { vscode .window .showInformationMessage( `The PowerShell extension has been updated to version ${extensionVersion}!`, showReleaseNotes) - .then(choice => { + .then((choice) => { if (choice === showReleaseNotes) { vscode.commands.executeCommand( - 'markdown.showPreview', + "markdown.showPreview", vscode.Uri.file(path.resolve(__dirname, "../../CHANGELOG.md"))); } }); @@ -175,7 +174,7 @@ function checkForUpdatedVersion(context: vscode.ExtensionContext) { export function deactivate(): void { // Clean up all extension features - extensionFeatures.forEach(feature => { + extensionFeatures.forEach((feature) => { feature.dispose(); }); diff --git a/src/platform.ts b/src/platform.ts index b1109f75de..b561cf614c 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -2,82 +2,77 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import fs = require('fs'); -import os = require('os'); -import path = require('path'); -import vscode = require('vscode'); -import process = require('process'); -import Settings = require('./settings'); +import fs = require("fs"); +import os = require("os"); +import path = require("path"); +import process = require("process"); +import vscode = require("vscode"); +import Settings = require("./settings"); export enum OperatingSystem { Unknown, Windows, MacOS, - Linux + Linux, } -export interface PlatformDetails { - operatingSystem: OperatingSystem - isOS64Bit: boolean - isProcess64Bit: boolean +export interface IPlatformDetails { + operatingSystem: OperatingSystem; + isOS64Bit: boolean; + isProcess64Bit: boolean; } -export interface PowerShellExeDetails { +export interface IPowerShellExeDetails { versionName: string; exePath: string; } -export function getPlatformDetails(): PlatformDetails { - var operatingSystem = OperatingSystem.Unknown; +export function getPlatformDetails(): IPlatformDetails { + let operatingSystem = OperatingSystem.Unknown; if (process.platform === "win32") { operatingSystem = OperatingSystem.Windows; - } - else if (process.platform === "darwin") { + } else if (process.platform === "darwin") { operatingSystem = OperatingSystem.MacOS; - } - else if (process.platform === "linux") { + } else if (process.platform === "linux") { operatingSystem = OperatingSystem.Linux; } - let isProcess64Bit = process.arch === "x64"; + const isProcess64Bit = process.arch === "x64"; return { - operatingSystem: operatingSystem, - isOS64Bit: isProcess64Bit || process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), - isProcess64Bit: isProcess64Bit - } + operatingSystem, + isOS64Bit: isProcess64Bit || process.env.hasOwnProperty("PROCESSOR_ARCHITEW6432"), + isProcess64Bit, + }; } export function getDefaultPowerShellPath( - platformDetails: PlatformDetails, + platformDetails: IPlatformDetails, use32Bit: boolean = false): string | null { - var powerShellExePath = undefined; + let powerShellExePath; // Find the path to powershell.exe based on the current platform // and the user's desire to run the x86 version of PowerShell - if (platformDetails.operatingSystem == OperatingSystem.Windows) { + if (platformDetails.operatingSystem === OperatingSystem.Windows) { if (use32Bit) { powerShellExePath = platformDetails.isOS64Bit && platformDetails.isProcess64Bit ? SysWow64PowerShellPath - : System32PowerShellPath - } - else { + : System32PowerShellPath; + } else { powerShellExePath = !platformDetails.isOS64Bit || platformDetails.isProcess64Bit ? System32PowerShellPath - : SysnativePowerShellPath + : SysnativePowerShellPath; } - } - else if (platformDetails.operatingSystem == OperatingSystem.MacOS) { + } else if (platformDetails.operatingSystem === OperatingSystem.MacOS) { powerShellExePath = "/usr/local/bin/powershell"; if (fs.existsSync("/usr/local/bin/pwsh")) { powerShellExePath = "/usr/local/bin/pwsh"; } - } - else if (platformDetails.operatingSystem == OperatingSystem.Linux) { + } else if (platformDetails.operatingSystem === OperatingSystem.Linux) { powerShellExePath = "/usr/bin/powershell"; if (fs.existsSync("/usr/bin/pwsh")) { powerShellExePath = "/usr/bin/pwsh"; @@ -88,12 +83,12 @@ export function getDefaultPowerShellPath( } export function getWindowsSystemPowerShellPath(systemFolderName: string) { - return `${process.env.windir}\\${systemFolderName}\\WindowsPowerShell\\v1.0\\powershell.exe` + return `${process.env.windir}\\${systemFolderName}\\WindowsPowerShell\\v1.0\\powershell.exe`; } -export const System32PowerShellPath = getWindowsSystemPowerShellPath('System32'); -export const SysnativePowerShellPath = getWindowsSystemPowerShellPath('Sysnative'); -export const SysWow64PowerShellPath = getWindowsSystemPowerShellPath('SysWow64'); +export const System32PowerShellPath = getWindowsSystemPowerShellPath("System32"); +export const SysnativePowerShellPath = getWindowsSystemPowerShellPath("Sysnative"); +export const SysWow64PowerShellPath = getWindowsSystemPowerShellPath("SysWow64"); export const WindowsPowerShell64BitLabel = "Windows PowerShell (x64)"; export const WindowsPowerShell32BitLabel = "Windows PowerShell (x86)"; @@ -101,8 +96,8 @@ export const WindowsPowerShell32BitLabel = "Windows PowerShell (x86)"; const powerShell64BitPathOn32Bit = SysnativePowerShellPath.toLocaleLowerCase(); const powerShell32BitPathOn64Bit = SysWow64PowerShellPath.toLocaleLowerCase(); -export function fixWindowsPowerShellPath(powerShellExePath: string, platformDetails: PlatformDetails): string { - let lowerCasedPath = powerShellExePath.toLocaleLowerCase(); +export function fixWindowsPowerShellPath(powerShellExePath: string, platformDetails: IPlatformDetails): string { + const lowerCasedPath = powerShellExePath.toLocaleLowerCase(); if ((platformDetails.isProcess64Bit && (lowerCasedPath === powerShell64BitPathOn32Bit)) || (!platformDetails.isProcess64Bit && (lowerCasedPath === powerShell32BitPathOn64Bit))) { @@ -113,45 +108,44 @@ export function fixWindowsPowerShellPath(powerShellExePath: string, platformDeta return powerShellExePath; } -export function getAvailablePowerShellExes(platformDetails: PlatformDetails): PowerShellExeDetails[] { +export function getAvailablePowerShellExes(platformDetails: IPlatformDetails): IPowerShellExeDetails[] { - var paths: PowerShellExeDetails[] = []; + let paths: IPowerShellExeDetails[] = []; if (platformDetails.operatingSystem === OperatingSystem.Windows) { const psCoreInstallPath = - (!platformDetails.isProcess64Bit ? process.env.ProgramW6432 : process.env.ProgramFiles) + '\\PowerShell'; + (!platformDetails.isProcess64Bit ? process.env.ProgramW6432 : process.env.ProgramFiles) + "\\PowerShell"; if (platformDetails.isProcess64Bit) { paths.push({ versionName: WindowsPowerShell64BitLabel, - exePath: System32PowerShellPath - }) + exePath: System32PowerShellPath, + }); paths.push({ versionName: WindowsPowerShell32BitLabel, - exePath: SysWow64PowerShellPath - }) - } - else { + exePath: SysWow64PowerShellPath, + }); + } else { if (platformDetails.isOS64Bit) { paths.push({ versionName: WindowsPowerShell64BitLabel, - exePath: SysnativePowerShellPath - }) + exePath: SysnativePowerShellPath, + }); } paths.push({ versionName: WindowsPowerShell32BitLabel, - exePath: System32PowerShellPath - }) + exePath: System32PowerShellPath, + }); } if (fs.existsSync(psCoreInstallPath)) { - var psCorePaths = + const psCorePaths = fs.readdirSync(psCoreInstallPath) - .map(item => path.join(psCoreInstallPath, item)) - .filter(item => fs.lstatSync(item).isDirectory()) - .map(item => { + .map((item) => path.join(psCoreInstallPath, item)) + .filter((item) => fs.lstatSync(item).isDirectory()) + .map((item) => { let exePath = path.join(item, "pwsh.exe"); if (!fs.existsSync(exePath)) { exePath = path.join(item, "powershell.exe"); @@ -159,7 +153,7 @@ export function getAvailablePowerShellExes(platformDetails: PlatformDetails): Po return { versionName: `PowerShell Core ${path.parse(item).base}`, - exePath: exePath + exePath, }; }); @@ -167,12 +161,10 @@ export function getAvailablePowerShellExes(platformDetails: PlatformDetails): Po paths = paths.concat(psCorePaths); } } - } - else { - + } else { paths.push({ versionName: "PowerShell Core", - exePath: this.getDefaultPowerShellPath(platformDetails) + exePath: this.getDefaultPowerShellPath(platformDetails), }); } diff --git a/src/process.ts b/src/process.ts index 520b7ef288..da430334ab 100644 --- a/src/process.ts +++ b/src/process.ts @@ -2,25 +2,24 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import os = require('os'); -import fs = require('fs'); -import net = require('net'); -import path = require('path'); -import utils = require('./utils'); -import vscode = require('vscode'); -import cp = require('child_process'); -import Settings = require('./settings'); - -import { Logger } from './logging'; +import cp = require("child_process"); +import fs = require("fs"); +import net = require("net"); +import os = require("os"); +import path = require("path"); +import vscode = require("vscode"); +import { Logger } from "./logging"; +import Settings = require("./settings"); +import utils = require("./utils"); export class PowerShellProcess { + public onExited: vscode.Event; + private onExitedEmitter = new vscode.EventEmitter(); + private consoleTerminal: vscode.Terminal = undefined; private consoleCloseSubscription: vscode.Disposable; - private sessionDetails: utils.EditorServicesSessionDetails; - - private onExitedEmitter = new vscode.EventEmitter(); - public onExited: vscode.Event = this.onExitedEmitter.event; + private sessionDetails: utils.IEditorServicesSessionDetails; constructor( public exePath: string, @@ -29,46 +28,47 @@ export class PowerShellProcess { private startArgs: string, private sessionFilePath: string, private sessionSettings: Settings.ISettings) { + + this.onExited = this.onExitedEmitter.event; } - public start(logFileName: string): Thenable { + public start(logFileName: string): Thenable { - return new Promise( + return new Promise( (resolve, reject) => { - try - { - let startScriptPath = + try { + const startScriptPath = path.resolve( __dirname, - '../../scripts/Start-EditorServices.ps1'); + "../../scripts/Start-EditorServices.ps1"); - var editorServicesLogPath = this.log.getLogFilePath(logFileName); + const editorServicesLogPath = this.log.getLogFilePath(logFileName); - var featureFlags = + const featureFlags = this.sessionSettings.developer.featureFlags !== undefined - ? this.sessionSettings.developer.featureFlags.map(f => `'${f}'`).join(', ') + ? this.sessionSettings.developer.featureFlags.map((f) => `'${f}'`).join(", ") : ""; this.startArgs += `-LogPath '${editorServicesLogPath}' ` + `-SessionDetailsPath '${this.sessionFilePath}' ` + - `-FeatureFlags @(${featureFlags})` + `-FeatureFlags @(${featureFlags})`; - var powerShellArgs = [ + const powerShellArgs = [ "-NoProfile", - "-NonInteractive" - ] + "-NonInteractive", + ]; // Only add ExecutionPolicy param on Windows if (utils.isWindowsOS()) { - powerShellArgs.push("-ExecutionPolicy", "Bypass") + powerShellArgs.push("-ExecutionPolicy", "Bypass"); } powerShellArgs.push( "-Command", "& '" + startScriptPath + "' " + this.startArgs); - var powerShellExePath = this.exePath; + let powerShellExePath = this.exePath; if (this.sessionSettings.developer.powerShellExeIsWindowsDevBuild) { // Windows PowerShell development builds need the DEVPATH environment @@ -77,7 +77,7 @@ export class PowerShellProcess { // NOTE: This batch file approach is needed temporarily until VS Code's // createTerminal API gets an argument for setting environment variables // on the launched process. - var batScriptPath = path.resolve(__dirname, '../../sessions/powershell.bat'); + const batScriptPath = path.resolve(__dirname, "../../sessions/powershell.bat"); fs.writeFileSync( batScriptPath, `@set DEVPATH=${path.dirname(powerShellExePath)}\r\n@${powerShellExePath} %*`); @@ -88,7 +88,7 @@ export class PowerShellProcess { this.log.write( "Language server starting --", " exe: " + powerShellExePath, - " args: " + startScriptPath + ' ' + this.startArgs); + " args: " + startScriptPath + " " + this.startArgs); // Make sure no old session file exists utils.deleteSessionFile(this.sessionFilePath); @@ -113,43 +113,27 @@ export class PowerShellProcess { if (error) { reject(error); - } - else { + } else { this.sessionDetails = sessionDetails; resolve(this.sessionDetails); } }); - // this.powerShellProcess.stderr.on( - // 'data', - // (data) => { - // this.log.writeError("ERROR: " + data); - - // if (this.sessionStatus === SessionStatus.Initializing) { - // this.setSessionFailure("PowerShell could not be started, click 'Show Logs' for more details."); - // } - // else if (this.sessionStatus === SessionStatus.Running) { - // this.promptForRestart(); - // } - // }); - - this.consoleCloseSubscription = - vscode.window.onDidCloseTerminal( - terminal => { - if (terminal === this.consoleTerminal) { - this.log.write("powershell.exe terminated or terminal UI was closed"); - this.onExitedEmitter.fire(); - } - }); - - this.consoleTerminal.processId.then( - pid => { this.log.write(`powershell.exe started, pid: ${pid}`); }); - } - catch (e) - { - reject(e); - } - }); + this.consoleCloseSubscription = + vscode.window.onDidCloseTerminal( + (terminal) => { + if (terminal === this.consoleTerminal) { + this.log.write("powershell.exe terminated or terminal UI was closed"); + this.onExitedEmitter.fire(); + } + }); + + this.consoleTerminal.processId.then( + (pid) => { this.log.write(`powershell.exe started, pid: ${pid}`); }); + } catch (e) { + reject(e); + } + }); } public showConsole(preserveFocus: boolean) { diff --git a/src/session.ts b/src/session.ts index f5ab6760c1..6dba23798e 100644 --- a/src/session.ts +++ b/src/session.ts @@ -2,38 +2,35 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import os = require('os'); -import fs = require('fs'); -import net = require('net'); -import path = require('path'); -import utils = require('./utils'); -import vscode = require('vscode'); -import cp = require('child_process'); -import Settings = require('./settings'); - -import { Logger } from './logging'; -import { IFeature } from './feature'; -import { Message } from 'vscode-jsonrpc'; -import { PowerShellProcess } from './process'; -import { StringDecoder } from 'string_decoder'; +import cp = require("child_process"); +import fs = require("fs"); +import net = require("net"); +import os = require("os"); +import path = require("path"); +import { StringDecoder } from "string_decoder"; +import vscode = require("vscode"); +import { Message } from "vscode-jsonrpc"; +import { IFeature } from "./feature"; +import { Logger } from "./logging"; +import { PowerShellProcess } from "./process"; +import Settings = require("./settings"); +import utils = require("./utils"); import { - LanguageClient, LanguageClientOptions, Executable, - RequestType, RequestType0, NotificationType, - StreamInfo, ErrorAction, CloseAction, RevealOutputChannelOn, - Middleware, ResolveCodeLensSignature } from 'vscode-languageclient'; + CloseAction, ErrorAction, Executable, LanguageClient, LanguageClientOptions, + Middleware, NotificationType, RequestType, RequestType0, + ResolveCodeLensSignature, RevealOutputChannelOn, StreamInfo } from "vscode-languageclient"; import { - OperatingSystem, PlatformDetails, getDefaultPowerShellPath, - getPlatformDetails, fixWindowsPowerShellPath, - getAvailablePowerShellExes } from './platform'; + fixWindowsPowerShellPath, getAvailablePowerShellExes, getDefaultPowerShellPath, + getPlatformDetails, IPlatformDetails, OperatingSystem } from "./platform"; export enum SessionStatus { NotStarted, Initializing, Running, Stopping, - Failed + Failed, } export class SessionManager implements Middleware { @@ -46,16 +43,16 @@ export class SessionManager implements Middleware { private sessionStatus: SessionStatus; private suppressRestartPrompt: boolean; private focusConsoleOnExecute: boolean; - private platformDetails: PlatformDetails; + private platformDetails: IPlatformDetails; private extensionFeatures: IFeature[] = []; private statusBarItem: vscode.StatusBarItem; private languageServerProcess: PowerShellProcess; private debugSessionProcess: PowerShellProcess; - private versionDetails: PowerShellVersionDetails; + private versionDetails: IPowerShellVersionDetails; private registeredCommands: vscode.Disposable[] = []; private languageServerClient: LanguageClient = undefined; private sessionSettings: Settings.ISettings = undefined; - private sessionDetails: utils.EditorServicesSessionDetails; + private sessionDetails: utils.IEditorServicesSessionDetails; // When in development mode, VS Code's session ID is a fake // value of "someValue.machineId". Use that to detect dev @@ -77,8 +74,8 @@ export class SessionManager implements Middleware { .packageJSON .version; - let osBitness = this.platformDetails.isOS64Bit ? "64-bit" : "32-bit"; - let procBitness = this.platformDetails.isProcess64Bit ? "64-bit" : "32-bit"; + const osBitness = this.platformDetails.isOS64Bit ? "64-bit" : "32-bit"; + const procBitness = this.platformDetails.isProcess64Bit ? "64-bit" : "32-bit"; this.log.write( `Visual Studio Code v${vscode.version} ${procBitness}`, @@ -88,11 +85,19 @@ export class SessionManager implements Middleware { // Fix the host version so that PowerShell can consume it. // This is needed when the extension uses a prerelease // version string like 0.9.1-insiders-1234. - this.hostVersion = this.hostVersion.split('-')[0]; + this.hostVersion = this.hostVersion.split("-")[0]; this.registerCommands(); } + public dispose(): void { + // Stop the current session + this.stop(); + + // Dispose of all commands + this.registeredCommands.forEach((command) => { command.dispose(); }); + } + public setExtensionFeatures(extensionFeatures: IFeature[]) { this.extensionFeatures = extensionFeatures; } @@ -109,25 +114,28 @@ export class SessionManager implements Middleware { // Check for OpenSSL dependency on macOS when running PowerShell Core alpha. Look for the default // Homebrew installation path and if that fails check the system-wide library path. - if (os.platform() == "darwin" && this.getPowerShellVersionLabel() == "alpha") { + if (os.platform() === "darwin" && this.getPowerShellVersionLabel() === "alpha") { if (!(utils.checkIfFileExists("/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib") && utils.checkIfFileExists("/usr/local/opt/openssl/lib/libssl.1.0.0.dylib")) && !(utils.checkIfFileExists("/usr/local/lib/libcrypto.1.0.0.dylib") && utils.checkIfFileExists("/usr/local/lib/libssl.1.0.0.dylib"))) { - var thenable = + const thenable = vscode.window.showWarningMessage( - "The PowerShell extension will not work without OpenSSL on macOS and OS X when using PowerShell alpha", + "The PowerShell extension will not work without OpenSSL on macOS and OS X when using " + + "PowerShell Core alpha", "Show Documentation"); thenable.then( (s) => { if (s === "Show Documentation") { - cp.exec("open https://github.com/PowerShell/vscode-powershell/blob/master/docs/troubleshooting.md#1-powershell-intellisense-does-not-work-cant-debug-scripts"); + cp.exec("open https://github.com/PowerShell/vscode-powershell/blob/master/docs/" + + "troubleshooting.md#1-powershell-intellisense-does-not-work-cant-debug-scripts"); } }); // Don't continue initializing since Editor Services will not load successfully - this.setSessionFailure("Cannot start PowerShell Editor Services due to missing OpenSSL dependency."); + this.setSessionFailure( + "Cannot start PowerShell Editor Services due to missing OpenSSL dependency."); return; } } @@ -136,11 +144,10 @@ export class SessionManager implements Middleware { if (this.powerShellExePath) { - var bundledModulesPath = path.resolve(__dirname, "../../modules"); + let bundledModulesPath = path.resolve(__dirname, "../../modules"); if (this.inDevelopmentMode) { - var devBundledModulesPath = - // this.sessionSettings.developer.bundledModulesPath || + const devBundledModulesPath = path.resolve( __dirname, this.sessionSettings.developer.bundledModulesPath || @@ -149,10 +156,10 @@ export class SessionManager implements Middleware { // Make sure the module's bin path exists if (fs.existsSync(path.join(devBundledModulesPath, "PowerShellEditorServices/bin"))) { bundledModulesPath = devBundledModulesPath; - } - else { + } else { this.log.write( - `\nWARNING: In development mode but PowerShellEditorServices dev module path cannot be found (or has not been built yet): ${devBundledModulesPath}\n`); + "\nWARNING: In development mode but PowerShellEditorServices dev module path cannot be " + + `found (or has not been built yet): ${devBundledModulesPath}\n`); } } @@ -166,10 +173,10 @@ export class SessionManager implements Middleware { "-EnableConsoleRepl "; if (this.sessionSettings.developer.editorServicesWaitForDebugger) { - this.editorServicesArgs += '-WaitForDebugger '; + this.editorServicesArgs += "-WaitForDebugger "; } if (this.sessionSettings.developer.editorServicesLogLevel) { - this.editorServicesArgs += "-LogLevel '" + this.sessionSettings.developer.editorServicesLogLevel + "' " + this.editorServicesArgs += "-LogLevel '" + this.sessionSettings.developer.editorServicesLogLevel + "' "; } this.startPowerShell( @@ -177,8 +184,7 @@ export class SessionManager implements Middleware { this.sessionSettings.developer.powerShellExeIsWindowsDevBuild, bundledModulesPath, this.editorServicesArgs); - } - else { + } else { this.setSessionFailure("PowerShell could not be started, click 'Show Logs' for more details."); } } @@ -214,22 +220,14 @@ export class SessionManager implements Middleware { this.sessionStatus = SessionStatus.NotStarted; } - public getSessionDetails(): utils.EditorServicesSessionDetails { + public getSessionDetails(): utils.IEditorServicesSessionDetails { return this.sessionDetails; } - public getPowerShellVersionDetails() : PowerShellVersionDetails { + public getPowerShellVersionDetails(): IPowerShellVersionDetails { return this.versionDetails; } - public dispose() : void { - // Stop the current session - this.stop(); - - // Dispose of all commands - this.registeredCommands.forEach(command => { command.dispose(); }); - } - public createDebugSessionProcess( sessionPath: string, sessionSettings: Settings.ISettings): PowerShellProcess { @@ -246,8 +244,153 @@ export class SessionManager implements Middleware { return this.debugSessionProcess; } + public getPowerShellExePath(): string { + + if (!this.sessionSettings.powerShellExePath && + this.sessionSettings.developer.powerShellExePath) { + // Show deprecation message with fix action. + // We don't need to wait on this to complete + // because we can finish gathering the configured + // PowerShell path without the fix + vscode + .window + .showWarningMessage( + "The 'powershell.developer.powerShellExePath' setting is deprecated, use " + + "'powershell.powerShellExePath' instead.", + "Fix Automatically") + .then((choice) => { + if (choice) { + this.suppressRestartPrompt = true; + Settings + .change( + "powerShellExePath", + this.sessionSettings.developer.powerShellExePath, + true) + .then(() => { + return Settings.change( + "developer.powerShellExePath", + undefined, + true); + }) + .then(() => { + this.suppressRestartPrompt = false; + }); + } + }); + } + + // Is there a setting override for the PowerShell path? + let powerShellExePath = + (this.sessionSettings.powerShellExePath || + this.sessionSettings.developer.powerShellExePath || + "").trim(); + + // New versions of PS Core uninstall the previous version + // so make sure the path stored in the settings exists. + if (!fs.existsSync(powerShellExePath)) { + this.log.write( + `Path specified by 'powerShellExePath' setting - '${powerShellExePath}' - not found, ` + + "reverting to default PowerShell path."); + powerShellExePath = ""; + } + + if (this.platformDetails.operatingSystem === OperatingSystem.Windows && + powerShellExePath.length > 0) { + + // Check the path bitness + const fixedPath = + fixWindowsPowerShellPath( + powerShellExePath, + this.platformDetails); + + if (fixedPath !== powerShellExePath) { + const bitness = this.platformDetails.isOS64Bit ? 64 : 32; + // Show deprecation message with fix action. + // We don't need to wait on this to complete + // because we can finish gathering the configured + // PowerShell path without the fix + vscode + .window + .showWarningMessage( + `The specified PowerShell path is incorrect for ${bitness}-bit VS Code, using '${fixedPath}' ` + + "instead.", + "Fix Setting Automatically") + .then((choice) => { + if (choice) { + this.suppressRestartPrompt = true; + Settings + .change( + "powerShellExePath", + this.sessionSettings.developer.powerShellExePath, + true) + .then(() => { + return Settings.change( + "developer.powerShellExePath", + undefined, + true); + }) + .then(() => { + this.suppressRestartPrompt = false; + }); + } + }); + + powerShellExePath = fixedPath; + } + } + + return powerShellExePath.length > 0 + ? this.resolvePowerShellPath(powerShellExePath) + : getDefaultPowerShellPath(this.platformDetails, this.sessionSettings.useX86Host); + } + + // ----- LanguageClient middleware methods ----- + + public resolveCodeLens( + codeLens: vscode.CodeLens, + token: vscode.CancellationToken, + next: ResolveCodeLensSignature): vscode.ProviderResult { + const resolvedCodeLens = next(codeLens, token); + const resolveFunc = + (codeLensToFix: vscode.CodeLens): vscode.CodeLens => { + if (codeLensToFix.command.command === "editor.action.showReferences") { + const oldArgs = codeLensToFix.command.arguments; + + // Our JSON objects don't get handled correctly by + // VS Code's built in editor.action.showReferences + // command so we need to convert them into the + // appropriate types to send them as command + // arguments. + + codeLensToFix.command.arguments = [ + vscode.Uri.parse(oldArgs[0]), + new vscode.Position(oldArgs[1].line, oldArgs[1].character), + oldArgs[2].map((position) => { + return new vscode.Location( + vscode.Uri.parse(position.uri), + new vscode.Range( + position.range.start.line, + position.range.start.character, + position.range.end.line, + position.range.end.character)); + }), + ]; + } + + return codeLensToFix; + }; + + if ((resolvedCodeLens as Thenable).then) { + return (resolvedCodeLens as Thenable).then(resolveFunc); + } else if (resolvedCodeLens as vscode.CodeLens) { + return resolveFunc(resolvedCodeLens as vscode.CodeLens); + } + + return resolvedCodeLens; + } + private onConfigurationUpdated() { - var settings = Settings.load(); + const settings = Settings.load(); this.focusConsoleOnExecute = settings.integratedConsole.focusConsoleOnExecute; @@ -255,9 +398,12 @@ export class SessionManager implements Middleware { if (!this.suppressRestartPrompt && (settings.useX86Host !== this.sessionSettings.useX86Host || settings.powerShellExePath.toLowerCase() !== this.sessionSettings.powerShellExePath.toLowerCase() || - settings.developer.powerShellExePath.toLowerCase() !== this.sessionSettings.developer.powerShellExePath.toLowerCase() || - settings.developer.editorServicesLogLevel.toLowerCase() !== this.sessionSettings.developer.editorServicesLogLevel.toLowerCase() || - settings.developer.bundledModulesPath.toLowerCase() !== this.sessionSettings.developer.bundledModulesPath.toLowerCase())) { + settings.developer.powerShellExePath.toLowerCase() !== + this.sessionSettings.developer.powerShellExePath.toLowerCase() || + settings.developer.editorServicesLogLevel.toLowerCase() !== + this.sessionSettings.developer.editorServicesLogLevel.toLowerCase() || + settings.developer.bundledModulesPath.toLowerCase() !== + this.sessionSettings.developer.bundledModulesPath.toLowerCase())) { vscode.window.showInformationMessage( "The PowerShell runtime configuration has changed, would you like to start a new session?", @@ -270,16 +416,17 @@ export class SessionManager implements Middleware { } } - private setStatusBarVersionString( - runspaceDetails: RunspaceDetails) { + private setStatusBarVersionString(runspaceDetails: IRunspaceDetails) { + + const psVersion = runspaceDetails.powerShellVersion; - var versionString = + let versionString = this.versionDetails.architecture === "x86" - ? `${runspaceDetails.powerShellVersion.displayVersion} (${runspaceDetails.powerShellVersion.architecture})` - : runspaceDetails.powerShellVersion.displayVersion; + ? `${psVersion.displayVersion} (${psVersion.architecture})` + : psVersion.displayVersion; - if (runspaceDetails.runspaceType != RunspaceType.Local) { - versionString += ` [${runspaceDetails.connectionString}]` + if (runspaceDetails.runspaceType !== RunspaceType.Local) { + versionString += ` [${runspaceDetails.connectionString}]`; } this.setSessionStatus( @@ -287,13 +434,14 @@ export class SessionManager implements Middleware { SessionStatus.Running); } - private registerCommands() : void { + private registerCommands(): void { this.registeredCommands = [ - vscode.commands.registerCommand('PowerShell.RestartSession', () => { this.restartSession(); }), + vscode.commands.registerCommand("PowerShell.RestartSession", () => { this.restartSession(); }), vscode.commands.registerCommand(this.ShowSessionMenuCommandName, () => { this.showSessionMenu(); }), vscode.workspace.onDidChangeConfiguration(() => this.onConfigurationUpdated()), - vscode.commands.registerCommand('PowerShell.ShowSessionConsole', (isExecute?: boolean) => { this.showSessionConsole(isExecute); }) - ] + vscode.commands.registerCommand( + "PowerShell.ShowSessionConsole", (isExecute?: boolean) => { this.showSessionConsole(isExecute); }), + ]; } private startPowerShell( @@ -306,7 +454,7 @@ export class SessionManager implements Middleware { "Starting PowerShell...", SessionStatus.Initializing); - var sessionFilePath = + const sessionFilePath = utils.getSessionFilePath( Math.floor(100000 + Math.random() * 900000)); @@ -330,7 +478,7 @@ export class SessionManager implements Middleware { this.languageServerProcess .start("EditorServices") .then( - sessionDetails => { + (sessionDetails) => { this.sessionDetails = sessionDetails; if (sessionDetails.status === "started") { @@ -338,28 +486,27 @@ export class SessionManager implements Middleware { // Start the language service client this.startLanguageClient(sessionDetails); - } - else if (sessionDetails.status === "failed") { + } else if (sessionDetails.status === "failed") { if (sessionDetails.reason === "unsupported") { this.setSessionFailure( - `PowerShell language features are only supported on PowerShell version 3 and above. The current version is ${sessionDetails.powerShellVersion}.`) - } - else if (sessionDetails.reason === "languageMode") { + "PowerShell language features are only supported on PowerShell version 3 and above. " + + `The current version is ${sessionDetails.powerShellVersion}.`); + } else if (sessionDetails.reason === "languageMode") { this.setSessionFailure( - `PowerShell language features are disabled due to an unsupported LanguageMode: ${sessionDetails.detail}`); - } - else { - this.setSessionFailure(`PowerShell could not be started for an unknown reason '${sessionDetails.reason}'`) + "PowerShell language features are disabled due to an unsupported LanguageMode: " + + `${sessionDetails.detail}`); + } else { + this.setSessionFailure( + `PowerShell could not be started for an unknown reason '${sessionDetails.reason}'`); } - } - else { + } else { // TODO: Handle other response cases } }, - error => { + (error) => { this.log.write("Language server startup failed."); this.setSessionFailure("The language service could not be started: ", error); - } + }, ); } @@ -370,35 +517,34 @@ export class SessionManager implements Middleware { .then((answer) => { if (answer === "Yes") { this.restartSession(); }}); } - private startLanguageClient(sessionDetails: utils.EditorServicesSessionDetails) { + private startLanguageClient(sessionDetails: utils.IEditorServicesSessionDetails) { - var port = sessionDetails.languageServicePort; + const port = sessionDetails.languageServicePort; // Log the session details object this.log.write(JSON.stringify(sessionDetails)); - try - { + try { this.log.write("Connecting to language service on port " + port + "..."); - let connectFunc = () => { + const connectFunc = () => { return new Promise( (resolve, reject) => { - var socket = net.connect(port); + const socket = net.connect(port); socket.on( - 'connect', + "connect", () => { this.log.write("Language service connected."); - resolve({writer: socket, reader: socket}) + resolve({writer: socket, reader: socket}); }); }); }; - let clientOptions: LanguageClientOptions = { + const clientOptions: LanguageClientOptions = { documentSelector: [utils.PowerShellLanguageId], synchronize: { configurationSection: utils.PowerShellLanguageId, - //fileEvents: vscode.workspace.createFileSystemWatcher('**/.eslintrc') + // fileEvents: vscode.workspace.createFileSystemWatcher('**/.eslintrc') }, errorHandler: { // Override the default error handler to prevent it from @@ -410,23 +556,23 @@ export class SessionManager implements Middleware { }, closed: () => { // We have our own restart experience - return CloseAction.DoNotRestart - } + return CloseAction.DoNotRestart; + }, }, revealOutputChannelOn: RevealOutputChannelOn.Never, - middleware: this - } + middleware: this, + }; this.languageServerClient = new LanguageClient( - 'PowerShell Editor Services', + "PowerShell Editor Services", connectFunc, clientOptions); this.languageServerClient.onReady().then( () => { this.languageServerClient - .sendRequest(PowerShellVersionRequest.type) + .sendRequest(PowerShellVersionRequestType) .then( (versionDetails) => { this.versionDetails = versionDetails; @@ -442,24 +588,21 @@ export class SessionManager implements Middleware { // before the connection is established. this.updateExtensionFeatures(this.languageServerClient); this.languageServerClient.onNotification( - RunspaceChangedEvent.type, + RunspaceChangedEventType, (runspaceDetails) => { this.setStatusBarVersionString(runspaceDetails); }); }, (reason) => { this.setSessionFailure("Could not start language service: ", reason); }); - this.languageServerClient.start(); - } - catch (e) - { + } catch (e) { this.setSessionFailure("The language service could not be started: ", e); } } private updateExtensionFeatures(languageClient: LanguageClient) { - this.extensionFeatures.forEach(feature => { + this.extensionFeatures.forEach((feature) => { feature.setLanguageClient(languageClient); }); } @@ -481,28 +624,26 @@ export class SessionManager implements Middleware { this.statusBarItem.command = this.ShowSessionMenuCommandName; this.statusBarItem.tooltip = "Show PowerShell Session Menu"; this.statusBarItem.show(); - vscode.window.onDidChangeActiveTextEditor(textEditor => { + vscode.window.onDidChangeActiveTextEditor((textEditor) => { if (textEditor === undefined || textEditor.document.languageId !== "powershell") { this.statusBarItem.hide(); - } - else { + } else { this.statusBarItem.show(); } - }) + }); } } private setSessionStatus(statusText: string, status: SessionStatus): void { // Set color and icon for 'Running' by default - var statusIconText = "$(terminal) "; - var statusColor = "#affc74"; + let statusIconText = "$(terminal) "; + let statusColor = "#affc74"; - if (status == SessionStatus.Initializing) { + if (status === SessionStatus.Initializing) { statusIconText = "$(sync) "; statusColor = "#f3fc74"; - } - else if (status == SessionStatus.Failed) { + } else if (status === SessionStatus.Failed) { statusIconText = "$(alert) "; statusColor = "#fcc174"; } @@ -520,104 +661,6 @@ export class SessionManager implements Middleware { SessionStatus.Failed); } - public getPowerShellExePath(): string { - - if (!this.sessionSettings.powerShellExePath && - this.sessionSettings.developer.powerShellExePath) - { - // Show deprecation message with fix action. - // We don't need to wait on this to complete - // because we can finish gathering the configured - // PowerShell path without the fix - vscode - .window - .showWarningMessage( - "The 'powershell.developer.powerShellExePath' setting is deprecated, use 'powershell.powerShellExePath' instead.", - "Fix Automatically") - .then(choice => { - if (choice) { - this.suppressRestartPrompt = true; - Settings - .change( - "powerShellExePath", - this.sessionSettings.developer.powerShellExePath, - true) - .then(() => { - return Settings.change( - "developer.powerShellExePath", - undefined, - true) - }) - .then(() => { - this.suppressRestartPrompt = false; - }); - } - }); - } - - // Is there a setting override for the PowerShell path? - var powerShellExePath = - (this.sessionSettings.powerShellExePath || - this.sessionSettings.developer.powerShellExePath || - "").trim(); - - // New versions of PS Core uninstall the previous version - // so make sure the path stored in the settings exists. - if (!fs.existsSync(powerShellExePath)) { - this.log.write( - `Path specified by 'powerShellExePath' setting - '${powerShellExePath}' - not found, reverting to default PowerShell path.`); - powerShellExePath = ""; - } - - if (this.platformDetails.operatingSystem === OperatingSystem.Windows && - powerShellExePath.length > 0) { - - // Check the path bitness - let fixedPath = - fixWindowsPowerShellPath( - powerShellExePath, - this.platformDetails); - - if (fixedPath !== powerShellExePath) { - let bitness = this.platformDetails.isOS64Bit ? 64 : 32; - // Show deprecation message with fix action. - // We don't need to wait on this to complete - // because we can finish gathering the configured - // PowerShell path without the fix - vscode - .window - .showWarningMessage( - `The specified PowerShell path is incorrect for ${bitness}-bit VS Code, using '${fixedPath}' instead.`, - "Fix Setting Automatically") - .then(choice => { - if (choice) { - this.suppressRestartPrompt = true; - Settings - .change( - "powerShellExePath", - this.sessionSettings.developer.powerShellExePath, - true) - .then(() => { - return Settings.change( - "developer.powerShellExePath", - undefined, - true) - }) - .then(() => { - this.suppressRestartPrompt = false; - }); - } - }); - - powerShellExePath = fixedPath; - } - } - - return powerShellExePath.length > 0 - ? this.resolvePowerShellPath(powerShellExePath) - : getDefaultPowerShellPath(this.platformDetails, this.sessionSettings.useX86Host); - } - private changePowerShellExePath(exePath: string) { this.suppressRestartPrompt = true; Settings @@ -626,7 +669,7 @@ export class SessionManager implements Middleware { } private resolvePowerShellPath(powerShellExePath: string): string { - var resolvedPath = path.resolve(__dirname, powerShellExePath); + const resolvedPath = path.resolve(__dirname, powerShellExePath); // If the path does not exist, show an error if (!utils.checkIfFileExists(resolvedPath)) { @@ -641,26 +684,25 @@ export class SessionManager implements Middleware { private getPowerShellVersionLabel(): string { if (this.powerShellExePath) { - var powerShellCommandLine = [ + const powerShellCommandLine = [ this.powerShellExePath, "-NoProfile", - "-NonInteractive" + "-NonInteractive", ]; // Only add ExecutionPolicy param on Windows if (utils.isWindowsOS()) { - powerShellCommandLine.push("-ExecutionPolicy", "Bypass") + powerShellCommandLine.push("-ExecutionPolicy", "Bypass"); } powerShellCommandLine.push( "-Command", "'$PSVersionTable | ConvertTo-Json'"); - var powerShellOutput = cp.execSync(powerShellCommandLine.join(' ')); - var versionDetails = JSON.parse(powerShellOutput.toString()); + const powerShellOutput = cp.execSync(powerShellCommandLine.join(" ")); + const versionDetails = JSON.parse(powerShellOutput.toString()); return versionDetails.PSVersion.Label; - } - else { + } else { // TODO: throw instead? return null; } @@ -668,26 +710,26 @@ export class SessionManager implements Middleware { private showSessionConsole(isExecute?: boolean) { if (this.languageServerProcess) { - this.languageServerProcess.showConsole( - isExecute && !this.focusConsoleOnExecute); + this.languageServerProcess.showConsole(isExecute && !this.focusConsoleOnExecute); } } private showSessionMenu() { - var menuItems: SessionMenuItem[] = []; + let menuItems: SessionMenuItem[] = []; if (this.sessionStatus === SessionStatus.Running) { menuItems = [ new SessionMenuItem( - `Current session: PowerShell ${this.versionDetails.displayVersion} (${this.versionDetails.architecture}) ${this.versionDetails.edition} Edition [${this.versionDetails.version}]`, + `Current session: PowerShell ${this.versionDetails.displayVersion} ` + + `(${this.versionDetails.architecture}) ${this.versionDetails.edition} Edition ` + + `[${this.versionDetails.version}]`, () => { vscode.commands.executeCommand("PowerShell.ShowLogs"); }), new SessionMenuItem( "Restart Current Session", () => { this.restartSession(); }), ]; - } - else if (this.sessionStatus === SessionStatus.Failed) { + } else if (this.sessionStatus === SessionStatus.Failed) { menuItems = [ new SessionMenuItem( `Session initialization failed, click here to show PowerShell extension logs`, @@ -695,14 +737,14 @@ export class SessionManager implements Middleware { ]; } - var currentExePath = (this.powerShellExePath || "").toLowerCase(); - var powerShellItems = + const currentExePath = (this.powerShellExePath || "").toLowerCase(); + const powerShellItems = getAvailablePowerShellExes(this.platformDetails) - .filter(item => item.exePath.toLowerCase() !== currentExePath) - .map(item => { + .filter((item) => item.exePath.toLowerCase() !== currentExePath) + .map((item) => { return new SessionMenuItem( `Switch to ${item.versionName}`, - () => { this.changePowerShellExePath(item.exePath) }); + () => { this.changePowerShellExePath(item.exePath); }); }); menuItems = menuItems.concat(powerShellItems); @@ -717,53 +759,6 @@ export class SessionManager implements Middleware { .showQuickPick(menuItems) .then((selectedItem) => { selectedItem.callback(); }); } - - // ----- LanguageClient middleware methods ----- - - resolveCodeLens( - codeLens: vscode.CodeLens, - token: vscode.CancellationToken, - next: ResolveCodeLensSignature): vscode.ProviderResult { - var resolvedCodeLens = next(codeLens, token); - - let resolveFunc = - (codeLens: vscode.CodeLens): vscode.CodeLens => { - if (codeLens.command.command === "editor.action.showReferences") { - var oldArgs = codeLens.command.arguments; - - // Our JSON objects don't get handled correctly by - // VS Code's built in editor.action.showReferences - // command so we need to convert them into the - // appropriate types to send them as command - // arguments. - - codeLens.command.arguments = [ - vscode.Uri.parse(oldArgs[0]), - new vscode.Position(oldArgs[1].line, oldArgs[1].character), - oldArgs[2].map(position => { - return new vscode.Location( - vscode.Uri.parse(position.uri), - new vscode.Range( - position.range.start.line, - position.range.start.character, - position.range.end.line, - position.range.end.character)); - }) - ] - } - - return codeLens; - } - - if ((>resolvedCodeLens).then) { - return (>resolvedCodeLens).then(resolveFunc); - } - else if (resolvedCodeLens) { - return resolveFunc(resolvedCodeLens); - } - - return resolvedCodeLens; - } } class SessionMenuItem implements vscode.QuickPickItem { @@ -771,34 +766,34 @@ class SessionMenuItem implements vscode.QuickPickItem { constructor( public readonly label: string, - public readonly callback: () => void = () => { }) - { + // tslint:disable-next-line:no-empty + public readonly callback: () => void = () => {}) { } } -export namespace PowerShellVersionRequest { - export const type = new RequestType0('powerShell/getVersion'); +export const PowerShellVersionRequestType = + new RequestType0( + "powerShell/getVersion"); + +export const RunspaceChangedEventType = + new NotificationType( + "powerShell/runspaceChanged"); + +export enum RunspaceType { + Local, + Process, + Remote, } -export interface PowerShellVersionDetails { +export interface IPowerShellVersionDetails { version: string; displayVersion: string; edition: string; architecture: string; } -export enum RunspaceType { - Local, - Process, - Remote -} - -export interface RunspaceDetails { - powerShellVersion: PowerShellVersionDetails; +export interface IRunspaceDetails { + powerShellVersion: IPowerShellVersionDetails; runspaceType: RunspaceType; connectionString: string; } - -export namespace RunspaceChangedEvent { - export const type = new NotificationType('powerShell/runspaceChanged'); -} diff --git a/src/settings.ts b/src/settings.ts index 4f9e3a6ad9..a9a626562c 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -2,16 +2,16 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -'use strict'; +"use strict"; -import vscode = require('vscode'); -import utils = require('./utils'); +import vscode = require("vscode"); +import utils = require("./utils"); enum CodeFormattingPreset { Custom, Allman, OTBS, - Stroustrup + Stroustrup, } export interface IBugReportingSettings { @@ -59,7 +59,7 @@ export interface ISettings { developer?: IDeveloperSettings; codeFormatting?: ICodeFormattingSettings; integratedConsole?: IIntegratedConsoleSettings; - bugReporting?: IBugReportingSettings + bugReporting?: IBugReportingSettings; } export interface IIntegratedConsoleSettings { @@ -68,33 +68,33 @@ export interface IIntegratedConsoleSettings { } export function load(): ISettings { - let configuration: vscode.WorkspaceConfiguration = + const configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration( utils.PowerShellLanguageId); - let defaultBugReportingSettings: IBugReportingSettings = { - project: "https://github.com/PowerShell/vscode-powershell" + const defaultBugReportingSettings: IBugReportingSettings = { + project: "https://github.com/PowerShell/vscode-powershell", }; - let defaultScriptAnalysisSettings: IScriptAnalysisSettings = { + const defaultScriptAnalysisSettings: IScriptAnalysisSettings = { enable: true, - settingsPath: "" + settingsPath: "", }; - let defaultDebuggingSettings: IDebuggingSettings = { + const defaultDebuggingSettings: IDebuggingSettings = { createTemporaryIntegratedConsole: false, }; - let defaultDeveloperSettings: IDeveloperSettings = { + const defaultDeveloperSettings: IDeveloperSettings = { featureFlags: [], powerShellExePath: undefined, bundledModulesPath: undefined, editorServicesLogLevel: "Normal", editorServicesWaitForDebugger: false, - powerShellExeIsWindowsDevBuild: false + powerShellExeIsWindowsDevBuild: false, }; - let defaultCodeFormattingSettings: ICodeFormattingSettings = { + const defaultCodeFormattingSettings: ICodeFormattingSettings = { preset: CodeFormattingPreset.Custom, openBraceOnSameLine: true, newLineAfterOpenBrace: true, @@ -104,30 +104,40 @@ export function load(): ISettings { whitespaceAroundOperator: true, whitespaceAfterSeparator: true, ignoreOneLineBlock: true, - alignPropertyValuePairs: true + alignPropertyValuePairs: true, }; - let defaultIntegratedConsoleSettings: IIntegratedConsoleSettings = { + const defaultIntegratedConsoleSettings: IIntegratedConsoleSettings = { showOnStartup: true, - focusConsoleOnExecute: true + focusConsoleOnExecute: true, }; return { - startAutomatically: configuration.get("startAutomatically", true), - powerShellExePath: configuration.get("powerShellExePath", undefined), - useX86Host: configuration.get("useX86Host", false), - enableProfileLoading: configuration.get("enableProfileLoading", false), - scriptAnalysis: configuration.get("scriptAnalysis", defaultScriptAnalysisSettings), - debugging: configuration.get("debugging", defaultDebuggingSettings), - developer: configuration.get("developer", defaultDeveloperSettings), - codeFormatting: configuration.get("codeFormatting", defaultCodeFormattingSettings), - integratedConsole: configuration.get("integratedConsole", defaultIntegratedConsoleSettings), - bugReporting: configuration.get("bugReporting", defaultBugReportingSettings) + startAutomatically: + configuration.get("startAutomatically", true), + powerShellExePath: + configuration.get("powerShellExePath", undefined), + useX86Host: + configuration.get("useX86Host", false), + enableProfileLoading: + configuration.get("enableProfileLoading", false), + scriptAnalysis: + configuration.get("scriptAnalysis", defaultScriptAnalysisSettings), + debugging: + configuration.get("debugging", defaultDebuggingSettings), + developer: + configuration.get("developer", defaultDeveloperSettings), + codeFormatting: + configuration.get("codeFormatting", defaultCodeFormattingSettings), + integratedConsole: + configuration.get("integratedConsole", defaultIntegratedConsoleSettings), + bugReporting: + configuration.get("bugReporting", defaultBugReportingSettings), }; } export function change(settingName: string, newValue: any, global: boolean = false): Thenable { - let configuration: vscode.WorkspaceConfiguration = + const configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration( utils.PowerShellLanguageId); diff --git a/src/utils.ts b/src/utils.ts index edffeb1d90..65ec4332bc 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,31 +1,35 @@ -import fs = require('fs'); -import os = require('os'); -import path = require('path'); +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ -export let PowerShellLanguageId = 'powershell'; +"use strict"; + +import fs = require("fs"); +import os = require("os"); +import path = require("path"); + +export let PowerShellLanguageId = "powershell"; export function ensurePathExists(targetPath: string) { // Ensure that the path exists try { fs.mkdirSync(targetPath); - } - catch (e) { - // If the exception isn't to indicate that the folder - // exists already, rethrow it. - if (e.code != 'EEXIST') { + } catch (e) { + // If the exception isn't to indicate that the folder exists already, rethrow it. + if (e.code !== "EEXIST") { throw e; } } } export function getPipePath(pipeName: string) { - if (os.platform() == "win32") { + if (os.platform() === "win32") { return "\\\\.\\pipe\\" + pipeName; - } - else { + } else { // On UNIX platforms the pipe will live under the temp path // For details on how this path is computed, see the corefx // source for System.IO.Pipes.PipeStream: + // tslint:disable-next-line:max-line-length // https://github.com/dotnet/corefx/blob/d0dc5fc099946adc1035b34a8b1f6042eddb0c75/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs#L340 return path.resolve( os.tmpdir(), @@ -34,7 +38,7 @@ export function getPipePath(pipeName: string) { } } -export interface EditorServicesSessionDetails { +export interface IEditorServicesSessionDetails { status: string; reason: string; detail: string; @@ -44,16 +48,11 @@ export interface EditorServicesSessionDetails { debugServicePort: number; } -export interface ReadSessionFileCallback { - (details: EditorServicesSessionDetails): void; -} - -export interface WaitForSessionFileCallback { - (details: EditorServicesSessionDetails, error: string): void; -} +export type IReadSessionFileCallback = (details: IEditorServicesSessionDetails) => void; +export type IWaitForSessionFileCallback = (details: IEditorServicesSessionDetails, error: string) => void; -let sessionsFolder = path.resolve(__dirname, "..", "..", "sessions/"); -let sessionFilePathPrefix = path.resolve(sessionsFolder, "PSES-VSCode-" + process.env.VSCODE_PID); +const sessionsFolder = path.resolve(__dirname, "..", "..", "sessions/"); +const sessionFilePathPrefix = path.resolve(sessionsFolder, "PSES-VSCode-" + process.env.VSCODE_PID); // Create the sessions path if it doesn't exist already ensurePathExists(sessionsFolder); @@ -66,27 +65,25 @@ export function getDebugSessionFilePath() { return `${sessionFilePathPrefix}-Debug`; } -export function writeSessionFile(sessionFilePath: string, sessionDetails: EditorServicesSessionDetails) { +export function writeSessionFile(sessionFilePath: string, sessionDetails: IEditorServicesSessionDetails) { ensurePathExists(sessionsFolder); - var writeStream = fs.createWriteStream(sessionFilePath); + const writeStream = fs.createWriteStream(sessionFilePath); writeStream.write(JSON.stringify(sessionDetails)); writeStream.close(); } -export function waitForSessionFile(sessionFilePath: string, callback: WaitForSessionFileCallback) { +export function waitForSessionFile(sessionFilePath: string, callback: IWaitForSessionFileCallback) { function innerTryFunc(remainingTries: number, delayMilliseconds: number) { - if (remainingTries == 0) { + if (remainingTries === 0) { callback(undefined, "Timed out waiting for session file to appear."); - } - else if(!checkIfFileExists(sessionFilePath)) { + } else if (!checkIfFileExists(sessionFilePath)) { // Wait a bit and try again setTimeout( - function() { innerTryFunc(remainingTries - 1, delayMilliseconds); }, + () => { innerTryFunc(remainingTries - 1, delayMilliseconds); }, delayMilliseconds); - } - else { + } else { // Session file was found, load and return it callback(readSessionFile(sessionFilePath), undefined); } @@ -96,35 +93,33 @@ export function waitForSessionFile(sessionFilePath: string, callback: WaitForSes innerTryFunc(60, 1000); } -export function readSessionFile(sessionFilePath: string): EditorServicesSessionDetails { - let fileContents = fs.readFileSync(sessionFilePath, "utf-8"); - return JSON.parse(fileContents) +export function readSessionFile(sessionFilePath: string): IEditorServicesSessionDetails { + const fileContents = fs.readFileSync(sessionFilePath, "utf-8"); + return JSON.parse(fileContents); } export function deleteSessionFile(sessionFilePath: string) { try { fs.unlinkSync(sessionFilePath); - } - catch (e) { + } catch (e) { // TODO: Be more specific about what we're catching } } export function checkIfFileExists(filePath: string): boolean { try { - fs.accessSync(filePath, fs.constants.R_OK) + fs.accessSync(filePath, fs.constants.R_OK); return true; - } - catch (e) { + } catch (e) { return false; } } export function getTimestampString() { - var time = new Date(); - return `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}]` + const time = new Date(); + return `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}]`; } export function isWindowsOS(): boolean { - return os.platform() == "win32"; -} \ No newline at end of file + return os.platform() === "win32"; +} diff --git a/test/index.ts b/test/index.ts index 1d6519d0d3..8ff1de2e82 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,9 +1,9 @@ -var testRunner = require('vscode/lib/testrunner'); +let testRunner = require("vscode/lib/testrunner"); // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for options testRunner.configure({ - ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results + ui: "tdd", // the TDD UI is being used in extension.test.ts (suite, test, etc.) + useColors: true, // colored output from test results }); module.exports = testRunner; diff --git a/test/platform.test.ts b/test/platform.test.ts index b115451e77..8ca3ab51cf 100644 --- a/test/platform.test.ts +++ b/test/platform.test.ts @@ -2,9 +2,9 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import * as assert from 'assert'; -import * as vscode from 'vscode'; -import * as platform from '../src/platform'; +import * as assert from "assert"; +import * as vscode from "vscode"; +import * as platform from "../src/platform"; function checkDefaultPowerShellPath(platformDetails, expectedPath) { test("returns correct default path", () => { @@ -15,14 +15,14 @@ function checkDefaultPowerShellPath(platformDetails, expectedPath) { } function checkAvailableWindowsPowerShellPaths( - platformDetails: platform.PlatformDetails, - expectedPaths: platform.PowerShellExeDetails[]) { + platformDetails: platform.IPlatformDetails, + expectedPaths: platform.IPowerShellExeDetails[]) { test("correctly enumerates available Windows PowerShell paths", () => { // The system may return PowerShell Core paths so only // enumerate the first list items. - let enumeratedPaths = platform.getAvailablePowerShellExes(platformDetails); - for (var i; i < expectedPaths.length; i++) { + const enumeratedPaths = platform.getAvailablePowerShellExes(platformDetails); + for (let i; i < expectedPaths.length; i++) { assert.equal(enumeratedPaths[i], expectedPaths[i]); } }); @@ -39,10 +39,10 @@ function checkFixedWindowsPowerShellpath(platformDetails, inputPath, expectedPat suite("Platform module", () => { suite("64-bit Windows, 64-bit VS Code", () => { - let platformDetails: platform.PlatformDetails = { + const platformDetails: platform.IPlatformDetails = { operatingSystem: platform.OperatingSystem.Windows, isOS64Bit: true, - isProcess64Bit: true + isProcess64Bit: true, }; checkDefaultPowerShellPath( @@ -54,12 +54,12 @@ suite("Platform module", () => { [ { versionName: platform.WindowsPowerShell64BitLabel, - exePath: platform.System32PowerShellPath + exePath: platform.System32PowerShellPath, }, { versionName: platform.WindowsPowerShell32BitLabel, - exePath: platform.SysWow64PowerShellPath - } + exePath: platform.SysWow64PowerShellPath, + }, ]); checkFixedWindowsPowerShellpath( @@ -69,10 +69,10 @@ suite("Platform module", () => { }); suite("64-bit Windows, 32-bit VS Code", () => { - let platformDetails: platform.PlatformDetails = { + const platformDetails: platform.IPlatformDetails = { operatingSystem: platform.OperatingSystem.Windows, isOS64Bit: true, - isProcess64Bit: false + isProcess64Bit: false, }; checkDefaultPowerShellPath( @@ -84,12 +84,12 @@ suite("Platform module", () => { [ { versionName: platform.WindowsPowerShell64BitLabel, - exePath: platform.SysnativePowerShellPath + exePath: platform.SysnativePowerShellPath, }, { versionName: platform.WindowsPowerShell32BitLabel, - exePath: platform.System32PowerShellPath - } + exePath: platform.System32PowerShellPath, + }, ]); checkFixedWindowsPowerShellpath( @@ -99,10 +99,10 @@ suite("Platform module", () => { }); suite("32-bit Windows, 32-bit VS Code", () => { - let platformDetails: platform.PlatformDetails = { + const platformDetails: platform.IPlatformDetails = { operatingSystem: platform.OperatingSystem.Windows, isOS64Bit: false, - isProcess64Bit: false + isProcess64Bit: false, }; checkDefaultPowerShellPath( @@ -114,8 +114,8 @@ suite("Platform module", () => { [ { versionName: platform.WindowsPowerShell32BitLabel, - exePath: platform.System32PowerShellPath - } + exePath: platform.System32PowerShellPath, + }, ]); }); }); diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..9b346bb304 --- /dev/null +++ b/tslint.json @@ -0,0 +1,12 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "indent": [true, "spaces", 4], + "max-classes-per-file": false + }, + "rulesDirectory": [] +}