44using System . Collections . Generic ;
55using System . ComponentModel . Composition ;
66using System . Diagnostics ;
7+ using System . IO ;
78using System . Linq ;
89using System . Threading ;
910using Microsoft . NodejsTools . Npm ;
@@ -75,26 +76,28 @@ public int Exec(List<WorkspaceVisualNodeBase> selection, Guid pguidCmdGroup, uin
7576
7677 if ( pguidCmdGroup == Guids . NodeToolsWorkspaceCmdSet )
7778 {
78- this . outputPane . ShowWindow ( ) ;
79+ this . outputPane . InitializeOutputPanes ( ) ;
80+
81+ var fileNode = ( ( IFileNode ) node ) . FullPath ;
7982
8083 switch ( nCmdID )
8184 {
8285 case PkgCmdId . cmdidWorkSpaceNpmInstallMissing :
83- ExecNpmInstallMissing ( node ) ;
86+ ExecNpmInstallMissing ( fileNode ) ;
8487 return VSConstants . S_OK ;
8588
8689 case PkgCmdId . cmdidWorkSpaceNpmInstallNew :
87- ExecNpmInstallNew ( node ) ;
90+ ExecNpmInstallNew ( fileNode ) ;
8891 return VSConstants . S_OK ;
8992
9093 case PkgCmdId . cmdidWorkSpaceNpmUpdate :
91- ExecNpmUpdate ( node ) ;
94+ ExecNpmUpdate ( fileNode ) ;
9295 return VSConstants . S_OK ;
9396 }
9497
9598 if ( nCmdID >= PkgCmdId . cmdidWorkSpaceNpmDynamicScript && nCmdID < PkgCmdId . cmdidWorkSpaceNpmDynamicScriptMax )
9699 {
97- ExecDynamic ( node , nCmdID ) ;
100+ ExecDynamic ( fileNode , nCmdID ) ;
98101 return VSConstants . S_OK ;
99102 }
100103 }
@@ -116,44 +119,42 @@ public int Exec(List<WorkspaceVisualNodeBase> selection, Guid pguidCmdGroup, uin
116119 // Note: all the Exec commands are async, this allows us to call them in a fire and forget
117120 // pattern, without blocking the UI or losing any logging
118121
119- private async void ExecNpmInstallMissing ( WorkspaceVisualNodeBase node )
122+ private async void ExecNpmInstallMissing ( string filePath )
120123 {
121- using ( var npmController = this . CreateController ( node . Workspace ) )
124+ using ( var npmController = this . CreateController ( filePath ) )
122125 using ( var commander = npmController . CreateNpmCommander ( ) )
123126 {
124127 await commander . Install ( ) ;
125128 }
126129 }
127130
128- private void ExecNpmInstallNew ( WorkspaceVisualNodeBase node )
131+ private void ExecNpmInstallNew ( string filePath )
129132 {
130- using ( var npmController = this . CreateController ( node . Workspace ) )
133+ using ( var npmController = this . CreateController ( filePath ) )
131134 using ( var npmWorker = new NpmWorker ( npmController ) )
132135 using ( var manager = new NpmPackageInstallWindow ( npmController , npmWorker ) )
133136 {
134137 manager . ShowModal ( ) ;
135138 }
136139 }
137140
138- private async void ExecNpmUpdate ( WorkspaceVisualNodeBase node )
141+ private async void ExecNpmUpdate ( string filePath )
139142 {
140- using ( var npmController = this . CreateController ( node . Workspace ) )
143+ using ( var npmController = this . CreateController ( filePath ) )
141144 using ( var commander = npmController . CreateNpmCommander ( ) )
142145 {
143146 await commander . UpdatePackagesAsync ( ) ;
144147 }
145148 }
146149
147- private async void ExecDynamic ( WorkspaceVisualNodeBase node , uint nCmdID )
150+ private async void ExecDynamic ( string filePath , uint nCmdID )
148151 {
149152 // Unfortunately the NpmController (and NpmCommander), used for the install and update commands
150153 // doesn't support running arbitrary scripts. And changing that is outside
151154 // the scope of these changes.
152- var filePath = ( ( IFileNode ) node ) . FullPath ;
153155 if ( TryGetCommand ( nCmdID , filePath , out var commandName ) )
154156 {
155-
156- using ( var npmController = this . CreateController ( node . Workspace ) )
157+ using ( var npmController = this . CreateController ( filePath ) )
157158 using ( var commander = npmController . CreateNpmCommander ( ) )
158159 {
159160 await commander . ExecuteNpmCommandAsync ( $ "run-script { commandName } ", showConsole : true ) ;
@@ -166,8 +167,13 @@ private async void ExecDebugAsync(WorkspaceVisualNodeBase node)
166167 var workspace = node . Workspace ;
167168 var packageJson = PackageJsonFactory . Create ( ( ( IFileNode ) node ) . FullPath ) ;
168169
170+ if ( string . IsNullOrEmpty ( packageJson . Main ) )
171+ {
172+ return ;
173+ }
174+
169175 //invoke debuglaunchtargetprovider on this file
170- var fileContextActions = await node . Workspace . GetFileContextActionsAsync ( packageJson . Main , new [ ] { DebugLaunchActionContext . ContextTypeGuid } ) ;
176+ var fileContextActions = await workspace . GetFileContextActionsAsync ( packageJson . Main , new [ ] { DebugLaunchActionContext . ContextTypeGuid } ) ;
171177 if ( fileContextActions . Any ( ) )
172178 {
173179 // we requested a single context, so there should be a single grouping. Use the First action, since they're ordered by priority.
@@ -265,9 +271,12 @@ private static bool TryGetCommand(uint nCmdID, string filePath, out string comma
265271 return false ;
266272 }
267273
268- private INpmController CreateController ( IWorkspace workspace )
274+ private INpmController CreateController ( string packageJsonPath )
269275 {
270- var projectHome = workspace . Location ;
276+ Debug . Assert ( Path . IsPathRooted ( packageJsonPath ) ) ;
277+ Debug . Assert ( PackageJsonFactory . IsPackageJsonFile ( packageJsonPath ) ) ;
278+
279+ var projectHome = Path . GetDirectoryName ( packageJsonPath ) ;
271280
272281 var npmController = NpmControllerFactory . Create (
273282 projectHome ,
0 commit comments