diff --git a/.vsts-ci/templates/ci-general.yml b/.vsts-ci/templates/ci-general.yml index 5d3814b83d..46204cbebc 100644 --- a/.vsts-ci/templates/ci-general.yml +++ b/.vsts-ci/templates/ci-general.yml @@ -96,7 +96,7 @@ steps: targetType: inline pwsh: true script: | - $assembly = [Reflection.Assembly]::LoadFile('$(Build.SourcesDirectory)/vscode-powershell/modules/PowerShellEditorServices.VSCode/bin/Microsoft.PowerShell.EditorServices.VSCode.dll') + $assembly = [Reflection.Assembly]::LoadFile("$(Build.SourcesDirectory)/vscode-powershell/modules/PowerShellEditorServices/bin/Core/Microsoft.PowerShell.EditorServices.Hosting.dll") if ($assembly.GetCustomAttributes([System.Diagnostics.DebuggableAttribute], $true).IsJITOptimizerDisabled) { Write-Host '##vso[task.LogIssue type=error;]PowerShell Editor Services bits were not built in release configuration!' exit 1 diff --git a/examples/ContentViewTest.ps1 b/examples/ContentViewTest.ps1 deleted file mode 100644 index 21055149d5..0000000000 --- a/examples/ContentViewTest.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -$params = @{ - HtmlBodyContent = "Testing JavaScript and CSS paths..." - JavaScriptPaths = ".\Assets\script.js" - StyleSheetPaths = ".\Assets\style.css" -} - -$view = New-VSCodeHtmlContentView -Title "Test View" -ShowInColumn Two -Set-VSCodeHtmlContentView -View $view @params \ No newline at end of file diff --git a/src/features/CodeActions.ts b/src/features/CodeActions.ts index cf0de58a74..4be6ac9ed6 100644 --- a/src/features/CodeActions.ts +++ b/src/features/CodeActions.ts @@ -2,28 +2,17 @@ // Licensed under the MIT License. import vscode = require("vscode"); -import Window = vscode.window; import { ILogger } from "../logging"; export class CodeActionsFeature implements vscode.Disposable { - private applyEditsCommand: vscode.Disposable; private showDocumentationCommand: vscode.Disposable; constructor(private log: ILogger) { - // TODO: What type is `edit`, what uses this, and is it working? - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.applyEditsCommand = vscode.commands.registerCommand("PowerShell.ApplyCodeActionEdits", async (edit: any) => { - await Window.activeTextEditor?.edit((editBuilder) => { - editBuilder.replace( - new vscode.Range( - edit.StartLineNumber - 1, - edit.StartColumnNumber - 1, - edit.EndLineNumber - 1, - edit.EndColumnNumber - 1), - edit.Text); - }); - }); - + // NOTE: While not exposed to the user via package.json, this is + // required as the server's code action sends across a command name. + // + // TODO: In the far future with LSP 3.19 the server can just set a URL + // and this can go away. See https://github.com/microsoft/language-server-protocol/issues/1548 this.showDocumentationCommand = vscode.commands.registerCommand("PowerShell.ShowCodeActionDocumentation", async (ruleName: string) => { await this.showRuleDocumentation(ruleName); @@ -31,7 +20,6 @@ export class CodeActionsFeature implements vscode.Disposable { } public dispose(): void { - this.applyEditsCommand.dispose(); this.showDocumentationCommand.dispose(); } diff --git a/src/features/CustomViews.ts b/src/features/CustomViews.ts deleted file mode 100644 index f4b0a2f20d..0000000000 --- a/src/features/CustomViews.ts +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import * as path from "path"; -import * as vscode from "vscode"; -import { RequestType } from "vscode-languageclient"; -import { LanguageClient } from "vscode-languageclient/node"; -import { LanguageClientConsumer } from "../languageClientConsumer"; - -export class CustomViewsFeature extends LanguageClientConsumer { - - private commands: vscode.Disposable[] = []; - private contentProvider: PowerShellContentProvider; - - constructor() { - super(); - this.contentProvider = new PowerShellContentProvider(); - this.commands.push( - vscode.workspace.registerTextDocumentContentProvider( - "powershell", - this.contentProvider)); - } - - public dispose(): void { - for (const command of this.commands) { - command.dispose(); - } - } - - public override setLanguageClient(languageClient: LanguageClient): void { - - languageClient.onRequest( - NewCustomViewRequestType, - (args) => { - this.contentProvider.createView( - args.id, - args.title, - args.viewType); - }); - - languageClient.onRequest( - ShowCustomViewRequestType, - (args) => { - this.contentProvider.showView( - args.id, - args.viewColumn); - }); - - languageClient.onRequest( - CloseCustomViewRequestType, - (args) => { - this.contentProvider.closeView(args.id); - }); - - languageClient.onRequest( - SetHtmlContentViewRequestType, - (args) => { - this.contentProvider.setHtmlContentView( - args.id, - args.htmlContent); - }); - - languageClient.onRequest( - AppendHtmlOutputViewRequestType, - (args) => { - this.contentProvider.appendHtmlOutputView( - args.id, - args.appendedHtmlBodyContent); - }); - } -} - -class PowerShellContentProvider implements vscode.TextDocumentContentProvider { - - private viewIndex: Record = {}; - private didChangeEvent: vscode.EventEmitter = new vscode.EventEmitter(); - - 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): void { - 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): void { - const uriString = this.getUri(id); - (this.viewIndex[uriString] as HtmlContentView).showContent(viewColumn); - } - - public closeView(id: string): void { - const uriString = this.getUri(id); - - vscode.workspace.textDocuments.some((doc) => { - if (doc.uri.toString() === uriString) { - void vscode.window.showTextDocument(doc); - void vscode.commands.executeCommand("workbench.action.closeActiveEditor"); - return true; - } - - return false; - }); - } - - public setHtmlContentView(id: string, content: IHtmlContent): void { - const uriString = this.getUri(id); - const view: CustomView = this.viewIndex[uriString]; - - (view as HtmlContentView).setContent(content); - this.didChangeEvent.fire(vscode.Uri.parse(uriString)); - } - - public appendHtmlOutputView(id: string, content: string): void { - const uriString = this.getUri(id); - const view: CustomView = this.viewIndex[uriString]; - - (view as HtmlContentView).appendContent(content); - this.didChangeEvent.fire(vscode.Uri.parse(uriString)); - } - - private getUri(id: string): string { - return `powershell://views/${id}`; - } -} - -abstract class CustomView { - - constructor( - public id: string, - public title: string, - public viewType: CustomViewType) { - } - - public abstract getContent(): string; -} - -class HtmlContentView extends CustomView { - - private htmlContent: IHtmlContent = { - bodyContent: "", - javaScriptPaths: [], - styleSheetPaths: [], - }; - - private webviewPanel: vscode.WebviewPanel | undefined; - - constructor( - id: string, - title: string) { - super(id, title, CustomViewType.HtmlContent); - } - - public setContent(htmlContent: IHtmlContent): void { - this.htmlContent = htmlContent; - } - - public appendContent(content: string): void { - this.htmlContent.bodyContent += content; - } - - public getContent(): string { - let styleTags = ""; - if (this.htmlContent.styleSheetPaths.length > 0) { - for (const styleSheetPath of this.htmlContent.styleSheetPaths) { - styleTags += `\n`; - } - } - - let scriptTags = ""; - if (this.htmlContent.javaScriptPaths.length > 0) { - for (const javaScriptPath of this.htmlContent.javaScriptPaths) { - scriptTags += `\n`; - } - } - - // Return an HTML page with the specified content - return `${styleTags}\n${this.htmlContent.bodyContent}\n${scriptTags}`; - } - - public showContent(viewColumn: vscode.ViewColumn): void { - this.webviewPanel?.dispose(); - - let localResourceRoots: vscode.Uri[] = []; - localResourceRoots = localResourceRoots.concat(this.htmlContent.javaScriptPaths.map((p) => { - return vscode.Uri.parse(path.dirname(p)); - })); - - localResourceRoots = localResourceRoots.concat(this.htmlContent.styleSheetPaths.map((p) => { - return vscode.Uri.parse(path.dirname(p)); - })); - - this.webviewPanel = vscode.window.createWebviewPanel( - this.id, - this.title, - viewColumn, - { - enableScripts: true, - enableFindWidget: true, - enableCommandUris: true, - retainContextWhenHidden: true, - localResourceRoots, - }); - this.webviewPanel.webview.html = this.getContent(); - this.webviewPanel.reveal(viewColumn); - } -} - -enum CustomViewType { - HtmlContent = 1, -} - -export const NewCustomViewRequestType = - new RequestType( - "powerShell/newCustomView"); - -interface INewCustomViewRequestArguments { - id: string; - title: string; - viewType: CustomViewType; -} - -export const ShowCustomViewRequestType = - new RequestType( - "powerShell/showCustomView"); - -interface IShowCustomViewRequestArguments { - id: string; - viewColumn: vscode.ViewColumn; -} - -export const CloseCustomViewRequestType = - new RequestType( - "powerShell/closeCustomView"); - -interface ICloseCustomViewRequestArguments { - id: string; -} - -export const SetHtmlContentViewRequestType = - new RequestType( - "powerShell/setHtmlViewContent"); - -interface IHtmlContent { - bodyContent: string; - javaScriptPaths: string[]; - styleSheetPaths: string[]; -} - -interface ISetHtmlContentViewRequestArguments { - id: string; - htmlContent: IHtmlContent; -} - -export const AppendHtmlOutputViewRequestType = - new RequestType( - "powerShell/appendHtmlViewContent"); - -interface IAppendHtmlOutputViewRequestArguments { - id: string; - appendedHtmlBodyContent: string; -} diff --git a/src/features/RunCode.ts b/src/features/RunCode.ts deleted file mode 100644 index 652cf55daf..0000000000 --- a/src/features/RunCode.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import vscode = require("vscode"); -import { SessionManager } from "../session"; -import { ILogger } from "../logging"; -import { getSettings, getChosenWorkspace } from "../settings"; - -enum LaunchType { - Debug, - Run, -} - -export class RunCodeFeature implements vscode.Disposable { - private command: vscode.Disposable; - - constructor(private sessionManager: SessionManager, private logger: ILogger) { - this.command = vscode.commands.registerCommand( - "PowerShell.RunCode", - async (runInDebugger: boolean, scriptToRun: string, args: string[]) => { - await this.launchTask(runInDebugger, scriptToRun, args); - }); - } - - public dispose(): void { - this.command.dispose(); - } - - private async launchTask( - runInDebugger: boolean, - scriptToRun: string, - args: string[]): Promise { - - const launchType = runInDebugger ? LaunchType.Debug : LaunchType.Run; - const launchConfig = createLaunchConfig(launchType, scriptToRun, args); - await this.launch(launchConfig); - } - - private async launch(launchConfig: string | vscode.DebugConfiguration): Promise { - // Create or show the interactive console - // TODO: #367: Check if "newSession" mode is configured - this.sessionManager.showDebugTerminal(true); - await vscode.debug.startDebugging(await getChosenWorkspace(this.logger), launchConfig); - } -} - -function createLaunchConfig(launchType: LaunchType, commandToRun: string, args: string[]): vscode.DebugConfiguration { - const settings = getSettings(); - - const launchConfig = { - request: "launch", - type: "PowerShell", - name: "PowerShell: Run Code", - internalConsoleOptions: "neverOpen", - noDebug: (launchType === LaunchType.Run), - createTemporaryIntegratedConsole: settings.debugging.createTemporaryIntegratedConsole, - script: commandToRun, - args, - }; - - return launchConfig; -} diff --git a/src/main.ts b/src/main.ts index 5b0fee117e..9cbaeac5af 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,6 @@ import TelemetryReporter from "@vscode/extension-telemetry"; import { DocumentSelector } from "vscode-languageclient"; import { CodeActionsFeature } from "./features/CodeActions"; import { ConsoleFeature } from "./features/Console"; -import { CustomViewsFeature } from "./features/CustomViews"; import { DebugSessionFeature } from "./features/DebugSession"; import { ExamplesFeature } from "./features/Examples"; import { ExpandAliasFeature } from "./features/ExpandAlias"; @@ -21,7 +20,6 @@ import { OpenInISEFeature } from "./features/OpenInISE"; import { PesterTestsFeature } from "./features/PesterTests"; import { PickPSHostProcessFeature, PickRunspaceFeature } from "./features/DebugSession"; import { RemoteFilesFeature } from "./features/RemoteFiles"; -import { RunCodeFeature } from "./features/RunCode"; import { ShowHelpFeature } from "./features/ShowHelp"; import { SpecifyScriptArgsFeature } from "./features/DebugSession"; import { Logger } from "./logging"; @@ -139,7 +137,6 @@ export async function activate(context: vscode.ExtensionContext): Promise -hello -`, - }, - - // A test that adds a js file. - { - name: "with a JavaScript file but no CSS", - htmlContent: "hello", - javaScriptFiles: [ - { - fileName: "testCustomViews.js", - content: "console.log('asdf');", - }, - ], - cssFiles: [], - expectedHtmlString: ` -hello - -`, - }, - - // A test that adds a js file in the current directory, and the parent directory. - { - name: "with two JavaScript files in different locations, but no CSS", - htmlContent: "hello", - javaScriptFiles: [ - { - fileName: "testCustomViews.js", - content: "console.log('asdf');", - }, - { - fileName: "../testCustomViews.js", - content: "console.log('asdf');", - }, - ], - cssFiles: [], - expectedHtmlString: ` -hello - - -`, - }, - - // A test that adds a js file and a css file. - { - name: "with a JavaScript and a CSS file", - htmlContent: "hello", - javaScriptFiles: [ - { - fileName: "testCustomViews.js", - content: "console.log('asdf');", - }, - ], - cssFiles: [ - { - fileName: "testCustomViews.css", - content: "body: { background-color: green; }", - }, - ], - expectedHtmlString: ` - -hello - -`, - }, - ]; - - for (const testCase of testCases) { - it(`Correctly creates an HtmlContentView ${testCase.name}`, async function () { - const htmlContentView = new HtmlContentView(); - - const jsPaths = await Promise.all(testCase.javaScriptFiles.map(async (jsFile) => { - const jsPath: vscode.Uri = vscode.Uri.file(path.join(__dirname, jsFile.fileName)); - await vscode.workspace.fs.writeFile(jsPath, Buffer.from(jsFile.content)); - return jsPath.toString(); - })); - - const cssPaths = await Promise.all(testCase.cssFiles.map(async (cssFile) => { - const cssPath: vscode.Uri = vscode.Uri.file(path.join(__dirname, cssFile.fileName)); - await vscode.workspace.fs.writeFile(cssPath, Buffer.from(cssFile.content)); - return cssPath.toString(); - })); - - htmlContentView.htmlContent = { - bodyContent: testCase.htmlContent, - javaScriptPaths: jsPaths, - styleSheetPaths: cssPaths, - }; - try { - assert.strictEqual(htmlContentView.getContent(), testCase.expectedHtmlString); - } finally { - for (const jsPath of jsPaths) { - await vscode.workspace.fs.delete(vscode.Uri.parse(jsPath)); - } - for (const cssPath of cssPaths) { - await vscode.workspace.fs.delete(vscode.Uri.parse(cssPath)); - } - } - }); - } -}); diff --git a/test/features/RunCode.test.ts b/test/features/RunCode.test.ts deleted file mode 100644 index c837a798fe..0000000000 --- a/test/features/RunCode.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import assert from "assert"; -import * as path from "path"; -import rewire = require("rewire"); -import vscode = require("vscode"); -import utils = require("../utils"); -import { checkIfFileExists } from "../../src/utils"; - -// Setup function that is not exported. -const customViews = rewire("../../src/features/RunCode"); -const createLaunchConfig = customViews.__get__("createLaunchConfig"); - -enum LaunchType { - Debug, - Run, -} - -describe("RunCode feature", function () { - before(utils.ensureEditorServicesIsConnected); - - it("Creates the launch config", function () { - const commandToRun = "Invoke-Build"; - const args: string[] = ["Clean"]; - - const expected: object = { - request: "launch", - type: "PowerShell", - name: "PowerShell: Run Code", - internalConsoleOptions: "neverOpen", - noDebug: false, - createTemporaryIntegratedConsole: false, - script: commandToRun, - args, - }; - - const actual: object = createLaunchConfig(LaunchType.Debug, commandToRun, args); - assert.deepStrictEqual(actual, expected); - }); - - it("Runs Pester tests from a file", async function () { - const pesterTests = path.resolve(__dirname, "../../../examples/Tests/SampleModule.Tests.ps1"); - assert(checkIfFileExists(pesterTests)); - const pesterTestDebugStarted = utils.WaitEvent(vscode.debug.onDidStartDebugSession, - session => session.name === "PowerShell: Launch Pester Tests" - ); - - await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(pesterTests)); - assert(await vscode.commands.executeCommand("PowerShell.RunPesterTestsFromFile")); - const debugSession = await pesterTestDebugStarted; - await vscode.debug.stopDebugging(); - - assert(debugSession.type === "PowerShell"); - }); -}); diff --git a/test/runTests.ts b/test/runTests.ts index a4d7d360bc..bfeb87fe20 100644 --- a/test/runTests.ts +++ b/test/runTests.ts @@ -23,13 +23,6 @@ async function main(): Promise { process.exit(1); } - // Test for the presence of modules folder and error if not found - const PSESPath = path.resolve(__dirname, "../../modules/PowerShellEditorServices.VSCode/bin/Microsoft.PowerShell.EditorServices.VSCode.dll"); - if (!existsSync(PSESPath)) { - console.error("ERROR: A PowerShell Editor Services build was not found in the modules directory. Please run a build first, using either the 'Run Build Task' in VSCode or ./build.ps1 in PowerShell."); - process.exit(1); - } - try { /** The folder containing the Extension Manifest package.json. Passed to `--extensionDevelopmentPath */ const extensionDevelopmentPath = path.resolve(__dirname, "../../");