@@ -9,6 +9,8 @@ import * as fs from 'fs';
99import * as httpRequest from 'request-light' ;
1010import * as vscode from 'vscode' ;
1111import * as nls from 'vscode-nls' ;
12+ import * as minimatch from 'minimatch' ;
13+
1214const localize = nls . loadMessageBundle ( ) ;
1315
1416import { addJSONProviders } from './features/jsonContributions' ;
@@ -97,15 +99,17 @@ function isNotPreOrPostScript(script: string): boolean {
9799async function provideNpmScripts ( ) : Promise < vscode . Task [ ] > {
98100 let emptyTasks : vscode . Task [ ] = [ ] ;
99101 let allTasks : vscode . Task [ ] = [ ] ;
100- let folders = vscode . workspace . workspaceFolders ;
101102
102- if ( ! folders ) {
103+ let paths = await vscode . workspace . findFiles ( '**/package.json' , '**/node_modules/**' ) ;
104+ if ( paths . length === 0 ) {
103105 return emptyTasks ;
104106 }
107+
105108 try {
106- for ( let i = 0 ; i < folders . length ; i ++ ) {
107- if ( isEnabled ( folders [ i ] ) ) {
108- let tasks = await provideNpmScriptsForFolder ( folders [ i ] ) ;
109+ for ( let i = 0 ; i < paths . length ; i ++ ) {
110+ let folder = vscode . workspace . getWorkspaceFolder ( paths [ i ] ) ;
111+ if ( folder && isEnabled ( folder ) && ! isExcluded ( folder , paths [ i ] ) ) {
112+ let tasks = await provideNpmScriptsForFolder ( paths [ i ] ) ;
109113 allTasks . push ( ...tasks ) ;
110114 }
111115 }
@@ -119,19 +123,45 @@ function isEnabled(folder: vscode.WorkspaceFolder): boolean {
119123 return vscode . workspace . getConfiguration ( 'npm' , folder . uri ) . get < AutoDetect > ( 'autoDetect' ) === 'on' ;
120124}
121125
122- async function provideNpmScriptsForFolder ( folder : vscode . WorkspaceFolder ) : Promise < vscode . Task [ ] > {
126+ function isExcluded ( folder : vscode . WorkspaceFolder , packageJsonUri : vscode . Uri ) {
127+ function testForExclusionPattern ( path : string , pattern : string ) : boolean {
128+ return minimatch ( path , pattern , { dot : true } ) ;
129+ }
130+
131+ let exclude = vscode . workspace . getConfiguration ( 'npm' , folder . uri ) . get < string | string [ ] > ( 'exclude' ) ;
132+
133+ if ( exclude ) {
134+ if ( Array . isArray ( exclude ) ) {
135+ for ( let pattern of exclude ) {
136+ if ( testForExclusionPattern ( packageJsonUri . fsPath , pattern ) ) {
137+ return true ;
138+ }
139+ }
140+ } else if ( testForExclusionPattern ( packageJsonUri . fsPath , exclude ) ) {
141+ return true ;
142+ }
143+ }
144+ return false ;
145+ }
146+
147+ async function provideNpmScriptsForFolder ( packageJsonUri : vscode . Uri ) : Promise < vscode . Task [ ] > {
123148 let emptyTasks : vscode . Task [ ] = [ ] ;
124149
125- if ( folder . uri . scheme !== 'file' ) {
150+ if ( packageJsonUri . scheme !== 'file' ) {
126151 return emptyTasks ;
127152 }
128- let rootPath = folder . uri . fsPath ;
129153
130- let packageJson = path . join ( rootPath , 'package.json' ) ;
154+ let packageJson = packageJsonUri . fsPath ;
155+
131156 if ( ! await exists ( packageJson ) ) {
132157 return emptyTasks ;
133158 }
134159
160+ let folder = vscode . workspace . getWorkspaceFolder ( packageJsonUri ) ;
161+ if ( ! folder ) {
162+ return emptyTasks ;
163+ }
164+
135165 try {
136166 var contents = await readFile ( packageJson ) ;
137167 var json = JSON . parse ( contents ) ;
@@ -141,7 +171,7 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder): Promi
141171
142172 const result : vscode . Task [ ] = [ ] ;
143173 Object . keys ( json . scripts ) . filter ( isNotPreOrPostScript ) . forEach ( each => {
144- const task = createTask ( each , `run ${ each } ` , rootPath , folder ) ;
174+ const task = createTask ( each , `run ${ each } ` , folder ! , packageJsonUri ) ;
145175 const lowerCaseTaskName = each . toLowerCase ( ) ;
146176 if ( isBuildTask ( lowerCaseTaskName ) ) {
147177 task . group = vscode . TaskGroup . Build ;
@@ -154,14 +184,17 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder): Promi
154184 // result.push(createTask('install', 'install', rootPath, folder, []));
155185 return result ;
156186 } catch ( e ) {
157- let localizedParseError = localize ( 'npm.parseError' , 'Npm task detection: failed to parse the file {0}' , packageJson ) ;
187+ let localizedParseError = localize ( 'npm.parseError' , 'Npm task detection: failed to parse the file {0}' , packageJsonUri ) ;
158188 throw new Error ( localizedParseError ) ;
159189 }
160190}
161191
162- function createTask ( script : string , cmd : string , rootPath : string , folder : vscode . WorkspaceFolder , matcher ?: any ) : vscode . Task {
192+ function createTask ( script : string , cmd : string , folder : vscode . WorkspaceFolder , packageJsonUri : vscode . Uri , matcher ?: any ) : vscode . Task {
163193
164- function getTaskName ( script : string ) {
194+ function getTaskName ( script : string , file : string ) {
195+ if ( file . length ) {
196+ return `${ script } - ${ file . substring ( 0 , file . length - 1 ) } ` ;
197+ }
165198 return script ;
166199 }
167200
@@ -173,10 +206,21 @@ function createTask(script: string, cmd: string, rootPath: string, folder: vscod
173206 return `${ packageManager } ${ cmd } ` ;
174207 }
175208
209+ function getRelativePath ( folder : vscode . WorkspaceFolder , packageJsonUri : vscode . Uri ) : string {
210+ let rootUri = folder . uri ;
211+ let absolutePath = packageJsonUri . fsPath ;
212+ return absolutePath . substring ( rootUri . fsPath . length + 1 , absolutePath . length - 'package.json' . length ) ;
213+ }
214+
176215 let kind : NpmTaskDefinition = {
177216 type : 'npm' ,
178217 script : script
179218 } ;
180- let taskName = getTaskName ( script ) ;
181- return new vscode . Task ( kind , folder , taskName , 'npm' , new vscode . ShellExecution ( getCommandLine ( folder , cmd ) , { cwd : rootPath } ) , matcher ) ;
219+ let relativePackageJson = getRelativePath ( folder , packageJsonUri ) ;
220+ if ( relativePackageJson . length ) {
221+ kind . file = getRelativePath ( folder , packageJsonUri ) ;
222+ }
223+ let taskName = getTaskName ( script , relativePackageJson ) ;
224+ let cwd = path . dirname ( packageJsonUri . fsPath ) ;
225+ return new vscode . Task ( kind , folder , taskName , 'npm' , new vscode . ShellExecution ( getCommandLine ( folder , cmd ) , { cwd : cwd } ) , matcher ) ;
182226}
0 commit comments