diff --git a/Nodejs/Product/Nodejs/Project/ProjectResources.cs b/Nodejs/Product/Nodejs/Project/ProjectResources.cs index 3f90b1c98..25cbc92d8 100644 --- a/Nodejs/Product/Nodejs/Project/ProjectResources.cs +++ b/Nodejs/Product/Nodejs/Project/ProjectResources.cs @@ -163,6 +163,7 @@ internal class SR : CommonSR { internal const string PropertiesClassLocalSubPackage = "PropertiesClassLocalSubPackage"; internal const string PropertiesClassNpm = "PropertiesClassNpm"; internal const string ReplInitializationMessage = "ReplInitializationMessage"; + internal const string ReplWindowNpmInitNoYesFlagWarning = "ReplWindowNpmInitNoYesFlagWarning"; internal const string RequestedVersionRangeNone = "RequestedVersionRangeNone"; internal const string ScriptArgumentsToolTip = "ScriptArgumentsToolTip"; internal const string ScriptFileToolTip = "ScriptFileTooltip"; diff --git a/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs b/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs index 7fb7c2b2d..6cc8e3fa1 100644 --- a/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs +++ b/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs @@ -58,8 +58,15 @@ public async Task Execute(IReplWindow window, string arguments) // at beginning and end of string (e.g. '--global') npmArguments = string.Format(" {0} ", npmArguments); + // Prevent running `npm init` without the `-y` flag since it will freeze the repl window, + // waiting for user input that will never come. + if (npmArguments.Contains(" init ") && !(npmArguments.Contains(" -y ") || npmArguments.Contains(" --yes "))) { + window.WriteError(SR.GetString(SR.ReplWindowNpmInitNoYesFlagWarning)); + return ExecutionResult.Failure; + } + var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution; - IEnumerable loadedProjects = solution.EnumerateLoadedProjects(onlyNodeProjects: true); + IEnumerable loadedProjects = solution.EnumerateLoadedProjects(onlyNodeProjects: false); var projectNameToDirectoryDictionary = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (IVsProject project in loadedProjects) { @@ -76,19 +83,33 @@ public async Task Execute(IReplWindow window, string arguments) continue; } - EnvDTE.Properties properties = dteProject.Properties; - if (dteProject.Properties == null) { + string projectName = dteProject.Name; + if (string.IsNullOrEmpty(projectName)) { continue; } - string projectName = dteProject.Name; - EnvDTE.Property projectHome = properties.Item("ProjectHome"); - if (projectHome == null || projectName == null) { - continue; + // Try checking the `ProjectHome` property first + EnvDTE.Properties properties = dteProject.Properties; + if (dteProject.Properties != null) { + EnvDTE.Property projectHome = null; + try { + projectHome = properties.Item("ProjectHome"); + } catch (ArgumentException) { + // noop + } + + if (projectHome != null) { + var projectHomeDirectory = projectHome.Value as string; + if (!string.IsNullOrEmpty(projectHomeDirectory)) { + projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectHomeDirectory, hierarchy)); + continue; + } + } } - var projectDirectory = projectHome.Value as string; - if (projectDirectory != null) { + // Otherwise, fall back to using fullname + string projectDirectory = Path.GetDirectoryName(dteProject.FullName); + if (!string.IsNullOrEmpty(projectDirectory)) { projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectDirectory, hierarchy)); } } @@ -118,7 +139,7 @@ public async Task Execute(IReplWindow window, string arguments) // In case someone copies filename string projectDirectoryPath = File.Exists(projectPath) ? Path.GetDirectoryName(projectPath) : projectPath; - if (!isGlobalCommand && !(Directory.Exists(projectDirectoryPath) && File.Exists(Path.Combine(projectDirectoryPath, "package.json")))) { + if (!isGlobalCommand && !Directory.Exists(projectDirectoryPath)) { window.WriteError("Please specify a valid Node.js project or project directory. If your solution contains multiple projects, specify a target project using .npm [ProjectName or ProjectDir] For example: .npm [MyApp] list"); return ExecutionResult.Failure; } @@ -137,7 +158,6 @@ public async Task Execute(IReplWindow window, string arguments) } var npmReplRedirector = new NpmReplRedirector(window); - await ExecuteNpmCommandAsync( npmReplRedirector, npmPath, diff --git a/Nodejs/Product/Nodejs/Resources.resx b/Nodejs/Product/Nodejs/Resources.resx index 7fdf07e1f..c9daeaf7a 100644 --- a/Nodejs/Product/Nodejs/Resources.resx +++ b/Nodejs/Product/Nodejs/Resources.resx @@ -473,6 +473,9 @@ NAME2=value2 Node.js interactive window. Type .help for a list of commands. + + Please run '.npm init -y' to create a new package.json file. + Specifies the path to the node.exe executable.