From 73b72464b3f71db7ac3b763f37e84769bd411a7b Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Thu, 26 Jul 2018 09:10:55 +0200 Subject: [PATCH] Replace lenses with hover links --- extensions/npm/package.json | 6 -- extensions/npm/package.nls.json | 1 - extensions/npm/src/lenses.ts | 86 ----------------------- extensions/npm/src/main.ts | 17 ++--- extensions/npm/src/scriptHover.ts | 109 ++++++++++++++++++++++++++++++ extensions/npm/src/tasks.ts | 9 ++- 6 files changed, 122 insertions(+), 106 deletions(-) delete mode 100644 extensions/npm/src/lenses.ts create mode 100644 extensions/npm/src/scriptHover.ts diff --git a/extensions/npm/package.json b/extensions/npm/package.json index 434f7ea20b1..df9c903fcb4 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -178,12 +178,6 @@ "scope": "resource", "description": "%config.npm.runSilent%" }, - "npm.scriptCodeLens.enable": { - "type": "boolean", - "default": false, - "scope": "resource", - "description": "%config.scriptCodeLens.enable%" - }, "npm.packageManager": { "scope": "resource", "type": "string", diff --git a/extensions/npm/package.nls.json b/extensions/npm/package.nls.json index be9381e3377..92665d5f65a 100644 --- a/extensions/npm/package.nls.json +++ b/extensions/npm/package.nls.json @@ -7,7 +7,6 @@ "config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.", "config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts.", "config.npm.scriptExplorerAction": "The default click action used in the scripts explorer: 'open' or 'run', the default is 'open'.", - "config.scriptCodeLens.enable": "Enable the code lens to 'Run' or 'Debug' an npm script.", "npm.parseError": "Npm task detection: failed to parse the file {0}", "taskdef.script": "The npm script to customize.", "taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.", diff --git a/extensions/npm/src/lenses.ts b/extensions/npm/src/lenses.ts deleted file mode 100644 index 6394fbad5b3..00000000000 --- a/extensions/npm/src/lenses.ts +++ /dev/null @@ -1,86 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { - ExtensionContext, CodeLensProvider, TextDocument, commands, ProviderResult, CodeLens, CancellationToken, - workspace, tasks, Range, Command, Event, EventEmitter -} from 'vscode'; -import { - createTask, startDebugging, findAllScriptRanges, extractDebugArgFromScript -} from './tasks'; -import * as nls from 'vscode-nls'; - -const localize = nls.loadMessageBundle(); - -export class NpmLensProvider implements CodeLensProvider { - private extensionContext: ExtensionContext; - private _onDidChangeCodeLenses: EventEmitter = new EventEmitter(); - readonly onDidChangeCodeLenses: Event = this._onDidChangeCodeLenses.event; - - constructor(context: ExtensionContext) { - this.extensionContext = context; - context.subscriptions.push(commands.registerCommand('npm.runScriptFromLens', this.runScriptFromLens, this)); - context.subscriptions.push(commands.registerCommand('npm.debugScriptFromLens', this.debugScriptFromLens, this)); - } - - public provideCodeLenses(document: TextDocument, _token: CancellationToken): ProviderResult { - let result = findAllScriptRanges(document.getText()); - let folder = workspace.getWorkspaceFolder(document.uri); - let lenses: CodeLens[] = []; - - - if (folder && !workspace.getConfiguration('npm', folder.uri).get('scriptCodeLens.enable', 'true')) { - return lenses; - } - - result.forEach((value, key) => { - let start = document.positionAt(value[0]); - let end = document.positionAt(value[0] + value[1]); - let range = new Range(start, end); - - let command: Command = { - command: 'npm.runScriptFromLens', - title: localize('run', "Run"), - arguments: [document, key] - }; - let lens: CodeLens = new CodeLens(range, command); - lenses.push(lens); - - let debugArgs = extractDebugArgFromScript(value[2]); - if (debugArgs) { - command = { - command: 'npm.debugScriptFromLens', - title: localize('debug', "Debug"), - arguments: [document, key, debugArgs[0], debugArgs[1]] - }; - lens = new CodeLens(range, command); - lenses.push(lens); - } - }); - return lenses; - } - - public refresh() { - this._onDidChangeCodeLenses.fire(); - } - - public runScriptFromLens(document: TextDocument, script: string) { - let uri = document.uri; - let folder = workspace.getWorkspaceFolder(uri); - if (folder) { - let task = createTask(script, `run ${script}`, folder, uri); - tasks.executeTask(task); - } - } - - public debugScriptFromLens(document: TextDocument, script: string, protocol: string, port: number) { - let uri = document.uri; - let folder = workspace.getWorkspaceFolder(uri); - if (folder) { - startDebugging(script, protocol, port, folder); - } - } -} diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index f2c80f5f476..be077371d0c 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -6,16 +6,15 @@ import * as httpRequest from 'request-light'; import * as vscode from 'vscode'; - import { addJSONProviders } from './features/jsonContributions'; import { NpmScriptsTreeDataProvider } from './npmView'; import { invalidateScriptsCache, NpmTaskProvider } from './tasks'; -import { NpmLensProvider } from './lenses'; +import { NpmScriptHoverProvider } from './scriptHover'; export async function activate(context: vscode.ExtensionContext): Promise { const taskProvider = registerTaskProvider(context); const treeDataProvider = registerExplorer(context); - const lensProvider = registerLensProvider(context); + const hoverProvider = registerHoverProvider(context); configureHttpRequest(); vscode.workspace.onDidChangeConfiguration((e) => { @@ -31,11 +30,6 @@ export async function activate(context: vscode.ExtensionContext): Promise treeDataProvider.refresh(); } } - if (e.affectsConfiguration('npm.scriptCodeLens.enable')) { - if (lensProvider) { - lensProvider.refresh(); - } - } }); context.subscriptions.push(addJSONProviders(httpRequest.xhr)); } @@ -66,20 +60,21 @@ function registerExplorer(context: vscode.ExtensionContext): NpmScriptsTreeDataP return undefined; } -function registerLensProvider(context: vscode.ExtensionContext): NpmLensProvider | undefined { +function registerHoverProvider(context: vscode.ExtensionContext): NpmScriptHoverProvider | undefined { if (vscode.workspace.workspaceFolders) { let npmSelector: vscode.DocumentSelector = { language: 'json', scheme: 'file', pattern: '**/package.json' }; - let provider = new NpmLensProvider(context); - context.subscriptions.push(vscode.languages.registerCodeLensProvider(npmSelector, provider)); + let provider = new NpmScriptHoverProvider(context); + context.subscriptions.push(vscode.languages.registerHoverProvider(npmSelector, provider)); return provider; } return undefined; } + function configureHttpRequest() { const httpSettings = vscode.workspace.getConfiguration('http'); httpRequest.configure(httpSettings.get('proxy', ''), httpSettings.get('proxyStrictSSL', true)); diff --git a/extensions/npm/src/scriptHover.ts b/extensions/npm/src/scriptHover.ts new file mode 100644 index 00000000000..5eafb19dfe1 --- /dev/null +++ b/extensions/npm/src/scriptHover.ts @@ -0,0 +1,109 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { + ExtensionContext, TextDocument, commands, ProviderResult, CancellationToken, + workspace, tasks, Range, HoverProvider, Hover, Position, MarkdownString, Uri +} from 'vscode'; +import { + createTask, startDebugging, findAllScriptRanges, extractDebugArgFromScript +} from './tasks'; +import * as nls from 'vscode-nls'; + +const localize = nls.loadMessageBundle(); + +export class NpmScriptHoverProvider implements HoverProvider { + private extensionContext: ExtensionContext; + + constructor(context: ExtensionContext) { + this.extensionContext = context; + context.subscriptions.push(commands.registerCommand('npm.runScriptFromHover', this.runScriptFromHover, this)); + context.subscriptions.push(commands.registerCommand('npm.debugScriptFromHover', this.debugScriptFromHover, this)); + } + + public provideHover(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult { + let result = findAllScriptRanges(document.getText()); + let hover: Hover | undefined = undefined; + + result.forEach((value, key) => { + let start = document.positionAt(value[0]); + let end = document.positionAt(value[0] + value[1]); + let range = new Range(start, end); + + if (range.contains(position)) { + let contents: MarkdownString = new MarkdownString(); + contents.isTrusted = true; + contents.appendMarkdown(this.createRunScriptMarkdown(key, document.uri)); + + let debugArgs = extractDebugArgFromScript(value[2]); + if (debugArgs) { + contents.appendMarkdown(this.createDebugScriptMarkdown(key, document.uri, debugArgs[0], debugArgs[1])); + } + hover = new Hover(contents); + } + }); + return hover; + } + + private createRunScriptMarkdown(script: string, documentUri: Uri): string { + let args = { + documentUri: documentUri, + script: script, + }; + return this.createMarkdownLink( + localize('runScript', 'Run Script'), + 'npm.runScriptFromHover', + args, + localize('runScript.tooltip', 'Run the script as a task') + ); + } + + private createDebugScriptMarkdown(script: string, documentUri: Uri, protocol: string, port: number): string { + let args = { + documentUri: documentUri, + script: script, + protocol: protocol, + port: port + }; + return this.createMarkdownLink( + localize('debugScript', 'Debug Script'), + 'npm.debugScriptFromHover', + args, + localize('debugScript.tooltip', 'Runs the script under the debugger'), + '|' + ); + } + + private createMarkdownLink(label: string, cmd: string, args: any, tooltip: string, separator?: string): string { + let encodedArgs = encodeURIComponent(JSON.stringify(args)); + let prefix = ''; + if (separator) { + prefix = ` ${separator} `; + } + return `${prefix}[${label}](command:${cmd}?${encodedArgs} "${tooltip}")`; + } + + public runScriptFromHover(args: any) { + let script = args.script; + let documentUri = args.documentUri; + let folder = workspace.getWorkspaceFolder(documentUri); + if (folder) { + let task = createTask(script, `run ${script}`, folder, documentUri); + tasks.executeTask(task); + } + } + + public debugScriptFromHover(args: any) { + let script = args.script; + let documentUri = args.documentUri; + let protocol = args.protocol; + let port = args.port; + let folder = workspace.getWorkspaceFolder(documentUri); + if (folder) { + startDebugging(script, protocol, port, folder); + } + } +} diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index 5d19a4c4c00..b4b63e85f19 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -371,6 +371,9 @@ async function findAllScripts(buffer: string): Promise { export function findAllScriptRanges(buffer: string): Map { var scripts: Map = new Map(); let script: string | undefined = undefined; + let offset: number; + let length: number; + let inScripts = false; let visitor: JSONVisitor = { @@ -381,18 +384,20 @@ export function findAllScriptRanges(buffer: string): Map