Fixing #31217 npm script not detected if the package.json is not in root folder
This commit is contained in:
parent
86d5aba450
commit
a6dde81592
5 changed files with 100 additions and 16 deletions
|
@ -11,3 +11,4 @@ To run scripts as tasks you use the `Tasks` menu.
|
||||||
- `npm.autoDetect` enable detecting scripts as tasks, the default is `on`.
|
- `npm.autoDetect` enable detecting scripts as tasks, the default is `on`.
|
||||||
- `npm.runSilent` run npm script with the `--silent` option, the default is `false`.
|
- `npm.runSilent` run npm script with the `--silent` option, the default is `false`.
|
||||||
- `npm.packageManager` the package manager used to run the scripts: `npm` or `yarn`, the default is `npm`.
|
- `npm.packageManager` the package manager used to run the scripts: `npm` or `yarn`, the default is `npm`.
|
||||||
|
- `npm.exclude` glob patterns for folders that should be excluded from automatic script detection. The pattern is matched against the **absolute path** of the package.json. For example to exclude all test folders user '**/test/**.
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonc-parser": "^1.0.0",
|
"jsonc-parser": "^1.0.0",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
"request-light": "^0.2.2",
|
"request-light": "^0.2.2",
|
||||||
"vscode-nls": "^3.2.1"
|
"vscode-nls": "^3.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/minimatch": "^3.0.3",
|
||||||
"@types/node": "7.0.43"
|
"@types/node": "7.0.43"
|
||||||
},
|
},
|
||||||
"main": "./out/main",
|
"main": "./out/main",
|
||||||
|
@ -59,6 +61,17 @@
|
||||||
],
|
],
|
||||||
"default": "npm",
|
"default": "npm",
|
||||||
"description": "%config.npm.packageManager%"
|
"description": "%config.npm.packageManager%"
|
||||||
|
},
|
||||||
|
"npm.exclude": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"array"
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "%config.npm.exclude%",
|
||||||
|
"scope": "window"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -91,4 +104,4 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"config.npm.autoDetect": "Controls whether auto detection of npm scripts is on or off. Default is on.",
|
"config.npm.autoDetect": "Controls whether auto detection of npm scripts is on or off. Default is on.",
|
||||||
"config.npm.runSilent": "Run npm commands with the `--silent` option.",
|
"config.npm.runSilent": "Run npm commands with the `--silent` option.",
|
||||||
"config.npm.packageManager": "The package manager used to run scripts.",
|
"config.npm.packageManager": "The package manager used to run scripts.",
|
||||||
|
"config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.",
|
||||||
"npm.parseError": "Npm task detection: failed to parse the file {0}",
|
"npm.parseError": "Npm task detection: failed to parse the file {0}",
|
||||||
"taskdef.script": "The npm script to customize.",
|
"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 ommitted."
|
"taskdef.path": "The path to the folder of the package.json file that provides the script. Can be ommitted."
|
||||||
|
|
|
@ -9,6 +9,8 @@ import * as fs from 'fs';
|
||||||
import * as httpRequest from 'request-light';
|
import * as httpRequest from 'request-light';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as minimatch from 'minimatch';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
import { addJSONProviders } from './features/jsonContributions';
|
import { addJSONProviders } from './features/jsonContributions';
|
||||||
|
@ -97,15 +99,17 @@ function isNotPreOrPostScript(script: string): boolean {
|
||||||
async function provideNpmScripts(): Promise<vscode.Task[]> {
|
async function provideNpmScripts(): Promise<vscode.Task[]> {
|
||||||
let emptyTasks: vscode.Task[] = [];
|
let emptyTasks: vscode.Task[] = [];
|
||||||
let allTasks: vscode.Task[] = [];
|
let allTasks: vscode.Task[] = [];
|
||||||
let folders = vscode.workspace.workspaceFolders;
|
|
||||||
|
|
||||||
if (!folders) {
|
let paths = await vscode.workspace.findFiles('**/package.json', '**/node_modules/**');
|
||||||
|
if (paths.length === 0) {
|
||||||
return emptyTasks;
|
return emptyTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < folders.length; i++) {
|
for (let i = 0; i < paths.length; i++) {
|
||||||
if (isEnabled(folders[i])) {
|
let folder = vscode.workspace.getWorkspaceFolder(paths[i]);
|
||||||
let tasks = await provideNpmScriptsForFolder(folders[i]);
|
if (folder && isEnabled(folder) && !isExcluded(folder, paths[i])) {
|
||||||
|
let tasks = await provideNpmScriptsForFolder(paths[i]);
|
||||||
allTasks.push(...tasks);
|
allTasks.push(...tasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,19 +123,45 @@ function isEnabled(folder: vscode.WorkspaceFolder): boolean {
|
||||||
return vscode.workspace.getConfiguration('npm', folder.uri).get<AutoDetect>('autoDetect') === 'on';
|
return vscode.workspace.getConfiguration('npm', folder.uri).get<AutoDetect>('autoDetect') === 'on';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder): Promise<vscode.Task[]> {
|
function isExcluded(folder: vscode.WorkspaceFolder, packageJsonUri: vscode.Uri) {
|
||||||
|
function testForExclusionPattern(path: string, pattern: string): boolean {
|
||||||
|
return minimatch(path, pattern, { dot: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
let exclude = vscode.workspace.getConfiguration('npm', folder.uri).get<string | string[]>('exclude');
|
||||||
|
|
||||||
|
if (exclude) {
|
||||||
|
if (Array.isArray(exclude)) {
|
||||||
|
for (let pattern of exclude) {
|
||||||
|
if (testForExclusionPattern(packageJsonUri.fsPath, pattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (testForExclusionPattern(packageJsonUri.fsPath, exclude)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function provideNpmScriptsForFolder(packageJsonUri: vscode.Uri): Promise<vscode.Task[]> {
|
||||||
let emptyTasks: vscode.Task[] = [];
|
let emptyTasks: vscode.Task[] = [];
|
||||||
|
|
||||||
if (folder.uri.scheme !== 'file') {
|
if (packageJsonUri.scheme !== 'file') {
|
||||||
return emptyTasks;
|
return emptyTasks;
|
||||||
}
|
}
|
||||||
let rootPath = folder.uri.fsPath;
|
|
||||||
|
|
||||||
let packageJson = path.join(rootPath, 'package.json');
|
let packageJson = packageJsonUri.fsPath;
|
||||||
|
|
||||||
if (!await exists(packageJson)) {
|
if (!await exists(packageJson)) {
|
||||||
return emptyTasks;
|
return emptyTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let folder = vscode.workspace.getWorkspaceFolder(packageJsonUri);
|
||||||
|
if (!folder) {
|
||||||
|
return emptyTasks;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var contents = await readFile(packageJson);
|
var contents = await readFile(packageJson);
|
||||||
var json = JSON.parse(contents);
|
var json = JSON.parse(contents);
|
||||||
|
@ -141,7 +171,7 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder): Promi
|
||||||
|
|
||||||
const result: vscode.Task[] = [];
|
const result: vscode.Task[] = [];
|
||||||
Object.keys(json.scripts).filter(isNotPreOrPostScript).forEach(each => {
|
Object.keys(json.scripts).filter(isNotPreOrPostScript).forEach(each => {
|
||||||
const task = createTask(each, `run ${each}`, rootPath, folder);
|
const task = createTask(each, `run ${each}`, folder!, packageJsonUri);
|
||||||
const lowerCaseTaskName = each.toLowerCase();
|
const lowerCaseTaskName = each.toLowerCase();
|
||||||
if (isBuildTask(lowerCaseTaskName)) {
|
if (isBuildTask(lowerCaseTaskName)) {
|
||||||
task.group = vscode.TaskGroup.Build;
|
task.group = vscode.TaskGroup.Build;
|
||||||
|
@ -154,14 +184,17 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder): Promi
|
||||||
// result.push(createTask('install', 'install', rootPath, folder, []));
|
// result.push(createTask('install', 'install', rootPath, folder, []));
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let localizedParseError = localize('npm.parseError', 'Npm task detection: failed to parse the file {0}', packageJson);
|
let localizedParseError = localize('npm.parseError', 'Npm task detection: failed to parse the file {0}', packageJsonUri);
|
||||||
throw new Error(localizedParseError);
|
throw new Error(localizedParseError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTask(script: string, cmd: string, rootPath: string, folder: vscode.WorkspaceFolder, matcher?: any): vscode.Task {
|
function createTask(script: string, cmd: string, folder: vscode.WorkspaceFolder, packageJsonUri: vscode.Uri, matcher?: any): vscode.Task {
|
||||||
|
|
||||||
function getTaskName(script: string) {
|
function getTaskName(script: string, file: string) {
|
||||||
|
if (file.length) {
|
||||||
|
return `${script} - ${file.substring(0, file.length - 1)}`;
|
||||||
|
}
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +206,21 @@ function createTask(script: string, cmd: string, rootPath: string, folder: vscod
|
||||||
return `${packageManager} ${cmd}`;
|
return `${packageManager} ${cmd}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRelativePath(folder: vscode.WorkspaceFolder, packageJsonUri: vscode.Uri): string {
|
||||||
|
let rootUri = folder.uri;
|
||||||
|
let absolutePath = packageJsonUri.fsPath;
|
||||||
|
return absolutePath.substring(rootUri.fsPath.length + 1, absolutePath.length - 'package.json'.length);
|
||||||
|
}
|
||||||
|
|
||||||
let kind: NpmTaskDefinition = {
|
let kind: NpmTaskDefinition = {
|
||||||
type: 'npm',
|
type: 'npm',
|
||||||
script: script
|
script: script
|
||||||
};
|
};
|
||||||
let taskName = getTaskName(script);
|
let relativePackageJson = getRelativePath(folder, packageJsonUri);
|
||||||
return new vscode.Task(kind, folder, taskName, 'npm', new vscode.ShellExecution(getCommandLine(folder, cmd), { cwd: rootPath }), matcher);
|
if (relativePackageJson.length) {
|
||||||
|
kind.file = getRelativePath(folder, packageJsonUri);
|
||||||
|
}
|
||||||
|
let taskName = getTaskName(script, relativePackageJson);
|
||||||
|
let cwd = path.dirname(packageJsonUri.fsPath);
|
||||||
|
return new vscode.Task(kind, folder, taskName, 'npm', new vscode.ShellExecution(getCommandLine(folder, cmd), { cwd: cwd }), matcher);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@types/minimatch@^3.0.3":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||||
|
|
||||||
"@types/node@7.0.43":
|
"@types/node@7.0.43":
|
||||||
version "7.0.43"
|
version "7.0.43"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
||||||
|
@ -12,6 +16,21 @@ agent-base@4, agent-base@^4.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promisify "^5.0.0"
|
es6-promisify "^5.0.0"
|
||||||
|
|
||||||
|
balanced-match@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
|
|
||||||
|
brace-expansion@^1.1.7:
|
||||||
|
version "1.1.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
|
dependencies:
|
||||||
|
balanced-match "^1.0.0"
|
||||||
|
concat-map "0.0.1"
|
||||||
|
|
||||||
|
concat-map@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
|
|
||||||
debug@2:
|
debug@2:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
|
@ -52,6 +71,12 @@ jsonc-parser@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.1.tgz#7f8f296414e6e7c4a33b9e4914fc8c47e4421675"
|
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.1.tgz#7f8f296414e6e7c4a33b9e4914fc8c47e4421675"
|
||||||
|
|
||||||
|
minimatch@^3.0.4:
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
|
|
Loading…
Reference in a new issue