Replace lenses with hover links

This commit is contained in:
Erich Gamma 2018-07-26 09:10:55 +02:00
parent 8e8e8023ce
commit 73b72464b3
6 changed files with 122 additions and 106 deletions

View file

@ -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",

View file

@ -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.",

View file

@ -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<void> = new EventEmitter<void>();
readonly onDidChangeCodeLenses: Event<void> = 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<CodeLens[]> {
let result = findAllScriptRanges(document.getText());
let folder = workspace.getWorkspaceFolder(document.uri);
let lenses: CodeLens[] = [];
if (folder && !workspace.getConfiguration('npm', folder.uri).get<string>('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);
}
}
}

View file

@ -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<void> {
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<void>
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<string>('proxy', ''), httpSettings.get<boolean>('proxyStrictSSL', true));

View file

@ -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<Hover> {
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);
}
}
}

View file

@ -371,6 +371,9 @@ async function findAllScripts(buffer: string): Promise<StringMap> {
export function findAllScriptRanges(buffer: string): Map<string, [number, number, string]> {
var scripts: Map<string, [number, number, string]> = 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<string, [number, number
inScripts = false;
}
},
onLiteralValue(value: any, offset: number, length: number) {
onLiteralValue(value: any, _offset: number, _length: number) {
if (script) {
scripts.set(script, [offset, length, value]);
script = undefined;
}
},
onObjectProperty(property: string, offset: number, length: number) {
onObjectProperty(property: string, off: number, len: number) {
if (property === 'scripts') {
inScripts = true;
}
else if (inScripts) {
script = property;
offset = off;
length = len;
}
}
};