available = null;
-
- string json = br.DocumentText;
- if (!string.IsNullOrEmpty(json)) {
- int startIndex = json.IndexOf("");
- if (startIndex > 0) {
- int endIndex = json.IndexOf("", startIndex);
- if (endIndex > 0) {
- json = json.Substring(startIndex + 5, endIndex - startIndex - 5);
-
- try {
- // Example JSON data returned by the server:
- //{
- // "cannotvoteagain": [],
- // "notvoted": [
- // "http://ptvs.azurewebsites.net/news/141",
- // "http://ptvs.azurewebsites.net/news/41",
- // ],
- // "canvoteagain": [
- // "http://ptvs.azurewebsites.net/news/51"
- // ]
- //}
-
- // Description of each list:
- // voted: cookie found
- // notvoted: cookie not found
- // canvoteagain: cookie found, but multiple votes are allowed
- JavaScriptSerializer serializer = new JavaScriptSerializer();
- var results = serializer.Deserialize>>(json);
- available = results["notvoted"];
- } catch (ArgumentException) {
- } catch (InvalidOperationException) {
- }
- }
- }
- }
-
- if (available != null && available.Count > 0) {
- BrowseSurveyNews(available[0]);
- } else if (warnIfNoneAvailable) {
- if (available != null) {
- BrowseSurveyNews(GeneralOptionsPage.SurveyNewsIndexUrl);
- } else {
- BrowseSurveyNews(NodejsToolsInstallPath.GetFile("NoSurveyNewsFeed.html"));
- }
- }
-
- Application.ExitThread();
- }
- }
-
- internal void CheckSurveyNews(bool forceCheckAndWarnIfNoneAvailable) {
- bool shouldQueryServer = false;
- if (forceCheckAndWarnIfNoneAvailable) {
- shouldQueryServer = true;
- } else {
- shouldQueryServer = true;
- var options = GeneralOptionsPage;
- // Ensure that we don't prompt the user on their very first project creation.
- // Delay by 3 days by pretending we checked 4 days ago (the default of check
- // once a week ensures we'll check again in 3 days).
- if (options.SurveyNewsLastCheck == DateTime.MinValue) {
- options.SurveyNewsLastCheck = DateTime.Now - TimeSpan.FromDays(4);
- options.SaveSettingsToStorage();
- }
-
- var elapsedTime = DateTime.Now - options.SurveyNewsLastCheck;
- switch (options.SurveyNewsCheck) {
- case SurveyNewsPolicy.Disabled:
- break;
- case SurveyNewsPolicy.CheckOnceDay:
- shouldQueryServer = elapsedTime.TotalDays >= 1;
- break;
- case SurveyNewsPolicy.CheckOnceWeek:
- shouldQueryServer = elapsedTime.TotalDays >= 7;
- break;
- case SurveyNewsPolicy.CheckOnceMonth:
- shouldQueryServer = elapsedTime.TotalDays >= 30;
- break;
- default:
- Debug.Assert(false, String.Format("Unexpected SurveyNewsPolicy: {0}.", options.SurveyNewsCheck));
- break;
- }
- }
-
- if (shouldQueryServer) {
- var options = GeneralOptionsPage;
- options.SurveyNewsLastCheck = DateTime.Now;
- options.SaveSettingsToStorage();
- CheckSurveyNewsThread(new Uri(options.SurveyNewsFeedUrl), forceCheckAndWarnIfNoneAvailable);
- }
- }
-
- internal static void NavigateTo(string filename, int line, int col) {
- VsUtilities.NavigateTo(Instance, filename, NodejsProjectNode.IsNodejsFile(filename) ? typeof(NodejsEditorFactory).GUID : Guid.Empty, line, col);
- }
-
- internal static void NavigateTo(string filename, int pos) {
- VsUtilities.NavigateTo(Instance, filename, NodejsProjectNode.IsNodejsFile(filename) ? typeof(NodejsEditorFactory).GUID : Guid.Empty, pos);
- }
-
- ///
- /// The analyzer which is used for loose files.
- ///
- internal VsProjectAnalyzer DefaultAnalyzer {
- get {
- if (_analyzer == null) {
- _analyzer = new VsProjectAnalyzer();
- LogLooseFileAnalysisLevel();
- _analyzer.MaxLogLength = IntellisenseOptionsPage.AnalysisLogMax;
- IntellisenseOptionsPage.AnalysisLevelChanged += IntellisenseOptionsPageAnalysisLevelChanged;
- IntellisenseOptionsPage.SaveToDiskChanged += IntellisenseOptionsPageSaveToDiskChanged;
- }
- return _analyzer;
- }
- }
-
- private void IntellisenseOptionsPageSaveToDiskChanged(object sender, EventArgs e) {
- _analyzer.SaveToDisk = IntellisenseOptionsPage.SaveToDisk;
- }
-
- private void IntellisenseOptionsPageAnalysisLevelChanged(object sender, EventArgs e) {
- var analyzer = new VsProjectAnalyzer();
- analyzer.SwitchAnalyzers(_analyzer);
- if (_analyzer.RemoveUser()) {
- _analyzer.Dispose();
- }
- _analyzer = analyzer;
- LogLooseFileAnalysisLevel();
- }
-
- private void LogLooseFileAnalysisLevel() {
- var analyzer = _analyzer;
- if(analyzer != null)
- {
- var val = analyzer.AnalysisLevel;
- _logger.LogEvent(NodejsToolsLogEvent.AnalysisLevel, (int)val);
- }
- }
-
-
-#if UNIT_TEST_INTEGRATION
- // var testCase = require('./test/test-doubled.js'); for(var x in testCase) { console.log(x); }
- public static string EvaluateJavaScript(string code) {
- // TODO: Escaping code
- string args = "-e \"" + code + "\"";
- var psi = new ProcessStartInfo(NodePath, args);
- psi.RedirectStandardOutput = true;
- psi.RedirectStandardError = true;
- var proc = Process.Start(psi);
- var outpReceiver = new OutputReceiver();
- proc.OutputDataReceived += outpReceiver.DataRead;
- proc.BeginErrorReadLine();
- proc.BeginOutputReadLine();
-
- return outpReceiver._data.ToString();
- }
-
- private void GetTestCases(string module) {
- var testCases = EvaluateJavaScript(
- String.Format("var testCase = require('{0}'); for(var x in testCase) { console.log(x); }", module));
- foreach (var testCase in testCases.Split(new[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) {
- }
- }
-
- class OutputReceiver {
- internal readonly StringBuilder _data = new StringBuilder();
-
- public void DataRead(object sender, DataReceivedEventArgs e) {
- if (e.Data != null) {
- _data.Append(e.Data);
- }
- }
- }
-#endif
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Web.Script.Serialization;
+using System.Windows.Forms;
+using Microsoft.NodejsTools.Analysis;
+using Microsoft.NodejsTools.Commands;
+using Microsoft.NodejsTools.Debugger.DataTips;
+using Microsoft.NodejsTools.Debugger.DebugEngine;
+using Microsoft.NodejsTools.Debugger.Remote;
+using Microsoft.NodejsTools.Intellisense;
+using Microsoft.NodejsTools.Jade;
+using Microsoft.NodejsTools.Logging;
+using Microsoft.NodejsTools.Options;
+using Microsoft.NodejsTools.Project;
+using Microsoft.NodejsTools.ProjectWizard;
+using Microsoft.NodejsTools.Repl;
+using Microsoft.NodejsTools.Telemetry;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.ComponentModelHost;
+using Microsoft.VisualStudio.Debugger.Interop;
+using Microsoft.VisualStudio.OLE.Interop;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.TextManager.Interop;
+using Microsoft.VisualStudio.Utilities;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using Microsoft.Win32;
+
+namespace Microsoft.NodejsTools {
+ ///
+ /// This is the class that implements the package exposed by this assembly.
+ ///
+ /// The minimum requirement for a class to be considered a valid package for Visual Studio
+ /// is to implement the IVsPackage interface and register itself with the shell.
+ /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
+ /// to do it: it derives from the Package class that provides the implementation of the
+ /// IVsPackage interface and uses the registration attributes defined in the framework to
+ /// register itself and its components with the shell.
+ ///
+ // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
+ // a package.
+ [PackageRegistration(UseManagedResourcesOnly = true)]
+ // This attribute is used to register the information needed to show this package
+ // in the Help/About dialog of Visual Studio.
+ [InstalledProductRegistration("#110", "#112", AssemblyVersionInfo.Version, IconResourceID = 400)]
+ [Guid(Guids.NodejsPackageString)]
+ [ProvideOptionPage(typeof(NodejsGeneralOptionsPage), "Node.js Tools", "General", 114, 115, true)]
+ [ProvideOptionPage(typeof(NodejsNpmOptionsPage), "Node.js Tools", "Npm", 114, 116, true)]
+ [ProvideDebugEngine("Node.js Debugging", typeof(AD7ProgramProvider), typeof(AD7Engine), AD7Engine.DebugEngineId, setNextStatement: false, hitCountBp: true, justMyCodeStepping: false)]
+ [ProvideLanguageService(typeof(NodejsLanguageInfo), NodejsConstants.Nodejs, 106, RequestStockColors = true, ShowSmartIndent = true, ShowCompletion = true, DefaultToInsertSpaces = true, HideAdvancedMembersByDefault = true, EnableAdvancedMembersOption = true, ShowDropDownOptions = true)]
+ [ProvideDebugLanguage(NodejsConstants.Nodejs, Guids.NodejsDebugLanguageString, NodeExpressionEvaluatorGuid, AD7Engine.DebugEngineId)]
+ [WebSiteProject("JavaScript", "JavaScript")]
+ [ProvideProjectFactory(typeof(NodejsProjectFactory), null, null, null, null, ".\\NullPath", LanguageVsTemplate = NodejsConstants.JavaScript, SortPriority=0x17)] // outer flavor, no file extension
+ [ProvideDebugPortSupplier("Node remote debugging", typeof(NodeRemoteDebugPortSupplier), NodeRemoteDebugPortSupplier.PortSupplierId)]
+ [ProvideMenuResource(1000, 1)] // This attribute is needed to let the shell know that this package exposes some menus.
+ [ProvideBraceCompletion(NodejsConstants.Nodejs)]
+ [ProvideEditorExtension2(typeof(NodejsEditorFactory), NodeJsFileType, 50, "*:1", ProjectGuid = "{78D985FC-2CA0-4D08-9B6B-35ACD5E5294A}", NameResourceID = 102, DefaultName = "server", TemplateDir = ".\\NullPath")]
+ [ProvideEditorExtension2(typeof(NodejsEditorFactoryPromptForEncoding), NodeJsFileType, 50, "*:1", ProjectGuid = "{78D985FC-2CA0-4D08-9B6B-35ACD5E5294A}", NameResourceID = 113, DefaultName = "server")]
+ [ProvideEditorLogicalView(typeof(NodejsEditorFactory), VSConstants.LOGVIEWID.TextView_string)]
+ [ProvideEditorLogicalView(typeof(NodejsEditorFactoryPromptForEncoding), VSConstants.LOGVIEWID.TextView_string)]
+ [ProvideProjectItem(typeof(BaseNodeProjectFactory), NodejsConstants.Nodejs, "FileTemplates\\NewItem", 0)]
+ [ProvideLanguageTemplates("{349C5851-65DF-11DA-9384-00065B846F21}", NodejsConstants.JavaScript, Guids.NodejsPackageString, "Web", "Node.js Project Templates", "{" + Guids.NodejsBaseProjectFactoryString + "}", ".js", NodejsConstants.Nodejs, "{" + Guids.NodejsBaseProjectFactoryString + "}")]
+ [ProvideTextEditorAutomation(NodejsConstants.Nodejs, 106, 102, ProfileMigrationType.PassThrough)]
+ [ProvideLanguageService(typeof(JadeLanguageInfo), JadeContentTypeDefinition.JadeLanguageName, 3041, RequestStockColors = true, ShowSmartIndent = false, ShowCompletion = false, DefaultToInsertSpaces = true, HideAdvancedMembersByDefault = false, EnableAdvancedMembersOption = false, ShowDropDownOptions = false)]
+ [ProvideEditorExtension2(typeof(JadeEditorFactory), JadeContentTypeDefinition.JadeFileExtension, 50, __VSPHYSICALVIEWATTRIBUTES.PVA_SupportsPreview, "*:1", ProjectGuid = VSConstants.CLSID.MiscellaneousFilesProject_string, NameResourceID = 3041, EditorNameResourceId = 3045)]
+ [ProvideEditorLogicalView(typeof(JadeEditorFactory), VSConstants.LOGVIEWID.TextView_string)]
+ [ProvideLanguageExtension(typeof(JadeEditorFactory), JadeContentTypeDefinition.JadeFileExtension)]
+ [ProvideTextEditorAutomation(JadeContentTypeDefinition.JadeLanguageName, 3041, 3045, ProfileMigrationType.PassThrough)]
+ [ProvideLanguageEditorOptionPage(typeof(NodejsFormattingSpacingOptionsPage), NodejsConstants.Nodejs, "Formatting", "Spacing", "3042")]
+ [ProvideLanguageEditorOptionPage(typeof(NodejsFormattingBracesOptionsPage), NodejsConstants.Nodejs, "Formatting", "Braces", "3043")]
+ [ProvideLanguageEditorOptionPage(typeof(NodejsFormattingGeneralOptionsPage), NodejsConstants.Nodejs, "Formatting", "General", "3044")]
+ [ProvideLanguageEditorOptionPage(typeof(NodejsIntellisenseOptionsPage), NodejsConstants.Nodejs, "IntelliSense", "", "3048")]
+ [ProvideLanguageEditorOptionPage(typeof(NodejsAdvancedEditorOptionsPage), NodejsConstants.Nodejs, "Advanced", "", "3050")]
+ [ProvideCodeExpansions(Guids.NodejsLanguageInfoString, false, 106, "Nodejs", @"Snippets\%LCID%\SnippetsIndex.xml", @"Snippets\%LCID%\Nodejs\")]
+ [ProvideCodeExpansionPath("Nodejs", "Test", @"Snippets\%LCID%\Test\")]
+ internal sealed partial class NodejsPackage : CommonPackage {
+ internal const string NodeExpressionEvaluatorGuid = "{F16F2A71-1C45-4BAB-BECE-09D28CFDE3E6}";
+ private IContentType _contentType;
+ internal const string NodeJsFileType = ".njs";
+ internal static NodejsPackage Instance;
+ private string _surveyNewsUrl;
+ private object _surveyNewsUrlLock = new object();
+ internal HashSet ChangedBuffers = new HashSet();
+ private LanguagePreferences _langPrefs;
+ internal VsProjectAnalyzer _analyzer;
+ private NodejsToolsLogger _logger;
+ private ITelemetryLogger _telemetryLogger;
+ // Hold references for the subscribed events. Otherwise the callbacks will be garbage collected
+ // after the initialization
+ private List _subscribedCommandEvents = new List();
+
+ ///
+ /// Default constructor of the package.
+ /// Inside this method you can place any initialization code that does not require
+ /// any Visual Studio service because at this point the package object is created but
+ /// not sited yet inside Visual Studio environment. The place to do all the other
+ /// initialization is the Initialize method.
+ ///
+ public NodejsPackage() {
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
+ Debug.Assert(Instance == null, "NodejsPackage created multiple times");
+ Instance = this;
+ }
+
+ public NodejsGeneralOptionsPage GeneralOptionsPage {
+ get {
+ return (NodejsGeneralOptionsPage)GetDialogPage(typeof(NodejsGeneralOptionsPage));
+ }
+ }
+
+ public NodejsNpmOptionsPage NpmOptionsPage {
+ get {
+ return (NodejsNpmOptionsPage)GetDialogPage(typeof(NodejsNpmOptionsPage));
+ }
+ }
+
+ public NodejsFormattingSpacingOptionsPage FormattingSpacingOptionsPage {
+ get {
+ return (NodejsFormattingSpacingOptionsPage)GetDialogPage(typeof(NodejsFormattingSpacingOptionsPage));
+ }
+ }
+
+ public NodejsFormattingBracesOptionsPage FormattingBracesOptionsPage {
+ get {
+ return (NodejsFormattingBracesOptionsPage)GetDialogPage(typeof(NodejsFormattingBracesOptionsPage));
+ }
+ }
+
+ public NodejsFormattingGeneralOptionsPage FormattingGeneralOptionsPage {
+ get {
+ return (NodejsFormattingGeneralOptionsPage)GetDialogPage(typeof(NodejsFormattingGeneralOptionsPage));
+ }
+ }
+
+ public NodejsIntellisenseOptionsPage IntellisenseOptionsPage {
+ get {
+ return (NodejsIntellisenseOptionsPage)GetDialogPage(typeof(NodejsIntellisenseOptionsPage));
+ }
+ }
+
+ public NodejsAdvancedEditorOptionsPage AdvancedEditorOptionsPage {
+ get {
+ return (NodejsAdvancedEditorOptionsPage)GetDialogPage(typeof(NodejsAdvancedEditorOptionsPage));
+ }
+ }
+
+ public NodejsDiagnosticsOptionsPage DiagnosticsOptionsPage {
+ get {
+ return (NodejsDiagnosticsOptionsPage)GetDialogPage(typeof(NodejsDiagnosticsOptionsPage));
+ }
+ }
+
+ public EnvDTE.DTE DTE {
+ get {
+ return (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Overridden Package Implementation
+ #region Package Members
+
+ ///
+ /// Initialization of the package; this method is called right after the package is sited, so this is the place
+ /// where you can put all the initialization code that rely on services provided by VisualStudio.
+ ///
+ protected override void Initialize() {
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
+ base.Initialize();
+
+ SubscribeToVsCommandEvents(
+ (int)VSConstants.VSStd97CmdID.AddNewProject,
+ delegate { NewProjectFromExistingWizard.IsAddNewProjectCmd = true; },
+ delegate { NewProjectFromExistingWizard.IsAddNewProjectCmd = false; }
+ );
+
+ var langService = new NodejsLanguageInfo(this);
+ ((IServiceContainer)this).AddService(langService.GetType(), langService, true);
+
+ ((IServiceContainer)this).AddService(typeof(ClipboardServiceBase), new ClipboardService(), true);
+
+ RegisterProjectFactory(new NodejsProjectFactory(this));
+ RegisterEditorFactory(new NodejsEditorFactory(this));
+ RegisterEditorFactory(new NodejsEditorFactoryPromptForEncoding(this));
+ RegisterEditorFactory(new JadeEditorFactory(this));
+
+ // Add our command handlers for menu (commands must exist in the .vsct file)
+ var commands = new List {
+ new OpenReplWindowCommand(),
+ new OpenRemoteDebugProxyFolderCommand(),
+ new OpenRemoteDebugDocumentationCommand(),
+ new SurveyNewsCommand(),
+ new ImportWizardCommand(),
+ new DiagnosticsCommand(this)
+ };
+ try {
+ commands.Add(new AzureExplorerAttachDebuggerCommand());
+ } catch (NotSupportedException) {
+ }
+ RegisterCommands(commands, Guids.NodejsCmdSet);
+
+ IVsTextManager textMgr = (IVsTextManager)Instance.GetService(typeof(SVsTextManager));
+
+ var langPrefs = new LANGPREFERENCES[1];
+ langPrefs[0].guidLang = typeof(NodejsLanguageInfo).GUID;
+ ErrorHandler.ThrowOnFailure(textMgr.GetUserPreferences(null, null, langPrefs, null));
+ _langPrefs = new LanguagePreferences(langPrefs[0]);
+
+ var textManagerEvents2Guid = typeof(IVsTextManagerEvents2).GUID;
+ IConnectionPoint textManagerEvents2ConnectionPoint;
+ ((IConnectionPointContainer)textMgr).FindConnectionPoint(ref textManagerEvents2Guid, out textManagerEvents2ConnectionPoint);
+ uint cookie;
+ textManagerEvents2ConnectionPoint.Advise(_langPrefs, out cookie);
+
+ var textManagerEventsGuid = typeof(IVsTextManagerEvents).GUID;
+ IConnectionPoint textManagerEventsConnectionPoint;
+ ((IConnectionPointContainer)textMgr).FindConnectionPoint(ref textManagerEventsGuid, out textManagerEventsConnectionPoint);
+ textManagerEventsConnectionPoint.Advise(new DataTipTextManagerEvents(this), out cookie);
+
+ MakeDebuggerContextAvailable();
+
+ IntellisenseOptionsPage.AnalysisLogMaximumChanged += IntellisenseOptionsPage_AnalysisLogMaximumChanged;
+
+ InitializeLogging();
+
+ InitializeTelemetry();
+
+ // The variable is inherited by child processes backing Test Explorer, and is used in
+ // the NTVS test discoverer and test executor to connect back to VS.
+ Environment.SetEnvironmentVariable(NodejsConstants.NodeToolsProcessIdEnvironmentVariable, Process.GetCurrentProcess().Id.ToString());
+ }
+
+ private void SubscribeToVsCommandEvents(
+ int eventId,
+ EnvDTE._dispCommandEvents_BeforeExecuteEventHandler beforeExecute = null,
+ EnvDTE._dispCommandEvents_AfterExecuteEventHandler afterExecute = null) {
+ var commandEventGuid = typeof(VSConstants.VSStd97CmdID).GUID.ToString("B");
+ var targetEvent = DTE.Events.CommandEvents[commandEventGuid, eventId];
+ if (beforeExecute != null) {
+ targetEvent.BeforeExecute += beforeExecute;
+ }
+ if (afterExecute != null) {
+ targetEvent.AfterExecute += afterExecute;
+ }
+ _subscribedCommandEvents.Add(targetEvent);
+ }
+
+
+ private void IntellisenseOptionsPage_AnalysisLogMaximumChanged(object sender, EventArgs e) {
+ if (_analyzer != null) {
+ _analyzer.MaxLogLength = IntellisenseOptionsPage.AnalysisLogMax;
+ }
+ }
+
+ private void InitializeLogging() {
+ _logger = new NodejsToolsLogger(ComponentModel.GetExtensions().ToArray());
+
+ // log interesting stats on startup
+ _logger.LogEvent(NodejsToolsLogEvent.SurveyNewsFrequency, GeneralOptionsPage.SurveyNewsCheck);
+ _logger.LogEvent(NodejsToolsLogEvent.AnalysisLevel, IntellisenseOptionsPage.AnalysisLevel);
+ }
+
+ private void InitializeTelemetry() {
+ var thisAssembly = typeof(NodejsPackage).Assembly;
+
+ // Get telemetry logger
+ _telemetryLogger = TelemetrySetup.Instance.GetLogger(thisAssembly);
+
+ TelemetrySetup.Instance.LogPackageLoad(_telemetryLogger, Guid.Parse(Guids.NodejsPackageString), thisAssembly, Application.ProductVersion);
+ }
+
+ public new IComponentModel ComponentModel {
+ get {
+ return this.GetComponentModel();
+ }
+ }
+
+ internal NodejsToolsLogger Logger {
+ get {
+ return _logger;
+ }
+ }
+
+ internal ITelemetryLogger TelemetryLogger {
+ get {
+ return _telemetryLogger;
+ }
+ }
+
+ ///
+ /// Makes the debugger context available - this enables our debugger when we're installed into
+ /// a SKU which doesn't support every installed debugger.
+ ///
+ private void MakeDebuggerContextAvailable() {
+ var monitorSelection = (IVsMonitorSelection)GetService(typeof(SVsShellMonitorSelection));
+ Guid debugEngineGuid = AD7Engine.DebugEngineGuid;
+ uint contextCookie;
+ if (ErrorHandler.Succeeded(monitorSelection.GetCmdUIContextCookie(ref debugEngineGuid, out contextCookie))) {
+ ErrorHandler.ThrowOnFailure(monitorSelection.SetCmdUIContext(contextCookie, 1));
+ }
+ }
+
+ internal IReplWindow2 OpenReplWindow(bool focus = true) {
+ var compModel = ComponentModel;
+ var provider = compModel.GetService();
+
+ var window = (IReplWindow2)provider.FindReplWindow(NodejsReplEvaluatorProvider.NodeReplId);
+ if (window == null) {
+ window = (IReplWindow2)provider.CreateReplWindow(
+ ReplContentType,
+ "Node.js Interactive Window",
+ typeof(NodejsLanguageInfo).GUID,
+ NodejsReplEvaluatorProvider.NodeReplId
+ );
+ }
+
+ IVsWindowFrame windowFrame = (IVsWindowFrame)((ToolWindowPane)window).Frame;
+ ErrorHandler.ThrowOnFailure(windowFrame.Show());
+
+ if (focus) {
+ window.Focus();
+ }
+
+ return window;
+ }
+
+ internal static bool TryGetStartupFileAndDirectory(System.IServiceProvider serviceProvider, out string fileName, out string directory) {
+ var startupProject = GetStartupProject(serviceProvider);
+ if (startupProject != null) {
+ fileName = startupProject.GetStartupFile();
+ directory = startupProject.GetWorkingDirectory();
+ } else {
+ var textView = CommonPackage.GetActiveTextView(serviceProvider);
+ if (textView == null) {
+ fileName = null;
+ directory = null;
+ return false;
+ }
+ fileName = textView.GetFilePath();
+ directory = Path.GetDirectoryName(fileName);
+ }
+ return true;
+ }
+
+ private static string remoteDebugProxyFolder = null;
+
+ internal LanguagePreferences LangPrefs {
+ get {
+ return _langPrefs;
+ }
+ }
+
+ public static string RemoteDebugProxyFolder {
+ get {
+ // Lazily evaluated
+ if (remoteDebugProxyFolder != null) {
+ return remoteDebugProxyFolder;
+ }
+
+ const string ROOT_KEY = "Software\\Microsoft\\NodeJSTools\\" + AssemblyVersionInfo.VSVersion;
+
+ // Try HKCU
+ try {
+ using (RegistryKey node = Registry.CurrentUser.OpenSubKey(ROOT_KEY)) {
+ if (node != null) {
+ remoteDebugProxyFolder = (string)node.GetValue("RemoteDebugProxyFolder");
+ }
+ }
+ } catch (Exception) {
+ }
+
+ // Try HKLM
+ if (remoteDebugProxyFolder == null) {
+ try {
+ using (RegistryKey node = Registry.LocalMachine.OpenSubKey(ROOT_KEY)) {
+ if (node != null) {
+ remoteDebugProxyFolder = (string)node.GetValue("RemoteDebugProxyFolder");
+ }
+ }
+ } catch (Exception) {
+ }
+ }
+
+ return remoteDebugProxyFolder;
+ }
+ }
+
+ private IContentType ReplContentType {
+ get {
+ if (_contentType == null) {
+ _contentType = ComponentModel.GetService().GetContentType(NodejsConstants.Nodejs);
+ }
+ return _contentType;
+ }
+ }
+
+ #endregion
+
+ internal override VisualStudioTools.Navigation.LibraryManager CreateLibraryManager(CommonPackage package) {
+ return new NodejsLibraryManager(this);
+ }
+
+ public override Type GetLibraryManagerType() {
+ return typeof(NodejsLibraryManager);
+ }
+
+ public override bool IsRecognizedFile(string filename) {
+ var ext = Path.GetExtension(filename);
+
+ return String.Equals(ext, NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase);
+ }
+
+ internal new object GetService(Type serviceType) {
+ return base.GetService(serviceType);
+ }
+
+ public static string NodejsReferencePath {
+ get {
+ return Path.Combine(
+ Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ "nodejsref.js"
+ );
+ }
+ }
+
+ public string BrowseForFileOpen(IntPtr owner, string filter, string initialPath = null) {
+ if (string.IsNullOrEmpty(initialPath)) {
+ initialPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar;
+ }
+
+ IVsUIShell uiShell = GetService(typeof(SVsUIShell)) as IVsUIShell;
+ if (null == uiShell) {
+ using (var sfd = new System.Windows.Forms.OpenFileDialog()) {
+ sfd.AutoUpgradeEnabled = true;
+ sfd.Filter = filter;
+ sfd.FileName = Path.GetFileName(initialPath);
+ sfd.InitialDirectory = Path.GetDirectoryName(initialPath);
+ DialogResult result;
+ if (owner == IntPtr.Zero) {
+ result = sfd.ShowDialog();
+ } else {
+ result = sfd.ShowDialog(NativeWindow.FromHandle(owner));
+ }
+ if (result == DialogResult.OK) {
+ return sfd.FileName;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ if (owner == IntPtr.Zero) {
+ ErrorHandler.ThrowOnFailure(uiShell.GetDialogOwnerHwnd(out owner));
+ }
+
+ VSOPENFILENAMEW[] openInfo = new VSOPENFILENAMEW[1];
+ openInfo[0].lStructSize = (uint)Marshal.SizeOf(typeof(VSOPENFILENAMEW));
+ openInfo[0].pwzFilter = filter.Replace('|', '\0') + "\0";
+ openInfo[0].hwndOwner = owner;
+ openInfo[0].nMaxFileName = 260;
+ var pFileName = Marshal.AllocCoTaskMem(520);
+ openInfo[0].pwzFileName = pFileName;
+ openInfo[0].pwzInitialDir = Path.GetDirectoryName(initialPath);
+ var nameArray = (Path.GetFileName(initialPath) + "\0").ToCharArray();
+ Marshal.Copy(nameArray, 0, pFileName, nameArray.Length);
+ try {
+ int hr = uiShell.GetOpenFileNameViaDlg(openInfo);
+ if (hr == VSConstants.OLE_E_PROMPTSAVECANCELLED) {
+ return null;
+ }
+ ErrorHandler.ThrowOnFailure(hr);
+ return Marshal.PtrToStringAuto(openInfo[0].pwzFileName);
+ } finally {
+ if (pFileName != IntPtr.Zero) {
+ Marshal.FreeCoTaskMem(pFileName);
+ }
+ }
+ }
+
+ public string BrowseForFileSave(IntPtr owner, string filter, string initialPath = null) {
+ if (string.IsNullOrEmpty(initialPath)) {
+ initialPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar;
+ }
+
+ IVsUIShell uiShell = GetService(typeof(SVsUIShell)) as IVsUIShell;
+ if (null == uiShell) {
+ using (var sfd = new System.Windows.Forms.SaveFileDialog()) {
+ sfd.AutoUpgradeEnabled = true;
+ sfd.Filter = filter;
+ sfd.FileName = Path.GetFileName(initialPath);
+ sfd.InitialDirectory = Path.GetDirectoryName(initialPath);
+ DialogResult result;
+ if (owner == IntPtr.Zero) {
+ result = sfd.ShowDialog();
+ } else {
+ result = sfd.ShowDialog(NativeWindow.FromHandle(owner));
+ }
+ if (result == DialogResult.OK) {
+ return sfd.FileName;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ if (owner == IntPtr.Zero) {
+ ErrorHandler.ThrowOnFailure(uiShell.GetDialogOwnerHwnd(out owner));
+ }
+
+ VSSAVEFILENAMEW[] saveInfo = new VSSAVEFILENAMEW[1];
+ saveInfo[0].lStructSize = (uint)Marshal.SizeOf(typeof(VSSAVEFILENAMEW));
+ saveInfo[0].pwzFilter = filter.Replace('|', '\0') + "\0";
+ saveInfo[0].hwndOwner = owner;
+ saveInfo[0].nMaxFileName = 260;
+ var pFileName = Marshal.AllocCoTaskMem(520);
+ saveInfo[0].pwzFileName = pFileName;
+ saveInfo[0].pwzInitialDir = Path.GetDirectoryName(initialPath);
+ var nameArray = (Path.GetFileName(initialPath) + "\0").ToCharArray();
+ Marshal.Copy(nameArray, 0, pFileName, nameArray.Length);
+ try {
+ int hr = uiShell.GetSaveFileNameViaDlg(saveInfo);
+ if (hr == VSConstants.OLE_E_PROMPTSAVECANCELLED) {
+ return null;
+ }
+ ErrorHandler.ThrowOnFailure(hr);
+ return Marshal.PtrToStringAuto(saveInfo[0].pwzFileName);
+ } finally {
+ if (pFileName != IntPtr.Zero) {
+ Marshal.FreeCoTaskMem(pFileName);
+ }
+ }
+ }
+
+ public string BrowseForDirectory(IntPtr owner, string initialDirectory = null) {
+ IVsUIShell uiShell = GetService(typeof(SVsUIShell)) as IVsUIShell;
+ if (null == uiShell) {
+ using (var ofd = new FolderBrowserDialog()) {
+ ofd.RootFolder = Environment.SpecialFolder.Desktop;
+ ofd.ShowNewFolderButton = false;
+ DialogResult result;
+ if (owner == IntPtr.Zero) {
+ result = ofd.ShowDialog();
+ } else {
+ result = ofd.ShowDialog(NativeWindow.FromHandle(owner));
+ }
+ if (result == DialogResult.OK) {
+ return ofd.SelectedPath;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ if (owner == IntPtr.Zero) {
+ ErrorHandler.ThrowOnFailure(uiShell.GetDialogOwnerHwnd(out owner));
+ }
+
+ VSBROWSEINFOW[] browseInfo = new VSBROWSEINFOW[1];
+ browseInfo[0].lStructSize = (uint)Marshal.SizeOf(typeof(VSBROWSEINFOW));
+ browseInfo[0].pwzInitialDir = initialDirectory;
+ browseInfo[0].hwndOwner = owner;
+ browseInfo[0].nMaxDirName = 260;
+ IntPtr pDirName = IntPtr.Zero;
+ try {
+ browseInfo[0].pwzDirName = pDirName = Marshal.AllocCoTaskMem(520);
+ int hr = uiShell.GetDirectoryViaBrowseDlg(browseInfo);
+ if (hr == VSConstants.OLE_E_PROMPTSAVECANCELLED) {
+ return null;
+ }
+ ErrorHandler.ThrowOnFailure(hr);
+ return Marshal.PtrToStringAuto(browseInfo[0].pwzDirName);
+ } finally {
+ if (pDirName != IntPtr.Zero) {
+ Marshal.FreeCoTaskMem(pDirName);
+ }
+ }
+ }
+
+ private void BrowseSurveyNewsOnIdle(object sender, ComponentManagerEventArgs e) {
+ this.OnIdle -= BrowseSurveyNewsOnIdle;
+
+ lock (_surveyNewsUrlLock) {
+ if (!string.IsNullOrEmpty(_surveyNewsUrl)) {
+ OpenVsWebBrowser(this, _surveyNewsUrl);
+ _surveyNewsUrl = null;
+ }
+ }
+ }
+
+ internal void BrowseSurveyNews(string url) {
+ lock (_surveyNewsUrlLock) {
+ _surveyNewsUrl = url;
+ }
+
+ this.OnIdle += BrowseSurveyNewsOnIdle;
+ }
+
+ private void CheckSurveyNewsThread(Uri url, bool warnIfNoneAvailable) {
+ // We can't use a simple WebRequest, because that doesn't have access
+ // to the browser's session cookies. Cookies are used to remember
+ // which survey/news item the user has submitted/accepted. The server
+ // checks the cookies and returns the survey/news urls that are
+ // currently available (availability is determined via the survey/news
+ // item start and end date).
+ var th = new Thread(() => {
+ var br = new WebBrowser();
+ br.Tag = warnIfNoneAvailable;
+ br.DocumentCompleted += OnSurveyNewsDocumentCompleted;
+ br.Navigate(url);
+ Application.Run();
+ });
+ th.SetApartmentState(ApartmentState.STA);
+ th.Start();
+ }
+
+ private void OnSurveyNewsDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
+ var br = (WebBrowser)sender;
+ var warnIfNoneAvailable = (bool)br.Tag;
+ if (br.Url == e.Url) {
+ List available = null;
+
+ string json = br.DocumentText;
+ if (!string.IsNullOrEmpty(json)) {
+ int startIndex = json.IndexOf("");
+ if (startIndex > 0) {
+ int endIndex = json.IndexOf("", startIndex);
+ if (endIndex > 0) {
+ json = json.Substring(startIndex + 5, endIndex - startIndex - 5);
+
+ try {
+ // Example JSON data returned by the server:
+ //{
+ // "cannotvoteagain": [],
+ // "notvoted": [
+ // "http://ptvs.azurewebsites.net/news/141",
+ // "http://ptvs.azurewebsites.net/news/41",
+ // ],
+ // "canvoteagain": [
+ // "http://ptvs.azurewebsites.net/news/51"
+ // ]
+ //}
+
+ // Description of each list:
+ // voted: cookie found
+ // notvoted: cookie not found
+ // canvoteagain: cookie found, but multiple votes are allowed
+ JavaScriptSerializer serializer = new JavaScriptSerializer();
+ var results = serializer.Deserialize>>(json);
+ available = results["notvoted"];
+ } catch (ArgumentException) {
+ } catch (InvalidOperationException) {
+ }
+ }
+ }
+ }
+
+ if (available != null && available.Count > 0) {
+ BrowseSurveyNews(available[0]);
+ } else if (warnIfNoneAvailable) {
+ if (available != null) {
+ BrowseSurveyNews(GeneralOptionsPage.SurveyNewsIndexUrl);
+ } else {
+ BrowseSurveyNews(NodejsToolsInstallPath.GetFile("NoSurveyNewsFeed.html"));
+ }
+ }
+
+ Application.ExitThread();
+ }
+ }
+
+ internal void CheckSurveyNews(bool forceCheckAndWarnIfNoneAvailable) {
+ bool shouldQueryServer = false;
+ if (forceCheckAndWarnIfNoneAvailable) {
+ shouldQueryServer = true;
+ } else {
+ shouldQueryServer = true;
+ var options = GeneralOptionsPage;
+ // Ensure that we don't prompt the user on their very first project creation.
+ // Delay by 3 days by pretending we checked 4 days ago (the default of check
+ // once a week ensures we'll check again in 3 days).
+ if (options.SurveyNewsLastCheck == DateTime.MinValue) {
+ options.SurveyNewsLastCheck = DateTime.Now - TimeSpan.FromDays(4);
+ options.SaveSettingsToStorage();
+ }
+
+ var elapsedTime = DateTime.Now - options.SurveyNewsLastCheck;
+ switch (options.SurveyNewsCheck) {
+ case SurveyNewsPolicy.Disabled:
+ break;
+ case SurveyNewsPolicy.CheckOnceDay:
+ shouldQueryServer = elapsedTime.TotalDays >= 1;
+ break;
+ case SurveyNewsPolicy.CheckOnceWeek:
+ shouldQueryServer = elapsedTime.TotalDays >= 7;
+ break;
+ case SurveyNewsPolicy.CheckOnceMonth:
+ shouldQueryServer = elapsedTime.TotalDays >= 30;
+ break;
+ default:
+ Debug.Assert(false, String.Format("Unexpected SurveyNewsPolicy: {0}.", options.SurveyNewsCheck));
+ break;
+ }
+ }
+
+ if (shouldQueryServer) {
+ var options = GeneralOptionsPage;
+ options.SurveyNewsLastCheck = DateTime.Now;
+ options.SaveSettingsToStorage();
+ CheckSurveyNewsThread(new Uri(options.SurveyNewsFeedUrl), forceCheckAndWarnIfNoneAvailable);
+ }
+ }
+
+ internal static void NavigateTo(string filename, int line, int col) {
+ VsUtilities.NavigateTo(Instance, filename, NodejsProjectNode.IsNodejsFile(filename) ? typeof(NodejsEditorFactory).GUID : Guid.Empty, line, col);
+ }
+
+ internal static void NavigateTo(string filename, int pos) {
+ VsUtilities.NavigateTo(Instance, filename, NodejsProjectNode.IsNodejsFile(filename) ? typeof(NodejsEditorFactory).GUID : Guid.Empty, pos);
+ }
+
+ ///
+ /// The analyzer which is used for loose files.
+ ///
+ internal VsProjectAnalyzer DefaultAnalyzer {
+ get {
+ if (_analyzer == null) {
+ _analyzer = new VsProjectAnalyzer();
+ LogLooseFileAnalysisLevel();
+ _analyzer.MaxLogLength = IntellisenseOptionsPage.AnalysisLogMax;
+ IntellisenseOptionsPage.AnalysisLevelChanged += IntellisenseOptionsPageAnalysisLevelChanged;
+ IntellisenseOptionsPage.SaveToDiskChanged += IntellisenseOptionsPageSaveToDiskChanged;
+ }
+ return _analyzer;
+ }
+ }
+
+ private void IntellisenseOptionsPageSaveToDiskChanged(object sender, EventArgs e) {
+ _analyzer.SaveToDisk = IntellisenseOptionsPage.SaveToDisk;
+ }
+
+ private void IntellisenseOptionsPageAnalysisLevelChanged(object sender, EventArgs e) {
+ var analyzer = new VsProjectAnalyzer();
+ analyzer.SwitchAnalyzers(_analyzer);
+ if (_analyzer.RemoveUser()) {
+ _analyzer.Dispose();
+ }
+ _analyzer = analyzer;
+ LogLooseFileAnalysisLevel();
+ }
+
+ private void LogLooseFileAnalysisLevel() {
+ var analyzer = _analyzer;
+ if(analyzer != null)
+ {
+ var val = analyzer.AnalysisLevel;
+ _logger.LogEvent(NodejsToolsLogEvent.AnalysisLevel, (int)val);
+ }
+ }
+
+
+#if UNIT_TEST_INTEGRATION
+ // var testCase = require('./test/test-doubled.js'); for(var x in testCase) { console.log(x); }
+ public static string EvaluateJavaScript(string code) {
+ // TODO: Escaping code
+ string args = "-e \"" + code + "\"";
+ var psi = new ProcessStartInfo(NodePath, args);
+ psi.RedirectStandardOutput = true;
+ psi.RedirectStandardError = true;
+ var proc = Process.Start(psi);
+ var outpReceiver = new OutputReceiver();
+ proc.OutputDataReceived += outpReceiver.DataRead;
+ proc.BeginErrorReadLine();
+ proc.BeginOutputReadLine();
+
+ return outpReceiver._data.ToString();
+ }
+
+ private void GetTestCases(string module) {
+ var testCases = EvaluateJavaScript(
+ String.Format("var testCase = require('{0}'); for(var x in testCase) { console.log(x); }", module));
+ foreach (var testCase in testCases.Split(new[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) {
+ }
+ }
+
+ class OutputReceiver {
+ internal readonly StringBuilder _data = new StringBuilder();
+
+ public void DataRead(object sender, DataReceivedEventArgs e) {
+ if (e.Data != null) {
+ _data.Append(e.Data);
+ }
+ }
+ }
+#endif
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NodejsProject.cs b/Nodejs/Product/Nodejs/NodejsProject.cs
index 5b467b801..38dd482ce 100644
--- a/Nodejs/Product/Nodejs/NodejsProject.cs
+++ b/Nodejs/Product/Nodejs/NodejsProject.cs
@@ -1,1014 +1,1014 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Design;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Xml;
-using Microsoft.NodejsTools.Project;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Azure;
-using Microsoft.VisualStudio.OLE.Interop;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudio.Shell.Flavor;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudio.TextManager.Interop;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-
-namespace Microsoft.NodejsTools {
- [Guid("78D985FC-2CA0-4D08-9B6B-35ACD5E5294A")]
- class NodejsProject : FlavoredProjectBase, IOleCommandTarget, IVsProjectFlavorCfgProvider, IVsProject, IVsProject2, IAzureRoleProject {
- internal IVsProject _innerProject;
- internal IVsProject3 _innerProject3;
- internal NodejsPackage _package;
- private OleMenuCommandService _menuService;
- private List _commands = new List();
- private IVsProjectFlavorCfgProvider _innerVsProjectFlavorCfgProvider;
-
- protected override void Close() {
- if (_menuService != null) {
- foreach (var command in _commands) {
- _menuService.RemoveCommand(command);
- }
- _menuService.Dispose();
- }
- _commands.Clear();
- base.Close();
- }
-
- protected override void InitializeForOuter(string fileName, string location, string name, uint flags, ref Guid guidProject, out bool cancel) {
- CommandID menuCommandID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.Open);
- OleMenuCommand menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
- AddCommand(menuItem);
-
- menuCommandID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.ViewCode);
- menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
- AddCommand(menuItem);
-
- menuCommandID = new CommandID(VSConstants.VSStd2K, (int)VSConstants.VSStd2KCmdID.ECMD_VIEWMARKUP);
- menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
- AddCommand(menuItem);
-
- base.InitializeForOuter(fileName, location, name, flags, ref guidProject, out cancel);
-
- object extObject;
- ErrorHandler.ThrowOnFailure(
- _innerVsHierarchy.GetProperty(
- VSConstants.VSITEMID_ROOT,
- (int)__VSHPROPID.VSHPROPID_ExtObject,
- out extObject
- )
- );
-
- var proj = extObject as EnvDTE.Project;
- if (proj != null) {
- try {
- object webAppExtender = proj.get_Extender("WebApplication");
- if (webAppExtender != null && webAppExtender is WebAppExtenderFilter) {
- ((dynamic)((WebAppExtenderFilter)webAppExtender).InnerObject).StartWebServerOnDebug = false;
- }
- } catch (COMException) {
- // extender doesn't exist...
- }
- }
- }
-
- private void AddCommand(OleMenuCommand menuItem) {
- _menuService.AddCommand(menuItem);
- _commands.Add(menuItem);
- }
-
- private void OpenFile(object sender, EventArgs e) {
- var oleMenu = sender as OleMenuCommand;
- oleMenu.Supported = false;
-
- foreach (var vsItemSelection in GetSelectedItems()) {
- if (IsJavaScriptFile(Name(vsItemSelection))) {
- ErrorHandler.ThrowOnFailure(OpenWithNodejsEditor(vsItemSelection.itemid));
- } else {
- ErrorHandler.ThrowOnFailure(OpenWithDefaultEditor(vsItemSelection.itemid));
- }
- }
- }
-
- private void OpenFileBeforeQueryStatus(object sender, EventArgs e) {
- var oleMenu = sender as OleMenuCommand;
- oleMenu.Supported = false;
-
- foreach (var vsItemSelection in GetSelectedItems()) {
- object name;
- ErrorHandler.ThrowOnFailure(vsItemSelection.pHier.GetProperty(vsItemSelection.itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
-
- if (IsJavaScriptFile(Name(vsItemSelection))) {
- oleMenu.Supported = true;
- }
- }
- }
-
- internal static string Name(VSITEMSELECTION item) {
- return GetItemName(item.pHier, item.itemid);
- }
-
- internal static string GetItemName(IVsHierarchy hier, uint itemid) {
- object name;
- ErrorHandler.ThrowOnFailure(hier.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
- return (string)name;
- }
-
- private int OpenWithDefaultEditor(uint selectionItemId) {
- Guid view = Guid.Empty;
- IVsWindowFrame frame;
- int hr = ((IVsProject)_innerVsHierarchy).OpenItem(
- selectionItemId,
- ref view,
- IntPtr.Zero,
- out frame
- );
- if (ErrorHandler.Succeeded(hr)) {
- hr = frame.Show();
- }
- return hr;
- }
-
- protected override void SetInnerProject(IntPtr innerIUnknown) {
- var inner = Marshal.GetObjectForIUnknown(innerIUnknown);
-
- // The reason why we keep a reference to those is that doing a QI after being
- // aggregated would do the AddRef on the outer object.
- _innerProject = inner as IVsProject;
- _innerProject3 = inner as IVsProject3;
- _innerVsHierarchy = inner as IVsHierarchy;
- _innerVsProjectFlavorCfgProvider = inner as IVsProjectFlavorCfgProvider;
-
- // Ensure we have a service provider as this is required for menu items to work
- if (this.serviceProvider == null)
- this.serviceProvider = (System.IServiceProvider)this._package;
-
- // Now let the base implementation set the inner object
- base.SetInnerProject(innerIUnknown);
-
- // Add our commands (this must run after we called base.SetInnerProject)
- _menuService = ((System.IServiceProvider)this).GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
-
- }
-
- private bool TryHandleRightClick(IntPtr pvaIn, out int res) {
- Guid itemType = GetSelectedItemType();
-
- if (TryShowContextMenu(pvaIn, itemType, out res)) {
- return true;
- }
-
- return false;
- }
-
- ///
- /// Gets all of the currently selected items.
- ///
- ///
- private IEnumerable GetSelectedItems() {
- IVsMonitorSelection monitorSelection = _package.GetService(typeof(IVsMonitorSelection)) as IVsMonitorSelection;
-
- IntPtr hierarchyPtr = IntPtr.Zero;
- IntPtr selectionContainer = IntPtr.Zero;
- try {
- uint selectionItemId;
- IVsMultiItemSelect multiItemSelect = null;
- ErrorHandler.ThrowOnFailure(monitorSelection.GetCurrentSelection(out hierarchyPtr, out selectionItemId, out multiItemSelect, out selectionContainer));
-
- if (selectionItemId != VSConstants.VSITEMID_NIL && hierarchyPtr != IntPtr.Zero) {
- IVsHierarchy hierarchy = Marshal.GetObjectForIUnknown(hierarchyPtr) as IVsHierarchy;
-
- if (selectionItemId != VSConstants.VSITEMID_SELECTION) {
- // This is a single selection. Compare hirarchy with our hierarchy and get node from itemid
- if (Utilities.IsSameComObject(this, hierarchy)) {
- yield return new VSITEMSELECTION() { itemid = selectionItemId, pHier = hierarchy };
- }
- } else if (multiItemSelect != null) {
- // This is a multiple item selection.
- // Get number of items selected and also determine if the items are located in more than one hierarchy
-
- uint numberOfSelectedItems;
- int isSingleHierarchyInt;
- ErrorHandler.ThrowOnFailure(multiItemSelect.GetSelectionInfo(out numberOfSelectedItems, out isSingleHierarchyInt));
- bool isSingleHierarchy = (isSingleHierarchyInt != 0);
-
- // Now loop all selected items and add to the list only those that are selected within this hierarchy
- if (!isSingleHierarchy || (isSingleHierarchy && Utilities.IsSameComObject(this, hierarchy))) {
- Debug.Assert(numberOfSelectedItems > 0, "Bad number of selected itemd");
- VSITEMSELECTION[] vsItemSelections = new VSITEMSELECTION[numberOfSelectedItems];
- uint flags = (isSingleHierarchy) ? (uint)__VSGSIFLAGS.GSI_fOmitHierPtrs : 0;
- ErrorHandler.ThrowOnFailure(multiItemSelect.GetSelectedItems(flags, numberOfSelectedItems, vsItemSelections));
-
- foreach (VSITEMSELECTION vsItemSelection in vsItemSelections) {
- yield return new VSITEMSELECTION() { itemid = vsItemSelection.itemid, pHier = hierarchy };
- }
- }
- }
- }
- } finally {
- if (hierarchyPtr != IntPtr.Zero) {
- Marshal.Release(hierarchyPtr);
- }
- if (selectionContainer != IntPtr.Zero) {
- Marshal.Release(selectionContainer);
- }
- }
- }
-
- private Guid GetSelectedItemType() {
- Guid itemType = Guid.Empty;
- foreach (var vsItemSelection in GetSelectedItems()) {
- Guid typeGuid = GetItemType(vsItemSelection);
-
- if (itemType == Guid.Empty) {
- itemType = typeGuid;
- } else if (itemType != typeGuid) {
- // we have multiple item types
- itemType = Guid.Empty;
- break;
- }
- }
- return itemType;
- }
-
- private bool TryShowContextMenu(IntPtr pvaIn, Guid itemType, out int res) {
- if (itemType == new Guid(Guids.NodejsProjectFactoryString)) {
- // multiple Node prjoect nodes selected
- res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_PROJNODE/*IDM_VS_CTXT_WEBPROJECT*/);
- return true;
- } else if (itemType == VSConstants.GUID_ItemType_PhysicalFile) {
- // multiple files selected
- res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_ITEMNODE);
- return true;
- } else if (itemType == VSConstants.GUID_ItemType_PhysicalFolder) {
- res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_FOLDERNODE);
- return true;
- }
- res = VSConstants.E_FAIL;
- return false;
- }
-
- private int ShowContextMenu(IntPtr pvaIn, int ctxMenu) {
- object variant = Marshal.GetObjectForNativeVariant(pvaIn);
- UInt32 pointsAsUint = (UInt32)variant;
- short x = (short)(pointsAsUint & 0x0000ffff);
- short y = (short)((pointsAsUint & 0xffff0000) / 0x10000);
-
- POINTS points = new POINTS();
- points.x = x;
- points.y = y;
-
- return ShowContextMenu(ctxMenu, VsMenus.guidSHLMainMenu, points);
- }
-
- ///
- /// Shows the specified context menu at a specified location.
- ///
- /// The context menu ID.
- /// The GUID of the menu group.
- /// The location at which to show the menu.
- internal int ShowContextMenu(int menuId, Guid menuGroup, POINTS points) {
- IVsUIShell shell = _package.GetService(typeof(SVsUIShell)) as IVsUIShell;
-
- Debug.Assert(shell != null, "Could not get the ui shell from the project");
- if (shell == null) {
- return VSConstants.E_FAIL;
- }
- POINTS[] pnts = new POINTS[1];
- pnts[0].x = points.x;
- pnts[0].y = points.y;
- return shell.ShowContextMenu(0, ref menuGroup, menuId, pnts, (Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget)this);
- }
-
- protected override int ExecCommand(uint itemid, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (pguidCmdGroup == VsMenus.guidVsUIHierarchyWindowCmds) {
- switch ((VSConstants.VsUIHierarchyWindowCmdIds)nCmdID) {
- case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_RightClick:
- int res;
- if (TryHandleRightClick(pvaIn, out res)) {
- return res;
- }
- break;
- case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_DoubleClick:
- case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_EnterKey:
- // open the document if it's an JavaScript file
- if (IsJavaScriptFile(_innerVsHierarchy, itemid)) {
- int hr = OpenWithNodejsEditor(itemid);
-
- if (ErrorHandler.Succeeded(hr)) {
- return hr;
- }
- }
- break;
-
- }
- }
-
- var result = base.ExecCommand(itemid, ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
- return result;
- }
-
- int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- return ((IOleCommandTarget)_menuService).Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
- }
-
- private bool IsJavaScriptFile(IVsHierarchy iVsHierarchy, uint itemid) {
- object name;
- ErrorHandler.ThrowOnFailure(iVsHierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
-
- return IsJavaScriptFile(name);
- }
-
- private static bool IsJavaScriptFile(object name) {
- string strName = name as string;
- if (strName != null) {
- var ext = Path.GetExtension(strName);
- if (String.Equals(ext, ".js", StringComparison.OrdinalIgnoreCase)) {
- return true;
- }
- }
- return false;
- }
-
- int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
- if (pguidCmdGroup == Guids.Eureka) {
- for (int i = 0; i < prgCmds.Length; i++) {
- switch (prgCmds[i].cmdID) {
- case 0x102: // View in Web Page Inspector from Eureka web tools
- prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
- return VSConstants.S_OK;
- }
- }
- } else if (pguidCmdGroup == Guids.VenusCommandId) {
- for (int i = 0; i < prgCmds.Length; i++) {
- switch (prgCmds[i].cmdID) {
- case 0x034: /* add app assembly folder */
- case 0x035: /* add app code folder */
- case 0x036: /* add global resources */
- case 0x037: /* add local resources */
- case 0x038: /* add web refs folder */
- case 0x039: /* add data folder */
- case 0x040: /* add browser folders */
- case 0x041: /* theme */
- case 0x054: /* package settings */
- case 0x055: /* context package settings */
-
- prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
- return VSConstants.S_OK;
- }
- }
- } else if (pguidCmdGroup == Guids.WebPackageCommandId) {
- if (prgCmds[0].cmdID == 0x101 /* EnablePublishToWindowsAzureMenuItem*/) {
- }
- } else if (pguidCmdGroup == Guids.WebAppCmdId) {
- for (int i = 0; i < prgCmds.Length; i++) {
- switch (prgCmds[i].cmdID) {
- case 0x06A: /* check accessibility */
- prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
- return VSConstants.S_OK;
- }
- }
- } else if (pguidCmdGroup == VSConstants.VSStd2K) {
- for (int i = 0; i < prgCmds.Length; i++) {
- switch ((VSConstants.VSStd2KCmdID)prgCmds[i].cmdID) {
- case VSConstants.VSStd2KCmdID.SETASSTARTPAGE:
- case VSConstants.VSStd2KCmdID.CHECK_ACCESSIBILITY:
- prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
- return VSConstants.S_OK;
- }
- }
- } else if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) {
- for (int i = 0; i < prgCmds.Length; i++) {
- switch ((VSConstants.VSStd97CmdID)prgCmds[i].cmdID) {
- case VSConstants.VSStd97CmdID.PreviewInBrowser:
- case VSConstants.VSStd97CmdID.BrowseWith:
- prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
- return VSConstants.S_OK;
- }
- }
- }
-
- return ((IOleCommandTarget)_menuService).QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
- }
-
-
- #region IVsProjectFlavorCfgProvider Members
-
- public int CreateProjectFlavorCfg(IVsCfg pBaseProjectCfg, out IVsProjectFlavorCfg ppFlavorCfg) {
- // We're flavored with a Web Application project and our normal project... But we don't
- // want the web application project to influence our config as that alters our debug
- // launch story. We control that w/ the Django project which is actually just letting the
- // base Node.js project handle it. So we keep the base Node.js project config here.
- IVsProjectFlavorCfg webCfg;
- ErrorHandler.ThrowOnFailure(
- _innerVsProjectFlavorCfgProvider.CreateProjectFlavorCfg(
- pBaseProjectCfg,
- out webCfg
- )
- );
- ppFlavorCfg = new NodejsProjectConfig(pBaseProjectCfg, webCfg);
-
- return VSConstants.S_OK;
- }
-
- #endregion
-
-
- protected override int GetProperty(uint itemId, int propId, out object property) {
- switch ((__VSHPROPID)propId) {
- case __VSHPROPID.VSHPROPID_IconIndex:
- case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
- // Venus wants to change the icon for special folders using the IconIndex. All of our
- // folders respond to IconHandles so we just force folders down that code path rather
- // than trying to hand out the correct IconIndex here
- if (GetItemType(new VSITEMSELECTION() { itemid = itemId, pHier = this }) == VSConstants.GUID_ItemType_PhysicalFolder) {
- property = null;
- return VSConstants.DISP_E_MEMBERNOTFOUND;
- }
- break;
- }
- switch ((__VSHPROPID4)propId) {
-
- case __VSHPROPID4.VSHPROPID_TargetFrameworkMoniker:
- // really only here for testing so WAP projects load correctly...
- // But this also impacts the toolbox by filtering what available items there are.
- property = ".NETFramework,Version=v4.5,Profile=Client";
- return VSConstants.S_OK;
- }
- switch ((__VSHPROPID2)propId) {
- case __VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList: {
- var res = base.GetProperty(itemId, propId, out property);
- property = RemovePropertyPagesFromList((string)property, CfgSpecificPropertyPagesToRemove);
- return res;
- }
- case __VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList: {
- var res = base.GetProperty(itemId, propId, out property);
- property = RemovePropertyPagesFromList((string)property, PropertyPagesToRemove);
- return res;
- }
- }
-#if DEV14_OR_LATER
- switch((__VSHPROPID8)propId) {
- case __VSHPROPID8.VSHPROPID_SupportsIconMonikers:
- property = true;
- return VSConstants.S_OK;
- }
-#endif
-
- return base.GetProperty(itemId, propId, out property);
- }
-
- internal static string[] CfgSpecificPropertyPagesToRemove = new[] {
- "{A553AD0B-2F9E-4BCE-95B3-9A1F7074BC27}", // Package/Publish Web
- "{9AB2347D-948D-4CD2-8DBE-F15F0EF78ED3}", // Package/Publish SQL
- };
-
- internal static string[] PropertyPagesToRemove = new[] {
- "{8C0201FE-8ECA-403C-92A3-1BC55F031979}", // typeof(DeployPropertyPageComClass)
- "{ED3B544C-26D8-4348-877B-A1F7BD505ED9}", // typeof(DatabaseDeployPropertyPageComClass)
- "{909D16B3-C8E8-43D1-A2B8-26EA0D4B6B57}", // Microsoft.VisualStudio.Web.Application.WebPropertyPage
- "{379354F2-BBB3-4BA9-AA71-FBE7B0E5EA94}" // Microsoft.VisualStudio.Web.Application.SilverlightLinksPage
- };
-
- internal string RemovePropertyPagesFromList(string propertyPagesList, string[] pagesToRemove) {
- if (pagesToRemove != null) {
- propertyPagesList = propertyPagesList.ToUpper(CultureInfo.InvariantCulture);
- foreach (string s in pagesToRemove) {
- int index = propertyPagesList.IndexOf(s, StringComparison.Ordinal);
- if (index != -1) {
- // Guids are separated by ';' so if we remove the last one also remove the last ';'
- int index2 = index + s.Length + 1;
- if (index2 >= propertyPagesList.Length)
- propertyPagesList = propertyPagesList.Substring(0, index).TrimEnd(';');
- else
- propertyPagesList = propertyPagesList.Substring(0, index) + propertyPagesList.Substring(index2);
- }
- }
- }
- return propertyPagesList;
- }
-
- internal static Guid GetItemType(VSITEMSELECTION vsItemSelection) {
- Guid typeGuid;
- try {
- ErrorHandler.ThrowOnFailure(
- vsItemSelection.pHier.GetGuidProperty(
- vsItemSelection.itemid,
- (int)__VSHPROPID.VSHPROPID_TypeGuid,
- out typeGuid
- )
- );
- } catch (System.Runtime.InteropServices.COMException) {
- return Guid.Empty;
- }
- return typeGuid;
- }
-
- private static EnvDTE.ProjectItem GetExtensionObject(IVsHierarchy hierarchy, uint itemId) {
- object project;
-
- ErrorHandler.ThrowOnFailure(
- hierarchy.GetProperty(
- itemId,
- (int)__VSHPROPID.VSHPROPID_ExtObject,
- out project
- )
- );
-
- return (project as EnvDTE.ProjectItem);
- }
-
- private int OpenWithNodejsEditor(uint selectionItemId) {
- // If the item type of this file is not compile, we don't actually want to open with Nodejs and should instead use the default.
- Guid ourEditor;
- var properties = GetExtensionObject(_innerVsHierarchy, selectionItemId).Properties;
- try {
- var itemType = properties.Item("ItemType").Value;
- ourEditor = (string)itemType == ProjectFileConstants.Compile && !IsES6IntellisensePreview() ? Guids.NodejsEditorFactory : Guid.Empty;
- } catch (ArgumentException) {
- // no item type, file is excluded from project.
- ourEditor = Guids.NodejsEditorFactory;
- }
-
- Guid view = Guid.Empty;
- IVsWindowFrame frame;
-
- // DOCDATAEXISTING_UNKNOWN http://msdn.microsoft.com/en-us/library/vstudio/bb139396(v=vs.110).aspx
- // Force OpenStandardEditor to lookup if the document is currently open or not, and if it is. If it's
- // open in a different editor the user will be prompted to close it.
- var docDataExistingUnknown = new IntPtr(-1);
- int hr = ((IVsProject3)_innerVsHierarchy).OpenItemWithSpecific(
- selectionItemId,
- 0,
- ref ourEditor,
- null,
- ref view,
- docDataExistingUnknown,
- out frame
- );
- if (frame != null && ErrorHandler.Succeeded(hr)) {
- hr = frame.Show();
- }
- return hr;
- }
-
- private bool IsES6IntellisensePreview() {
- // If the analysis level is set to preview then use the TypeScript language service for node.js
- return NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel == Options.AnalysisLevel.Preview;
- }
-
- #region IVsProject Members
-
- public int AddItem(uint itemidLoc, VSADDITEMOPERATION dwAddItemOperation, string pszItemName, uint cFilesToOpen, string[] rgpszFilesToOpen, IntPtr hwndDlgOwner, VSADDRESULT[] pResult) {
- // Check if we are adding an item to a folder that consists of browser-side code.
- // In this case, we will want to open the file with the default editor.
- var isClientCode = false;
- var project = _innerVsHierarchy.GetProject().GetNodejsProject();
-
- var selectedItems = this.GetSelectedItems().GetEnumerator();
- if (selectedItems.MoveNext()) {
- var currentId = selectedItems.Current.itemid;
- string name;
- GetCanonicalName(currentId, out name);
- var nodeFolderNode = project.FindNodeByFullPath(name) as NodejsFolderNode;
-
- if (nodeFolderNode != null) {
- if (nodeFolderNode.ContentType == FolderContentType.Browser) {
- isClientCode = true;
- }
- }
- }
-
- if (!isClientCode && _innerProject3 != null && IsJavaScriptFile(pszItemName)) {
- Guid ourEditor = IsES6IntellisensePreview() ? Guid.Empty : typeof(NodejsEditorFactory).GUID;
- Guid view = Guid.Empty;
- return _innerProject3.AddItemWithSpecific(
- itemidLoc,
- dwAddItemOperation,
- pszItemName,
- cFilesToOpen,
- rgpszFilesToOpen,
- hwndDlgOwner,
- dwAddItemOperation == VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE ?
- (uint)__VSSPECIFICEDITORFLAGS.VSSPECIFICEDITOR_DoOpen :
- 0,
- ref ourEditor,
- String.Empty,
- ref view,
- pResult
- );
- }
- return _innerProject.AddItem(itemidLoc, dwAddItemOperation, pszItemName, cFilesToOpen, rgpszFilesToOpen, hwndDlgOwner, pResult);
- }
-
- public int GenerateUniqueItemName(uint itemidLoc, string pszExt, string pszSuggestedRoot, out string pbstrItemName) {
- return _innerProject.GenerateUniqueItemName(itemidLoc, pszExt, pszSuggestedRoot, out pbstrItemName);
- }
-
- public int GetItemContext(uint itemid, out VisualStudio.OLE.Interop.IServiceProvider ppSP) {
- return _innerProject.GetItemContext(itemid, out ppSP);
- }
-
- public int GetMkDocument(uint itemid, out string pbstrMkDocument) {
- return _innerProject.GetMkDocument(itemid, out pbstrMkDocument);
- }
-
- public int IsDocumentInProject(string pszMkDocument, out int pfFound, VSDOCUMENTPRIORITY[] pdwPriority, out uint pitemid) {
- return _innerProject.IsDocumentInProject(pszMkDocument, out pfFound, pdwPriority, out pitemid);
- }
-
- public int OpenItem(uint itemid, ref Guid rguidLogicalView, IntPtr punkDocDataExisting, out IVsWindowFrame ppWindowFrame) {
- if (_innerProject3 != null && IsJavaScriptFile(GetItemName(_innerVsHierarchy, itemid))) {
- // force .js files opened w/o an editor type to be opened w/ our editor factory.
- Guid guid = IsES6IntellisensePreview() ? Guid.Empty : typeof(NodejsEditorFactory).GUID;
- Guid view = Guid.Empty;
- int hr = _innerProject3.OpenItemWithSpecific(
- itemid,
- 0,
- ref guid,
- null,
- rguidLogicalView,
- punkDocDataExisting,
- out ppWindowFrame
- );
- return hr;
- }
-
- return _innerProject.OpenItem(itemid, rguidLogicalView, punkDocDataExisting, out ppWindowFrame);
- }
-
- #endregion
-
- #region IVsProject2 Members
-
- public int RemoveItem(uint dwReserved, uint itemid, out int pfResult) {
- if (_innerProject3 != null) {
- return _innerProject3.RemoveItem(dwReserved, itemid, out pfResult);
- }
- pfResult = 0;
- return VSConstants.E_NOTIMPL;
- }
-
- public int ReopenItem(uint itemid, ref Guid rguidEditorType, string pszPhysicalView, ref Guid rguidLogicalView, IntPtr punkDocDataExisting, out IVsWindowFrame ppWindowFrame) {
- if (_innerProject3 != null) {
- if (IsJavaScriptFile(GetItemName(_innerVsHierarchy, itemid))) {
- // force .js files opened w/o an editor type to be opened w/ our editor factory.
- // If the item type of this file is not compile, we don't actually want to open with Nodejs and should instead use the default.
- var itemType = GetExtensionObject(_innerVsHierarchy, itemid).Properties.Item("ItemType").Value;
- Guid guid = (string)itemType == ProjectFileConstants.Compile && !IsES6IntellisensePreview() ? Guids.NodejsEditorFactory : Guid.Empty;
-
- return _innerProject3.ReopenItem(
- itemid,
- ref guid,
- pszPhysicalView,
- ref rguidLogicalView,
- punkDocDataExisting,
- out ppWindowFrame
- );
-
- }
- return _innerProject3.ReopenItem(itemid, ref rguidEditorType, pszPhysicalView, ref rguidLogicalView, punkDocDataExisting, out ppWindowFrame);
- }
- ppWindowFrame = null;
- return VSConstants.E_NOTIMPL;
- }
-
- #endregion
-
- public void AddedAsRole(object azureProjectHierarchy, string roleType) {
- var hier = azureProjectHierarchy as IVsHierarchy;
-
- if (hier == null) {
- return;
- }
-
- this._package.GetUIThread().Invoke(() => {
- string caption;
- object captionObj;
- if (ErrorHandler.Failed(_innerVsHierarchy.GetProperty(
- (uint)VSConstants.VSITEMID.Root,
- (int)__VSHPROPID.VSHPROPID_Caption,
- out captionObj
- )) || string.IsNullOrEmpty(caption = captionObj as string)) {
- return;
- }
-
- UpdateServiceDefinition(
- hier,
- roleType,
- caption,
- new ServiceProvider(GetSite())
- );
- });
- }
-
- private static bool TryGetItemId(object obj, out uint id) {
- const uint nil = (uint)VSConstants.VSITEMID.Nil;
- id = obj as uint? ?? nil;
- if (id == nil) {
- var asInt = obj as int?;
- if (asInt.HasValue) {
- id = unchecked((uint)asInt.Value);
- }
- }
- return id != nil;
- }
-
- ///
- /// Updates the ServiceDefinition.csdef file in
- /// to include the default startup and
- /// runtime tasks for Python projects.
- ///
- ///
- /// The Cloud Service project to update.
- ///
- ///
- /// The type of role being added, either "Web" or "Worker".
- ///
- ///
- /// The name of the role. This typically matches the Caption property.
- ///
- ///
- /// VS service provider.
- ///
- internal static void UpdateServiceDefinition(
- IVsHierarchy project,
- string roleType,
- string projectName,
- System.IServiceProvider site
- ) {
- Utilities.ArgumentNotNull("project", project);
-
- object obj;
- ErrorHandler.ThrowOnFailure(project.GetProperty(
- (uint)VSConstants.VSITEMID.Root,
- (int)__VSHPROPID.VSHPROPID_FirstChild,
- out obj
- ));
-
- uint id;
- while (TryGetItemId(obj, out id)) {
- Guid itemType;
- string mkDoc;
-
- if (ErrorHandler.Succeeded(project.GetGuidProperty(id, (int)__VSHPROPID.VSHPROPID_TypeGuid, out itemType)) &&
- itemType == VSConstants.GUID_ItemType_PhysicalFile &&
- ErrorHandler.Succeeded(project.GetProperty(id, (int)__VSHPROPID.VSHPROPID_Name, out obj)) &&
- "ServiceDefinition.csdef".Equals(obj as string, StringComparison.InvariantCultureIgnoreCase) &&
- ErrorHandler.Succeeded(project.GetCanonicalName(id, out mkDoc)) &&
- !string.IsNullOrEmpty(mkDoc)
- ) {
- // We have found the file
- var rdt = site.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
-
- IVsHierarchy docHier;
- uint docId, docCookie;
- IntPtr pDocData;
-
- bool updateFileOnDisk = true;
-
- if (ErrorHandler.Succeeded(rdt.FindAndLockDocument(
- (uint)_VSRDTFLAGS.RDT_EditLock,
- mkDoc,
- out docHier,
- out docId,
- out pDocData,
- out docCookie
- ))) {
- try {
- if (pDocData != IntPtr.Zero) {
- try {
- // File is open, so edit it through the document
- UpdateServiceDefinition(
- Marshal.GetObjectForIUnknown(pDocData) as IVsTextLines,
- roleType,
- projectName
- );
-
- ErrorHandler.ThrowOnFailure(rdt.SaveDocuments(
- (uint)__VSRDTSAVEOPTIONS.RDTSAVEOPT_ForceSave,
- docHier,
- docId,
- docCookie
- ));
-
- updateFileOnDisk = false;
- } catch (ArgumentException) {
- } catch (InvalidOperationException) {
- } catch (COMException) {
- } finally {
- Marshal.Release(pDocData);
- }
- }
- } finally {
- ErrorHandler.ThrowOnFailure(rdt.UnlockDocument(
- (uint)_VSRDTFLAGS.RDT_Unlock_SaveIfDirty | (uint)_VSRDTFLAGS.RDT_RequestUnlock,
- docCookie
- ));
- }
- }
-
- if (updateFileOnDisk) {
- // File is not open, so edit it on disk
- FileStream stream = null;
- try {
- UpdateServiceDefinition(mkDoc, roleType, projectName);
- } finally {
- if (stream != null) {
- stream.Close();
- }
- }
- }
-
- break;
- }
-
- if (ErrorHandler.Failed(project.GetProperty(id, (int)__VSHPROPID.VSHPROPID_NextSibling, out obj))) {
- break;
- }
- }
- }
-
- private class StringWriterWithEncoding : StringWriter {
- private readonly Encoding _encoding;
-
- public StringWriterWithEncoding(Encoding encoding) {
- _encoding = encoding;
- }
-
- public override Encoding Encoding {
- get { return _encoding; }
- }
- }
-
- private static void UpdateServiceDefinition(IVsTextLines lines, string roleType, string projectName) {
- if (lines == null) {
- throw new ArgumentException("lines");
- }
-
- int lastLine, lastIndex;
- string text;
-
- ErrorHandler.ThrowOnFailure(lines.GetLastLineIndex(out lastLine, out lastIndex));
- ErrorHandler.ThrowOnFailure(lines.GetLineText(0, 0, lastLine, lastIndex, out text));
-
- var doc = new XmlDocument();
- doc.LoadXml(text);
-
- UpdateServiceDefinition(doc, roleType, projectName);
-
- var encoding = Encoding.UTF8;
-
- var userData = lines as IVsUserData;
- if (userData != null) {
- var guid = VSConstants.VsTextBufferUserDataGuid.VsBufferEncodingVSTFF_guid;
- object data;
- int cp;
- if (ErrorHandler.Succeeded(userData.GetData(ref guid, out data)) &&
- (cp = (data as int? ?? (int)(data as uint? ?? 0)) & (int)__VSTFF.VSTFF_CPMASK) != 0) {
- try {
- encoding = Encoding.GetEncoding(cp);
- } catch (NotSupportedException) {
- } catch (ArgumentException) {
- }
- }
- }
-
- var sw = new StringWriterWithEncoding(encoding);
- doc.Save(XmlWriter.Create(
- sw,
- new XmlWriterSettings {
- Indent = true,
- IndentChars = " ",
- NewLineHandling = NewLineHandling.Entitize,
- Encoding = encoding
- }
- ));
-
- var sb = sw.GetStringBuilder();
- var len = sb.Length;
- var pStr = Marshal.StringToCoTaskMemUni(sb.ToString());
-
- try {
- ErrorHandler.ThrowOnFailure(lines.ReplaceLines(0, 0, lastLine, lastIndex, pStr, len, new TextSpan[1]));
- } finally {
- Marshal.FreeCoTaskMem(pStr);
- }
- }
-
- private static void UpdateServiceDefinition(string path, string roleType, string projectName) {
- var doc = new XmlDocument();
- doc.Load(path);
-
- UpdateServiceDefinition(doc, roleType, projectName);
-
- doc.Save(XmlWriter.Create(
- path,
- new XmlWriterSettings {
- Indent = true,
- IndentChars = " ",
- NewLineHandling = NewLineHandling.Entitize,
- Encoding = Encoding.UTF8
- }
- ));
- }
-
- ///
- /// Modifies the provided XML document to contain the service definition
- /// nodes needed for the specified project.
- ///
- ///
- /// is not one of "Web" or "Worker".
- ///
- ///
- /// A required element is missing from the document.
- ///
- internal static void UpdateServiceDefinition(XmlDocument doc, string roleType, string projectName) {
- bool isWeb = roleType == "Web";
- bool isWorker = roleType == "Worker";
- if (isWeb == isWorker) {
- throw new ArgumentException("Unknown role type: " + (roleType ?? "(null)"), "roleType");
- }
-
- var nav = doc.CreateNavigator();
-
- var ns = new XmlNamespaceManager(doc.NameTable);
- ns.AddNamespace("sd", "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition");
-
- var role = nav.SelectSingleNode(string.Format(
- "/sd:ServiceDefinition/sd:{0}Role[@name='{1}']", roleType, projectName
- ), ns);
-
- if (role == null) {
- throw new InvalidOperationException("Missing role entry");
- }
-
- var startup = role.SelectSingleNode("sd:Startup", ns);
- if (startup != null) {
- startup.DeleteSelf();
- }
-
- role.AppendChildElement(null, "Startup", null, null);
- startup = role.SelectSingleNode("sd:Startup", ns);
- if (startup == null) {
- throw new InvalidOperationException("Missing Startup entry");
- }
-
- startup.ReplaceSelf(string.Format(@"
-
-
-
-
-
-
-
-
- {1}
-", roleType.ToLowerInvariant(), isWorker ? @"" : string.Empty));
-
- if (isWorker) {
- var runtime = role.SelectSingleNode("sd:Runtime", ns);
- if (runtime != null) {
- runtime.DeleteSelf();
- }
- role.AppendChildElement(null, "Runtime", null, null);
-
- runtime = role.SelectSingleNode("sd:Runtime", ns);
- if (startup == null) {
- throw new InvalidOperationException("Missing Runtime entry");
- }
-
- runtime.ReplaceSelf(@"
-
-
-
-
-
-
-
-
-");
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Xml;
+using Microsoft.NodejsTools.Project;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Azure;
+using Microsoft.VisualStudio.OLE.Interop;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Flavor;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TextManager.Interop;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+
+namespace Microsoft.NodejsTools {
+ [Guid("78D985FC-2CA0-4D08-9B6B-35ACD5E5294A")]
+ class NodejsProject : FlavoredProjectBase, IOleCommandTarget, IVsProjectFlavorCfgProvider, IVsProject, IVsProject2, IAzureRoleProject {
+ internal IVsProject _innerProject;
+ internal IVsProject3 _innerProject3;
+ internal NodejsPackage _package;
+ private OleMenuCommandService _menuService;
+ private List _commands = new List();
+ private IVsProjectFlavorCfgProvider _innerVsProjectFlavorCfgProvider;
+
+ protected override void Close() {
+ if (_menuService != null) {
+ foreach (var command in _commands) {
+ _menuService.RemoveCommand(command);
+ }
+ _menuService.Dispose();
+ }
+ _commands.Clear();
+ base.Close();
+ }
+
+ protected override void InitializeForOuter(string fileName, string location, string name, uint flags, ref Guid guidProject, out bool cancel) {
+ CommandID menuCommandID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.Open);
+ OleMenuCommand menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
+ AddCommand(menuItem);
+
+ menuCommandID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.ViewCode);
+ menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
+ AddCommand(menuItem);
+
+ menuCommandID = new CommandID(VSConstants.VSStd2K, (int)VSConstants.VSStd2KCmdID.ECMD_VIEWMARKUP);
+ menuItem = new OleMenuCommand(OpenFile, null, OpenFileBeforeQueryStatus, menuCommandID);
+ AddCommand(menuItem);
+
+ base.InitializeForOuter(fileName, location, name, flags, ref guidProject, out cancel);
+
+ object extObject;
+ ErrorHandler.ThrowOnFailure(
+ _innerVsHierarchy.GetProperty(
+ VSConstants.VSITEMID_ROOT,
+ (int)__VSHPROPID.VSHPROPID_ExtObject,
+ out extObject
+ )
+ );
+
+ var proj = extObject as EnvDTE.Project;
+ if (proj != null) {
+ try {
+ object webAppExtender = proj.get_Extender("WebApplication");
+ if (webAppExtender != null && webAppExtender is WebAppExtenderFilter) {
+ ((dynamic)((WebAppExtenderFilter)webAppExtender).InnerObject).StartWebServerOnDebug = false;
+ }
+ } catch (COMException) {
+ // extender doesn't exist...
+ }
+ }
+ }
+
+ private void AddCommand(OleMenuCommand menuItem) {
+ _menuService.AddCommand(menuItem);
+ _commands.Add(menuItem);
+ }
+
+ private void OpenFile(object sender, EventArgs e) {
+ var oleMenu = sender as OleMenuCommand;
+ oleMenu.Supported = false;
+
+ foreach (var vsItemSelection in GetSelectedItems()) {
+ if (IsJavaScriptFile(Name(vsItemSelection))) {
+ ErrorHandler.ThrowOnFailure(OpenWithNodejsEditor(vsItemSelection.itemid));
+ } else {
+ ErrorHandler.ThrowOnFailure(OpenWithDefaultEditor(vsItemSelection.itemid));
+ }
+ }
+ }
+
+ private void OpenFileBeforeQueryStatus(object sender, EventArgs e) {
+ var oleMenu = sender as OleMenuCommand;
+ oleMenu.Supported = false;
+
+ foreach (var vsItemSelection in GetSelectedItems()) {
+ object name;
+ ErrorHandler.ThrowOnFailure(vsItemSelection.pHier.GetProperty(vsItemSelection.itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
+
+ if (IsJavaScriptFile(Name(vsItemSelection))) {
+ oleMenu.Supported = true;
+ }
+ }
+ }
+
+ internal static string Name(VSITEMSELECTION item) {
+ return GetItemName(item.pHier, item.itemid);
+ }
+
+ internal static string GetItemName(IVsHierarchy hier, uint itemid) {
+ object name;
+ ErrorHandler.ThrowOnFailure(hier.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
+ return (string)name;
+ }
+
+ private int OpenWithDefaultEditor(uint selectionItemId) {
+ Guid view = Guid.Empty;
+ IVsWindowFrame frame;
+ int hr = ((IVsProject)_innerVsHierarchy).OpenItem(
+ selectionItemId,
+ ref view,
+ IntPtr.Zero,
+ out frame
+ );
+ if (ErrorHandler.Succeeded(hr)) {
+ hr = frame.Show();
+ }
+ return hr;
+ }
+
+ protected override void SetInnerProject(IntPtr innerIUnknown) {
+ var inner = Marshal.GetObjectForIUnknown(innerIUnknown);
+
+ // The reason why we keep a reference to those is that doing a QI after being
+ // aggregated would do the AddRef on the outer object.
+ _innerProject = inner as IVsProject;
+ _innerProject3 = inner as IVsProject3;
+ _innerVsHierarchy = inner as IVsHierarchy;
+ _innerVsProjectFlavorCfgProvider = inner as IVsProjectFlavorCfgProvider;
+
+ // Ensure we have a service provider as this is required for menu items to work
+ if (this.serviceProvider == null)
+ this.serviceProvider = (System.IServiceProvider)this._package;
+
+ // Now let the base implementation set the inner object
+ base.SetInnerProject(innerIUnknown);
+
+ // Add our commands (this must run after we called base.SetInnerProject)
+ _menuService = ((System.IServiceProvider)this).GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+
+ }
+
+ private bool TryHandleRightClick(IntPtr pvaIn, out int res) {
+ Guid itemType = GetSelectedItemType();
+
+ if (TryShowContextMenu(pvaIn, itemType, out res)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Gets all of the currently selected items.
+ ///
+ ///
+ private IEnumerable GetSelectedItems() {
+ IVsMonitorSelection monitorSelection = _package.GetService(typeof(IVsMonitorSelection)) as IVsMonitorSelection;
+
+ IntPtr hierarchyPtr = IntPtr.Zero;
+ IntPtr selectionContainer = IntPtr.Zero;
+ try {
+ uint selectionItemId;
+ IVsMultiItemSelect multiItemSelect = null;
+ ErrorHandler.ThrowOnFailure(monitorSelection.GetCurrentSelection(out hierarchyPtr, out selectionItemId, out multiItemSelect, out selectionContainer));
+
+ if (selectionItemId != VSConstants.VSITEMID_NIL && hierarchyPtr != IntPtr.Zero) {
+ IVsHierarchy hierarchy = Marshal.GetObjectForIUnknown(hierarchyPtr) as IVsHierarchy;
+
+ if (selectionItemId != VSConstants.VSITEMID_SELECTION) {
+ // This is a single selection. Compare hirarchy with our hierarchy and get node from itemid
+ if (Utilities.IsSameComObject(this, hierarchy)) {
+ yield return new VSITEMSELECTION() { itemid = selectionItemId, pHier = hierarchy };
+ }
+ } else if (multiItemSelect != null) {
+ // This is a multiple item selection.
+ // Get number of items selected and also determine if the items are located in more than one hierarchy
+
+ uint numberOfSelectedItems;
+ int isSingleHierarchyInt;
+ ErrorHandler.ThrowOnFailure(multiItemSelect.GetSelectionInfo(out numberOfSelectedItems, out isSingleHierarchyInt));
+ bool isSingleHierarchy = (isSingleHierarchyInt != 0);
+
+ // Now loop all selected items and add to the list only those that are selected within this hierarchy
+ if (!isSingleHierarchy || (isSingleHierarchy && Utilities.IsSameComObject(this, hierarchy))) {
+ Debug.Assert(numberOfSelectedItems > 0, "Bad number of selected itemd");
+ VSITEMSELECTION[] vsItemSelections = new VSITEMSELECTION[numberOfSelectedItems];
+ uint flags = (isSingleHierarchy) ? (uint)__VSGSIFLAGS.GSI_fOmitHierPtrs : 0;
+ ErrorHandler.ThrowOnFailure(multiItemSelect.GetSelectedItems(flags, numberOfSelectedItems, vsItemSelections));
+
+ foreach (VSITEMSELECTION vsItemSelection in vsItemSelections) {
+ yield return new VSITEMSELECTION() { itemid = vsItemSelection.itemid, pHier = hierarchy };
+ }
+ }
+ }
+ }
+ } finally {
+ if (hierarchyPtr != IntPtr.Zero) {
+ Marshal.Release(hierarchyPtr);
+ }
+ if (selectionContainer != IntPtr.Zero) {
+ Marshal.Release(selectionContainer);
+ }
+ }
+ }
+
+ private Guid GetSelectedItemType() {
+ Guid itemType = Guid.Empty;
+ foreach (var vsItemSelection in GetSelectedItems()) {
+ Guid typeGuid = GetItemType(vsItemSelection);
+
+ if (itemType == Guid.Empty) {
+ itemType = typeGuid;
+ } else if (itemType != typeGuid) {
+ // we have multiple item types
+ itemType = Guid.Empty;
+ break;
+ }
+ }
+ return itemType;
+ }
+
+ private bool TryShowContextMenu(IntPtr pvaIn, Guid itemType, out int res) {
+ if (itemType == new Guid(Guids.NodejsProjectFactoryString)) {
+ // multiple Node prjoect nodes selected
+ res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_PROJNODE/*IDM_VS_CTXT_WEBPROJECT*/);
+ return true;
+ } else if (itemType == VSConstants.GUID_ItemType_PhysicalFile) {
+ // multiple files selected
+ res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_ITEMNODE);
+ return true;
+ } else if (itemType == VSConstants.GUID_ItemType_PhysicalFolder) {
+ res = ShowContextMenu(pvaIn, VsMenus.IDM_VS_CTXT_FOLDERNODE);
+ return true;
+ }
+ res = VSConstants.E_FAIL;
+ return false;
+ }
+
+ private int ShowContextMenu(IntPtr pvaIn, int ctxMenu) {
+ object variant = Marshal.GetObjectForNativeVariant(pvaIn);
+ UInt32 pointsAsUint = (UInt32)variant;
+ short x = (short)(pointsAsUint & 0x0000ffff);
+ short y = (short)((pointsAsUint & 0xffff0000) / 0x10000);
+
+ POINTS points = new POINTS();
+ points.x = x;
+ points.y = y;
+
+ return ShowContextMenu(ctxMenu, VsMenus.guidSHLMainMenu, points);
+ }
+
+ ///
+ /// Shows the specified context menu at a specified location.
+ ///
+ /// The context menu ID.
+ /// The GUID of the menu group.
+ /// The location at which to show the menu.
+ internal int ShowContextMenu(int menuId, Guid menuGroup, POINTS points) {
+ IVsUIShell shell = _package.GetService(typeof(SVsUIShell)) as IVsUIShell;
+
+ Debug.Assert(shell != null, "Could not get the ui shell from the project");
+ if (shell == null) {
+ return VSConstants.E_FAIL;
+ }
+ POINTS[] pnts = new POINTS[1];
+ pnts[0].x = points.x;
+ pnts[0].y = points.y;
+ return shell.ShowContextMenu(0, ref menuGroup, menuId, pnts, (Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget)this);
+ }
+
+ protected override int ExecCommand(uint itemid, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (pguidCmdGroup == VsMenus.guidVsUIHierarchyWindowCmds) {
+ switch ((VSConstants.VsUIHierarchyWindowCmdIds)nCmdID) {
+ case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_RightClick:
+ int res;
+ if (TryHandleRightClick(pvaIn, out res)) {
+ return res;
+ }
+ break;
+ case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_DoubleClick:
+ case VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_EnterKey:
+ // open the document if it's an JavaScript file
+ if (IsJavaScriptFile(_innerVsHierarchy, itemid)) {
+ int hr = OpenWithNodejsEditor(itemid);
+
+ if (ErrorHandler.Succeeded(hr)) {
+ return hr;
+ }
+ }
+ break;
+
+ }
+ }
+
+ var result = base.ExecCommand(itemid, ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
+ return result;
+ }
+
+ int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ return ((IOleCommandTarget)_menuService).Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+ private bool IsJavaScriptFile(IVsHierarchy iVsHierarchy, uint itemid) {
+ object name;
+ ErrorHandler.ThrowOnFailure(iVsHierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_Name, out name));
+
+ return IsJavaScriptFile(name);
+ }
+
+ private static bool IsJavaScriptFile(object name) {
+ string strName = name as string;
+ if (strName != null) {
+ var ext = Path.GetExtension(strName);
+ if (String.Equals(ext, ".js", StringComparison.OrdinalIgnoreCase)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
+ if (pguidCmdGroup == Guids.Eureka) {
+ for (int i = 0; i < prgCmds.Length; i++) {
+ switch (prgCmds[i].cmdID) {
+ case 0x102: // View in Web Page Inspector from Eureka web tools
+ prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (pguidCmdGroup == Guids.VenusCommandId) {
+ for (int i = 0; i < prgCmds.Length; i++) {
+ switch (prgCmds[i].cmdID) {
+ case 0x034: /* add app assembly folder */
+ case 0x035: /* add app code folder */
+ case 0x036: /* add global resources */
+ case 0x037: /* add local resources */
+ case 0x038: /* add web refs folder */
+ case 0x039: /* add data folder */
+ case 0x040: /* add browser folders */
+ case 0x041: /* theme */
+ case 0x054: /* package settings */
+ case 0x055: /* context package settings */
+
+ prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (pguidCmdGroup == Guids.WebPackageCommandId) {
+ if (prgCmds[0].cmdID == 0x101 /* EnablePublishToWindowsAzureMenuItem*/) {
+ }
+ } else if (pguidCmdGroup == Guids.WebAppCmdId) {
+ for (int i = 0; i < prgCmds.Length; i++) {
+ switch (prgCmds[i].cmdID) {
+ case 0x06A: /* check accessibility */
+ prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (pguidCmdGroup == VSConstants.VSStd2K) {
+ for (int i = 0; i < prgCmds.Length; i++) {
+ switch ((VSConstants.VSStd2KCmdID)prgCmds[i].cmdID) {
+ case VSConstants.VSStd2KCmdID.SETASSTARTPAGE:
+ case VSConstants.VSStd2KCmdID.CHECK_ACCESSIBILITY:
+ prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) {
+ for (int i = 0; i < prgCmds.Length; i++) {
+ switch ((VSConstants.VSStd97CmdID)prgCmds[i].cmdID) {
+ case VSConstants.VSStd97CmdID.PreviewInBrowser:
+ case VSConstants.VSStd97CmdID.BrowseWith:
+ prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE | OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_DEFHIDEONCTXTMENU | OLECMDF.OLECMDF_ENABLED);
+ return VSConstants.S_OK;
+ }
+ }
+ }
+
+ return ((IOleCommandTarget)_menuService).QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
+ }
+
+
+ #region IVsProjectFlavorCfgProvider Members
+
+ public int CreateProjectFlavorCfg(IVsCfg pBaseProjectCfg, out IVsProjectFlavorCfg ppFlavorCfg) {
+ // We're flavored with a Web Application project and our normal project... But we don't
+ // want the web application project to influence our config as that alters our debug
+ // launch story. We control that w/ the Django project which is actually just letting the
+ // base Node.js project handle it. So we keep the base Node.js project config here.
+ IVsProjectFlavorCfg webCfg;
+ ErrorHandler.ThrowOnFailure(
+ _innerVsProjectFlavorCfgProvider.CreateProjectFlavorCfg(
+ pBaseProjectCfg,
+ out webCfg
+ )
+ );
+ ppFlavorCfg = new NodejsProjectConfig(pBaseProjectCfg, webCfg);
+
+ return VSConstants.S_OK;
+ }
+
+ #endregion
+
+
+ protected override int GetProperty(uint itemId, int propId, out object property) {
+ switch ((__VSHPROPID)propId) {
+ case __VSHPROPID.VSHPROPID_IconIndex:
+ case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
+ // Venus wants to change the icon for special folders using the IconIndex. All of our
+ // folders respond to IconHandles so we just force folders down that code path rather
+ // than trying to hand out the correct IconIndex here
+ if (GetItemType(new VSITEMSELECTION() { itemid = itemId, pHier = this }) == VSConstants.GUID_ItemType_PhysicalFolder) {
+ property = null;
+ return VSConstants.DISP_E_MEMBERNOTFOUND;
+ }
+ break;
+ }
+ switch ((__VSHPROPID4)propId) {
+
+ case __VSHPROPID4.VSHPROPID_TargetFrameworkMoniker:
+ // really only here for testing so WAP projects load correctly...
+ // But this also impacts the toolbox by filtering what available items there are.
+ property = ".NETFramework,Version=v4.5,Profile=Client";
+ return VSConstants.S_OK;
+ }
+ switch ((__VSHPROPID2)propId) {
+ case __VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList: {
+ var res = base.GetProperty(itemId, propId, out property);
+ property = RemovePropertyPagesFromList((string)property, CfgSpecificPropertyPagesToRemove);
+ return res;
+ }
+ case __VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList: {
+ var res = base.GetProperty(itemId, propId, out property);
+ property = RemovePropertyPagesFromList((string)property, PropertyPagesToRemove);
+ return res;
+ }
+ }
+#if DEV14_OR_LATER
+ switch((__VSHPROPID8)propId) {
+ case __VSHPROPID8.VSHPROPID_SupportsIconMonikers:
+ property = true;
+ return VSConstants.S_OK;
+ }
+#endif
+
+ return base.GetProperty(itemId, propId, out property);
+ }
+
+ internal static string[] CfgSpecificPropertyPagesToRemove = new[] {
+ "{A553AD0B-2F9E-4BCE-95B3-9A1F7074BC27}", // Package/Publish Web
+ "{9AB2347D-948D-4CD2-8DBE-F15F0EF78ED3}", // Package/Publish SQL
+ };
+
+ internal static string[] PropertyPagesToRemove = new[] {
+ "{8C0201FE-8ECA-403C-92A3-1BC55F031979}", // typeof(DeployPropertyPageComClass)
+ "{ED3B544C-26D8-4348-877B-A1F7BD505ED9}", // typeof(DatabaseDeployPropertyPageComClass)
+ "{909D16B3-C8E8-43D1-A2B8-26EA0D4B6B57}", // Microsoft.VisualStudio.Web.Application.WebPropertyPage
+ "{379354F2-BBB3-4BA9-AA71-FBE7B0E5EA94}" // Microsoft.VisualStudio.Web.Application.SilverlightLinksPage
+ };
+
+ internal string RemovePropertyPagesFromList(string propertyPagesList, string[] pagesToRemove) {
+ if (pagesToRemove != null) {
+ propertyPagesList = propertyPagesList.ToUpper(CultureInfo.InvariantCulture);
+ foreach (string s in pagesToRemove) {
+ int index = propertyPagesList.IndexOf(s, StringComparison.Ordinal);
+ if (index != -1) {
+ // Guids are separated by ';' so if we remove the last one also remove the last ';'
+ int index2 = index + s.Length + 1;
+ if (index2 >= propertyPagesList.Length)
+ propertyPagesList = propertyPagesList.Substring(0, index).TrimEnd(';');
+ else
+ propertyPagesList = propertyPagesList.Substring(0, index) + propertyPagesList.Substring(index2);
+ }
+ }
+ }
+ return propertyPagesList;
+ }
+
+ internal static Guid GetItemType(VSITEMSELECTION vsItemSelection) {
+ Guid typeGuid;
+ try {
+ ErrorHandler.ThrowOnFailure(
+ vsItemSelection.pHier.GetGuidProperty(
+ vsItemSelection.itemid,
+ (int)__VSHPROPID.VSHPROPID_TypeGuid,
+ out typeGuid
+ )
+ );
+ } catch (System.Runtime.InteropServices.COMException) {
+ return Guid.Empty;
+ }
+ return typeGuid;
+ }
+
+ private static EnvDTE.ProjectItem GetExtensionObject(IVsHierarchy hierarchy, uint itemId) {
+ object project;
+
+ ErrorHandler.ThrowOnFailure(
+ hierarchy.GetProperty(
+ itemId,
+ (int)__VSHPROPID.VSHPROPID_ExtObject,
+ out project
+ )
+ );
+
+ return (project as EnvDTE.ProjectItem);
+ }
+
+ private int OpenWithNodejsEditor(uint selectionItemId) {
+ // If the item type of this file is not compile, we don't actually want to open with Nodejs and should instead use the default.
+ Guid ourEditor;
+ var properties = GetExtensionObject(_innerVsHierarchy, selectionItemId).Properties;
+ try {
+ var itemType = properties.Item("ItemType").Value;
+ ourEditor = (string)itemType == ProjectFileConstants.Compile && !IsES6IntellisensePreview() ? Guids.NodejsEditorFactory : Guid.Empty;
+ } catch (ArgumentException) {
+ // no item type, file is excluded from project.
+ ourEditor = Guids.NodejsEditorFactory;
+ }
+
+ Guid view = Guid.Empty;
+ IVsWindowFrame frame;
+
+ // DOCDATAEXISTING_UNKNOWN http://msdn.microsoft.com/en-us/library/vstudio/bb139396(v=vs.110).aspx
+ // Force OpenStandardEditor to lookup if the document is currently open or not, and if it is. If it's
+ // open in a different editor the user will be prompted to close it.
+ var docDataExistingUnknown = new IntPtr(-1);
+ int hr = ((IVsProject3)_innerVsHierarchy).OpenItemWithSpecific(
+ selectionItemId,
+ 0,
+ ref ourEditor,
+ null,
+ ref view,
+ docDataExistingUnknown,
+ out frame
+ );
+ if (frame != null && ErrorHandler.Succeeded(hr)) {
+ hr = frame.Show();
+ }
+ return hr;
+ }
+
+ private bool IsES6IntellisensePreview() {
+ // If the analysis level is set to preview then use the TypeScript language service for node.js
+ return NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel == Options.AnalysisLevel.Preview;
+ }
+
+ #region IVsProject Members
+
+ public int AddItem(uint itemidLoc, VSADDITEMOPERATION dwAddItemOperation, string pszItemName, uint cFilesToOpen, string[] rgpszFilesToOpen, IntPtr hwndDlgOwner, VSADDRESULT[] pResult) {
+ // Check if we are adding an item to a folder that consists of browser-side code.
+ // In this case, we will want to open the file with the default editor.
+ var isClientCode = false;
+ var project = _innerVsHierarchy.GetProject().GetNodejsProject();
+
+ var selectedItems = this.GetSelectedItems().GetEnumerator();
+ if (selectedItems.MoveNext()) {
+ var currentId = selectedItems.Current.itemid;
+ string name;
+ GetCanonicalName(currentId, out name);
+ var nodeFolderNode = project.FindNodeByFullPath(name) as NodejsFolderNode;
+
+ if (nodeFolderNode != null) {
+ if (nodeFolderNode.ContentType == FolderContentType.Browser) {
+ isClientCode = true;
+ }
+ }
+ }
+
+ if (!isClientCode && _innerProject3 != null && IsJavaScriptFile(pszItemName)) {
+ Guid ourEditor = IsES6IntellisensePreview() ? Guid.Empty : typeof(NodejsEditorFactory).GUID;
+ Guid view = Guid.Empty;
+ return _innerProject3.AddItemWithSpecific(
+ itemidLoc,
+ dwAddItemOperation,
+ pszItemName,
+ cFilesToOpen,
+ rgpszFilesToOpen,
+ hwndDlgOwner,
+ dwAddItemOperation == VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE ?
+ (uint)__VSSPECIFICEDITORFLAGS.VSSPECIFICEDITOR_DoOpen :
+ 0,
+ ref ourEditor,
+ String.Empty,
+ ref view,
+ pResult
+ );
+ }
+ return _innerProject.AddItem(itemidLoc, dwAddItemOperation, pszItemName, cFilesToOpen, rgpszFilesToOpen, hwndDlgOwner, pResult);
+ }
+
+ public int GenerateUniqueItemName(uint itemidLoc, string pszExt, string pszSuggestedRoot, out string pbstrItemName) {
+ return _innerProject.GenerateUniqueItemName(itemidLoc, pszExt, pszSuggestedRoot, out pbstrItemName);
+ }
+
+ public int GetItemContext(uint itemid, out VisualStudio.OLE.Interop.IServiceProvider ppSP) {
+ return _innerProject.GetItemContext(itemid, out ppSP);
+ }
+
+ public int GetMkDocument(uint itemid, out string pbstrMkDocument) {
+ return _innerProject.GetMkDocument(itemid, out pbstrMkDocument);
+ }
+
+ public int IsDocumentInProject(string pszMkDocument, out int pfFound, VSDOCUMENTPRIORITY[] pdwPriority, out uint pitemid) {
+ return _innerProject.IsDocumentInProject(pszMkDocument, out pfFound, pdwPriority, out pitemid);
+ }
+
+ public int OpenItem(uint itemid, ref Guid rguidLogicalView, IntPtr punkDocDataExisting, out IVsWindowFrame ppWindowFrame) {
+ if (_innerProject3 != null && IsJavaScriptFile(GetItemName(_innerVsHierarchy, itemid))) {
+ // force .js files opened w/o an editor type to be opened w/ our editor factory.
+ Guid guid = IsES6IntellisensePreview() ? Guid.Empty : typeof(NodejsEditorFactory).GUID;
+ Guid view = Guid.Empty;
+ int hr = _innerProject3.OpenItemWithSpecific(
+ itemid,
+ 0,
+ ref guid,
+ null,
+ rguidLogicalView,
+ punkDocDataExisting,
+ out ppWindowFrame
+ );
+ return hr;
+ }
+
+ return _innerProject.OpenItem(itemid, rguidLogicalView, punkDocDataExisting, out ppWindowFrame);
+ }
+
+ #endregion
+
+ #region IVsProject2 Members
+
+ public int RemoveItem(uint dwReserved, uint itemid, out int pfResult) {
+ if (_innerProject3 != null) {
+ return _innerProject3.RemoveItem(dwReserved, itemid, out pfResult);
+ }
+ pfResult = 0;
+ return VSConstants.E_NOTIMPL;
+ }
+
+ public int ReopenItem(uint itemid, ref Guid rguidEditorType, string pszPhysicalView, ref Guid rguidLogicalView, IntPtr punkDocDataExisting, out IVsWindowFrame ppWindowFrame) {
+ if (_innerProject3 != null) {
+ if (IsJavaScriptFile(GetItemName(_innerVsHierarchy, itemid))) {
+ // force .js files opened w/o an editor type to be opened w/ our editor factory.
+ // If the item type of this file is not compile, we don't actually want to open with Nodejs and should instead use the default.
+ var itemType = GetExtensionObject(_innerVsHierarchy, itemid).Properties.Item("ItemType").Value;
+ Guid guid = (string)itemType == ProjectFileConstants.Compile && !IsES6IntellisensePreview() ? Guids.NodejsEditorFactory : Guid.Empty;
+
+ return _innerProject3.ReopenItem(
+ itemid,
+ ref guid,
+ pszPhysicalView,
+ ref rguidLogicalView,
+ punkDocDataExisting,
+ out ppWindowFrame
+ );
+
+ }
+ return _innerProject3.ReopenItem(itemid, ref rguidEditorType, pszPhysicalView, ref rguidLogicalView, punkDocDataExisting, out ppWindowFrame);
+ }
+ ppWindowFrame = null;
+ return VSConstants.E_NOTIMPL;
+ }
+
+ #endregion
+
+ public void AddedAsRole(object azureProjectHierarchy, string roleType) {
+ var hier = azureProjectHierarchy as IVsHierarchy;
+
+ if (hier == null) {
+ return;
+ }
+
+ this._package.GetUIThread().Invoke(() => {
+ string caption;
+ object captionObj;
+ if (ErrorHandler.Failed(_innerVsHierarchy.GetProperty(
+ (uint)VSConstants.VSITEMID.Root,
+ (int)__VSHPROPID.VSHPROPID_Caption,
+ out captionObj
+ )) || string.IsNullOrEmpty(caption = captionObj as string)) {
+ return;
+ }
+
+ UpdateServiceDefinition(
+ hier,
+ roleType,
+ caption,
+ new ServiceProvider(GetSite())
+ );
+ });
+ }
+
+ private static bool TryGetItemId(object obj, out uint id) {
+ const uint nil = (uint)VSConstants.VSITEMID.Nil;
+ id = obj as uint? ?? nil;
+ if (id == nil) {
+ var asInt = obj as int?;
+ if (asInt.HasValue) {
+ id = unchecked((uint)asInt.Value);
+ }
+ }
+ return id != nil;
+ }
+
+ ///
+ /// Updates the ServiceDefinition.csdef file in
+ /// to include the default startup and
+ /// runtime tasks for Python projects.
+ ///
+ ///
+ /// The Cloud Service project to update.
+ ///
+ ///
+ /// The type of role being added, either "Web" or "Worker".
+ ///
+ ///
+ /// The name of the role. This typically matches the Caption property.
+ ///
+ ///
+ /// VS service provider.
+ ///
+ internal static void UpdateServiceDefinition(
+ IVsHierarchy project,
+ string roleType,
+ string projectName,
+ System.IServiceProvider site
+ ) {
+ Utilities.ArgumentNotNull("project", project);
+
+ object obj;
+ ErrorHandler.ThrowOnFailure(project.GetProperty(
+ (uint)VSConstants.VSITEMID.Root,
+ (int)__VSHPROPID.VSHPROPID_FirstChild,
+ out obj
+ ));
+
+ uint id;
+ while (TryGetItemId(obj, out id)) {
+ Guid itemType;
+ string mkDoc;
+
+ if (ErrorHandler.Succeeded(project.GetGuidProperty(id, (int)__VSHPROPID.VSHPROPID_TypeGuid, out itemType)) &&
+ itemType == VSConstants.GUID_ItemType_PhysicalFile &&
+ ErrorHandler.Succeeded(project.GetProperty(id, (int)__VSHPROPID.VSHPROPID_Name, out obj)) &&
+ "ServiceDefinition.csdef".Equals(obj as string, StringComparison.InvariantCultureIgnoreCase) &&
+ ErrorHandler.Succeeded(project.GetCanonicalName(id, out mkDoc)) &&
+ !string.IsNullOrEmpty(mkDoc)
+ ) {
+ // We have found the file
+ var rdt = site.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
+
+ IVsHierarchy docHier;
+ uint docId, docCookie;
+ IntPtr pDocData;
+
+ bool updateFileOnDisk = true;
+
+ if (ErrorHandler.Succeeded(rdt.FindAndLockDocument(
+ (uint)_VSRDTFLAGS.RDT_EditLock,
+ mkDoc,
+ out docHier,
+ out docId,
+ out pDocData,
+ out docCookie
+ ))) {
+ try {
+ if (pDocData != IntPtr.Zero) {
+ try {
+ // File is open, so edit it through the document
+ UpdateServiceDefinition(
+ Marshal.GetObjectForIUnknown(pDocData) as IVsTextLines,
+ roleType,
+ projectName
+ );
+
+ ErrorHandler.ThrowOnFailure(rdt.SaveDocuments(
+ (uint)__VSRDTSAVEOPTIONS.RDTSAVEOPT_ForceSave,
+ docHier,
+ docId,
+ docCookie
+ ));
+
+ updateFileOnDisk = false;
+ } catch (ArgumentException) {
+ } catch (InvalidOperationException) {
+ } catch (COMException) {
+ } finally {
+ Marshal.Release(pDocData);
+ }
+ }
+ } finally {
+ ErrorHandler.ThrowOnFailure(rdt.UnlockDocument(
+ (uint)_VSRDTFLAGS.RDT_Unlock_SaveIfDirty | (uint)_VSRDTFLAGS.RDT_RequestUnlock,
+ docCookie
+ ));
+ }
+ }
+
+ if (updateFileOnDisk) {
+ // File is not open, so edit it on disk
+ FileStream stream = null;
+ try {
+ UpdateServiceDefinition(mkDoc, roleType, projectName);
+ } finally {
+ if (stream != null) {
+ stream.Close();
+ }
+ }
+ }
+
+ break;
+ }
+
+ if (ErrorHandler.Failed(project.GetProperty(id, (int)__VSHPROPID.VSHPROPID_NextSibling, out obj))) {
+ break;
+ }
+ }
+ }
+
+ private class StringWriterWithEncoding : StringWriter {
+ private readonly Encoding _encoding;
+
+ public StringWriterWithEncoding(Encoding encoding) {
+ _encoding = encoding;
+ }
+
+ public override Encoding Encoding {
+ get { return _encoding; }
+ }
+ }
+
+ private static void UpdateServiceDefinition(IVsTextLines lines, string roleType, string projectName) {
+ if (lines == null) {
+ throw new ArgumentException("lines");
+ }
+
+ int lastLine, lastIndex;
+ string text;
+
+ ErrorHandler.ThrowOnFailure(lines.GetLastLineIndex(out lastLine, out lastIndex));
+ ErrorHandler.ThrowOnFailure(lines.GetLineText(0, 0, lastLine, lastIndex, out text));
+
+ var doc = new XmlDocument();
+ doc.LoadXml(text);
+
+ UpdateServiceDefinition(doc, roleType, projectName);
+
+ var encoding = Encoding.UTF8;
+
+ var userData = lines as IVsUserData;
+ if (userData != null) {
+ var guid = VSConstants.VsTextBufferUserDataGuid.VsBufferEncodingVSTFF_guid;
+ object data;
+ int cp;
+ if (ErrorHandler.Succeeded(userData.GetData(ref guid, out data)) &&
+ (cp = (data as int? ?? (int)(data as uint? ?? 0)) & (int)__VSTFF.VSTFF_CPMASK) != 0) {
+ try {
+ encoding = Encoding.GetEncoding(cp);
+ } catch (NotSupportedException) {
+ } catch (ArgumentException) {
+ }
+ }
+ }
+
+ var sw = new StringWriterWithEncoding(encoding);
+ doc.Save(XmlWriter.Create(
+ sw,
+ new XmlWriterSettings {
+ Indent = true,
+ IndentChars = " ",
+ NewLineHandling = NewLineHandling.Entitize,
+ Encoding = encoding
+ }
+ ));
+
+ var sb = sw.GetStringBuilder();
+ var len = sb.Length;
+ var pStr = Marshal.StringToCoTaskMemUni(sb.ToString());
+
+ try {
+ ErrorHandler.ThrowOnFailure(lines.ReplaceLines(0, 0, lastLine, lastIndex, pStr, len, new TextSpan[1]));
+ } finally {
+ Marshal.FreeCoTaskMem(pStr);
+ }
+ }
+
+ private static void UpdateServiceDefinition(string path, string roleType, string projectName) {
+ var doc = new XmlDocument();
+ doc.Load(path);
+
+ UpdateServiceDefinition(doc, roleType, projectName);
+
+ doc.Save(XmlWriter.Create(
+ path,
+ new XmlWriterSettings {
+ Indent = true,
+ IndentChars = " ",
+ NewLineHandling = NewLineHandling.Entitize,
+ Encoding = Encoding.UTF8
+ }
+ ));
+ }
+
+ ///
+ /// Modifies the provided XML document to contain the service definition
+ /// nodes needed for the specified project.
+ ///
+ ///
+ /// is not one of "Web" or "Worker".
+ ///
+ ///
+ /// A required element is missing from the document.
+ ///
+ internal static void UpdateServiceDefinition(XmlDocument doc, string roleType, string projectName) {
+ bool isWeb = roleType == "Web";
+ bool isWorker = roleType == "Worker";
+ if (isWeb == isWorker) {
+ throw new ArgumentException("Unknown role type: " + (roleType ?? "(null)"), "roleType");
+ }
+
+ var nav = doc.CreateNavigator();
+
+ var ns = new XmlNamespaceManager(doc.NameTable);
+ ns.AddNamespace("sd", "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition");
+
+ var role = nav.SelectSingleNode(string.Format(
+ "/sd:ServiceDefinition/sd:{0}Role[@name='{1}']", roleType, projectName
+ ), ns);
+
+ if (role == null) {
+ throw new InvalidOperationException("Missing role entry");
+ }
+
+ var startup = role.SelectSingleNode("sd:Startup", ns);
+ if (startup != null) {
+ startup.DeleteSelf();
+ }
+
+ role.AppendChildElement(null, "Startup", null, null);
+ startup = role.SelectSingleNode("sd:Startup", ns);
+ if (startup == null) {
+ throw new InvalidOperationException("Missing Startup entry");
+ }
+
+ startup.ReplaceSelf(string.Format(@"
+
+
+
+
+
+
+
+
+ {1}
+", roleType.ToLowerInvariant(), isWorker ? @"" : string.Empty));
+
+ if (isWorker) {
+ var runtime = role.SelectSingleNode("sd:Runtime", ns);
+ if (runtime != null) {
+ runtime.DeleteSelf();
+ }
+ role.AppendChildElement(null, "Runtime", null, null);
+
+ runtime = role.SelectSingleNode("sd:Runtime", ns);
+ if (startup == null) {
+ throw new InvalidOperationException("Missing Runtime entry");
+ }
+
+ runtime.ReplaceSelf(@"
+
+
+
+
+
+
+
+
+");
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NpmUI/ErrorHelper.cs b/Nodejs/Product/Nodejs/NpmUI/ErrorHelper.cs
index f715e82b1..0afef14bd 100644
--- a/Nodejs/Product/Nodejs/NpmUI/ErrorHelper.cs
+++ b/Nodejs/Product/Nodejs/NpmUI/ErrorHelper.cs
@@ -1,101 +1,101 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Text;
-using System.Windows;
-using Microsoft.NodejsTools.Npm;
-
-namespace Microsoft.NodejsTools.NpmUI
-{
- internal static class ErrorHelper {
-
- private const string CaptionNpmNotInstalled = "npm Not Installed";
-
- private static Exception _lastNpmNotFoundException;
-
- public static string GetExceptionDetailsText(Exception e) {
- var buff = new StringBuilder();
- var current = e;
- do {
- if (buff.Length > 0) {
- buff.Append("Caused by:\r\n");
- }
- buff.Append(current.Message);
- buff.Append("\r\n");
-#if DEBUG
- buff.Append(current.GetType());
- buff.Append("\r\n");
- buff.Append(current.StackTrace);
-#endif
- current = current.InnerException;
- } while (null != current);
- return buff.ToString();
- }
-
- private static Exception GetNpmNotFoundException(Exception source) {
- do {
- if (source is NpmNotFoundException) {
- return source;
- }
- source = source.InnerException;
- } while (null != source);
- return null;
- }
-
- public static void ReportNpmNotInstalled(
- Window owner,
- Exception ex) {
- var nnfe = GetNpmNotFoundException(ex);
- if (null == nnfe) {
- nnfe = ex;
- } else {
- // Don't want to keep bombarding user with same message - there's a real danger this popup
- // could appear quite a lot if changes are made to the filesystem.
- bool report = (null == _lastNpmNotFoundException || ex.Message != _lastNpmNotFoundException.Message);
-
- _lastNpmNotFoundException = nnfe;
-
- if (!report) {
- return;
- }
- }
-
- var message =
- string.Format(@"Could not find npm.cmd. Ensure you have a recent version of node.js installed and have specified the location of node.exe in the project properties, or that it is available on your system PATH.
-
-The following error occurred trying to execute npm.cmd:
-
-{0}", nnfe.Message);
-
- if (null == owner) {
- MessageBox.Show(
- message,
- CaptionNpmNotInstalled,
- MessageBoxButton.OK,
- MessageBoxImage.Error);
- } else {
- MessageBox.Show(
- owner,
- message,
- CaptionNpmNotInstalled,
- MessageBoxButton.OK,
- MessageBoxImage.Error);
- }
-
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Text;
+using System.Windows;
+using Microsoft.NodejsTools.Npm;
+
+namespace Microsoft.NodejsTools.NpmUI
+{
+ internal static class ErrorHelper {
+
+ private const string CaptionNpmNotInstalled = "npm Not Installed";
+
+ private static Exception _lastNpmNotFoundException;
+
+ public static string GetExceptionDetailsText(Exception e) {
+ var buff = new StringBuilder();
+ var current = e;
+ do {
+ if (buff.Length > 0) {
+ buff.Append("Caused by:\r\n");
+ }
+ buff.Append(current.Message);
+ buff.Append("\r\n");
+#if DEBUG
+ buff.Append(current.GetType());
+ buff.Append("\r\n");
+ buff.Append(current.StackTrace);
+#endif
+ current = current.InnerException;
+ } while (null != current);
+ return buff.ToString();
+ }
+
+ private static Exception GetNpmNotFoundException(Exception source) {
+ do {
+ if (source is NpmNotFoundException) {
+ return source;
+ }
+ source = source.InnerException;
+ } while (null != source);
+ return null;
+ }
+
+ public static void ReportNpmNotInstalled(
+ Window owner,
+ Exception ex) {
+ var nnfe = GetNpmNotFoundException(ex);
+ if (null == nnfe) {
+ nnfe = ex;
+ } else {
+ // Don't want to keep bombarding user with same message - there's a real danger this popup
+ // could appear quite a lot if changes are made to the filesystem.
+ bool report = (null == _lastNpmNotFoundException || ex.Message != _lastNpmNotFoundException.Message);
+
+ _lastNpmNotFoundException = nnfe;
+
+ if (!report) {
+ return;
+ }
+ }
+
+ var message =
+ string.Format(@"Could not find npm.cmd. Ensure you have a recent version of node.js installed and have specified the location of node.exe in the project properties, or that it is available on your system PATH.
+
+The following error occurred trying to execute npm.cmd:
+
+{0}", nnfe.Message);
+
+ if (null == owner) {
+ MessageBox.Show(
+ message,
+ CaptionNpmNotInstalled,
+ MessageBoxButton.OK,
+ MessageBoxImage.Error);
+ } else {
+ MessageBox.Show(
+ owner,
+ message,
+ CaptionNpmNotInstalled,
+ MessageBoxButton.OK,
+ MessageBoxImage.Error);
+ }
+
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NpmUI/LastRefreshedMessageProvider.cs b/Nodejs/Product/Nodejs/NpmUI/LastRefreshedMessageProvider.cs
index 66cf4d574..79f4eb285 100644
--- a/Nodejs/Product/Nodejs/NpmUI/LastRefreshedMessageProvider.cs
+++ b/Nodejs/Product/Nodejs/NpmUI/LastRefreshedMessageProvider.cs
@@ -1,72 +1,72 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using Microsoft.NodejsTools.Project;
-
-namespace Microsoft.NodejsTools.NpmUI {
- internal class LastRefreshedMessageProvider {
- public static readonly LastRefreshedMessageProvider RefreshFailed = new LastRefreshedMessageProvider {
- Days = int.MaxValue,
- Description = SR.GetString(SR.PackageCatalogRefreshFailed)
- };
-
- public static readonly LastRefreshedMessageProvider RefreshInProgress = new LastRefreshedMessageProvider {
- Days = 0,
- Description = SR.GetString(SR.PackageCatalogRefreshing)
- };
-
- public static readonly LastRefreshedMessageProvider NpmNotFound = new LastRefreshedMessageProvider {
- Days = int.MaxValue,
- Description = "npm not installed"
- };
-
- private LastRefreshedMessageProvider() { }
-
- public LastRefreshedMessageProvider(DateTime lastRefreshTime) {
- if (lastRefreshTime == DateTime.MinValue) {
- Days = int.MaxValue;
- Description = SR.GetString(SR.PackageCatalogRefreshFailed);
- } else {
- Days = (int)(DateTime.Now.Date - lastRefreshTime.Date).TotalDays;
- if (Days == 0) {
- Description = SR.GetString(SR.PackageCatalogRefresh0Days, lastRefreshTime);
- } else if (Days == 1) {
- Description = SR.GetString(SR.PackageCatalogRefresh1Day, lastRefreshTime);
- } else if (Days <= 7) {
- Description = SR.GetString(SR.PackageCatalogRefresh2To7Days, Days);
- } else if (Days <= 14) {
- Description = SR.GetString(SR.PackageCatalogRefresh1Week);
- } else if (Days <= 21) {
- Description = SR.GetString(SR.PackageCatalogRefresh2Weeks);
- } else if (Days <= 31) {
- Description = SR.GetString(SR.PackageCatalogRefresh3Weeks);
- } else if (Days <= 92) {
- Description = SR.GetString(SR.PackageCatalogRefresh1Month);
- } else {
- Description = SR.GetString(SR.PackageCatalogRefresh3Months);
- }
- }
- }
-
- public int Days { get; private set; }
-
- public string Description { get; private set; }
-
- public bool IsOld { get { return Days > 7; } }
- public bool IsAncient { get { return Days > 14; } }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using Microsoft.NodejsTools.Project;
+
+namespace Microsoft.NodejsTools.NpmUI {
+ internal class LastRefreshedMessageProvider {
+ public static readonly LastRefreshedMessageProvider RefreshFailed = new LastRefreshedMessageProvider {
+ Days = int.MaxValue,
+ Description = SR.GetString(SR.PackageCatalogRefreshFailed)
+ };
+
+ public static readonly LastRefreshedMessageProvider RefreshInProgress = new LastRefreshedMessageProvider {
+ Days = 0,
+ Description = SR.GetString(SR.PackageCatalogRefreshing)
+ };
+
+ public static readonly LastRefreshedMessageProvider NpmNotFound = new LastRefreshedMessageProvider {
+ Days = int.MaxValue,
+ Description = "npm not installed"
+ };
+
+ private LastRefreshedMessageProvider() { }
+
+ public LastRefreshedMessageProvider(DateTime lastRefreshTime) {
+ if (lastRefreshTime == DateTime.MinValue) {
+ Days = int.MaxValue;
+ Description = SR.GetString(SR.PackageCatalogRefreshFailed);
+ } else {
+ Days = (int)(DateTime.Now.Date - lastRefreshTime.Date).TotalDays;
+ if (Days == 0) {
+ Description = SR.GetString(SR.PackageCatalogRefresh0Days, lastRefreshTime);
+ } else if (Days == 1) {
+ Description = SR.GetString(SR.PackageCatalogRefresh1Day, lastRefreshTime);
+ } else if (Days <= 7) {
+ Description = SR.GetString(SR.PackageCatalogRefresh2To7Days, Days);
+ } else if (Days <= 14) {
+ Description = SR.GetString(SR.PackageCatalogRefresh1Week);
+ } else if (Days <= 21) {
+ Description = SR.GetString(SR.PackageCatalogRefresh2Weeks);
+ } else if (Days <= 31) {
+ Description = SR.GetString(SR.PackageCatalogRefresh3Weeks);
+ } else if (Days <= 92) {
+ Description = SR.GetString(SR.PackageCatalogRefresh1Month);
+ } else {
+ Description = SR.GetString(SR.PackageCatalogRefresh3Months);
+ }
+ }
+ }
+
+ public int Days { get; private set; }
+
+ public string Description { get; private set; }
+
+ public bool IsOld { get { return Days > 7; } }
+ public bool IsAncient { get { return Days > 14; } }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallViewModel.cs b/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallViewModel.cs
index 365cd7440..6f80f01f3 100644
--- a/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallViewModel.cs
+++ b/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallViewModel.cs
@@ -1,513 +1,513 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Windows;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Threading;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.NodejsTools.Project;
-
-namespace Microsoft.NodejsTools.NpmUI {
- internal class NpmPackageInstallViewModel : INotifyPropertyChanged {
- internal enum Indices {
- IndexStandard = 0,
- IndexDev = 1,
- IndexOptional = 2,
- IndexGlobal = 3
- }
-
- internal enum FilterState {
- NoFilterText,
- Filtering,
- ResultsAvailable,
- NoResults
- }
-
- public static readonly ICommand InstallCommand = new RoutedCommand();
- public static readonly ICommand OpenHomepageCommand = new RoutedCommand();
- public static readonly ICommand RefreshCatalogCommand = new RoutedCommand();
-
- private INpmController _npmController;
-
- private bool _isFiltering = false;
- private bool _isLoadingCatalog;
- private IPackageCatalog _allPackages;
- private readonly object _filteredPackagesLock = new object();
- private IList _filteredPackages = new List();
- private LastRefreshedMessageProvider _lastRefreshedMessage;
- private PackageCatalogEntryViewModel _selectedPackage;
- private bool _npmNotFound;
- private bool _isCatalogEmpty;
- private Visibility _catalogControlVisibility = Visibility.Collapsed;
- private string _catalogLoadingMessage = string.Empty;
- private string _catalogLoadingProgressMessage = string.Empty;
- private Visibility _loadingCatalogControlVisibility = Visibility.Collapsed;
- private int _selectedDependencyTypeIndex;
-
- private string _currentFilter = string.Empty;
- private string _filterText = string.Empty;
- private readonly Timer _filterTimer;
- private string _arguments = string.Empty;
- private bool _saveToPackageJson = true;
- private object _selectedVersion;
-
- private readonly Dispatcher _dispatcher;
-
- private readonly NpmOutputViewModel _executeViewModel;
-
- public NpmPackageInstallViewModel(
- NpmOutputViewModel executeViewModel,
- Dispatcher dispatcher
- ) {
- _dispatcher = dispatcher;
-
- _executeViewModel = executeViewModel;
- _filterTimer = new Timer(FilterTimer_Elapsed, null, Timeout.Infinite, Timeout.Infinite);
- }
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
- PropertyChangedEventHandler handler = PropertyChanged;
- if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
- }
-
- public INpmController NpmController {
- get { return _npmController; }
- set {
- if (null != _npmController) {
- _npmController.FinishedRefresh -= NpmController_FinishedRefresh;
- }
- _npmController = value;
- OnPropertyChanged();
- if (null != _npmController) {
- LoadCatalog();
- _npmController.FinishedRefresh += NpmController_FinishedRefresh;
- }
- }
- }
-
- void NpmController_FinishedRefresh(object sender, EventArgs e) {
- StartFilter();
- }
-
- public NpmOutputViewModel ExecuteViewModel {
- get { return _executeViewModel; }
- }
-
- #region Catalog control and refresh
- public bool IsLoadingCatalog {
- get { return _isLoadingCatalog; }
- private set {
- _isLoadingCatalog = value;
- OnPropertyChanged();
- OnPropertyChanged("CanRefreshCatalog");
- }
- }
-
- public bool CanRefreshCatalog {
- get { return !IsLoadingCatalog; }
- }
-
- public bool NpmNotFound {
- get { return _npmNotFound; }
- private set {
- _npmNotFound = value;
- OnPropertyChanged();
- }
- }
-
- public bool IsCatalogEmpty {
- get { return _isCatalogEmpty; }
- private set {
- _isCatalogEmpty = value;
- OnPropertyChanged();
- }
- }
-
- public string LoadingCatalogMessage {
- get { return _catalogLoadingMessage; }
- private set {
- _catalogLoadingMessage = value;
- OnPropertyChanged();
- }
- }
-
- public string LoadingCatalogProgressMessage {
- get { return _catalogLoadingProgressMessage; }
- private set {
- _catalogLoadingProgressMessage = value;
- OnPropertyChanged();
- }
- }
-
- public Visibility LoadingCatalogControlVisibility {
- get { return _loadingCatalogControlVisibility; }
- set {
- _loadingCatalogControlVisibility = value;
- OnPropertyChanged();
- OnPropertyChanged("FilterControlsVisibility");
- }
- }
-
- private async void LoadCatalog(bool forceRefresh) {
- IsLoadingCatalog = true;
-
- CatalogControlVisibility = Visibility.Collapsed;
- LoadingCatalogControlVisibility = Visibility.Visible;
- LoadingCatalogMessage = SR.GetString(SR.CatalogLoadingDefault);
-
- LastRefreshedMessage = LastRefreshedMessageProvider.RefreshInProgress;
-
- var controller = _npmController;
- controller.ErrorLogged += _executeViewModel.commander_ErrorLogged;
- controller.ExceptionLogged += _executeViewModel.commander_ExceptionLogged;
- controller.OutputLogged += _executeViewModel.commander_OutputLogged;
- _executeViewModel.SetCancellableSafe(false);
- try {
- _allPackages = await controller.GetRepositoryCatalogAsync(
- forceRefresh,
- new Progress(msg => LoadingCatalogProgressMessage = msg)
- );
- IsCatalogEmpty = false;
- } catch (NpmNotFoundException) {
- LastRefreshedMessage = LastRefreshedMessageProvider.NpmNotFound;
- } catch (NpmCatalogEmptyException) {
- IsCatalogEmpty = true;
- LastRefreshedMessage = new LastRefreshedMessageProvider(_allPackages.LastRefreshed);
- } catch (Exception ex) {
- if (IsCriticalException(ex)) {
- throw;
- }
-
- LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
- IsCatalogEmpty = true;
- } finally {
- IsLoadingCatalog = false;
- controller.ErrorLogged -= _executeViewModel.commander_ErrorLogged;
- controller.ExceptionLogged -= _executeViewModel.commander_ExceptionLogged;
- controller.OutputLogged -= _executeViewModel.commander_OutputLogged;
- _executeViewModel.SetCancellableSafe(true);
-
- // The catalog refresh operation spawns many long-lived Gen 2 objects,
- // so the garbage collector will take a while to get to them otherwise.
- GC.Collect();
- }
-
- // Reset the filter text, otherwise the results will be outdated.
- FilterText = string.Empty;
-
- // We want to show the catalog regardless of whether an exception was thrown so that the user has the chance to refresh it.
- LoadingCatalogControlVisibility = Visibility.Collapsed;
-
- StartFilter();
- }
-
- private static bool IsCriticalException(Exception ex) {
- return ex is StackOverflowException ||
- ex is OutOfMemoryException ||
- ex is ThreadAbortException ||
- ex is AccessViolationException;
- }
-
- public void LoadCatalog() {
- LoadCatalog(false);
- }
-
- public void RefreshCatalog() {
- LoadCatalog(true);
- }
-
- public Visibility CatalogControlVisibility {
- get { return _catalogControlVisibility; }
- set {
- _catalogControlVisibility = value;
- OnPropertyChanged();
- }
- }
-
- #endregion
-
- #region Filtering
- public FilterState PackageFilterState {
- get {
- if (IsFiltering) {
- return FilterState.Filtering;
- }
- if (string.IsNullOrEmpty(FilterText)) {
- return FilterState.NoFilterText;
- }
- if (!FilteredPackages.Any()) {
- return FilterState.NoResults;
- }
- return FilterState.ResultsAvailable;
- }
- }
-
- private bool IsFiltering {
- get { return _isFiltering; }
- set {
- _isFiltering = value;
- OnPropertyChanged();
- OnPropertyChanged("PackageFilterState");
- }
- }
-
- public IList FilteredPackages {
- get {
- lock (_filteredPackagesLock) {
- return _filteredPackages;
- }
- }
- set {
- lock (_filteredPackagesLock) {
- _filteredPackages = value;
- }
-
- // PackageFilterState should be triggered before FilteredPackages
- // to allow the UI to update the status before the package list,
- // making for a smoother experience.
- OnPropertyChanged("PackageFilterState");
- OnPropertyChanged();
- }
- }
-
- public string FilterText {
- get { return _filterText; }
- set {
- _filterText = value;
-
- StartFilter();
- IsFiltering = !string.IsNullOrWhiteSpace(_filterText);
-
- OnPropertyChanged();
- OnPropertyChanged("PackageFilterState");
- }
- }
-
- private void StartFilter() {
- _filterTimer.Change(300, Timeout.Infinite);
- }
-
- private async void FilterTimer_Elapsed(object state) {
- if (_allPackages == null) {
- LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
- IsFiltering = false;
- return;
- }
-
- var filterText = GetTrimmedTextSafe(_filterText);
-
- IEnumerable filtered;
- if (string.IsNullOrWhiteSpace(filterText)) {
- filtered = Enumerable.Empty();
- } else {
- try {
- filtered = await _allPackages.GetCatalogPackagesAsync(filterText);
- } catch (Exception ex) {
- LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
- if (IsCriticalException(ex)) {
- throw;
- }
- StartFilter();
- return;
- }
- }
-
- if (filtered == null) {
- // The database file must be in use. Display current results, but try again later.
- LastRefreshedMessage = LastRefreshedMessageProvider.RefreshInProgress;
- StartFilter();
- return;
- }
-
- var newItems = new List();
- if (filterText != GetTrimmedTextSafe(_filterText)) {
- return;
- }
-
- if (filtered.Any()) {
- IRootPackage rootPackage = null;
- IGlobalPackages globalPackages = null;
- var controller = _npmController;
- if (controller != null) {
- rootPackage = controller.RootPackage;
- globalPackages = controller.GlobalPackages;
- }
-
- newItems.AddRange(filtered.Select(package => new ReadOnlyPackageCatalogEntryViewModel(
- package,
- rootPackage != null ? rootPackage.Modules[package.Name] : null,
- globalPackages != null ? globalPackages.Modules[package.Name] : null
- )));
- }
-
- await _dispatcher.BeginInvoke((Action)(() => {
- if (filterText != GetTrimmedTextSafe(_filterText)) {
- return;
- }
-
- var originalSelectedPackage = SelectedPackage;
- FilteredPackages = newItems;
-
- // Reassign originalSelectedPackage to the original selected package in the new list of filtered packages.
- if (originalSelectedPackage != null) {
- originalSelectedPackage = FilteredPackages.FirstOrDefault(package => package.Name == originalSelectedPackage.Name);
- }
-
- // Maintain selection when the filter list refreshes (e.g. due to an installation running in the background)
- SelectedPackage = originalSelectedPackage ?? FilteredPackages.FirstOrDefault();
-
- _currentFilter = filterText;
-
- LastRefreshedMessage = IsCatalogEmpty
- ? LastRefreshedMessageProvider.RefreshFailed
- : new LastRefreshedMessageProvider(_allPackages.LastRefreshed);
- CatalogControlVisibility = Visibility.Visible;
- }));
-
- IsFiltering = false;
-
- // The catalog refresh operation spawns many long-lived Gen 2 objects,
- // so the garbage collector will take a while to get to them otherwise.
- GC.Collect();
- }
-
- private string GetTrimmedTextSafe(string text) {
- return text != null ? text.Trim() : string.Empty;
- }
-
- public LastRefreshedMessageProvider LastRefreshedMessage {
- get { return _lastRefreshedMessage; }
- set {
- _lastRefreshedMessage = value;
- OnPropertyChanged();
- }
- }
-
- public Visibility FilterControlsVisibility {
- get { return LoadingCatalogControlVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible; }
- }
-
- #endregion
-
- #region Installation
-
- public int SelectedDependencyTypeIndex {
- get { return _selectedDependencyTypeIndex; }
- set {
- _selectedDependencyTypeIndex = value;
- OnPropertyChanged();
- OnPropertyChanged("GlobalWarningVisibility");
- }
- }
-
- public object SelectedVersion {
- get { return _selectedVersion; }
- set {
- _selectedVersion = value;
- OnPropertyChanged();
- }
- }
-
- public Visibility GlobalWarningVisibility {
- get {
- return Indices.IndexGlobal == (Indices) SelectedDependencyTypeIndex
- ? Visibility.Visible
- : Visibility.Collapsed;
- }
- }
-
- internal bool CanInstall(PackageCatalogEntryViewModel package) {
- return package != null;
- }
-
- internal void Install(PackageCatalogEntryViewModel package) {
- var type = DependencyType.Standard;
- var isGlobal = false;
- switch ((Indices)SelectedDependencyTypeIndex) {
- case Indices.IndexDev:
- type = DependencyType.Development;
- break;
-
- case Indices.IndexOptional:
- type = DependencyType.Optional;
- break;
-
- case Indices.IndexGlobal:
- isGlobal = true;
- break;
- }
-
- if (!string.IsNullOrEmpty(package.Name)) {
- var selectedVersion = SelectedVersion is SemverVersion ? ((SemverVersion)SelectedVersion).ToString(): string.Empty;
- _executeViewModel.QueueCommand(
- NpmArgumentBuilder.GetNpmInstallArguments(
- package.Name,
- selectedVersion,
- type,
- isGlobal,
- SaveToPackageJson,
- Arguments));
- }
- }
-
- internal bool CanOpenHomepage(string homepage) {
- return !string.IsNullOrEmpty(homepage);
- }
-
- internal void OpenHomepage(string homepage) {
- if (!string.IsNullOrEmpty(homepage)) {
- Process.Start(homepage);
- }
- }
-
- public string Arguments {
- get { return _arguments; }
- set {
- _arguments = value;
- OnPropertyChanged();
- }
- }
-
- public bool SaveToPackageJson {
- get { return _saveToPackageJson; }
- set {
- _saveToPackageJson = value;
- OnPropertyChanged();
- }
- }
-
- public PackageCatalogEntryViewModel SelectedPackage {
- get { return _selectedPackage; }
- set {
- _selectedPackage = value;
- OnPropertyChanged();
- }
- }
-
- #endregion
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Windows;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Threading;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.NodejsTools.Project;
+
+namespace Microsoft.NodejsTools.NpmUI {
+ internal class NpmPackageInstallViewModel : INotifyPropertyChanged {
+ internal enum Indices {
+ IndexStandard = 0,
+ IndexDev = 1,
+ IndexOptional = 2,
+ IndexGlobal = 3
+ }
+
+ internal enum FilterState {
+ NoFilterText,
+ Filtering,
+ ResultsAvailable,
+ NoResults
+ }
+
+ public static readonly ICommand InstallCommand = new RoutedCommand();
+ public static readonly ICommand OpenHomepageCommand = new RoutedCommand();
+ public static readonly ICommand RefreshCatalogCommand = new RoutedCommand();
+
+ private INpmController _npmController;
+
+ private bool _isFiltering = false;
+ private bool _isLoadingCatalog;
+ private IPackageCatalog _allPackages;
+ private readonly object _filteredPackagesLock = new object();
+ private IList _filteredPackages = new List();
+ private LastRefreshedMessageProvider _lastRefreshedMessage;
+ private PackageCatalogEntryViewModel _selectedPackage;
+ private bool _npmNotFound;
+ private bool _isCatalogEmpty;
+ private Visibility _catalogControlVisibility = Visibility.Collapsed;
+ private string _catalogLoadingMessage = string.Empty;
+ private string _catalogLoadingProgressMessage = string.Empty;
+ private Visibility _loadingCatalogControlVisibility = Visibility.Collapsed;
+ private int _selectedDependencyTypeIndex;
+
+ private string _currentFilter = string.Empty;
+ private string _filterText = string.Empty;
+ private readonly Timer _filterTimer;
+ private string _arguments = string.Empty;
+ private bool _saveToPackageJson = true;
+ private object _selectedVersion;
+
+ private readonly Dispatcher _dispatcher;
+
+ private readonly NpmOutputViewModel _executeViewModel;
+
+ public NpmPackageInstallViewModel(
+ NpmOutputViewModel executeViewModel,
+ Dispatcher dispatcher
+ ) {
+ _dispatcher = dispatcher;
+
+ _executeViewModel = executeViewModel;
+ _filterTimer = new Timer(FilterTimer_Elapsed, null, Timeout.Infinite, Timeout.Infinite);
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public INpmController NpmController {
+ get { return _npmController; }
+ set {
+ if (null != _npmController) {
+ _npmController.FinishedRefresh -= NpmController_FinishedRefresh;
+ }
+ _npmController = value;
+ OnPropertyChanged();
+ if (null != _npmController) {
+ LoadCatalog();
+ _npmController.FinishedRefresh += NpmController_FinishedRefresh;
+ }
+ }
+ }
+
+ void NpmController_FinishedRefresh(object sender, EventArgs e) {
+ StartFilter();
+ }
+
+ public NpmOutputViewModel ExecuteViewModel {
+ get { return _executeViewModel; }
+ }
+
+ #region Catalog control and refresh
+ public bool IsLoadingCatalog {
+ get { return _isLoadingCatalog; }
+ private set {
+ _isLoadingCatalog = value;
+ OnPropertyChanged();
+ OnPropertyChanged("CanRefreshCatalog");
+ }
+ }
+
+ public bool CanRefreshCatalog {
+ get { return !IsLoadingCatalog; }
+ }
+
+ public bool NpmNotFound {
+ get { return _npmNotFound; }
+ private set {
+ _npmNotFound = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool IsCatalogEmpty {
+ get { return _isCatalogEmpty; }
+ private set {
+ _isCatalogEmpty = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string LoadingCatalogMessage {
+ get { return _catalogLoadingMessage; }
+ private set {
+ _catalogLoadingMessage = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string LoadingCatalogProgressMessage {
+ get { return _catalogLoadingProgressMessage; }
+ private set {
+ _catalogLoadingProgressMessage = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public Visibility LoadingCatalogControlVisibility {
+ get { return _loadingCatalogControlVisibility; }
+ set {
+ _loadingCatalogControlVisibility = value;
+ OnPropertyChanged();
+ OnPropertyChanged("FilterControlsVisibility");
+ }
+ }
+
+ private async void LoadCatalog(bool forceRefresh) {
+ IsLoadingCatalog = true;
+
+ CatalogControlVisibility = Visibility.Collapsed;
+ LoadingCatalogControlVisibility = Visibility.Visible;
+ LoadingCatalogMessage = SR.GetString(SR.CatalogLoadingDefault);
+
+ LastRefreshedMessage = LastRefreshedMessageProvider.RefreshInProgress;
+
+ var controller = _npmController;
+ controller.ErrorLogged += _executeViewModel.commander_ErrorLogged;
+ controller.ExceptionLogged += _executeViewModel.commander_ExceptionLogged;
+ controller.OutputLogged += _executeViewModel.commander_OutputLogged;
+ _executeViewModel.SetCancellableSafe(false);
+ try {
+ _allPackages = await controller.GetRepositoryCatalogAsync(
+ forceRefresh,
+ new Progress(msg => LoadingCatalogProgressMessage = msg)
+ );
+ IsCatalogEmpty = false;
+ } catch (NpmNotFoundException) {
+ LastRefreshedMessage = LastRefreshedMessageProvider.NpmNotFound;
+ } catch (NpmCatalogEmptyException) {
+ IsCatalogEmpty = true;
+ LastRefreshedMessage = new LastRefreshedMessageProvider(_allPackages.LastRefreshed);
+ } catch (Exception ex) {
+ if (IsCriticalException(ex)) {
+ throw;
+ }
+
+ LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
+ IsCatalogEmpty = true;
+ } finally {
+ IsLoadingCatalog = false;
+ controller.ErrorLogged -= _executeViewModel.commander_ErrorLogged;
+ controller.ExceptionLogged -= _executeViewModel.commander_ExceptionLogged;
+ controller.OutputLogged -= _executeViewModel.commander_OutputLogged;
+ _executeViewModel.SetCancellableSafe(true);
+
+ // The catalog refresh operation spawns many long-lived Gen 2 objects,
+ // so the garbage collector will take a while to get to them otherwise.
+ GC.Collect();
+ }
+
+ // Reset the filter text, otherwise the results will be outdated.
+ FilterText = string.Empty;
+
+ // We want to show the catalog regardless of whether an exception was thrown so that the user has the chance to refresh it.
+ LoadingCatalogControlVisibility = Visibility.Collapsed;
+
+ StartFilter();
+ }
+
+ private static bool IsCriticalException(Exception ex) {
+ return ex is StackOverflowException ||
+ ex is OutOfMemoryException ||
+ ex is ThreadAbortException ||
+ ex is AccessViolationException;
+ }
+
+ public void LoadCatalog() {
+ LoadCatalog(false);
+ }
+
+ public void RefreshCatalog() {
+ LoadCatalog(true);
+ }
+
+ public Visibility CatalogControlVisibility {
+ get { return _catalogControlVisibility; }
+ set {
+ _catalogControlVisibility = value;
+ OnPropertyChanged();
+ }
+ }
+
+ #endregion
+
+ #region Filtering
+ public FilterState PackageFilterState {
+ get {
+ if (IsFiltering) {
+ return FilterState.Filtering;
+ }
+ if (string.IsNullOrEmpty(FilterText)) {
+ return FilterState.NoFilterText;
+ }
+ if (!FilteredPackages.Any()) {
+ return FilterState.NoResults;
+ }
+ return FilterState.ResultsAvailable;
+ }
+ }
+
+ private bool IsFiltering {
+ get { return _isFiltering; }
+ set {
+ _isFiltering = value;
+ OnPropertyChanged();
+ OnPropertyChanged("PackageFilterState");
+ }
+ }
+
+ public IList FilteredPackages {
+ get {
+ lock (_filteredPackagesLock) {
+ return _filteredPackages;
+ }
+ }
+ set {
+ lock (_filteredPackagesLock) {
+ _filteredPackages = value;
+ }
+
+ // PackageFilterState should be triggered before FilteredPackages
+ // to allow the UI to update the status before the package list,
+ // making for a smoother experience.
+ OnPropertyChanged("PackageFilterState");
+ OnPropertyChanged();
+ }
+ }
+
+ public string FilterText {
+ get { return _filterText; }
+ set {
+ _filterText = value;
+
+ StartFilter();
+ IsFiltering = !string.IsNullOrWhiteSpace(_filterText);
+
+ OnPropertyChanged();
+ OnPropertyChanged("PackageFilterState");
+ }
+ }
+
+ private void StartFilter() {
+ _filterTimer.Change(300, Timeout.Infinite);
+ }
+
+ private async void FilterTimer_Elapsed(object state) {
+ if (_allPackages == null) {
+ LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
+ IsFiltering = false;
+ return;
+ }
+
+ var filterText = GetTrimmedTextSafe(_filterText);
+
+ IEnumerable filtered;
+ if (string.IsNullOrWhiteSpace(filterText)) {
+ filtered = Enumerable.Empty();
+ } else {
+ try {
+ filtered = await _allPackages.GetCatalogPackagesAsync(filterText);
+ } catch (Exception ex) {
+ LastRefreshedMessage = LastRefreshedMessageProvider.RefreshFailed;
+ if (IsCriticalException(ex)) {
+ throw;
+ }
+ StartFilter();
+ return;
+ }
+ }
+
+ if (filtered == null) {
+ // The database file must be in use. Display current results, but try again later.
+ LastRefreshedMessage = LastRefreshedMessageProvider.RefreshInProgress;
+ StartFilter();
+ return;
+ }
+
+ var newItems = new List();
+ if (filterText != GetTrimmedTextSafe(_filterText)) {
+ return;
+ }
+
+ if (filtered.Any()) {
+ IRootPackage rootPackage = null;
+ IGlobalPackages globalPackages = null;
+ var controller = _npmController;
+ if (controller != null) {
+ rootPackage = controller.RootPackage;
+ globalPackages = controller.GlobalPackages;
+ }
+
+ newItems.AddRange(filtered.Select(package => new ReadOnlyPackageCatalogEntryViewModel(
+ package,
+ rootPackage != null ? rootPackage.Modules[package.Name] : null,
+ globalPackages != null ? globalPackages.Modules[package.Name] : null
+ )));
+ }
+
+ await _dispatcher.BeginInvoke((Action)(() => {
+ if (filterText != GetTrimmedTextSafe(_filterText)) {
+ return;
+ }
+
+ var originalSelectedPackage = SelectedPackage;
+ FilteredPackages = newItems;
+
+ // Reassign originalSelectedPackage to the original selected package in the new list of filtered packages.
+ if (originalSelectedPackage != null) {
+ originalSelectedPackage = FilteredPackages.FirstOrDefault(package => package.Name == originalSelectedPackage.Name);
+ }
+
+ // Maintain selection when the filter list refreshes (e.g. due to an installation running in the background)
+ SelectedPackage = originalSelectedPackage ?? FilteredPackages.FirstOrDefault();
+
+ _currentFilter = filterText;
+
+ LastRefreshedMessage = IsCatalogEmpty
+ ? LastRefreshedMessageProvider.RefreshFailed
+ : new LastRefreshedMessageProvider(_allPackages.LastRefreshed);
+ CatalogControlVisibility = Visibility.Visible;
+ }));
+
+ IsFiltering = false;
+
+ // The catalog refresh operation spawns many long-lived Gen 2 objects,
+ // so the garbage collector will take a while to get to them otherwise.
+ GC.Collect();
+ }
+
+ private string GetTrimmedTextSafe(string text) {
+ return text != null ? text.Trim() : string.Empty;
+ }
+
+ public LastRefreshedMessageProvider LastRefreshedMessage {
+ get { return _lastRefreshedMessage; }
+ set {
+ _lastRefreshedMessage = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public Visibility FilterControlsVisibility {
+ get { return LoadingCatalogControlVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible; }
+ }
+
+ #endregion
+
+ #region Installation
+
+ public int SelectedDependencyTypeIndex {
+ get { return _selectedDependencyTypeIndex; }
+ set {
+ _selectedDependencyTypeIndex = value;
+ OnPropertyChanged();
+ OnPropertyChanged("GlobalWarningVisibility");
+ }
+ }
+
+ public object SelectedVersion {
+ get { return _selectedVersion; }
+ set {
+ _selectedVersion = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public Visibility GlobalWarningVisibility {
+ get {
+ return Indices.IndexGlobal == (Indices) SelectedDependencyTypeIndex
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+ }
+ }
+
+ internal bool CanInstall(PackageCatalogEntryViewModel package) {
+ return package != null;
+ }
+
+ internal void Install(PackageCatalogEntryViewModel package) {
+ var type = DependencyType.Standard;
+ var isGlobal = false;
+ switch ((Indices)SelectedDependencyTypeIndex) {
+ case Indices.IndexDev:
+ type = DependencyType.Development;
+ break;
+
+ case Indices.IndexOptional:
+ type = DependencyType.Optional;
+ break;
+
+ case Indices.IndexGlobal:
+ isGlobal = true;
+ break;
+ }
+
+ if (!string.IsNullOrEmpty(package.Name)) {
+ var selectedVersion = SelectedVersion is SemverVersion ? ((SemverVersion)SelectedVersion).ToString(): string.Empty;
+ _executeViewModel.QueueCommand(
+ NpmArgumentBuilder.GetNpmInstallArguments(
+ package.Name,
+ selectedVersion,
+ type,
+ isGlobal,
+ SaveToPackageJson,
+ Arguments));
+ }
+ }
+
+ internal bool CanOpenHomepage(string homepage) {
+ return !string.IsNullOrEmpty(homepage);
+ }
+
+ internal void OpenHomepage(string homepage) {
+ if (!string.IsNullOrEmpty(homepage)) {
+ Process.Start(homepage);
+ }
+ }
+
+ public string Arguments {
+ get { return _arguments; }
+ set {
+ _arguments = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool SaveToPackageJson {
+ get { return _saveToPackageJson; }
+ set {
+ _saveToPackageJson = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public PackageCatalogEntryViewModel SelectedPackage {
+ get { return _selectedPackage; }
+ set {
+ _selectedPackage = value;
+ OnPropertyChanged();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallWindow.xaml.cs b/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallWindow.xaml.cs
index a2bbb00c7..8a97ee03c 100644
--- a/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallWindow.xaml.cs
+++ b/Nodejs/Product/Nodejs/NpmUI/NpmPackageInstallWindow.xaml.cs
@@ -1,173 +1,173 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Diagnostics;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Threading;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.VisualStudioTools;
-
-namespace Microsoft.NodejsTools.NpmUI {
- ///
- /// Interaction logic for NpmPackageInstallWindow.xaml
- ///
- sealed partial class NpmPackageInstallWindow : DialogWindowVersioningWorkaround, IDisposable {
- private readonly NpmPackageInstallViewModel _vm;
- private NpmOutputWindow _outputWindow;
-
- internal NpmPackageInstallWindow(INpmController controller, NpmOutputViewModel executeVm, DependencyType dependencyType = DependencyType.Standard, bool isGlobal = false) {
- DataContext = _vm = new NpmPackageInstallViewModel(executeVm, Dispatcher);
- _vm.NpmController = controller;
- InitializeComponent();
- DependencyComboBox.SelectedIndex = isGlobal ? (int)NpmPackageInstallViewModel.Indices.IndexGlobal : (int)dependencyType;
- }
-
- public void Dispose() {
- // This will unregister event handlers on the controller and prevent
- // us from leaking view models.
- if (_outputWindow != null) {
- _outputWindow.Closing -= _outputWindow_Closing;
- _outputWindow.Close();
- }
-
- _vm.NpmController = null;
-
- // The catalog refresh operation spawns many long-lived Gen 2 objects,
- // so the garbage collector will take a while to get to them otherwise.
- GC.Collect();
- }
-
- void _outputWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
- e.Cancel = true;
- _outputWindow.Hide();
- }
-
- private void Close_Executed(object sender, ExecutedRoutedEventArgs e) {
- Close();
- }
-
- private void Close_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
- e.CanExecute = true;
- e.Handled = true;
- }
-
- private void InstallCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
- _vm.Install(e.Parameter as PackageCatalogEntryViewModel);
- }
-
- private void InstallCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
- e.CanExecute = !FilterTextBox.IsFocused && _vm.CanInstall(e.Parameter as PackageCatalogEntryViewModel);
- e.Handled = true;
- }
-
- private void RefreshCatalogCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
- _vm.RefreshCatalog();
- }
-
- private void RefreshCatalogCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
- e.CanExecute = _vm.CanRefreshCatalog;
- e.Handled = true;
- }
-
- private void OpenHomepageCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
- _vm.OpenHomepage(e.Parameter as string);
- }
-
- private void OpenHomepageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
- e.CanExecute = _vm.CanOpenHomepage(e.Parameter as string);
- e.Handled = true;
- }
-
- private void FilterTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
- if ((e.NewValue as bool?) ?? false) {
- ((UIElement)sender).Focus();
- }
- }
-
- private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e) {
- switch (e.Key) {
- case Key.Down:
- case Key.Enter:
- if (_packageList.SelectedIndex == -1 && _packageList.Items.Count > 0) {
- _packageList.SelectedIndex = 0;
- }
-
- FocusOnSelectedItemInPackageList();
- e.Handled = true;
- break;
- }
- }
-
- private void FocusOnSelectedItemInPackageList() {
- _packageList.ScrollIntoView(_packageList.SelectedItem);
- var itemContainer = (ListViewItem)_packageList.ItemContainerGenerator.ContainerFromItem(_packageList.SelectedItem);
- if (itemContainer != null) {
- itemContainer.Focus();
- }
- }
-
- private void _packageList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
- _packageList.ScrollIntoView(_packageList.SelectedItem);
- }
-
- private void _packageList_PreviewKeyDown(object sender, KeyEventArgs e) {
- if (e.Key == Key.Up && _packageList.SelectedIndex == 0) {
- FilterTextBox.Focus();
- e.Handled = true;
- }
- }
-
- private void ShowOutputWindow_Click(object sender, RoutedEventArgs e) {
- if (_outputWindow == null) {
- _outputWindow = new NpmOutputWindow() {
- Owner = this,
- WindowStartupLocation = System.Windows.WindowStartupLocation.Manual
- };
-
- _outputWindow.Left = Math.Max(0, this.Left - _outputWindow.Width - 30);
- _outputWindow.Top = Math.Max(0, this.Top);
-
- _outputWindow.Closing += _outputWindow_Closing;
- _outputWindow.DataContext = _vm.ExecuteViewModel;
- }
-
- _outputWindow.Show();
- if (_outputWindow.WindowState == WindowState.Minimized) {
- _outputWindow.WindowState = WindowState.Normal;
- }
- }
-
- private void ResetOptionsButton_Click(object sender, RoutedEventArgs e) {
- this.DependencyComboBox.SelectedIndex = (int)DependencyType.Standard;
- this.SaveToPackageJsonCheckbox.IsChecked = true;
-
- ArgumentsTextBox.Text = string.Empty;
- ArgumentsTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
- }
-
- private void SelectedVersionComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) {
- if (this.SelectedVersionComboBox.SelectedIndex == -1) {
- SelectedVersionComboBox.SelectedIndex = 0;
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Threading;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.VisualStudioTools;
+
+namespace Microsoft.NodejsTools.NpmUI {
+ ///
+ /// Interaction logic for NpmPackageInstallWindow.xaml
+ ///
+ sealed partial class NpmPackageInstallWindow : DialogWindowVersioningWorkaround, IDisposable {
+ private readonly NpmPackageInstallViewModel _vm;
+ private NpmOutputWindow _outputWindow;
+
+ internal NpmPackageInstallWindow(INpmController controller, NpmOutputViewModel executeVm, DependencyType dependencyType = DependencyType.Standard, bool isGlobal = false) {
+ DataContext = _vm = new NpmPackageInstallViewModel(executeVm, Dispatcher);
+ _vm.NpmController = controller;
+ InitializeComponent();
+ DependencyComboBox.SelectedIndex = isGlobal ? (int)NpmPackageInstallViewModel.Indices.IndexGlobal : (int)dependencyType;
+ }
+
+ public void Dispose() {
+ // This will unregister event handlers on the controller and prevent
+ // us from leaking view models.
+ if (_outputWindow != null) {
+ _outputWindow.Closing -= _outputWindow_Closing;
+ _outputWindow.Close();
+ }
+
+ _vm.NpmController = null;
+
+ // The catalog refresh operation spawns many long-lived Gen 2 objects,
+ // so the garbage collector will take a while to get to them otherwise.
+ GC.Collect();
+ }
+
+ void _outputWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
+ e.Cancel = true;
+ _outputWindow.Hide();
+ }
+
+ private void Close_Executed(object sender, ExecutedRoutedEventArgs e) {
+ Close();
+ }
+
+ private void Close_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
+ e.CanExecute = true;
+ e.Handled = true;
+ }
+
+ private void InstallCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
+ _vm.Install(e.Parameter as PackageCatalogEntryViewModel);
+ }
+
+ private void InstallCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
+ e.CanExecute = !FilterTextBox.IsFocused && _vm.CanInstall(e.Parameter as PackageCatalogEntryViewModel);
+ e.Handled = true;
+ }
+
+ private void RefreshCatalogCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
+ _vm.RefreshCatalog();
+ }
+
+ private void RefreshCatalogCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
+ e.CanExecute = _vm.CanRefreshCatalog;
+ e.Handled = true;
+ }
+
+ private void OpenHomepageCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
+ _vm.OpenHomepage(e.Parameter as string);
+ }
+
+ private void OpenHomepageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
+ e.CanExecute = _vm.CanOpenHomepage(e.Parameter as string);
+ e.Handled = true;
+ }
+
+ private void FilterTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
+ if ((e.NewValue as bool?) ?? false) {
+ ((UIElement)sender).Focus();
+ }
+ }
+
+ private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e) {
+ switch (e.Key) {
+ case Key.Down:
+ case Key.Enter:
+ if (_packageList.SelectedIndex == -1 && _packageList.Items.Count > 0) {
+ _packageList.SelectedIndex = 0;
+ }
+
+ FocusOnSelectedItemInPackageList();
+ e.Handled = true;
+ break;
+ }
+ }
+
+ private void FocusOnSelectedItemInPackageList() {
+ _packageList.ScrollIntoView(_packageList.SelectedItem);
+ var itemContainer = (ListViewItem)_packageList.ItemContainerGenerator.ContainerFromItem(_packageList.SelectedItem);
+ if (itemContainer != null) {
+ itemContainer.Focus();
+ }
+ }
+
+ private void _packageList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ _packageList.ScrollIntoView(_packageList.SelectedItem);
+ }
+
+ private void _packageList_PreviewKeyDown(object sender, KeyEventArgs e) {
+ if (e.Key == Key.Up && _packageList.SelectedIndex == 0) {
+ FilterTextBox.Focus();
+ e.Handled = true;
+ }
+ }
+
+ private void ShowOutputWindow_Click(object sender, RoutedEventArgs e) {
+ if (_outputWindow == null) {
+ _outputWindow = new NpmOutputWindow() {
+ Owner = this,
+ WindowStartupLocation = System.Windows.WindowStartupLocation.Manual
+ };
+
+ _outputWindow.Left = Math.Max(0, this.Left - _outputWindow.Width - 30);
+ _outputWindow.Top = Math.Max(0, this.Top);
+
+ _outputWindow.Closing += _outputWindow_Closing;
+ _outputWindow.DataContext = _vm.ExecuteViewModel;
+ }
+
+ _outputWindow.Show();
+ if (_outputWindow.WindowState == WindowState.Minimized) {
+ _outputWindow.WindowState = WindowState.Normal;
+ }
+ }
+
+ private void ResetOptionsButton_Click(object sender, RoutedEventArgs e) {
+ this.DependencyComboBox.SelectedIndex = (int)DependencyType.Standard;
+ this.SaveToPackageJsonCheckbox.IsChecked = true;
+
+ ArgumentsTextBox.Text = string.Empty;
+ ArgumentsTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
+ }
+
+ private void SelectedVersionComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (this.SelectedVersionComboBox.SelectedIndex == -1) {
+ SelectedVersionComboBox.SelectedIndex = 0;
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/NpmUI/PackageCatalogEntryViewModel.cs b/Nodejs/Product/Nodejs/NpmUI/PackageCatalogEntryViewModel.cs
index e36dc2008..049e246be 100644
--- a/Nodejs/Product/Nodejs/NpmUI/PackageCatalogEntryViewModel.cs
+++ b/Nodejs/Product/Nodejs/NpmUI/PackageCatalogEntryViewModel.cs
@@ -1,141 +1,141 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.NodejsTools.Project;
-
-namespace Microsoft.NodejsTools.NpmUI {
- abstract class PackageCatalogEntryViewModel {
- private readonly string _name;
- private readonly SemverVersion? _version;
- private readonly List _availableVersions;
- private readonly string _author;
- private readonly string _description;
- private readonly List _homepages;
- private readonly string _keywords;
-
- private readonly SemverVersion? _localVersion, _globalVersion;
-
- protected PackageCatalogEntryViewModel(
- string name,
- SemverVersion? version,
- IEnumerable availableVersions,
- string author,
- string description,
- IEnumerable homepages,
- string keywords,
- SemverVersion? localVersion,
- SemverVersion? globalVersion
- ) {
- _name = name;
- _version = version;
- _availableVersions = availableVersions != null ? availableVersions.ToList() : new List();
- _author = author;
- _description = description;
- _homepages = homepages != null ? homepages.ToList() : new List();
- _keywords = keywords;
- _localVersion = localVersion;
- _globalVersion = globalVersion;
- }
-
- public virtual string Name {
- get { return _name; }
- }
-
- public string Version {
- get { return ToString(_version); }
- }
-
- public IEnumerable AvailableVersions {
- get { return _availableVersions; }
- }
-
- public string Author {
- get { return _author; }
- }
-
- public Visibility AuthorVisibility {
- get { return string.IsNullOrEmpty(_author) ? Visibility.Collapsed : Visibility.Visible; }
- }
-
- public string Description { get { return _description; } }
-
- public Visibility DescriptionVisibility { get { return string.IsNullOrEmpty(_description) ? Visibility.Collapsed : Visibility.Visible; } }
-
- public IEnumerable Homepages { get { return _homepages; } }
-
- public Visibility HomepagesVisibility {
- get { return _homepages.Any() ? Visibility.Visible : Visibility.Collapsed; }
- }
-
- public string Keywords {
- get { return _keywords; }
- }
-
- public bool IsInstalledLocally {
- get { return _localVersion.HasValue; }
- }
-
- public bool IsInstalledGlobally {
- get { return _globalVersion.HasValue; }
- }
-
- public bool IsLocalInstallOutOfDate {
- get { return _localVersion.HasValue && _localVersion < _version; }
- }
-
- public bool IsGlobalInstallOutOfDate {
- get { return _globalVersion.HasValue && _globalVersion < _version; }
- }
-
- public string LocalVersion {
- get { return ToString(_localVersion); }
- }
-
- public string GlobalVersion {
- get { return ToString(_globalVersion); }
- }
-
- private static string ToString(SemverVersion? version) {
- return version.HasValue ? version.ToString() : string.Empty;
- }
- }
-
- internal class ReadOnlyPackageCatalogEntryViewModel : PackageCatalogEntryViewModel {
- public ReadOnlyPackageCatalogEntryViewModel(IPackage package, IPackage localInstall, IPackage globalInstall)
- : base(
- package.Name ?? string.Empty,
- package.Version,
- package.AvailableVersions,
- package.Author == null ? string.Empty : package.Author.ToString(),
- package.Description ?? string.Empty,
- package.Homepages,
- (package.Keywords != null && package.Keywords.Any())
- ? string.Join(", ", package.Keywords)
- : SR.GetString(SR.NoKeywordsInPackage),
- localInstall != null ? (SemverVersion?)localInstall.Version : null,
- globalInstall != null ? (SemverVersion?)globalInstall.Version : null
- ) {
- if (string.IsNullOrEmpty(Name)) {
- throw new ArgumentNullException("package.Name");
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.NodejsTools.Project;
+
+namespace Microsoft.NodejsTools.NpmUI {
+ abstract class PackageCatalogEntryViewModel {
+ private readonly string _name;
+ private readonly SemverVersion? _version;
+ private readonly List _availableVersions;
+ private readonly string _author;
+ private readonly string _description;
+ private readonly List _homepages;
+ private readonly string _keywords;
+
+ private readonly SemverVersion? _localVersion, _globalVersion;
+
+ protected PackageCatalogEntryViewModel(
+ string name,
+ SemverVersion? version,
+ IEnumerable availableVersions,
+ string author,
+ string description,
+ IEnumerable homepages,
+ string keywords,
+ SemverVersion? localVersion,
+ SemverVersion? globalVersion
+ ) {
+ _name = name;
+ _version = version;
+ _availableVersions = availableVersions != null ? availableVersions.ToList() : new List();
+ _author = author;
+ _description = description;
+ _homepages = homepages != null ? homepages.ToList() : new List();
+ _keywords = keywords;
+ _localVersion = localVersion;
+ _globalVersion = globalVersion;
+ }
+
+ public virtual string Name {
+ get { return _name; }
+ }
+
+ public string Version {
+ get { return ToString(_version); }
+ }
+
+ public IEnumerable AvailableVersions {
+ get { return _availableVersions; }
+ }
+
+ public string Author {
+ get { return _author; }
+ }
+
+ public Visibility AuthorVisibility {
+ get { return string.IsNullOrEmpty(_author) ? Visibility.Collapsed : Visibility.Visible; }
+ }
+
+ public string Description { get { return _description; } }
+
+ public Visibility DescriptionVisibility { get { return string.IsNullOrEmpty(_description) ? Visibility.Collapsed : Visibility.Visible; } }
+
+ public IEnumerable Homepages { get { return _homepages; } }
+
+ public Visibility HomepagesVisibility {
+ get { return _homepages.Any() ? Visibility.Visible : Visibility.Collapsed; }
+ }
+
+ public string Keywords {
+ get { return _keywords; }
+ }
+
+ public bool IsInstalledLocally {
+ get { return _localVersion.HasValue; }
+ }
+
+ public bool IsInstalledGlobally {
+ get { return _globalVersion.HasValue; }
+ }
+
+ public bool IsLocalInstallOutOfDate {
+ get { return _localVersion.HasValue && _localVersion < _version; }
+ }
+
+ public bool IsGlobalInstallOutOfDate {
+ get { return _globalVersion.HasValue && _globalVersion < _version; }
+ }
+
+ public string LocalVersion {
+ get { return ToString(_localVersion); }
+ }
+
+ public string GlobalVersion {
+ get { return ToString(_globalVersion); }
+ }
+
+ private static string ToString(SemverVersion? version) {
+ return version.HasValue ? version.ToString() : string.Empty;
+ }
+ }
+
+ internal class ReadOnlyPackageCatalogEntryViewModel : PackageCatalogEntryViewModel {
+ public ReadOnlyPackageCatalogEntryViewModel(IPackage package, IPackage localInstall, IPackage globalInstall)
+ : base(
+ package.Name ?? string.Empty,
+ package.Version,
+ package.AvailableVersions,
+ package.Author == null ? string.Empty : package.Author.ToString(),
+ package.Description ?? string.Empty,
+ package.Homepages,
+ (package.Keywords != null && package.Keywords.Any())
+ ? string.Join(", ", package.Keywords)
+ : SR.GetString(SR.NoKeywordsInPackage),
+ localInstall != null ? (SemverVersion?)localInstall.Version : null,
+ globalInstall != null ? (SemverVersion?)globalInstall.Version : null
+ ) {
+ if (string.IsNullOrEmpty(Name)) {
+ throw new ArgumentNullException("package.Name");
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Options/NodejsDiagnosticsOptionsPage.cs b/Nodejs/Product/Nodejs/Options/NodejsDiagnosticsOptionsPage.cs
index 61e779743..f78c1f5bf 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsDiagnosticsOptionsPage.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsDiagnosticsOptionsPage.cs
@@ -12,25 +12,25 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Options {
- internal class NodejsDiagnosticsOptionsPage : NodejsDialogPage {
- private bool _isLiveDiagnosticsEnabled;
- private const string IsLiveDiagnosticsEnabledSetting = "IsLiveDiagnosticsEnabled";
-
- public NodejsDiagnosticsOptionsPage() : base("Diagnostics") {
- _isLiveDiagnosticsEnabled = !NodejsPackage.Instance.Zombied && (LoadBool(IsLiveDiagnosticsEnabledSetting) ?? false);
- }
-
- public bool IsLiveDiagnosticsEnabled {
- get {
- return !NodejsPackage.Instance.Zombied && _isLiveDiagnosticsEnabled;
- }
- set {
- _isLiveDiagnosticsEnabled = value;
- SaveBool(IsLiveDiagnosticsEnabledSetting, value);
- }
- }
- }
-}
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Options {
+ internal class NodejsDiagnosticsOptionsPage : NodejsDialogPage {
+ private bool _isLiveDiagnosticsEnabled;
+ private const string IsLiveDiagnosticsEnabledSetting = "IsLiveDiagnosticsEnabled";
+
+ public NodejsDiagnosticsOptionsPage() : base("Diagnostics") {
+ _isLiveDiagnosticsEnabled = !NodejsPackage.Instance.Zombied && (LoadBool(IsLiveDiagnosticsEnabledSetting) ?? false);
+ }
+
+ public bool IsLiveDiagnosticsEnabled {
+ get {
+ return !NodejsPackage.Instance.Zombied && _isLiveDiagnosticsEnabled;
+ }
+ set {
+ _isLiveDiagnosticsEnabled = value;
+ SaveBool(IsLiveDiagnosticsEnabledSetting, value);
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.Designer.cs b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.Designer.cs
index 212006d76..8004732e6 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.Designer.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.Designer.cs
@@ -1,193 +1,193 @@
-namespace Microsoft.NodejsTools.Options {
- partial class NodejsGeneralOptionsControl {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
- this._surveyNewsCheckLabel = new System.Windows.Forms.Label();
- this._surveyNewsCheckCombo = new System.Windows.Forms.ComboBox();
- this._topOptionsPanel = new System.Windows.Forms.Panel();
- this._checkForLongPaths = new System.Windows.Forms.CheckBox();
- this._editAndContinue = new System.Windows.Forms.CheckBox();
- this._waitOnNormalExit = new System.Windows.Forms.CheckBox();
- this._waitOnAbnormalExit = new System.Windows.Forms.CheckBox();
- this._showBrowserAndNodeLabels = new System.Windows.Forms.CheckBox();
- this.tableLayoutPanel3.SuspendLayout();
- this._topOptionsPanel.SuspendLayout();
- this.SuspendLayout();
- //
- // tableLayoutPanel3
- //
- this.tableLayoutPanel3.AutoSize = true;
- this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
- this.tableLayoutPanel3.ColumnCount = 2;
- this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
- this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel3.Controls.Add(this._surveyNewsCheckLabel, 0, 7);
- this.tableLayoutPanel3.Controls.Add(this._surveyNewsCheckCombo, 1, 7);
- this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
- this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 149);
- this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.tableLayoutPanel3.Name = "tableLayoutPanel3";
- this.tableLayoutPanel3.RowCount = 9;
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
- this.tableLayoutPanel3.Size = new System.Drawing.Size(508, 208);
- this.tableLayoutPanel3.TabIndex = 0;
- //
- // _surveyNewsCheckLabel
- //
- this._surveyNewsCheckLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this._surveyNewsCheckLabel.AutoSize = true;
- this._surveyNewsCheckLabel.Location = new System.Drawing.Point(8, 7);
- this._surveyNewsCheckLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
- this._surveyNewsCheckLabel.Name = "_surveyNewsCheckLabel";
- this._surveyNewsCheckLabel.Size = new System.Drawing.Size(150, 17);
- this._surveyNewsCheckLabel.TabIndex = 7;
- this._surveyNewsCheckLabel.Text = "&Check for survey/news";
- this._surveyNewsCheckLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
- //
- // _surveyNewsCheckCombo
- //
- this._surveyNewsCheckCombo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
- this._surveyNewsCheckCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this._surveyNewsCheckCombo.DropDownWidth = 172;
- this._surveyNewsCheckCombo.FormattingEnabled = true;
- this._surveyNewsCheckCombo.Items.AddRange(new object[] {
- "Never",
- "Once a day",
- "Once a week",
- "Once a month"});
- this._surveyNewsCheckCombo.Location = new System.Drawing.Point(174, 4);
- this._surveyNewsCheckCombo.Margin = new System.Windows.Forms.Padding(8, 4, 8, 4);
- this._surveyNewsCheckCombo.Name = "_surveyNewsCheckCombo";
- this._surveyNewsCheckCombo.Size = new System.Drawing.Size(326, 24);
- this._surveyNewsCheckCombo.TabIndex = 8;
- //
- // _topOptionsPanel
- //
- this._topOptionsPanel.Controls.Add(this._showBrowserAndNodeLabels);
- this._topOptionsPanel.Controls.Add(this._checkForLongPaths);
- this._topOptionsPanel.Controls.Add(this._editAndContinue);
- this._topOptionsPanel.Controls.Add(this._waitOnNormalExit);
- this._topOptionsPanel.Controls.Add(this._waitOnAbnormalExit);
- this._topOptionsPanel.Dock = System.Windows.Forms.DockStyle.Top;
- this._topOptionsPanel.Location = new System.Drawing.Point(0, 0);
- this._topOptionsPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this._topOptionsPanel.Name = "_topOptionsPanel";
- this._topOptionsPanel.Size = new System.Drawing.Size(508, 149);
- this._topOptionsPanel.TabIndex = 1;
- //
- // _checkForLongPaths
- //
- this._checkForLongPaths.AutoSize = true;
- this._checkForLongPaths.Location = new System.Drawing.Point(5, 90);
- this._checkForLongPaths.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this._checkForLongPaths.Name = "_checkForLongPaths";
- this._checkForLongPaths.Size = new System.Drawing.Size(379, 21);
- this._checkForLongPaths.TabIndex = 4;
- this._checkForLongPaths.Text = "Check for paths that exceed the &MAX_PATH length limit";
- this._checkForLongPaths.UseVisualStyleBackColor = true;
- //
- // _editAndContinue
- //
- this._editAndContinue.AutoSize = true;
- this._editAndContinue.Location = new System.Drawing.Point(5, 62);
- this._editAndContinue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this._editAndContinue.Name = "_editAndContinue";
- this._editAndContinue.Size = new System.Drawing.Size(190, 21);
- this._editAndContinue.TabIndex = 3;
- this._editAndContinue.Text = "Enable &Edit and Continue";
- this._editAndContinue.UseVisualStyleBackColor = true;
- //
- // _waitOnNormalExit
- //
- this._waitOnNormalExit.AutoSize = true;
- this._waitOnNormalExit.Location = new System.Drawing.Point(5, 33);
- this._waitOnNormalExit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this._waitOnNormalExit.Name = "_waitOnNormalExit";
- this._waitOnNormalExit.Size = new System.Drawing.Size(294, 21);
- this._waitOnNormalExit.TabIndex = 2;
- this._waitOnNormalExit.Text = "Wai&t for input when process exits normally";
- this._waitOnNormalExit.UseVisualStyleBackColor = true;
- //
- // _waitOnAbnormalExit
- //
- this._waitOnAbnormalExit.AutoSize = true;
- this._waitOnAbnormalExit.Location = new System.Drawing.Point(5, 5);
- this._waitOnAbnormalExit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this._waitOnAbnormalExit.Name = "_waitOnAbnormalExit";
- this._waitOnAbnormalExit.Size = new System.Drawing.Size(310, 21);
- this._waitOnAbnormalExit.TabIndex = 1;
- this._waitOnAbnormalExit.Text = "&Wait for input when process exits abnormally";
- this._waitOnAbnormalExit.UseVisualStyleBackColor = true;
- //
- // _showBrowserAndNodeLabels
- //
- this._showBrowserAndNodeLabels.AutoSize = true;
- this._showBrowserAndNodeLabels.Location = new System.Drawing.Point(5, 119);
- this._showBrowserAndNodeLabels.Margin = new System.Windows.Forms.Padding(4);
- this._showBrowserAndNodeLabels.Name = "_showBrowserAndNodeLabels";
- this._showBrowserAndNodeLabels.Size = new System.Drawing.Size(471, 21);
- this._showBrowserAndNodeLabels.TabIndex = 6;
- this._showBrowserAndNodeLabels.Text = "Show &labels denoting browser and Node.js code in Solution Explorer";
- this._showBrowserAndNodeLabels.UseVisualStyleBackColor = true;
- //
- // NodejsGeneralOptionsControl
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.tableLayoutPanel3);
- this.Controls.Add(this._topOptionsPanel);
- this.Margin = new System.Windows.Forms.Padding(8, 10, 8, 10);
- this.Name = "NodejsGeneralOptionsControl";
- this.Size = new System.Drawing.Size(508, 357);
- this.tableLayoutPanel3.ResumeLayout(false);
- this.tableLayoutPanel3.PerformLayout();
- this._topOptionsPanel.ResumeLayout(false);
- this._topOptionsPanel.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
- private System.Windows.Forms.Label _surveyNewsCheckLabel;
- private System.Windows.Forms.ComboBox _surveyNewsCheckCombo;
- private System.Windows.Forms.Panel _topOptionsPanel;
- private System.Windows.Forms.CheckBox _waitOnNormalExit;
- private System.Windows.Forms.CheckBox _waitOnAbnormalExit;
- private System.Windows.Forms.CheckBox _editAndContinue;
- private System.Windows.Forms.CheckBox _checkForLongPaths;
- private System.Windows.Forms.CheckBox _showBrowserAndNodeLabels;
- }
-}
+namespace Microsoft.NodejsTools.Options {
+ partial class NodejsGeneralOptionsControl {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
+ this._surveyNewsCheckLabel = new System.Windows.Forms.Label();
+ this._surveyNewsCheckCombo = new System.Windows.Forms.ComboBox();
+ this._topOptionsPanel = new System.Windows.Forms.Panel();
+ this._checkForLongPaths = new System.Windows.Forms.CheckBox();
+ this._editAndContinue = new System.Windows.Forms.CheckBox();
+ this._waitOnNormalExit = new System.Windows.Forms.CheckBox();
+ this._waitOnAbnormalExit = new System.Windows.Forms.CheckBox();
+ this._showBrowserAndNodeLabels = new System.Windows.Forms.CheckBox();
+ this.tableLayoutPanel3.SuspendLayout();
+ this._topOptionsPanel.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tableLayoutPanel3
+ //
+ this.tableLayoutPanel3.AutoSize = true;
+ this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.tableLayoutPanel3.ColumnCount = 2;
+ this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayoutPanel3.Controls.Add(this._surveyNewsCheckLabel, 0, 7);
+ this.tableLayoutPanel3.Controls.Add(this._surveyNewsCheckCombo, 1, 7);
+ this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 149);
+ this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.tableLayoutPanel3.Name = "tableLayoutPanel3";
+ this.tableLayoutPanel3.RowCount = 9;
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
+ this.tableLayoutPanel3.Size = new System.Drawing.Size(508, 208);
+ this.tableLayoutPanel3.TabIndex = 0;
+ //
+ // _surveyNewsCheckLabel
+ //
+ this._surveyNewsCheckLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this._surveyNewsCheckLabel.AutoSize = true;
+ this._surveyNewsCheckLabel.Location = new System.Drawing.Point(8, 7);
+ this._surveyNewsCheckLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
+ this._surveyNewsCheckLabel.Name = "_surveyNewsCheckLabel";
+ this._surveyNewsCheckLabel.Size = new System.Drawing.Size(150, 17);
+ this._surveyNewsCheckLabel.TabIndex = 7;
+ this._surveyNewsCheckLabel.Text = "&Check for survey/news";
+ this._surveyNewsCheckLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // _surveyNewsCheckCombo
+ //
+ this._surveyNewsCheckCombo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this._surveyNewsCheckCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._surveyNewsCheckCombo.DropDownWidth = 172;
+ this._surveyNewsCheckCombo.FormattingEnabled = true;
+ this._surveyNewsCheckCombo.Items.AddRange(new object[] {
+ "Never",
+ "Once a day",
+ "Once a week",
+ "Once a month"});
+ this._surveyNewsCheckCombo.Location = new System.Drawing.Point(174, 4);
+ this._surveyNewsCheckCombo.Margin = new System.Windows.Forms.Padding(8, 4, 8, 4);
+ this._surveyNewsCheckCombo.Name = "_surveyNewsCheckCombo";
+ this._surveyNewsCheckCombo.Size = new System.Drawing.Size(326, 24);
+ this._surveyNewsCheckCombo.TabIndex = 8;
+ //
+ // _topOptionsPanel
+ //
+ this._topOptionsPanel.Controls.Add(this._showBrowserAndNodeLabels);
+ this._topOptionsPanel.Controls.Add(this._checkForLongPaths);
+ this._topOptionsPanel.Controls.Add(this._editAndContinue);
+ this._topOptionsPanel.Controls.Add(this._waitOnNormalExit);
+ this._topOptionsPanel.Controls.Add(this._waitOnAbnormalExit);
+ this._topOptionsPanel.Dock = System.Windows.Forms.DockStyle.Top;
+ this._topOptionsPanel.Location = new System.Drawing.Point(0, 0);
+ this._topOptionsPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._topOptionsPanel.Name = "_topOptionsPanel";
+ this._topOptionsPanel.Size = new System.Drawing.Size(508, 149);
+ this._topOptionsPanel.TabIndex = 1;
+ //
+ // _checkForLongPaths
+ //
+ this._checkForLongPaths.AutoSize = true;
+ this._checkForLongPaths.Location = new System.Drawing.Point(5, 90);
+ this._checkForLongPaths.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._checkForLongPaths.Name = "_checkForLongPaths";
+ this._checkForLongPaths.Size = new System.Drawing.Size(379, 21);
+ this._checkForLongPaths.TabIndex = 4;
+ this._checkForLongPaths.Text = "Check for paths that exceed the &MAX_PATH length limit";
+ this._checkForLongPaths.UseVisualStyleBackColor = true;
+ //
+ // _editAndContinue
+ //
+ this._editAndContinue.AutoSize = true;
+ this._editAndContinue.Location = new System.Drawing.Point(5, 62);
+ this._editAndContinue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._editAndContinue.Name = "_editAndContinue";
+ this._editAndContinue.Size = new System.Drawing.Size(190, 21);
+ this._editAndContinue.TabIndex = 3;
+ this._editAndContinue.Text = "Enable &Edit and Continue";
+ this._editAndContinue.UseVisualStyleBackColor = true;
+ //
+ // _waitOnNormalExit
+ //
+ this._waitOnNormalExit.AutoSize = true;
+ this._waitOnNormalExit.Location = new System.Drawing.Point(5, 33);
+ this._waitOnNormalExit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._waitOnNormalExit.Name = "_waitOnNormalExit";
+ this._waitOnNormalExit.Size = new System.Drawing.Size(294, 21);
+ this._waitOnNormalExit.TabIndex = 2;
+ this._waitOnNormalExit.Text = "Wai&t for input when process exits normally";
+ this._waitOnNormalExit.UseVisualStyleBackColor = true;
+ //
+ // _waitOnAbnormalExit
+ //
+ this._waitOnAbnormalExit.AutoSize = true;
+ this._waitOnAbnormalExit.Location = new System.Drawing.Point(5, 5);
+ this._waitOnAbnormalExit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._waitOnAbnormalExit.Name = "_waitOnAbnormalExit";
+ this._waitOnAbnormalExit.Size = new System.Drawing.Size(310, 21);
+ this._waitOnAbnormalExit.TabIndex = 1;
+ this._waitOnAbnormalExit.Text = "&Wait for input when process exits abnormally";
+ this._waitOnAbnormalExit.UseVisualStyleBackColor = true;
+ //
+ // _showBrowserAndNodeLabels
+ //
+ this._showBrowserAndNodeLabels.AutoSize = true;
+ this._showBrowserAndNodeLabels.Location = new System.Drawing.Point(5, 119);
+ this._showBrowserAndNodeLabels.Margin = new System.Windows.Forms.Padding(4);
+ this._showBrowserAndNodeLabels.Name = "_showBrowserAndNodeLabels";
+ this._showBrowserAndNodeLabels.Size = new System.Drawing.Size(471, 21);
+ this._showBrowserAndNodeLabels.TabIndex = 6;
+ this._showBrowserAndNodeLabels.Text = "Show &labels denoting browser and Node.js code in Solution Explorer";
+ this._showBrowserAndNodeLabels.UseVisualStyleBackColor = true;
+ //
+ // NodejsGeneralOptionsControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.tableLayoutPanel3);
+ this.Controls.Add(this._topOptionsPanel);
+ this.Margin = new System.Windows.Forms.Padding(8, 10, 8, 10);
+ this.Name = "NodejsGeneralOptionsControl";
+ this.Size = new System.Drawing.Size(508, 357);
+ this.tableLayoutPanel3.ResumeLayout(false);
+ this.tableLayoutPanel3.PerformLayout();
+ this._topOptionsPanel.ResumeLayout(false);
+ this._topOptionsPanel.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
+ private System.Windows.Forms.Label _surveyNewsCheckLabel;
+ private System.Windows.Forms.ComboBox _surveyNewsCheckCombo;
+ private System.Windows.Forms.Panel _topOptionsPanel;
+ private System.Windows.Forms.CheckBox _waitOnNormalExit;
+ private System.Windows.Forms.CheckBox _waitOnAbnormalExit;
+ private System.Windows.Forms.CheckBox _editAndContinue;
+ private System.Windows.Forms.CheckBox _checkForLongPaths;
+ private System.Windows.Forms.CheckBox _showBrowserAndNodeLabels;
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.cs b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.cs
index 0a074e921..74e87a858 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsControl.cs
@@ -1,85 +1,85 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Windows.Forms;
-
-namespace Microsoft.NodejsTools.Options {
- public partial class NodejsGeneralOptionsControl : UserControl {
- private const int SurveyNewsNeverIndex = 0;
- private const int SurveyNewsOnceDayIndex = 1;
- private const int SurveyNewsOnceWeekIndex = 2;
- private const int SurveyNewsOnceMonthIndex = 3;
-
- public NodejsGeneralOptionsControl() {
- InitializeComponent();
- }
-
- internal SurveyNewsPolicy SurveyNewsCheckCombo {
- get {
- switch (_surveyNewsCheckCombo.SelectedIndex) {
- case SurveyNewsNeverIndex:
- return SurveyNewsPolicy.Disabled;
- case SurveyNewsOnceDayIndex:
- return SurveyNewsPolicy.CheckOnceDay;
- case SurveyNewsOnceWeekIndex:
- return SurveyNewsPolicy.CheckOnceWeek;
- case SurveyNewsOnceMonthIndex:
- return SurveyNewsPolicy.CheckOnceMonth;
- default:
- return SurveyNewsPolicy.Disabled;
- }
- }
- set {
- switch (value) {
- case SurveyNewsPolicy.Disabled:
- _surveyNewsCheckCombo.SelectedIndex = SurveyNewsNeverIndex;
- break;
- case SurveyNewsPolicy.CheckOnceDay:
- _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceDayIndex;
- break;
- case SurveyNewsPolicy.CheckOnceWeek:
- _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceWeekIndex;
- break;
- case SurveyNewsPolicy.CheckOnceMonth:
- _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceMonthIndex;
- break;
- }
- }
- }
-
- internal void SyncControlWithPageSettings(NodejsGeneralOptionsPage page) {
- SurveyNewsCheckCombo = page.SurveyNewsCheck;
- _waitOnAbnormalExit.Checked = page.WaitOnAbnormalExit;
- _waitOnNormalExit.Checked = page.WaitOnNormalExit;
- _editAndContinue.Checked = page.EditAndContinue;
- _checkForLongPaths.Checked = page.CheckForLongPaths;
- _showBrowserAndNodeLabels.Checked = page.ShowBrowserAndNodeLabels;
-
- // Disable the show "browser" and "node" labels option when the user is in ES6 IntelliSense Preview mode
- _showBrowserAndNodeLabels.Enabled = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel != AnalysisLevel.Preview;
- }
-
- internal void SyncPageWithControlSettings(NodejsGeneralOptionsPage page) {
- page.SurveyNewsCheck = SurveyNewsCheckCombo;
- page.WaitOnAbnormalExit = _waitOnAbnormalExit.Checked;
- page.WaitOnNormalExit = _waitOnNormalExit.Checked;
- page.EditAndContinue = _editAndContinue.Checked;
- page.CheckForLongPaths = _checkForLongPaths.Checked;
- page.ShowBrowserAndNodeLabels = _showBrowserAndNodeLabels.Checked;
- }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Windows.Forms;
+
+namespace Microsoft.NodejsTools.Options {
+ public partial class NodejsGeneralOptionsControl : UserControl {
+ private const int SurveyNewsNeverIndex = 0;
+ private const int SurveyNewsOnceDayIndex = 1;
+ private const int SurveyNewsOnceWeekIndex = 2;
+ private const int SurveyNewsOnceMonthIndex = 3;
+
+ public NodejsGeneralOptionsControl() {
+ InitializeComponent();
+ }
+
+ internal SurveyNewsPolicy SurveyNewsCheckCombo {
+ get {
+ switch (_surveyNewsCheckCombo.SelectedIndex) {
+ case SurveyNewsNeverIndex:
+ return SurveyNewsPolicy.Disabled;
+ case SurveyNewsOnceDayIndex:
+ return SurveyNewsPolicy.CheckOnceDay;
+ case SurveyNewsOnceWeekIndex:
+ return SurveyNewsPolicy.CheckOnceWeek;
+ case SurveyNewsOnceMonthIndex:
+ return SurveyNewsPolicy.CheckOnceMonth;
+ default:
+ return SurveyNewsPolicy.Disabled;
+ }
+ }
+ set {
+ switch (value) {
+ case SurveyNewsPolicy.Disabled:
+ _surveyNewsCheckCombo.SelectedIndex = SurveyNewsNeverIndex;
+ break;
+ case SurveyNewsPolicy.CheckOnceDay:
+ _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceDayIndex;
+ break;
+ case SurveyNewsPolicy.CheckOnceWeek:
+ _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceWeekIndex;
+ break;
+ case SurveyNewsPolicy.CheckOnceMonth:
+ _surveyNewsCheckCombo.SelectedIndex = SurveyNewsOnceMonthIndex;
+ break;
+ }
+ }
+ }
+
+ internal void SyncControlWithPageSettings(NodejsGeneralOptionsPage page) {
+ SurveyNewsCheckCombo = page.SurveyNewsCheck;
+ _waitOnAbnormalExit.Checked = page.WaitOnAbnormalExit;
+ _waitOnNormalExit.Checked = page.WaitOnNormalExit;
+ _editAndContinue.Checked = page.EditAndContinue;
+ _checkForLongPaths.Checked = page.CheckForLongPaths;
+ _showBrowserAndNodeLabels.Checked = page.ShowBrowserAndNodeLabels;
+
+ // Disable the show "browser" and "node" labels option when the user is in ES6 IntelliSense Preview mode
+ _showBrowserAndNodeLabels.Enabled = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel != AnalysisLevel.Preview;
+ }
+
+ internal void SyncPageWithControlSettings(NodejsGeneralOptionsPage page) {
+ page.SurveyNewsCheck = SurveyNewsCheckCombo;
+ page.WaitOnAbnormalExit = _waitOnAbnormalExit.Checked;
+ page.WaitOnNormalExit = _waitOnNormalExit.Checked;
+ page.EditAndContinue = _editAndContinue.Checked;
+ page.CheckForLongPaths = _checkForLongPaths.Checked;
+ page.ShowBrowserAndNodeLabels = _showBrowserAndNodeLabels.Checked;
+ }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsPage.cs b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsPage.cs
index d3e35fb73..e361a6f4d 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsPage.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsPage.cs
@@ -1,188 +1,188 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Runtime.InteropServices;
-using System.Windows.Forms;
-
-namespace Microsoft.NodejsTools.Options {
- [ComVisible(true)]
- public class NodejsGeneralOptionsPage : NodejsDialogPage {
- private const string DefaultSurveyNewsFeedUrl = "http://go.microsoft.com/fwlink/?LinkId=328027";
- private const string DefaultSurveyNewsIndexUrl = "http://go.microsoft.com/fwlink/?LinkId=328029";
- private const string SurveyNewsCheckSetting = "SurveyNewsCheck";
- private const string SurveyNewsLastCheckSetting = "SurveyNewsLastCheck";
- private const string SurveyNewsFeedUrlSetting = "SurveyNewsFeedUrl";
- private const string SurveyNewsIndexUrlSetting = "SurveyNewsIndexUrl";
- private const string WaitOnAbnormalExitSetting = "WaitOnAbnormalExit";
- private const string WaitOnNormalExitSetting = "WaitOnNormalExit";
- private const string EditAndContinueSetting = "EditAndContinue";
- private const string CheckForLongPathsSetting = "CheckForLongPaths";
- private const string ShowBrowserAndNodeLabelsSetting = "ShowBrowserAndNodeLabels";
- private bool _showBrowserAndNodeLabels;
- private SurveyNewsPolicy _surveyNewsCheck;
- private string _surveyNewsFeedUrl;
- private string _surveyNewsIndexUrl;
- private DateTime _surveyNewsLastCheck;
- private NodejsGeneralOptionsControl _window;
-
- public NodejsGeneralOptionsPage()
- : base("General") {
- }
-
- // replace the default UI of the dialog page w/ our own UI.
- protected override IWin32Window Window {
- get {
- if (_window == null) {
- _window = new NodejsGeneralOptionsControl();
- LoadSettingsFromStorage();
- }
- return _window;
- }
- }
-
- ///
- /// Indicates whether or not the Output window should be shown when
- /// npm commands are being executed.
- ///
- public bool ShowOutputWindowWhenExecutingNpm { get; set; }
-
- ///
- /// True if Node processes should pause for input before exiting
- /// if they exit abnormally.
- ///
- public bool WaitOnAbnormalExit { get; set; }
-
- ///
- /// True if Node processes should pause for input before exiting
- /// if they exit normally.
- ///
- public bool WaitOnNormalExit { get; set; }
-
- ///
- /// Indicates whether Edit and Continue feature should be enabled.
- ///
- public bool EditAndContinue { get; set; }
-
- ///
- /// Indicates whether checks for long paths (exceeding MAX_PATH) are performed after installing packages.
- ///
- public bool CheckForLongPaths { get; set; }
-
- ///
- /// Indicates whether labels should be appended to folders in Solution Explorer denoting browser and Node.js code.
- ///
- public bool ShowBrowserAndNodeLabels {
- get { return _showBrowserAndNodeLabels; }
- set {
- var oldSetting = _showBrowserAndNodeLabels;
- _showBrowserAndNodeLabels = value;
- if (oldSetting != _showBrowserAndNodeLabels) {
- var changed = ShowBrowserAndNodeLabelsChanged;
- if (changed != null) {
- changed(this, EventArgs.Empty);
- }
- }
- }
- }
-
- public event EventHandler ShowBrowserAndNodeLabelsChanged;
-
- ///
- /// The frequency at which to check for updated news. Default is once
- /// per week.
- ///
- public SurveyNewsPolicy SurveyNewsCheck {
- get { return _surveyNewsCheck; }
- set { _surveyNewsCheck = value; }
- }
-
- ///
- /// The date/time when the last check for news occurred.
- ///
- public DateTime SurveyNewsLastCheck {
- get { return _surveyNewsLastCheck; }
- set { _surveyNewsLastCheck = value; }
- }
-
- ///
- /// The url of the news feed.
- ///
- public string SurveyNewsFeedUrl {
- get { return _surveyNewsFeedUrl; }
- set { _surveyNewsFeedUrl = value; }
- }
-
- ///
- /// The url of the news index page.
- ///
- public string SurveyNewsIndexUrl {
- get { return _surveyNewsIndexUrl; }
- set { _surveyNewsIndexUrl = value; }
- }
-
- ///
- /// Resets settings back to their defaults. This should be followed by
- /// a call to to commit the new
- /// values.
- ///
- public override void ResetSettings() {
- _surveyNewsCheck = SurveyNewsPolicy.CheckOnceWeek;
- _surveyNewsLastCheck = DateTime.MinValue;
- _surveyNewsFeedUrl = DefaultSurveyNewsFeedUrl;
- _surveyNewsIndexUrl = DefaultSurveyNewsIndexUrl;
- WaitOnAbnormalExit = true;
- WaitOnNormalExit = false;
- EditAndContinue = true;
- CheckForLongPaths = true;
- _showBrowserAndNodeLabels = true;
- }
-
- public override void LoadSettingsFromStorage() {
- // Load settings from storage.
- _surveyNewsCheck = LoadEnum(SurveyNewsCheckSetting) ?? SurveyNewsPolicy.CheckOnceWeek;
- _surveyNewsLastCheck = LoadDateTime(SurveyNewsLastCheckSetting) ?? DateTime.MinValue;
- _surveyNewsFeedUrl = LoadString(SurveyNewsFeedUrlSetting) ?? DefaultSurveyNewsFeedUrl;
- _surveyNewsIndexUrl = LoadString(SurveyNewsIndexUrlSetting) ?? DefaultSurveyNewsIndexUrl;
- WaitOnAbnormalExit = LoadBool(WaitOnAbnormalExitSetting) ?? true;
- WaitOnNormalExit = LoadBool(WaitOnNormalExitSetting) ?? false;
- EditAndContinue = LoadBool(EditAndContinueSetting) ?? true;
- CheckForLongPaths = LoadBool(CheckForLongPathsSetting) ?? true;
- _showBrowserAndNodeLabels = LoadBool(ShowBrowserAndNodeLabelsSetting) ?? true;
-
- // Synchronize UI with backing properties.
- if (_window != null) {
- _window.SyncControlWithPageSettings(this);
- }
- }
-
- public override void SaveSettingsToStorage() {
- // Synchronize backing properties with UI.
- if (_window != null) {
- _window.SyncPageWithControlSettings(this);
- }
-
- // Save settings.
- SaveEnum(SurveyNewsCheckSetting, _surveyNewsCheck);
- SaveDateTime(SurveyNewsLastCheckSetting, _surveyNewsLastCheck);
- SaveBool(WaitOnNormalExitSetting, WaitOnNormalExit);
- SaveBool(WaitOnAbnormalExitSetting, WaitOnAbnormalExit);
- SaveBool(EditAndContinueSetting, EditAndContinue);
- SaveBool(CheckForLongPathsSetting, CheckForLongPaths);
- SaveBool(ShowBrowserAndNodeLabelsSetting, ShowBrowserAndNodeLabels);
- }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace Microsoft.NodejsTools.Options {
+ [ComVisible(true)]
+ public class NodejsGeneralOptionsPage : NodejsDialogPage {
+ private const string DefaultSurveyNewsFeedUrl = "http://go.microsoft.com/fwlink/?LinkId=328027";
+ private const string DefaultSurveyNewsIndexUrl = "http://go.microsoft.com/fwlink/?LinkId=328029";
+ private const string SurveyNewsCheckSetting = "SurveyNewsCheck";
+ private const string SurveyNewsLastCheckSetting = "SurveyNewsLastCheck";
+ private const string SurveyNewsFeedUrlSetting = "SurveyNewsFeedUrl";
+ private const string SurveyNewsIndexUrlSetting = "SurveyNewsIndexUrl";
+ private const string WaitOnAbnormalExitSetting = "WaitOnAbnormalExit";
+ private const string WaitOnNormalExitSetting = "WaitOnNormalExit";
+ private const string EditAndContinueSetting = "EditAndContinue";
+ private const string CheckForLongPathsSetting = "CheckForLongPaths";
+ private const string ShowBrowserAndNodeLabelsSetting = "ShowBrowserAndNodeLabels";
+ private bool _showBrowserAndNodeLabels;
+ private SurveyNewsPolicy _surveyNewsCheck;
+ private string _surveyNewsFeedUrl;
+ private string _surveyNewsIndexUrl;
+ private DateTime _surveyNewsLastCheck;
+ private NodejsGeneralOptionsControl _window;
+
+ public NodejsGeneralOptionsPage()
+ : base("General") {
+ }
+
+ // replace the default UI of the dialog page w/ our own UI.
+ protected override IWin32Window Window {
+ get {
+ if (_window == null) {
+ _window = new NodejsGeneralOptionsControl();
+ LoadSettingsFromStorage();
+ }
+ return _window;
+ }
+ }
+
+ ///
+ /// Indicates whether or not the Output window should be shown when
+ /// npm commands are being executed.
+ ///
+ public bool ShowOutputWindowWhenExecutingNpm { get; set; }
+
+ ///
+ /// True if Node processes should pause for input before exiting
+ /// if they exit abnormally.
+ ///
+ public bool WaitOnAbnormalExit { get; set; }
+
+ ///
+ /// True if Node processes should pause for input before exiting
+ /// if they exit normally.
+ ///
+ public bool WaitOnNormalExit { get; set; }
+
+ ///
+ /// Indicates whether Edit and Continue feature should be enabled.
+ ///
+ public bool EditAndContinue { get; set; }
+
+ ///
+ /// Indicates whether checks for long paths (exceeding MAX_PATH) are performed after installing packages.
+ ///
+ public bool CheckForLongPaths { get; set; }
+
+ ///
+ /// Indicates whether labels should be appended to folders in Solution Explorer denoting browser and Node.js code.
+ ///
+ public bool ShowBrowserAndNodeLabels {
+ get { return _showBrowserAndNodeLabels; }
+ set {
+ var oldSetting = _showBrowserAndNodeLabels;
+ _showBrowserAndNodeLabels = value;
+ if (oldSetting != _showBrowserAndNodeLabels) {
+ var changed = ShowBrowserAndNodeLabelsChanged;
+ if (changed != null) {
+ changed(this, EventArgs.Empty);
+ }
+ }
+ }
+ }
+
+ public event EventHandler ShowBrowserAndNodeLabelsChanged;
+
+ ///
+ /// The frequency at which to check for updated news. Default is once
+ /// per week.
+ ///
+ public SurveyNewsPolicy SurveyNewsCheck {
+ get { return _surveyNewsCheck; }
+ set { _surveyNewsCheck = value; }
+ }
+
+ ///
+ /// The date/time when the last check for news occurred.
+ ///
+ public DateTime SurveyNewsLastCheck {
+ get { return _surveyNewsLastCheck; }
+ set { _surveyNewsLastCheck = value; }
+ }
+
+ ///
+ /// The url of the news feed.
+ ///
+ public string SurveyNewsFeedUrl {
+ get { return _surveyNewsFeedUrl; }
+ set { _surveyNewsFeedUrl = value; }
+ }
+
+ ///
+ /// The url of the news index page.
+ ///
+ public string SurveyNewsIndexUrl {
+ get { return _surveyNewsIndexUrl; }
+ set { _surveyNewsIndexUrl = value; }
+ }
+
+ ///
+ /// Resets settings back to their defaults. This should be followed by
+ /// a call to to commit the new
+ /// values.
+ ///
+ public override void ResetSettings() {
+ _surveyNewsCheck = SurveyNewsPolicy.CheckOnceWeek;
+ _surveyNewsLastCheck = DateTime.MinValue;
+ _surveyNewsFeedUrl = DefaultSurveyNewsFeedUrl;
+ _surveyNewsIndexUrl = DefaultSurveyNewsIndexUrl;
+ WaitOnAbnormalExit = true;
+ WaitOnNormalExit = false;
+ EditAndContinue = true;
+ CheckForLongPaths = true;
+ _showBrowserAndNodeLabels = true;
+ }
+
+ public override void LoadSettingsFromStorage() {
+ // Load settings from storage.
+ _surveyNewsCheck = LoadEnum(SurveyNewsCheckSetting) ?? SurveyNewsPolicy.CheckOnceWeek;
+ _surveyNewsLastCheck = LoadDateTime(SurveyNewsLastCheckSetting) ?? DateTime.MinValue;
+ _surveyNewsFeedUrl = LoadString(SurveyNewsFeedUrlSetting) ?? DefaultSurveyNewsFeedUrl;
+ _surveyNewsIndexUrl = LoadString(SurveyNewsIndexUrlSetting) ?? DefaultSurveyNewsIndexUrl;
+ WaitOnAbnormalExit = LoadBool(WaitOnAbnormalExitSetting) ?? true;
+ WaitOnNormalExit = LoadBool(WaitOnNormalExitSetting) ?? false;
+ EditAndContinue = LoadBool(EditAndContinueSetting) ?? true;
+ CheckForLongPaths = LoadBool(CheckForLongPathsSetting) ?? true;
+ _showBrowserAndNodeLabels = LoadBool(ShowBrowserAndNodeLabelsSetting) ?? true;
+
+ // Synchronize UI with backing properties.
+ if (_window != null) {
+ _window.SyncControlWithPageSettings(this);
+ }
+ }
+
+ public override void SaveSettingsToStorage() {
+ // Synchronize backing properties with UI.
+ if (_window != null) {
+ _window.SyncPageWithControlSettings(this);
+ }
+
+ // Save settings.
+ SaveEnum(SurveyNewsCheckSetting, _surveyNewsCheck);
+ SaveDateTime(SurveyNewsLastCheckSetting, _surveyNewsLastCheck);
+ SaveBool(WaitOnNormalExitSetting, WaitOnNormalExit);
+ SaveBool(WaitOnAbnormalExitSetting, WaitOnAbnormalExit);
+ SaveBool(EditAndContinueSetting, EditAndContinue);
+ SaveBool(CheckForLongPathsSetting, CheckForLongPaths);
+ SaveBool(ShowBrowserAndNodeLabelsSetting, ShowBrowserAndNodeLabels);
+ }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.Designer.cs b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.Designer.cs
index bc8fb664e..9357ee1bc 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.Designer.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.Designer.cs
@@ -1,245 +1,245 @@
-namespace Microsoft.NodejsTools.Options {
- partial class NodejsIntellisenseOptionsControl {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- System.Windows.Forms.ToolTip toolTip;
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NodejsIntellisenseOptionsControl));
- System.Windows.Forms.GroupBox intellisenseLevelGroupBox;
- System.Windows.Forms.GroupBox saveToDiskGroupBox;
- this._saveToDiskDisabledRadioButton = new System.Windows.Forms.RadioButton();
- this._saveToDiskEnabledRadioButton = new System.Windows.Forms.RadioButton();
- this._fullIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
- this._noIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
- this._mediumIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
- this._previewIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
- this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
- this._analysisLogMax = new System.Windows.Forms.ComboBox();
- this._analysisLogMaxLabel = new System.Windows.Forms.Label();
- this._analysisPreviewFeedbackLinkLabel = new System.Windows.Forms.LinkLabel();
- this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
- this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
- this._selectionInCompletionListGroupBox = new System.Windows.Forms.GroupBox();
- this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
- this._onlyTabOrEnterToCommit = new System.Windows.Forms.CheckBox();
- this._showCompletionListAfterCharacterTyped = new System.Windows.Forms.CheckBox();
- toolTip = new System.Windows.Forms.ToolTip(this.components);
- intellisenseLevelGroupBox = new System.Windows.Forms.GroupBox();
- saveToDiskGroupBox = new System.Windows.Forms.GroupBox();
- intellisenseLevelGroupBox.SuspendLayout();
- this.tableLayoutPanel2.SuspendLayout();
- saveToDiskGroupBox.SuspendLayout();
- this.tableLayoutPanel4.SuspendLayout();
- this.tableLayoutPanel1.SuspendLayout();
- this._selectionInCompletionListGroupBox.SuspendLayout();
- this.tableLayoutPanel3.SuspendLayout();
- this.SuspendLayout();
- //
- // _saveToDiskDisabledRadioButton
- //
- resources.ApplyResources(this._saveToDiskDisabledRadioButton, "_saveToDiskDisabledRadioButton");
- this._saveToDiskDisabledRadioButton.Name = "_saveToDiskDisabledRadioButton";
- this._saveToDiskDisabledRadioButton.TabStop = true;
- toolTip.SetToolTip(this._saveToDiskDisabledRadioButton, resources.GetString("_saveToDiskDisabledRadioButton.ToolTip"));
- this._saveToDiskDisabledRadioButton.UseVisualStyleBackColor = true;
- //
- // _saveToDiskEnabledRadioButton
- //
- resources.ApplyResources(this._saveToDiskEnabledRadioButton, "_saveToDiskEnabledRadioButton");
- this._saveToDiskEnabledRadioButton.Name = "_saveToDiskEnabledRadioButton";
- this._saveToDiskEnabledRadioButton.TabStop = true;
- toolTip.SetToolTip(this._saveToDiskEnabledRadioButton, resources.GetString("_saveToDiskEnabledRadioButton.ToolTip"));
- this._saveToDiskEnabledRadioButton.UseVisualStyleBackColor = true;
- //
- // _fullIntelliSenseRadioButton
- //
- resources.ApplyResources(this._fullIntelliSenseRadioButton, "_fullIntelliSenseRadioButton");
- this._fullIntelliSenseRadioButton.Name = "_fullIntelliSenseRadioButton";
- this._fullIntelliSenseRadioButton.TabStop = true;
- toolTip.SetToolTip(this._fullIntelliSenseRadioButton, resources.GetString("_fullIntelliSenseRadioButton.ToolTip"));
- this._fullIntelliSenseRadioButton.UseVisualStyleBackColor = true;
- //
- // _noIntelliSenseRadioButton
- //
- resources.ApplyResources(this._noIntelliSenseRadioButton, "_noIntelliSenseRadioButton");
- this._noIntelliSenseRadioButton.Name = "_noIntelliSenseRadioButton";
- this._noIntelliSenseRadioButton.TabStop = true;
- toolTip.SetToolTip(this._noIntelliSenseRadioButton, resources.GetString("_noIntelliSenseRadioButton.ToolTip"));
- this._noIntelliSenseRadioButton.UseVisualStyleBackColor = true;
- //
- // _mediumIntelliSenseRadioButton
- //
- resources.ApplyResources(this._mediumIntelliSenseRadioButton, "_mediumIntelliSenseRadioButton");
- this._mediumIntelliSenseRadioButton.Name = "_mediumIntelliSenseRadioButton";
- this._mediumIntelliSenseRadioButton.TabStop = true;
- toolTip.SetToolTip(this._mediumIntelliSenseRadioButton, resources.GetString("_mediumIntelliSenseRadioButton.ToolTip"));
- this._mediumIntelliSenseRadioButton.UseVisualStyleBackColor = true;
- //
- // _previewIntelliSenseRadioButton
- //
- resources.ApplyResources(this._previewIntelliSenseRadioButton, "_previewIntelliSenseRadioButton");
- this._previewIntelliSenseRadioButton.Name = "_previewIntelliSenseRadioButton";
- this._previewIntelliSenseRadioButton.TabStop = true;
- toolTip.SetToolTip(this._previewIntelliSenseRadioButton, resources.GetString("_previewIntelliSenseRadioButton.ToolTip"));
- this._previewIntelliSenseRadioButton.UseVisualStyleBackColor = true;
- //
- // intellisenseLevelGroupBox
- //
- resources.ApplyResources(intellisenseLevelGroupBox, "intellisenseLevelGroupBox");
- intellisenseLevelGroupBox.Controls.Add(this.tableLayoutPanel2);
- intellisenseLevelGroupBox.Name = "intellisenseLevelGroupBox";
- intellisenseLevelGroupBox.TabStop = false;
- //
- // tableLayoutPanel2
- //
- resources.ApplyResources(this.tableLayoutPanel2, "tableLayoutPanel2");
- this.tableLayoutPanel2.Controls.Add(this._previewIntelliSenseRadioButton, 0, 4);
- this.tableLayoutPanel2.Controls.Add(this._mediumIntelliSenseRadioButton, 0, 2);
- this.tableLayoutPanel2.Controls.Add(this._analysisLogMax, 1, 5);
- this.tableLayoutPanel2.Controls.Add(this._noIntelliSenseRadioButton, 0, 3);
- this.tableLayoutPanel2.Controls.Add(this._analysisLogMaxLabel, 0, 5);
- this.tableLayoutPanel2.Controls.Add(this._fullIntelliSenseRadioButton, 0, 0);
- this.tableLayoutPanel2.Controls.Add(this._analysisPreviewFeedbackLinkLabel, 1, 4);
- this.tableLayoutPanel2.Name = "tableLayoutPanel2";
- //
- // _analysisLogMax
- //
- resources.ApplyResources(this._analysisLogMax, "_analysisLogMax");
- this._analysisLogMax.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this._analysisLogMax.FormattingEnabled = true;
- this._analysisLogMax.Items.AddRange(new object[] {
- resources.GetString("_analysisLogMax.Items"),
- resources.GetString("_analysisLogMax.Items1"),
- resources.GetString("_analysisLogMax.Items2"),
- resources.GetString("_analysisLogMax.Items3"),
- resources.GetString("_analysisLogMax.Items4"),
- resources.GetString("_analysisLogMax.Items5"),
- resources.GetString("_analysisLogMax.Items6")});
- this._analysisLogMax.Name = "_analysisLogMax";
- //
- // _analysisLogMaxLabel
- //
- resources.ApplyResources(this._analysisLogMaxLabel, "_analysisLogMaxLabel");
- this._analysisLogMaxLabel.Name = "_analysisLogMaxLabel";
- //
- // _analysisPreviewFeedbackLinkLabel
- //
- resources.ApplyResources(this._analysisPreviewFeedbackLinkLabel, "_analysisPreviewFeedbackLinkLabel");
- this._analysisPreviewFeedbackLinkLabel.Name = "_analysisPreviewFeedbackLinkLabel";
- this._analysisPreviewFeedbackLinkLabel.TabStop = true;
- this._analysisPreviewFeedbackLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this._analysisPreviewFeedbackLinkLabel_LinkClicked);
- //
- // saveToDiskGroupBox
- //
- resources.ApplyResources(saveToDiskGroupBox, "saveToDiskGroupBox");
- saveToDiskGroupBox.Controls.Add(this.tableLayoutPanel4);
- saveToDiskGroupBox.Name = "saveToDiskGroupBox";
- saveToDiskGroupBox.TabStop = false;
- //
- // tableLayoutPanel4
- //
- resources.ApplyResources(this.tableLayoutPanel4, "tableLayoutPanel4");
- this.tableLayoutPanel4.Controls.Add(this._saveToDiskDisabledRadioButton, 0, 1);
- this.tableLayoutPanel4.Controls.Add(this._saveToDiskEnabledRadioButton, 0, 0);
- this.tableLayoutPanel4.Name = "tableLayoutPanel4";
- //
- // tableLayoutPanel1
- //
- resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1");
- this.tableLayoutPanel1.Controls.Add(this._selectionInCompletionListGroupBox, 0, 2);
- this.tableLayoutPanel1.Controls.Add(saveToDiskGroupBox, 0, 1);
- this.tableLayoutPanel1.Controls.Add(intellisenseLevelGroupBox, 0, 0);
- this.tableLayoutPanel1.Name = "tableLayoutPanel1";
- //
- // _selectionInCompletionListGroupBox
- //
- resources.ApplyResources(this._selectionInCompletionListGroupBox, "_selectionInCompletionListGroupBox");
- this._selectionInCompletionListGroupBox.Controls.Add(this.tableLayoutPanel3);
- this._selectionInCompletionListGroupBox.Name = "_selectionInCompletionListGroupBox";
- this._selectionInCompletionListGroupBox.TabStop = false;
- //
- // tableLayoutPanel3
- //
- resources.ApplyResources(this.tableLayoutPanel3, "tableLayoutPanel3");
- this.tableLayoutPanel3.Controls.Add(this._onlyTabOrEnterToCommit, 0, 0);
- this.tableLayoutPanel3.Controls.Add(this._showCompletionListAfterCharacterTyped, 0, 1);
- this.tableLayoutPanel3.Name = "tableLayoutPanel3";
- //
- // _onlyTabOrEnterToCommit
- //
- resources.ApplyResources(this._onlyTabOrEnterToCommit, "_onlyTabOrEnterToCommit");
- this._onlyTabOrEnterToCommit.Name = "_onlyTabOrEnterToCommit";
- this._onlyTabOrEnterToCommit.UseVisualStyleBackColor = true;
- //
- // _showCompletionListAfterCharacterTyped
- //
- resources.ApplyResources(this._showCompletionListAfterCharacterTyped, "_showCompletionListAfterCharacterTyped");
- this._showCompletionListAfterCharacterTyped.Name = "_showCompletionListAfterCharacterTyped";
- this._showCompletionListAfterCharacterTyped.UseVisualStyleBackColor = true;
- //
- // NodejsIntellisenseOptionsControl
- //
- resources.ApplyResources(this, "$this");
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.tableLayoutPanel1);
- this.Name = "NodejsIntellisenseOptionsControl";
- intellisenseLevelGroupBox.ResumeLayout(false);
- intellisenseLevelGroupBox.PerformLayout();
- this.tableLayoutPanel2.ResumeLayout(false);
- this.tableLayoutPanel2.PerformLayout();
- saveToDiskGroupBox.ResumeLayout(false);
- saveToDiskGroupBox.PerformLayout();
- this.tableLayoutPanel4.ResumeLayout(false);
- this.tableLayoutPanel4.PerformLayout();
- this.tableLayoutPanel1.ResumeLayout(false);
- this.tableLayoutPanel1.PerformLayout();
- this._selectionInCompletionListGroupBox.ResumeLayout(false);
- this._selectionInCompletionListGroupBox.PerformLayout();
- this.tableLayoutPanel3.ResumeLayout(false);
- this.tableLayoutPanel3.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
- private System.Windows.Forms.GroupBox _selectionInCompletionListGroupBox;
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
- private System.Windows.Forms.RadioButton _saveToDiskDisabledRadioButton;
- private System.Windows.Forms.RadioButton _saveToDiskEnabledRadioButton;
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
- private System.Windows.Forms.RadioButton _previewIntelliSenseRadioButton;
- private System.Windows.Forms.RadioButton _mediumIntelliSenseRadioButton;
- private System.Windows.Forms.ComboBox _analysisLogMax;
- private System.Windows.Forms.RadioButton _noIntelliSenseRadioButton;
- private System.Windows.Forms.Label _analysisLogMaxLabel;
- private System.Windows.Forms.RadioButton _fullIntelliSenseRadioButton;
- private System.Windows.Forms.LinkLabel _analysisPreviewFeedbackLinkLabel;
- private System.Windows.Forms.CheckBox _onlyTabOrEnterToCommit;
- private System.Windows.Forms.CheckBox _showCompletionListAfterCharacterTyped;
- }
-}
+namespace Microsoft.NodejsTools.Options {
+ partial class NodejsIntellisenseOptionsControl {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.ToolTip toolTip;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NodejsIntellisenseOptionsControl));
+ System.Windows.Forms.GroupBox intellisenseLevelGroupBox;
+ System.Windows.Forms.GroupBox saveToDiskGroupBox;
+ this._saveToDiskDisabledRadioButton = new System.Windows.Forms.RadioButton();
+ this._saveToDiskEnabledRadioButton = new System.Windows.Forms.RadioButton();
+ this._fullIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
+ this._noIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
+ this._mediumIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
+ this._previewIntelliSenseRadioButton = new System.Windows.Forms.RadioButton();
+ this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
+ this._analysisLogMax = new System.Windows.Forms.ComboBox();
+ this._analysisLogMaxLabel = new System.Windows.Forms.Label();
+ this._analysisPreviewFeedbackLinkLabel = new System.Windows.Forms.LinkLabel();
+ this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this._selectionInCompletionListGroupBox = new System.Windows.Forms.GroupBox();
+ this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
+ this._onlyTabOrEnterToCommit = new System.Windows.Forms.CheckBox();
+ this._showCompletionListAfterCharacterTyped = new System.Windows.Forms.CheckBox();
+ toolTip = new System.Windows.Forms.ToolTip(this.components);
+ intellisenseLevelGroupBox = new System.Windows.Forms.GroupBox();
+ saveToDiskGroupBox = new System.Windows.Forms.GroupBox();
+ intellisenseLevelGroupBox.SuspendLayout();
+ this.tableLayoutPanel2.SuspendLayout();
+ saveToDiskGroupBox.SuspendLayout();
+ this.tableLayoutPanel4.SuspendLayout();
+ this.tableLayoutPanel1.SuspendLayout();
+ this._selectionInCompletionListGroupBox.SuspendLayout();
+ this.tableLayoutPanel3.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _saveToDiskDisabledRadioButton
+ //
+ resources.ApplyResources(this._saveToDiskDisabledRadioButton, "_saveToDiskDisabledRadioButton");
+ this._saveToDiskDisabledRadioButton.Name = "_saveToDiskDisabledRadioButton";
+ this._saveToDiskDisabledRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._saveToDiskDisabledRadioButton, resources.GetString("_saveToDiskDisabledRadioButton.ToolTip"));
+ this._saveToDiskDisabledRadioButton.UseVisualStyleBackColor = true;
+ //
+ // _saveToDiskEnabledRadioButton
+ //
+ resources.ApplyResources(this._saveToDiskEnabledRadioButton, "_saveToDiskEnabledRadioButton");
+ this._saveToDiskEnabledRadioButton.Name = "_saveToDiskEnabledRadioButton";
+ this._saveToDiskEnabledRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._saveToDiskEnabledRadioButton, resources.GetString("_saveToDiskEnabledRadioButton.ToolTip"));
+ this._saveToDiskEnabledRadioButton.UseVisualStyleBackColor = true;
+ //
+ // _fullIntelliSenseRadioButton
+ //
+ resources.ApplyResources(this._fullIntelliSenseRadioButton, "_fullIntelliSenseRadioButton");
+ this._fullIntelliSenseRadioButton.Name = "_fullIntelliSenseRadioButton";
+ this._fullIntelliSenseRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._fullIntelliSenseRadioButton, resources.GetString("_fullIntelliSenseRadioButton.ToolTip"));
+ this._fullIntelliSenseRadioButton.UseVisualStyleBackColor = true;
+ //
+ // _noIntelliSenseRadioButton
+ //
+ resources.ApplyResources(this._noIntelliSenseRadioButton, "_noIntelliSenseRadioButton");
+ this._noIntelliSenseRadioButton.Name = "_noIntelliSenseRadioButton";
+ this._noIntelliSenseRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._noIntelliSenseRadioButton, resources.GetString("_noIntelliSenseRadioButton.ToolTip"));
+ this._noIntelliSenseRadioButton.UseVisualStyleBackColor = true;
+ //
+ // _mediumIntelliSenseRadioButton
+ //
+ resources.ApplyResources(this._mediumIntelliSenseRadioButton, "_mediumIntelliSenseRadioButton");
+ this._mediumIntelliSenseRadioButton.Name = "_mediumIntelliSenseRadioButton";
+ this._mediumIntelliSenseRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._mediumIntelliSenseRadioButton, resources.GetString("_mediumIntelliSenseRadioButton.ToolTip"));
+ this._mediumIntelliSenseRadioButton.UseVisualStyleBackColor = true;
+ //
+ // _previewIntelliSenseRadioButton
+ //
+ resources.ApplyResources(this._previewIntelliSenseRadioButton, "_previewIntelliSenseRadioButton");
+ this._previewIntelliSenseRadioButton.Name = "_previewIntelliSenseRadioButton";
+ this._previewIntelliSenseRadioButton.TabStop = true;
+ toolTip.SetToolTip(this._previewIntelliSenseRadioButton, resources.GetString("_previewIntelliSenseRadioButton.ToolTip"));
+ this._previewIntelliSenseRadioButton.UseVisualStyleBackColor = true;
+ //
+ // intellisenseLevelGroupBox
+ //
+ resources.ApplyResources(intellisenseLevelGroupBox, "intellisenseLevelGroupBox");
+ intellisenseLevelGroupBox.Controls.Add(this.tableLayoutPanel2);
+ intellisenseLevelGroupBox.Name = "intellisenseLevelGroupBox";
+ intellisenseLevelGroupBox.TabStop = false;
+ //
+ // tableLayoutPanel2
+ //
+ resources.ApplyResources(this.tableLayoutPanel2, "tableLayoutPanel2");
+ this.tableLayoutPanel2.Controls.Add(this._previewIntelliSenseRadioButton, 0, 4);
+ this.tableLayoutPanel2.Controls.Add(this._mediumIntelliSenseRadioButton, 0, 2);
+ this.tableLayoutPanel2.Controls.Add(this._analysisLogMax, 1, 5);
+ this.tableLayoutPanel2.Controls.Add(this._noIntelliSenseRadioButton, 0, 3);
+ this.tableLayoutPanel2.Controls.Add(this._analysisLogMaxLabel, 0, 5);
+ this.tableLayoutPanel2.Controls.Add(this._fullIntelliSenseRadioButton, 0, 0);
+ this.tableLayoutPanel2.Controls.Add(this._analysisPreviewFeedbackLinkLabel, 1, 4);
+ this.tableLayoutPanel2.Name = "tableLayoutPanel2";
+ //
+ // _analysisLogMax
+ //
+ resources.ApplyResources(this._analysisLogMax, "_analysisLogMax");
+ this._analysisLogMax.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._analysisLogMax.FormattingEnabled = true;
+ this._analysisLogMax.Items.AddRange(new object[] {
+ resources.GetString("_analysisLogMax.Items"),
+ resources.GetString("_analysisLogMax.Items1"),
+ resources.GetString("_analysisLogMax.Items2"),
+ resources.GetString("_analysisLogMax.Items3"),
+ resources.GetString("_analysisLogMax.Items4"),
+ resources.GetString("_analysisLogMax.Items5"),
+ resources.GetString("_analysisLogMax.Items6")});
+ this._analysisLogMax.Name = "_analysisLogMax";
+ //
+ // _analysisLogMaxLabel
+ //
+ resources.ApplyResources(this._analysisLogMaxLabel, "_analysisLogMaxLabel");
+ this._analysisLogMaxLabel.Name = "_analysisLogMaxLabel";
+ //
+ // _analysisPreviewFeedbackLinkLabel
+ //
+ resources.ApplyResources(this._analysisPreviewFeedbackLinkLabel, "_analysisPreviewFeedbackLinkLabel");
+ this._analysisPreviewFeedbackLinkLabel.Name = "_analysisPreviewFeedbackLinkLabel";
+ this._analysisPreviewFeedbackLinkLabel.TabStop = true;
+ this._analysisPreviewFeedbackLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this._analysisPreviewFeedbackLinkLabel_LinkClicked);
+ //
+ // saveToDiskGroupBox
+ //
+ resources.ApplyResources(saveToDiskGroupBox, "saveToDiskGroupBox");
+ saveToDiskGroupBox.Controls.Add(this.tableLayoutPanel4);
+ saveToDiskGroupBox.Name = "saveToDiskGroupBox";
+ saveToDiskGroupBox.TabStop = false;
+ //
+ // tableLayoutPanel4
+ //
+ resources.ApplyResources(this.tableLayoutPanel4, "tableLayoutPanel4");
+ this.tableLayoutPanel4.Controls.Add(this._saveToDiskDisabledRadioButton, 0, 1);
+ this.tableLayoutPanel4.Controls.Add(this._saveToDiskEnabledRadioButton, 0, 0);
+ this.tableLayoutPanel4.Name = "tableLayoutPanel4";
+ //
+ // tableLayoutPanel1
+ //
+ resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1");
+ this.tableLayoutPanel1.Controls.Add(this._selectionInCompletionListGroupBox, 0, 2);
+ this.tableLayoutPanel1.Controls.Add(saveToDiskGroupBox, 0, 1);
+ this.tableLayoutPanel1.Controls.Add(intellisenseLevelGroupBox, 0, 0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ //
+ // _selectionInCompletionListGroupBox
+ //
+ resources.ApplyResources(this._selectionInCompletionListGroupBox, "_selectionInCompletionListGroupBox");
+ this._selectionInCompletionListGroupBox.Controls.Add(this.tableLayoutPanel3);
+ this._selectionInCompletionListGroupBox.Name = "_selectionInCompletionListGroupBox";
+ this._selectionInCompletionListGroupBox.TabStop = false;
+ //
+ // tableLayoutPanel3
+ //
+ resources.ApplyResources(this.tableLayoutPanel3, "tableLayoutPanel3");
+ this.tableLayoutPanel3.Controls.Add(this._onlyTabOrEnterToCommit, 0, 0);
+ this.tableLayoutPanel3.Controls.Add(this._showCompletionListAfterCharacterTyped, 0, 1);
+ this.tableLayoutPanel3.Name = "tableLayoutPanel3";
+ //
+ // _onlyTabOrEnterToCommit
+ //
+ resources.ApplyResources(this._onlyTabOrEnterToCommit, "_onlyTabOrEnterToCommit");
+ this._onlyTabOrEnterToCommit.Name = "_onlyTabOrEnterToCommit";
+ this._onlyTabOrEnterToCommit.UseVisualStyleBackColor = true;
+ //
+ // _showCompletionListAfterCharacterTyped
+ //
+ resources.ApplyResources(this._showCompletionListAfterCharacterTyped, "_showCompletionListAfterCharacterTyped");
+ this._showCompletionListAfterCharacterTyped.Name = "_showCompletionListAfterCharacterTyped";
+ this._showCompletionListAfterCharacterTyped.UseVisualStyleBackColor = true;
+ //
+ // NodejsIntellisenseOptionsControl
+ //
+ resources.ApplyResources(this, "$this");
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.tableLayoutPanel1);
+ this.Name = "NodejsIntellisenseOptionsControl";
+ intellisenseLevelGroupBox.ResumeLayout(false);
+ intellisenseLevelGroupBox.PerformLayout();
+ this.tableLayoutPanel2.ResumeLayout(false);
+ this.tableLayoutPanel2.PerformLayout();
+ saveToDiskGroupBox.ResumeLayout(false);
+ saveToDiskGroupBox.PerformLayout();
+ this.tableLayoutPanel4.ResumeLayout(false);
+ this.tableLayoutPanel4.PerformLayout();
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.tableLayoutPanel1.PerformLayout();
+ this._selectionInCompletionListGroupBox.ResumeLayout(false);
+ this._selectionInCompletionListGroupBox.PerformLayout();
+ this.tableLayoutPanel3.ResumeLayout(false);
+ this.tableLayoutPanel3.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.GroupBox _selectionInCompletionListGroupBox;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
+ private System.Windows.Forms.RadioButton _saveToDiskDisabledRadioButton;
+ private System.Windows.Forms.RadioButton _saveToDiskEnabledRadioButton;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
+ private System.Windows.Forms.RadioButton _previewIntelliSenseRadioButton;
+ private System.Windows.Forms.RadioButton _mediumIntelliSenseRadioButton;
+ private System.Windows.Forms.ComboBox _analysisLogMax;
+ private System.Windows.Forms.RadioButton _noIntelliSenseRadioButton;
+ private System.Windows.Forms.Label _analysisLogMaxLabel;
+ private System.Windows.Forms.RadioButton _fullIntelliSenseRadioButton;
+ private System.Windows.Forms.LinkLabel _analysisPreviewFeedbackLinkLabel;
+ private System.Windows.Forms.CheckBox _onlyTabOrEnterToCommit;
+ private System.Windows.Forms.CheckBox _showCompletionListAfterCharacterTyped;
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.cs b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.cs
index 4b50a5ac6..15c0ff244 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsControl.cs
@@ -22,7 +22,7 @@
namespace Microsoft.NodejsTools.Options {
public partial class NodejsIntellisenseOptionsControl : UserControl {
public NodejsIntellisenseOptionsControl() {
- InitializeComponent();
+ InitializeComponent();
_previewIntelliSenseRadioButton.Enabled = NodejsPackage.Instance.IntellisenseOptionsPage.EnableES6Preview;
}
@@ -40,9 +40,9 @@ internal bool SaveToDisk {
}
internal AnalysisLevel AnalysisLevel {
- get {
- if (_previewIntelliSenseRadioButton.Checked) {
- return AnalysisLevel.Preview;
+ get {
+ if (_previewIntelliSenseRadioButton.Checked) {
+ return AnalysisLevel.Preview;
} else if (_fullIntelliSenseRadioButton.Checked) {
return AnalysisLevel.High;
} else if (_mediumIntelliSenseRadioButton.Checked) {
@@ -52,9 +52,9 @@ internal AnalysisLevel AnalysisLevel {
}
}
set {
- switch (value) {
- case AnalysisLevel.Preview:
- _previewIntelliSenseRadioButton.Checked = true;
+ switch (value) {
+ case AnalysisLevel.Preview:
+ _previewIntelliSenseRadioButton.Checked = true;
break;
case AnalysisLevel.High:
_fullIntelliSenseRadioButton.Checked = true;
@@ -102,42 +102,42 @@ internal int AnalysisLogMaximum {
}
}
- internal bool OnlyTabOrEnterToCommit {
- get {
- return _onlyTabOrEnterToCommit.Checked;
- }
- set {
- _onlyTabOrEnterToCommit.Checked = value;
- }
+ internal bool OnlyTabOrEnterToCommit {
+ get {
+ return _onlyTabOrEnterToCommit.Checked;
+ }
+ set {
+ _onlyTabOrEnterToCommit.Checked = value;
+ }
}
- internal bool ShowCompletionListAfterCharacterTyped {
- get {
- return _showCompletionListAfterCharacterTyped.Checked;
- }
- set {
- _showCompletionListAfterCharacterTyped.Checked = value;
- }
+ internal bool ShowCompletionListAfterCharacterTyped {
+ get {
+ return _showCompletionListAfterCharacterTyped.Checked;
+ }
+ set {
+ _showCompletionListAfterCharacterTyped.Checked = value;
+ }
}
internal void SyncPageWithControlSettings(NodejsIntellisenseOptionsPage page) {
page.AnalysisLevel = AnalysisLevel;
page.AnalysisLogMax = AnalysisLogMaximum;
- page.SaveToDisk = SaveToDisk;
+ page.SaveToDisk = SaveToDisk;
page.OnlyTabOrEnterToCommit = OnlyTabOrEnterToCommit;
page.ShowCompletionListAfterCharacterTyped = ShowCompletionListAfterCharacterTyped;
}
internal void SyncControlWithPageSettings(NodejsIntellisenseOptionsPage page) {
AnalysisLevel = page.AnalysisLevel;
- AnalysisLogMaximum = page.AnalysisLogMax;
+ AnalysisLogMaximum = page.AnalysisLogMax;
SaveToDisk = page.SaveToDisk;
OnlyTabOrEnterToCommit = page.OnlyTabOrEnterToCommit;
ShowCompletionListAfterCharacterTyped = page.ShowCompletionListAfterCharacterTyped;
- }
-
- private void _analysisPreviewFeedbackLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
- Process.Start("http://aka.ms/NtvsEs6Preview");
+ }
+
+ private void _analysisPreviewFeedbackLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+ Process.Start("http://aka.ms/NtvsEs6Preview");
}
}
}
diff --git a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsPage.cs b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsPage.cs
index 31dab60bf..91e4c2b54 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsPage.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsIntellisenseOptionsPage.cs
@@ -12,15 +12,15 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
-//*********************************************************//
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-using Microsoft.VisualStudio.Shell.Interop;
+//*********************************************************//
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
+using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudioTools;
namespace Microsoft.NodejsTools.Options {
@@ -30,20 +30,20 @@ public class NodejsIntellisenseOptionsPage : NodejsDialogPage {
private AnalysisLevel _level;
private int _analysisLogMax;
private bool _saveToDisk;
- private bool _onlyTabOrEnterToCommit;
- private bool _showCompletionListAfterCharacterTyped;
- private string _toolsVersion;
- private readonly bool _enableES6Preview;
+ private bool _onlyTabOrEnterToCommit;
+ private bool _showCompletionListAfterCharacterTyped;
+ private string _toolsVersion;
+ private readonly bool _enableES6Preview;
private readonly Version _typeScriptMinVersionForES6Preview = new Version("1.6");
public NodejsIntellisenseOptionsPage()
- : base("IntelliSense") {
- Version version;
- var versionString = GetTypeScriptToolsVersion();
- if (!string.IsNullOrEmpty(versionString) &&
- Version.TryParse(versionString, out version) &&
- version.CompareTo(_typeScriptMinVersionForES6Preview) > -1) {
- _enableES6Preview = true;
+ : base("IntelliSense") {
+ Version version;
+ var versionString = GetTypeScriptToolsVersion();
+ if (!string.IsNullOrEmpty(versionString) &&
+ Version.TryParse(versionString, out version) &&
+ version.CompareTo(_typeScriptMinVersionForES6Preview) > -1) {
+ _enableES6Preview = true;
}
}
@@ -56,8 +56,8 @@ protected override System.Windows.Forms.IWin32Window Window {
}
return _window;
}
- }
-
+ }
+
internal bool EnableES6Preview { get { return _enableES6Preview; } }
internal bool SaveToDisk {
@@ -80,11 +80,11 @@ internal AnalysisLevel AnalysisLevel {
}
set {
var oldLevel = _level;
- _level = value;
-
- // Fallback to full intellisense (High) if the ES6 intellisense preview isn't enabled
- if (_level == AnalysisLevel.Preview && !_enableES6Preview) {
- _level = AnalysisLevel.High;
+ _level = value;
+
+ // Fallback to full intellisense (High) if the ES6 intellisense preview isn't enabled
+ if (_level == AnalysisLevel.Preview && !_enableES6Preview) {
+ _level = AnalysisLevel.High;
}
if (oldLevel != _level) {
@@ -112,11 +112,11 @@ internal int AnalysisLogMax {
}
}
- internal bool OnlyTabOrEnterToCommit {
- get {
- return _onlyTabOrEnterToCommit;
- }
- set {
+ internal bool OnlyTabOrEnterToCommit {
+ get {
+ return _onlyTabOrEnterToCommit;
+ }
+ set {
var oldSetting = _onlyTabOrEnterToCommit;
_onlyTabOrEnterToCommit = value;
if (oldSetting != _onlyTabOrEnterToCommit) {
@@ -124,30 +124,30 @@ internal bool OnlyTabOrEnterToCommit {
if (changed != null) {
changed(this, EventArgs.Empty);
}
- }
- }
+ }
+ }
}
- internal bool ShowCompletionListAfterCharacterTyped {
- get {
- return _showCompletionListAfterCharacterTyped;
- }
- set {
- var oldSetting = _showCompletionListAfterCharacterTyped;
- _showCompletionListAfterCharacterTyped = value;
+ internal bool ShowCompletionListAfterCharacterTyped {
+ get {
+ return _showCompletionListAfterCharacterTyped;
+ }
+ set {
+ var oldSetting = _showCompletionListAfterCharacterTyped;
+ _showCompletionListAfterCharacterTyped = value;
if (oldSetting != _showCompletionListAfterCharacterTyped) {
var changed = ShowCompletionListAfterCharacterTypedChanged;
if (changed != null) {
changed(this, EventArgs.Empty);
}
- }
- }
+ }
+ }
}
public event EventHandler AnalysisLevelChanged;
- public event EventHandler AnalysisLogMaximumChanged;
- public event EventHandler SaveToDiskChanged;
- public event EventHandler OnlyTabOrEnterToCommitChanged;
+ public event EventHandler AnalysisLogMaximumChanged;
+ public event EventHandler SaveToDiskChanged;
+ public event EventHandler OnlyTabOrEnterToCommitChanged;
public event EventHandler ShowCompletionListAfterCharacterTypedChanged;
///
@@ -162,7 +162,7 @@ public override void ResetSettings() {
private const string AnalysisLevelSetting = "AnalysisLevel";
private const string AnalysisLogMaximumSetting = "AnalysisLogMaximum";
- private const string SaveToDiskSetting = "SaveToDisk";
+ private const string SaveToDiskSetting = "SaveToDisk";
private const string OnlyTabOrEnterToCommitSetting = "OnlyTabOrEnterToCommit";
private const string ShowCompletionListAfterCharacterTypedSetting = "ShowCompletionListAfterCharacterTyped";
@@ -177,11 +177,11 @@ public override void LoadSettingsFromStorage() {
// Synchronize UI with backing properties.
if (_window != null) {
_window.SyncControlWithPageSettings(this);
- }
-
- // Settings values can change after loading them from storage as there
- // are conditions which could make them fallback to default values.
- // Save the final settings back to storage.
+ }
+
+ // Settings values can change after loading them from storage as there
+ // are conditions which could make them fallback to default values.
+ // Save the final settings back to storage.
SaveSettingsToStorage();
}
@@ -194,49 +194,49 @@ public override void SaveSettingsToStorage() {
// Save settings.
SaveEnum(AnalysisLevelSetting, AnalysisLevel);
SaveInt(AnalysisLogMaximumSetting, AnalysisLogMax);
- SaveBool(SaveToDiskSetting, SaveToDisk);
+ SaveBool(SaveToDiskSetting, SaveToDisk);
SaveBool(OnlyTabOrEnterToCommitSetting, OnlyTabOrEnterToCommit);
SaveBool(ShowCompletionListAfterCharacterTypedSetting, ShowCompletionListAfterCharacterTyped);
- }
-
- private string GetTypeScriptToolsVersion() {
- if (_toolsVersion == null) {
- _toolsVersion = string.Empty;
- try {
- object installDirAsObject = null;
- var shell = NodejsPackage.Instance.GetService(typeof(SVsShell)) as IVsShell;
- if (shell != null) {
- shell.GetProperty((int)__VSSPROPID.VSSPROPID_InstallDirectory, out installDirAsObject);
- }
-
- var idePath = CommonUtils.NormalizeDirectoryPath((string)installDirAsObject) ?? string.Empty;
- if (string.IsNullOrEmpty(idePath)) {
- return _toolsVersion;
- }
-
- var typeScriptServicesPath = Path.Combine(idePath, @"CommonExtensions\Microsoft\TypeScript\typescriptServices.js");
- if (!File.Exists(typeScriptServicesPath)) {
- return _toolsVersion;
- }
-
- var regex = new Regex(@"toolsVersion = ""(?\d.\d?)"";");
- var fileText = File.ReadAllText(typeScriptServicesPath);
- var match = regex.Match(fileText);
-
- var version = match.Groups["version"].Value;
- if (!string.IsNullOrWhiteSpace(version)) {
- _toolsVersion = version;
- }
- } catch (Exception ex) {
- if (ex.IsCriticalException()) {
- throw;
- }
-
- Debug.WriteLine(string.Format("Failed to obtain TypeScript tools version: {0}", ex.ToString()));
- }
- }
-
- return _toolsVersion;
+ }
+
+ private string GetTypeScriptToolsVersion() {
+ if (_toolsVersion == null) {
+ _toolsVersion = string.Empty;
+ try {
+ object installDirAsObject = null;
+ var shell = NodejsPackage.Instance.GetService(typeof(SVsShell)) as IVsShell;
+ if (shell != null) {
+ shell.GetProperty((int)__VSSPROPID.VSSPROPID_InstallDirectory, out installDirAsObject);
+ }
+
+ var idePath = CommonUtils.NormalizeDirectoryPath((string)installDirAsObject) ?? string.Empty;
+ if (string.IsNullOrEmpty(idePath)) {
+ return _toolsVersion;
+ }
+
+ var typeScriptServicesPath = Path.Combine(idePath, @"CommonExtensions\Microsoft\TypeScript\typescriptServices.js");
+ if (!File.Exists(typeScriptServicesPath)) {
+ return _toolsVersion;
+ }
+
+ var regex = new Regex(@"toolsVersion = ""(?\d.\d?)"";");
+ var fileText = File.ReadAllText(typeScriptServicesPath);
+ var match = regex.Match(fileText);
+
+ var version = match.Groups["version"].Value;
+ if (!string.IsNullOrWhiteSpace(version)) {
+ _toolsVersion = version;
+ }
+ } catch (Exception ex) {
+ if (ex.IsCriticalException()) {
+ throw;
+ }
+
+ Debug.WriteLine(string.Format("Failed to obtain TypeScript tools version: {0}", ex.ToString()));
+ }
+ }
+
+ return _toolsVersion;
}
}
}
diff --git a/Nodejs/Product/Nodejs/PkgCmdId.cs b/Nodejs/Product/Nodejs/PkgCmdId.cs
index 88af9b2be..d87808e3b 100644
--- a/Nodejs/Product/Nodejs/PkgCmdId.cs
+++ b/Nodejs/Product/Nodejs/PkgCmdId.cs
@@ -1,49 +1,49 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Microsoft.NodejsTools {
- class PkgCmdId {
- public const int cmdidReplWindow = 0x200;
- public const int cmdidOpenReplWindow = 0x201;
- public const int cmdidOpenRemoteDebugProxyFolder = 0x202;
- public const int cmdidSetAsNodejsStartupFile = 0x203;
-
- public const int cmdidSurveyNews = 0x204;
- public const int cmdidImportWizard = 0x205;
- public const int cmdidOpenRemoteDebugDocumentation = 0x206;
-
- public const uint cmdidAzureExplorerAttachNodejsDebugger = 0x207;
-
- public const int cmdidDiagnostics = 0x208;
- public const int cmdidSetAsContent = 0x209;
- public const int cmdidSetAsCompile = 0x210;
-
- public const int cmdidNpmManageModules = 0x300;
- public const int cmdidNpmInstallModules = 0x301;
- public const int cmdidNpmUpdateModules = 0x302;
- public const int cmdidNpmUninstallModule = 0x303;
- public const int cmdidNpmInstallSingleMissingModule = 0x304;
- public const int cmdidNpmUpdateSingleModule = 0x305;
- public const int cmdidNpmOpenModuleHomepage = 0x306;
- public const int menuIdNpm = 0x3000;
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.NodejsTools {
+ class PkgCmdId {
+ public const int cmdidReplWindow = 0x200;
+ public const int cmdidOpenReplWindow = 0x201;
+ public const int cmdidOpenRemoteDebugProxyFolder = 0x202;
+ public const int cmdidSetAsNodejsStartupFile = 0x203;
+
+ public const int cmdidSurveyNews = 0x204;
+ public const int cmdidImportWizard = 0x205;
+ public const int cmdidOpenRemoteDebugDocumentation = 0x206;
+
+ public const uint cmdidAzureExplorerAttachNodejsDebugger = 0x207;
+
+ public const int cmdidDiagnostics = 0x208;
+ public const int cmdidSetAsContent = 0x209;
+ public const int cmdidSetAsCompile = 0x210;
+
+ public const int cmdidNpmManageModules = 0x300;
+ public const int cmdidNpmInstallModules = 0x301;
+ public const int cmdidNpmUpdateModules = 0x302;
+ public const int cmdidNpmUninstallModule = 0x303;
+ public const int cmdidNpmInstallSingleMissingModule = 0x304;
+ public const int cmdidNpmUpdateSingleModule = 0x305;
+ public const int cmdidNpmOpenModuleHomepage = 0x306;
+ public const int menuIdNpm = 0x3000;
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/AbstractNpmNode.cs b/Nodejs/Product/Nodejs/Project/AbstractNpmNode.cs
index f93831817..07f07f2c0 100644
--- a/Nodejs/Product/Nodejs/Project/AbstractNpmNode.cs
+++ b/Nodejs/Product/Nodejs/Project/AbstractNpmNode.cs
@@ -1,129 +1,129 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudioTools.Project;
-#if DEV14_OR_LATER
-using Microsoft.VisualStudio.Imaging.Interop;
-using Microsoft.VisualStudio.Imaging;
-#endif
-
-namespace Microsoft.NodejsTools.Project {
- internal abstract class AbstractNpmNode : HierarchyNode {
- protected readonly NodejsProjectNode _projectNode;
-
- protected AbstractNpmNode(NodejsProjectNode root)
- : base(root) {
- _projectNode = root;
- ExcludeNodeFromScc = true;
- }
-
- #region HierarchyNode implementation
-
- public override Guid ItemTypeGuid {
- get { return VSConstants.GUID_ItemType_VirtualFolder; }
- }
-
- public override Guid MenuGroupId {
- get { return Guids.NodejsNpmCmdSet; }
- }
-
- public override int MenuCommandId {
- get { return PkgCmdId.menuIdNpm; }
- }
-
- ///
- /// Disable inline editing of Caption.
- ///
- public sealed override string GetEditLabel() {
- return null;
- }
-#if DEV14_OR_LATER
- protected override bool SupportsIconMonikers {
- get { return true; }
- }
-
- ///
- /// Returns the icon to use.
- ///
- protected override ImageMoniker GetIconMoniker(bool open) {
- return KnownMonikers.Reference;
- }
-#else
- public sealed override object GetIconHandle(bool open) {
- //We don't want the icon to become an expanded folder 'OpenReferenceFolder'
- // Thus we always return 'ReferenceFolder'
- return ProjectMgr.GetIconHandleByName(ProjectNode.ImageName.ReferenceFolder);
- }
-#endif
-
- protected override NodeProperties CreatePropertiesObject() {
- return new NpmNodeProperties(this);
- }
-#endregion
-
- public abstract void ManageNpmModules();
-
- protected void ReloadHierarchy(HierarchyNode parent, IEnumerable modules) {
- // We're going to reuse nodes for which matching modules exist in the new set.
- // The reason for this is that we want to preserve the expansion state of the
- // hierarchy. If we just bin everything off and recreate it all from scratch
- // it'll all be in the collapsed state, which will be annoying for users who
- // have drilled down into the hierarchy
- var recycle = new Dictionary();
- var remove = new List();
- for (var current = parent.FirstChild; null != current; current = current.NextSibling) {
- var dep = current as DependencyNode;
- if (null == dep) {
- if (!(current is GlobalModulesNode) && !(current is LocalModulesNode)) {
- remove.Add(current);
- }
- continue;
- }
-
- if (modules != null && modules.Any(
- module =>
- module.Name == dep.Package.Name
- && module.Version == dep.Package.Version
- && module.IsBundledDependency == dep.Package.IsBundledDependency
- && module.IsDevDependency == dep.Package.IsDevDependency
- && module.IsListedInParentPackageJson == dep.Package.IsListedInParentPackageJson
- && module.IsMissing == dep.Package.IsMissing
- && module.IsOptionalDependency == dep.Package.IsOptionalDependency)) {
- recycle[dep.Package.Name] = dep;
- } else {
- remove.Add(current);
- }
- }
-
- foreach (var obsolete in remove) {
- parent.RemoveChild(obsolete);
- ProjectMgr.OnItemDeleted(obsolete);
- }
-
- if (modules != null) {
- foreach (var package in modules) {
- DependencyNode child;
-
- if (recycle.ContainsKey(package.Name)) {
- child = recycle[package.Name];
- child.Package = package;
- }
- else {
- child = new DependencyNode(_projectNode, parent as DependencyNode, package);
- parent.AddChild(child);
- }
-
- ReloadHierarchy(child, package.Modules);
- if (ProjectMgr.ParentHierarchy != null) {
- child.ExpandItem(EXPANDFLAGS.EXPF_CollapseFolder);
- }
- }
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudioTools.Project;
+#if DEV14_OR_LATER
+using Microsoft.VisualStudio.Imaging.Interop;
+using Microsoft.VisualStudio.Imaging;
+#endif
+
+namespace Microsoft.NodejsTools.Project {
+ internal abstract class AbstractNpmNode : HierarchyNode {
+ protected readonly NodejsProjectNode _projectNode;
+
+ protected AbstractNpmNode(NodejsProjectNode root)
+ : base(root) {
+ _projectNode = root;
+ ExcludeNodeFromScc = true;
+ }
+
+ #region HierarchyNode implementation
+
+ public override Guid ItemTypeGuid {
+ get { return VSConstants.GUID_ItemType_VirtualFolder; }
+ }
+
+ public override Guid MenuGroupId {
+ get { return Guids.NodejsNpmCmdSet; }
+ }
+
+ public override int MenuCommandId {
+ get { return PkgCmdId.menuIdNpm; }
+ }
+
+ ///
+ /// Disable inline editing of Caption.
+ ///
+ public sealed override string GetEditLabel() {
+ return null;
+ }
+#if DEV14_OR_LATER
+ protected override bool SupportsIconMonikers {
+ get { return true; }
+ }
+
+ ///
+ /// Returns the icon to use.
+ ///
+ protected override ImageMoniker GetIconMoniker(bool open) {
+ return KnownMonikers.Reference;
+ }
+#else
+ public sealed override object GetIconHandle(bool open) {
+ //We don't want the icon to become an expanded folder 'OpenReferenceFolder'
+ // Thus we always return 'ReferenceFolder'
+ return ProjectMgr.GetIconHandleByName(ProjectNode.ImageName.ReferenceFolder);
+ }
+#endif
+
+ protected override NodeProperties CreatePropertiesObject() {
+ return new NpmNodeProperties(this);
+ }
+#endregion
+
+ public abstract void ManageNpmModules();
+
+ protected void ReloadHierarchy(HierarchyNode parent, IEnumerable modules) {
+ // We're going to reuse nodes for which matching modules exist in the new set.
+ // The reason for this is that we want to preserve the expansion state of the
+ // hierarchy. If we just bin everything off and recreate it all from scratch
+ // it'll all be in the collapsed state, which will be annoying for users who
+ // have drilled down into the hierarchy
+ var recycle = new Dictionary();
+ var remove = new List();
+ for (var current = parent.FirstChild; null != current; current = current.NextSibling) {
+ var dep = current as DependencyNode;
+ if (null == dep) {
+ if (!(current is GlobalModulesNode) && !(current is LocalModulesNode)) {
+ remove.Add(current);
+ }
+ continue;
+ }
+
+ if (modules != null && modules.Any(
+ module =>
+ module.Name == dep.Package.Name
+ && module.Version == dep.Package.Version
+ && module.IsBundledDependency == dep.Package.IsBundledDependency
+ && module.IsDevDependency == dep.Package.IsDevDependency
+ && module.IsListedInParentPackageJson == dep.Package.IsListedInParentPackageJson
+ && module.IsMissing == dep.Package.IsMissing
+ && module.IsOptionalDependency == dep.Package.IsOptionalDependency)) {
+ recycle[dep.Package.Name] = dep;
+ } else {
+ remove.Add(current);
+ }
+ }
+
+ foreach (var obsolete in remove) {
+ parent.RemoveChild(obsolete);
+ ProjectMgr.OnItemDeleted(obsolete);
+ }
+
+ if (modules != null) {
+ foreach (var package in modules) {
+ DependencyNode child;
+
+ if (recycle.ContainsKey(package.Name)) {
+ child = recycle[package.Name];
+ child.Package = package;
+ }
+ else {
+ child = new DependencyNode(_projectNode, parent as DependencyNode, package);
+ parent.AddChild(child);
+ }
+
+ ReloadHierarchy(child, package.Modules);
+ if (ProjectMgr.ParentHierarchy != null) {
+ child.ExpandItem(EXPANDFLAGS.EXPF_CollapseFolder);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/Attributes.cs b/Nodejs/Product/Nodejs/Project/Attributes.cs
index d23988227..0afe08354 100644
--- a/Nodejs/Product/Nodejs/Project/Attributes.cs
+++ b/Nodejs/Product/Nodejs/Project/Attributes.cs
@@ -1,65 +1,65 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.ComponentModel;
-
-namespace Microsoft.NodejsTools.Project {
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
- internal sealed class SRDisplayNameAttribute : DisplayNameAttribute {
- string _name;
-
- public SRDisplayNameAttribute(string name) {
- _name = name;
- }
-
- public override string DisplayName {
- get {
- return SR.GetString(_name);
- }
- }
- }
-
- [AttributeUsage(AttributeTargets.All)]
- internal sealed class SRDescriptionAttribute : DescriptionAttribute {
- private bool _replaced;
-
- public SRDescriptionAttribute(string description)
- : base(description) {
- }
-
- public override string Description {
- get {
- if (!_replaced) {
- _replaced = true;
- DescriptionValue = SR.GetString(base.Description);
- }
- return base.Description;
- }
- }
- }
-
- [AttributeUsage(AttributeTargets.All)]
- internal sealed class SRCategoryAttribute : CategoryAttribute {
- public SRCategoryAttribute(string category)
- : base(category) {
- }
-
- protected override string GetLocalizedString(string value) {
- return SR.GetString(value);
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.ComponentModel;
+
+namespace Microsoft.NodejsTools.Project {
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+ internal sealed class SRDisplayNameAttribute : DisplayNameAttribute {
+ string _name;
+
+ public SRDisplayNameAttribute(string name) {
+ _name = name;
+ }
+
+ public override string DisplayName {
+ get {
+ return SR.GetString(_name);
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.All)]
+ internal sealed class SRDescriptionAttribute : DescriptionAttribute {
+ private bool _replaced;
+
+ public SRDescriptionAttribute(string description)
+ : base(description) {
+ }
+
+ public override string Description {
+ get {
+ if (!_replaced) {
+ _replaced = true;
+ DescriptionValue = SR.GetString(base.Description);
+ }
+ return base.Description;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.All)]
+ internal sealed class SRCategoryAttribute : CategoryAttribute {
+ public SRCategoryAttribute(string category)
+ : base(category) {
+ }
+
+ protected override string GetLocalizedString(string value) {
+ return SR.GetString(value);
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/DependencyNode.cs b/Nodejs/Product/Nodejs/Project/DependencyNode.cs
index 20dfbfa35..6ce8dc3bc 100644
--- a/Nodejs/Product/Nodejs/Project/DependencyNode.cs
+++ b/Nodejs/Product/Nodejs/Project/DependencyNode.cs
@@ -1,286 +1,286 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Text;
-using System.Windows.Forms;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
-
-namespace Microsoft.NodejsTools.Project {
- internal class DependencyNode : HierarchyNode {
- private readonly NodejsProjectNode _projectNode;
- private readonly DependencyNode _parent;
- private readonly string _displayString;
-
- public DependencyNode(
- NodejsProjectNode root,
- DependencyNode parent,
- IPackage package)
- : base(root) {
- _projectNode = root;
- _parent = parent;
- Package = package;
-
- var buff = new StringBuilder(package.Name);
- if (package.IsMissing) {
- buff.Append(" (missing)");
- } else {
- buff.Append('@');
- buff.Append(package.Version);
-
- if (!package.IsListedInParentPackageJson) {
- buff.AppendFormat(" (not listed in {0})", NodejsConstants.PackageJsonFile);
- } else {
- List dependencyTypes = new List(3);
- if (package.IsDependency) {
- dependencyTypes.Add("standard");
- }
- if (package.IsDevDependency) {
- dependencyTypes.Add("dev");
- }
- if (package.IsOptionalDependency) {
- dependencyTypes.Add("optional");
- }
-
- if (package.IsDevDependency || package.IsOptionalDependency) {
- buff.Append(" (");
- buff.Append(string.Join(", ", dependencyTypes.ToArray()));
- buff.Append(")");
- }
- }
- }
-
- if (package.IsBundledDependency) {
- buff.Append("[bundled]");
- }
-
- _displayString = buff.ToString();
- ExcludeNodeFromScc = true;
- }
-
- public IPackage Package { get; internal set; }
-
- internal INpmController NpmController {
- get {
- if (null != _projectNode) {
- var modulesNode = _projectNode.ModulesNode;
- if (null != modulesNode) {
- return modulesNode.NpmController;
- }
- }
- return null;
- }
- }
-
- #region HierarchyNode implementation
-
- private string GetRelativeUrlFragment() {
- var buff = new StringBuilder();
- if (null != _parent) {
- buff.Append(_parent.GetRelativeUrlFragment());
- buff.Append('/');
- }
- buff.Append("node_modules/");
- buff.Append(Package.Name);
- return buff.ToString();
- }
-
- public override string Url {
- get { return new Url(ProjectMgr.BaseURI, GetRelativeUrlFragment()).AbsoluteUrl; }
- }
-
- public override string Caption {
- get { return _displayString; }
- }
-
- public override Guid ItemTypeGuid {
- get { return VSConstants.GUID_ItemType_VirtualFolder; }
- }
-
- public override Guid MenuGroupId {
- get { return Guids.NodejsNpmCmdSet; }
- }
-
- public override int MenuCommandId {
- get { return PkgCmdId.menuIdNpm; }
- }
-
-#if DEV14_OR_LATER
- [Obsolete]
-#endif
- public override object GetIconHandle(bool open) {
- int imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.Dependency];
- if (Package.IsMissing) {
- imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.DependencyMissing];
- } else {
- if (!Package.IsListedInParentPackageJson) {
- imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.DependencyNotListed];
- } else {
- imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.Dependency];
- }
- }
-
- return _projectNode.ImageHandler.GetIconHandle(imageIndex);
- }
-
- public override string GetEditLabel() {
- return null;
- }
-
- protected override NodeProperties CreatePropertiesObject() {
- return new DependencyNodeProperties(this);
- }
-
- internal DependencyNodeProperties GetPropertiesObject() {
- return CreatePropertiesObject() as DependencyNodeProperties;
- }
-
-#endregion
-
-#region Command handling
-
- internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
- // Latter condition is because it's only valid to carry out npm operations
- // on top level dependencies of the user's project, not sub-dependencies.
- // Performing operations on sub-dependencies would just break things.
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmOpenModuleHomepage:
- if (this.Package.Homepages != null) {
- using (var enumerator = this.Package.Homepages.GetEnumerator()) {
- if (enumerator.MoveNext() && !string.IsNullOrEmpty(enumerator.Current)) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- }
- }
- return VSConstants.S_OK;
- }
-
- if (null == _parent) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmInstallSingleMissingModule:
- if (GetPropertiesObject().IsGlobalInstall) {
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
- } else if (null == _projectNode.ModulesNode
- || _projectNode.ModulesNode.IsCurrentStateASuppressCommandsMode()) {
- result = QueryStatusResult.SUPPORTED;
- } else {
- if (null != Package && Package.IsMissing) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmUpdateSingleModule:
- case PkgCmdId.cmdidNpmUninstallModule:
- if (null != _projectNode.ModulesNode &&
- !_projectNode.ModulesNode.IsCurrentStateASuppressCommandsMode()) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmInstallModules:
- case PkgCmdId.cmdidNpmUpdateModules:
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
- return VSConstants.S_OK;
- }
- }
- } else if (cmdGroup == Microsoft.VisualStudioTools.Project.VsMenus.guidStandardCommandSet2K) {
- switch ((VsCommands2K)cmd) {
- case CommonConstants.OpenFolderInExplorerCmdId:
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
- return VSConstants.S_OK;
- }
- }
-
- return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
- }
-
- internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmOpenModuleHomepage:
- if (this.Package.Homepages != null) {
- using (var enumerator = this.Package.Homepages.GetEnumerator()) {
- if (enumerator.MoveNext() && !string.IsNullOrEmpty(enumerator.Current)) {
- Process.Start(enumerator.Current);
- }
- }
- }
- return VSConstants.S_OK;
- }
- if (null == _parent) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmInstallSingleMissingModule:
- if (null != _projectNode.ModulesNode) {
- var t = _projectNode.ModulesNode.InstallMissingModule(this);
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmUninstallModule:
- if (null != _projectNode.ModulesNode) {
- var t = _projectNode.ModulesNode.UninstallModule(this);
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmUpdateSingleModule:
- if (null != _projectNode.ModulesNode) {
- var t = _projectNode.ModulesNode.UpdateModule(this);
- }
- return VSConstants.S_OK;
- }
- }
- } else if (cmdGroup == Microsoft.VisualStudioTools.Project.VsMenus.guidStandardCommandSet2K) {
- switch ((VsCommands2K)cmd) {
- case CommonConstants.OpenFolderInExplorerCmdId:
- string path = this.Package.Path;
- try {
- Process.Start(path);
- } catch (Exception ex) {
- if (ex is InvalidOperationException || ex is Win32Exception) {
- MessageBox.Show(
- String.Format("Path to module does not exist:\n {0}", path),
- SR.ProductName,
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- return VSConstants.S_FALSE;
- }
- throw;
- }
- return VSConstants.S_OK;
- }
- }
-
- return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
- }
-
-#endregion
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text;
+using System.Windows.Forms;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
+
+namespace Microsoft.NodejsTools.Project {
+ internal class DependencyNode : HierarchyNode {
+ private readonly NodejsProjectNode _projectNode;
+ private readonly DependencyNode _parent;
+ private readonly string _displayString;
+
+ public DependencyNode(
+ NodejsProjectNode root,
+ DependencyNode parent,
+ IPackage package)
+ : base(root) {
+ _projectNode = root;
+ _parent = parent;
+ Package = package;
+
+ var buff = new StringBuilder(package.Name);
+ if (package.IsMissing) {
+ buff.Append(" (missing)");
+ } else {
+ buff.Append('@');
+ buff.Append(package.Version);
+
+ if (!package.IsListedInParentPackageJson) {
+ buff.AppendFormat(" (not listed in {0})", NodejsConstants.PackageJsonFile);
+ } else {
+ List dependencyTypes = new List(3);
+ if (package.IsDependency) {
+ dependencyTypes.Add("standard");
+ }
+ if (package.IsDevDependency) {
+ dependencyTypes.Add("dev");
+ }
+ if (package.IsOptionalDependency) {
+ dependencyTypes.Add("optional");
+ }
+
+ if (package.IsDevDependency || package.IsOptionalDependency) {
+ buff.Append(" (");
+ buff.Append(string.Join(", ", dependencyTypes.ToArray()));
+ buff.Append(")");
+ }
+ }
+ }
+
+ if (package.IsBundledDependency) {
+ buff.Append("[bundled]");
+ }
+
+ _displayString = buff.ToString();
+ ExcludeNodeFromScc = true;
+ }
+
+ public IPackage Package { get; internal set; }
+
+ internal INpmController NpmController {
+ get {
+ if (null != _projectNode) {
+ var modulesNode = _projectNode.ModulesNode;
+ if (null != modulesNode) {
+ return modulesNode.NpmController;
+ }
+ }
+ return null;
+ }
+ }
+
+ #region HierarchyNode implementation
+
+ private string GetRelativeUrlFragment() {
+ var buff = new StringBuilder();
+ if (null != _parent) {
+ buff.Append(_parent.GetRelativeUrlFragment());
+ buff.Append('/');
+ }
+ buff.Append("node_modules/");
+ buff.Append(Package.Name);
+ return buff.ToString();
+ }
+
+ public override string Url {
+ get { return new Url(ProjectMgr.BaseURI, GetRelativeUrlFragment()).AbsoluteUrl; }
+ }
+
+ public override string Caption {
+ get { return _displayString; }
+ }
+
+ public override Guid ItemTypeGuid {
+ get { return VSConstants.GUID_ItemType_VirtualFolder; }
+ }
+
+ public override Guid MenuGroupId {
+ get { return Guids.NodejsNpmCmdSet; }
+ }
+
+ public override int MenuCommandId {
+ get { return PkgCmdId.menuIdNpm; }
+ }
+
+#if DEV14_OR_LATER
+ [Obsolete]
+#endif
+ public override object GetIconHandle(bool open) {
+ int imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.Dependency];
+ if (Package.IsMissing) {
+ imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.DependencyMissing];
+ } else {
+ if (!Package.IsListedInParentPackageJson) {
+ imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.DependencyNotListed];
+ } else {
+ imageIndex = _projectNode.ImageIndexFromNameDictionary[NodejsProjectImageName.Dependency];
+ }
+ }
+
+ return _projectNode.ImageHandler.GetIconHandle(imageIndex);
+ }
+
+ public override string GetEditLabel() {
+ return null;
+ }
+
+ protected override NodeProperties CreatePropertiesObject() {
+ return new DependencyNodeProperties(this);
+ }
+
+ internal DependencyNodeProperties GetPropertiesObject() {
+ return CreatePropertiesObject() as DependencyNodeProperties;
+ }
+
+#endregion
+
+#region Command handling
+
+ internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
+ // Latter condition is because it's only valid to carry out npm operations
+ // on top level dependencies of the user's project, not sub-dependencies.
+ // Performing operations on sub-dependencies would just break things.
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmOpenModuleHomepage:
+ if (this.Package.Homepages != null) {
+ using (var enumerator = this.Package.Homepages.GetEnumerator()) {
+ if (enumerator.MoveNext() && !string.IsNullOrEmpty(enumerator.Current)) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ }
+ }
+ return VSConstants.S_OK;
+ }
+
+ if (null == _parent) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmInstallSingleMissingModule:
+ if (GetPropertiesObject().IsGlobalInstall) {
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
+ } else if (null == _projectNode.ModulesNode
+ || _projectNode.ModulesNode.IsCurrentStateASuppressCommandsMode()) {
+ result = QueryStatusResult.SUPPORTED;
+ } else {
+ if (null != Package && Package.IsMissing) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmUpdateSingleModule:
+ case PkgCmdId.cmdidNpmUninstallModule:
+ if (null != _projectNode.ModulesNode &&
+ !_projectNode.ModulesNode.IsCurrentStateASuppressCommandsMode()) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmInstallModules:
+ case PkgCmdId.cmdidNpmUpdateModules:
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (cmdGroup == Microsoft.VisualStudioTools.Project.VsMenus.guidStandardCommandSet2K) {
+ switch ((VsCommands2K)cmd) {
+ case CommonConstants.OpenFolderInExplorerCmdId:
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
+ }
+
+ internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmOpenModuleHomepage:
+ if (this.Package.Homepages != null) {
+ using (var enumerator = this.Package.Homepages.GetEnumerator()) {
+ if (enumerator.MoveNext() && !string.IsNullOrEmpty(enumerator.Current)) {
+ Process.Start(enumerator.Current);
+ }
+ }
+ }
+ return VSConstants.S_OK;
+ }
+ if (null == _parent) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmInstallSingleMissingModule:
+ if (null != _projectNode.ModulesNode) {
+ var t = _projectNode.ModulesNode.InstallMissingModule(this);
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmUninstallModule:
+ if (null != _projectNode.ModulesNode) {
+ var t = _projectNode.ModulesNode.UninstallModule(this);
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmUpdateSingleModule:
+ if (null != _projectNode.ModulesNode) {
+ var t = _projectNode.ModulesNode.UpdateModule(this);
+ }
+ return VSConstants.S_OK;
+ }
+ }
+ } else if (cmdGroup == Microsoft.VisualStudioTools.Project.VsMenus.guidStandardCommandSet2K) {
+ switch ((VsCommands2K)cmd) {
+ case CommonConstants.OpenFolderInExplorerCmdId:
+ string path = this.Package.Path;
+ try {
+ Process.Start(path);
+ } catch (Exception ex) {
+ if (ex is InvalidOperationException || ex is Win32Exception) {
+ MessageBox.Show(
+ String.Format("Path to module does not exist:\n {0}", path),
+ SR.ProductName,
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ return VSConstants.S_FALSE;
+ }
+ throw;
+ }
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+#endregion
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Nodejs/Project/DependencyNodeProperties.cs b/Nodejs/Product/Nodejs/Project/DependencyNodeProperties.cs
index 8984a1377..030bc8754 100644
--- a/Nodejs/Product/Nodejs/Project/DependencyNodeProperties.cs
+++ b/Nodejs/Product/Nodejs/Project/DependencyNodeProperties.cs
@@ -1,274 +1,274 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System.Runtime.InteropServices;
-using System.Text;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.VisualStudioTools.Project;
-
-namespace Microsoft.NodejsTools.Project {
-
- [ComVisible(true)]
- [ClassInterface(ClassInterfaceType.AutoDual)]
- [Guid("CA6C9721-2F64-4A1F-99C9-C087F698CB34")]
- public class DependencyNodeProperties : NodeProperties {
- internal DependencyNodeProperties(DependencyNode node) : base(node) {}
-
- private DependencyNode DependencyNode { get { return Node as DependencyNode; } }
-
- private IPackage Package { get { return DependencyNode.Package; } }
-
- public override string GetClassName() {
- return SR.GetString(IsSubPackage
- ? (IsGlobalInstall ? SR.PropertiesClassGlobalSubPackage : SR.PropertiesClassLocalSubPackage)
- : (IsGlobalInstall ? SR.PropertiesClassGlobalPackage : SR.PropertiesClassLocalPackage)
- );
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageName)]
- [SRDescriptionAttribute(SR.NpmPackageNameDescription)]
- public string PackageName {
- get {
- return null == Package ? null : Package.Name;
- }
- }
-
- [SRCategoryAttribute(SR.CategoryVersion)]
- [SRDisplayName(SR.NpmPackageVersion)]
- [SRDescriptionAttribute(SR.NpmPackageVersionDescription)]
- public string PackageVersion {
- get {
- return null == Package ? null : Package.Version.ToString();
- }
- }
-
- [SRCategoryAttribute(SR.CategoryVersion)]
- [SRDisplayName(SR.NpmPackageRequestedVersionRange)]
- [SRDescriptionAttribute(SR.NpmPackageRequestedVersionRangeDescription)]
- public string RequestedVersionRange {
- get {
- var range = null == Package ? null : Package.RequestedVersionRange;
- return range ?? SR.GetString(SR.RequestedVersionRangeNone);
- }
- }
-
- private IPackageCatalog MostRecentlyLoadedCatalog {
- get {
- var controller = DependencyNode.NpmController;
- return null == controller ? null : controller.MostRecentlyLoadedCatalog;
- }
- }
-
- // TODO Retrieving the package information is currently too slow to include in properties pane.
- //[SRCategoryAttribute(SR.CategoryVersion)]
- //[SRDisplayName(SR.NpmPackageNewVersionAvailable)]
- //[SRDescriptionAttribute(SR.NpmPackageNewVersionAvailableDescription)]
- //public string NewVersionAvailable {
- // get {
- // if (IsSubPackage) {
- // return SR.GetString(SR.NewVersionNotApplicableSubpackage);
- // }
-
- // var package = Package;
- // var catalog = MostRecentlyLoadedCatalog;
- // if (null == catalog || null == package) {
- // return SR.GetString(SR.NewVersionUnknown);
- // }
-
- // var listed = catalog[package.Name];
- // if (null == listed) {
- // return SR.GetString(SR.NewVersionUnknown);
- // }
-
- // return listed.Version > package.Version
- // ? SR.GetString(SR.NewVersionYes, listed.Version)
- // : SR.GetString(SR.NewVersionNo);
- // }
- //}
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageDescription)]
- [SRDescriptionAttribute(SR.NpmPackageDescriptionDescription)]
- public string Description {
- get {
- return null == Package ? null : Package.Description;
- }
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageKeywords)]
- [SRDescriptionAttribute(SR.NpmPackageKeywordsDescription)]
- public string Keywords {
- get {
- if (null == Package) {
- return null;
- }
-
- var buff = new StringBuilder();
- foreach (var keyword in Package.Keywords) {
- if (buff.Length > 0) {
- buff.Append(", ");
- }
- buff.Append(keyword);
- }
- return buff.ToString();
- }
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageAuthor)]
- [SRDescriptionAttribute(SR.NpmPackageAuthorDescription)]
- public string Author {
- get {
- var author = null == Package ? null : Package.Author;
- return null == author ? null : author.ToString();
- }
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackagePath)]
- [SRDescriptionAttribute(SR.NpmPackagePathDescription)]
- public string Path {
- get {
- return null == Package ? null : Package.Path;
- }
- }
-
- internal bool IsGlobalInstall {
- get {
- var node = DependencyNode as HierarchyNode;
- while (null != node) {
- if (node is GlobalModulesNode) {
- return true;
- }
-
- node = node.Parent;
- }
- return false;
- }
- }
-
- internal bool IsSubPackage {
- get {
- var node = DependencyNode as HierarchyNode;
- if (null != node && node.Parent is DependencyNode) {
- return true;
- }
- return false;
- }
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageType)]
- [SRDescriptionAttribute(SR.NpmPackageTypeDescription)]
- public string PackageType {
- get {
- if (IsGlobalInstall) {
- return IsSubPackage
- ? SR.GetString(SR.PackageTypeGlobalSubpackage)
- : SR.GetString(SR.PackageTypeGlobal);
- }
-
- return IsSubPackage
- ? SR.GetString(SR.PackageTypeLocalSubpackage)
- : SR.GetString(SR.PackageTypeLocal);
- }
- }
-
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmPackageLinkStatus)]
- [SRDescriptionAttribute(SR.NpmPackageLinkStatusDescription)]
- public string LinkStatus {
- get {
- if (IsSubPackage) {
- return SR.GetString(SR.LinkStatusNotApplicableSubPackages);
- }
-
- var package = Package;
- var controller = DependencyNode.NpmController;
- if (null != controller && null != package) {
- if (IsGlobalInstall) {
- var root = controller.RootPackage;
- if (null != root) {
- var local = root.Modules[package.Name];
- return null == local || local.Version != package.Version
- ? SR.GetString(SR.LinkStatusNotLinkedToProject)
- : SR.GetString(SR.LinkStatusLinkedToProject);
- }
- } else {
- var global = controller.GlobalPackages;
- if (null != global) {
- var installed = global.Modules[package.Name];
- return null == installed || installed.Version != package.Version
- ? SR.GetString(SR.LinkStatusLocallyInstalled)
- : SR.GetString(SR.LinkStatusLinkedFromGlobal);
- }
- }
- }
-
- return SR.GetString(SR.LinkStatusUnknown);
- }
- }
-
- [SRCategoryAttribute(SR.CategoryStatus)]
- [SRDisplayName(SR.NpmPackageIsListedInParentPackageJson)]
- [SRDescriptionAttribute(SR.NpmPackageIsListedInParentPackageJsonDescription)]
- public bool IsListedInParentPackageJson {
- get {
- return null != Package && Package.IsListedInParentPackageJson;
- }
- }
-
- [SRCategoryAttribute(SR.CategoryStatus)]
- [SRDisplayName(SR.NpmPackageIsMissing)]
- [SRDescriptionAttribute(SR.NpmPackageIsMissingDescription)]
- public bool IsMissing {
- get {
- return null != Package && Package.IsMissing;
- }
- }
-
- [SRCategoryAttribute(SR.CategoryStatus)]
- [SRDisplayName(SR.NpmPackageIsDevDependency)]
- [SRDescriptionAttribute(SR.NpmPackageIsDevDependencyDescription)]
- public bool IsDevDependency {
- get {
- return null != Package && Package.IsDevDependency;
- }
- }
-
- [SRCategoryAttribute(SR.CategoryStatus)]
- [SRDisplayName(SR.NpmPackageIsOptionalDependency)]
- [SRDescriptionAttribute(SR.NpmPackageIsOptionalDependencyDescription)]
- public bool IsOptionalDependency {
- get {
- return null != Package && Package.IsOptionalDependency;
- }
- }
-
- [SRCategoryAttribute(SR.CategoryStatus)]
- [SRDisplayName(SR.NpmPackageIsBundledDependency)]
- [SRDescriptionAttribute(SR.NpmPackageIsBundledDependencyDescription)]
- public bool IsBundledDependency {
- get {
- return null != Package && Package.IsBundledDependency;
- }
- }
-
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.VisualStudioTools.Project;
+
+namespace Microsoft.NodejsTools.Project {
+
+ [ComVisible(true)]
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+ [Guid("CA6C9721-2F64-4A1F-99C9-C087F698CB34")]
+ public class DependencyNodeProperties : NodeProperties {
+ internal DependencyNodeProperties(DependencyNode node) : base(node) {}
+
+ private DependencyNode DependencyNode { get { return Node as DependencyNode; } }
+
+ private IPackage Package { get { return DependencyNode.Package; } }
+
+ public override string GetClassName() {
+ return SR.GetString(IsSubPackage
+ ? (IsGlobalInstall ? SR.PropertiesClassGlobalSubPackage : SR.PropertiesClassLocalSubPackage)
+ : (IsGlobalInstall ? SR.PropertiesClassGlobalPackage : SR.PropertiesClassLocalPackage)
+ );
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageName)]
+ [SRDescriptionAttribute(SR.NpmPackageNameDescription)]
+ public string PackageName {
+ get {
+ return null == Package ? null : Package.Name;
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryVersion)]
+ [SRDisplayName(SR.NpmPackageVersion)]
+ [SRDescriptionAttribute(SR.NpmPackageVersionDescription)]
+ public string PackageVersion {
+ get {
+ return null == Package ? null : Package.Version.ToString();
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryVersion)]
+ [SRDisplayName(SR.NpmPackageRequestedVersionRange)]
+ [SRDescriptionAttribute(SR.NpmPackageRequestedVersionRangeDescription)]
+ public string RequestedVersionRange {
+ get {
+ var range = null == Package ? null : Package.RequestedVersionRange;
+ return range ?? SR.GetString(SR.RequestedVersionRangeNone);
+ }
+ }
+
+ private IPackageCatalog MostRecentlyLoadedCatalog {
+ get {
+ var controller = DependencyNode.NpmController;
+ return null == controller ? null : controller.MostRecentlyLoadedCatalog;
+ }
+ }
+
+ // TODO Retrieving the package information is currently too slow to include in properties pane.
+ //[SRCategoryAttribute(SR.CategoryVersion)]
+ //[SRDisplayName(SR.NpmPackageNewVersionAvailable)]
+ //[SRDescriptionAttribute(SR.NpmPackageNewVersionAvailableDescription)]
+ //public string NewVersionAvailable {
+ // get {
+ // if (IsSubPackage) {
+ // return SR.GetString(SR.NewVersionNotApplicableSubpackage);
+ // }
+
+ // var package = Package;
+ // var catalog = MostRecentlyLoadedCatalog;
+ // if (null == catalog || null == package) {
+ // return SR.GetString(SR.NewVersionUnknown);
+ // }
+
+ // var listed = catalog[package.Name];
+ // if (null == listed) {
+ // return SR.GetString(SR.NewVersionUnknown);
+ // }
+
+ // return listed.Version > package.Version
+ // ? SR.GetString(SR.NewVersionYes, listed.Version)
+ // : SR.GetString(SR.NewVersionNo);
+ // }
+ //}
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageDescription)]
+ [SRDescriptionAttribute(SR.NpmPackageDescriptionDescription)]
+ public string Description {
+ get {
+ return null == Package ? null : Package.Description;
+ }
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageKeywords)]
+ [SRDescriptionAttribute(SR.NpmPackageKeywordsDescription)]
+ public string Keywords {
+ get {
+ if (null == Package) {
+ return null;
+ }
+
+ var buff = new StringBuilder();
+ foreach (var keyword in Package.Keywords) {
+ if (buff.Length > 0) {
+ buff.Append(", ");
+ }
+ buff.Append(keyword);
+ }
+ return buff.ToString();
+ }
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageAuthor)]
+ [SRDescriptionAttribute(SR.NpmPackageAuthorDescription)]
+ public string Author {
+ get {
+ var author = null == Package ? null : Package.Author;
+ return null == author ? null : author.ToString();
+ }
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackagePath)]
+ [SRDescriptionAttribute(SR.NpmPackagePathDescription)]
+ public string Path {
+ get {
+ return null == Package ? null : Package.Path;
+ }
+ }
+
+ internal bool IsGlobalInstall {
+ get {
+ var node = DependencyNode as HierarchyNode;
+ while (null != node) {
+ if (node is GlobalModulesNode) {
+ return true;
+ }
+
+ node = node.Parent;
+ }
+ return false;
+ }
+ }
+
+ internal bool IsSubPackage {
+ get {
+ var node = DependencyNode as HierarchyNode;
+ if (null != node && node.Parent is DependencyNode) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageType)]
+ [SRDescriptionAttribute(SR.NpmPackageTypeDescription)]
+ public string PackageType {
+ get {
+ if (IsGlobalInstall) {
+ return IsSubPackage
+ ? SR.GetString(SR.PackageTypeGlobalSubpackage)
+ : SR.GetString(SR.PackageTypeGlobal);
+ }
+
+ return IsSubPackage
+ ? SR.GetString(SR.PackageTypeLocalSubpackage)
+ : SR.GetString(SR.PackageTypeLocal);
+ }
+ }
+
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmPackageLinkStatus)]
+ [SRDescriptionAttribute(SR.NpmPackageLinkStatusDescription)]
+ public string LinkStatus {
+ get {
+ if (IsSubPackage) {
+ return SR.GetString(SR.LinkStatusNotApplicableSubPackages);
+ }
+
+ var package = Package;
+ var controller = DependencyNode.NpmController;
+ if (null != controller && null != package) {
+ if (IsGlobalInstall) {
+ var root = controller.RootPackage;
+ if (null != root) {
+ var local = root.Modules[package.Name];
+ return null == local || local.Version != package.Version
+ ? SR.GetString(SR.LinkStatusNotLinkedToProject)
+ : SR.GetString(SR.LinkStatusLinkedToProject);
+ }
+ } else {
+ var global = controller.GlobalPackages;
+ if (null != global) {
+ var installed = global.Modules[package.Name];
+ return null == installed || installed.Version != package.Version
+ ? SR.GetString(SR.LinkStatusLocallyInstalled)
+ : SR.GetString(SR.LinkStatusLinkedFromGlobal);
+ }
+ }
+ }
+
+ return SR.GetString(SR.LinkStatusUnknown);
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryStatus)]
+ [SRDisplayName(SR.NpmPackageIsListedInParentPackageJson)]
+ [SRDescriptionAttribute(SR.NpmPackageIsListedInParentPackageJsonDescription)]
+ public bool IsListedInParentPackageJson {
+ get {
+ return null != Package && Package.IsListedInParentPackageJson;
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryStatus)]
+ [SRDisplayName(SR.NpmPackageIsMissing)]
+ [SRDescriptionAttribute(SR.NpmPackageIsMissingDescription)]
+ public bool IsMissing {
+ get {
+ return null != Package && Package.IsMissing;
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryStatus)]
+ [SRDisplayName(SR.NpmPackageIsDevDependency)]
+ [SRDescriptionAttribute(SR.NpmPackageIsDevDependencyDescription)]
+ public bool IsDevDependency {
+ get {
+ return null != Package && Package.IsDevDependency;
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryStatus)]
+ [SRDisplayName(SR.NpmPackageIsOptionalDependency)]
+ [SRDescriptionAttribute(SR.NpmPackageIsOptionalDependencyDescription)]
+ public bool IsOptionalDependency {
+ get {
+ return null != Package && Package.IsOptionalDependency;
+ }
+ }
+
+ [SRCategoryAttribute(SR.CategoryStatus)]
+ [SRDisplayName(SR.NpmPackageIsBundledDependency)]
+ [SRDescriptionAttribute(SR.NpmPackageIsBundledDependencyDescription)]
+ public bool IsBundledDependency {
+ get {
+ return null != Package && Package.IsBundledDependency;
+ }
+ }
+
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/GlobalModulesNode.cs b/Nodejs/Product/Nodejs/Project/GlobalModulesNode.cs
index 64e6aa0fc..4d746b975 100644
--- a/Nodejs/Product/Nodejs/Project/GlobalModulesNode.cs
+++ b/Nodejs/Product/Nodejs/Project/GlobalModulesNode.cs
@@ -1,101 +1,101 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Linq;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudioTools.Project;
-
-namespace Microsoft.NodejsTools.Project {
- internal class GlobalModulesNode : AbstractNpmNode {
-
- ///
- /// The caption to display for this node
- ///
- private const string _cCaption = "global";
-
- ///
- /// The virtual name of this node.
- ///
- public const string GlobalModulesVirtualName = "GlobalModules";
-
- private NodeModulesNode _parent;
-
- public GlobalModulesNode(NodejsProjectNode root, NodeModulesNode parent)
- : base(root) {
- _parent = parent;
- }
-
- public override string Url {
- get { return GlobalModulesVirtualName; }
- }
-
- public override string Caption { // TODO: stick this string in a resource, along with the NodeModulesNode caption
- get { return _cCaption; }
- }
-
- public override int SortPriority {
- get { return -1; /* DefaultSortOrderNode.FolderNode; */ }
- }
-
- internal IGlobalPackages GlobalPackages { get; set; }
-
- internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmUpdateModules:
- if (_parent.IsCurrentStateASuppressCommandsMode()) {
- result = QueryStatusResult.SUPPORTED;
- } else {
- if (AllChildren.Any()) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmInstallModules:
- case PkgCmdId.cmdidNpmInstallSingleMissingModule:
- case PkgCmdId.cmdidNpmUninstallModule:
- case PkgCmdId.cmdidNpmUpdateSingleModule:
- case PkgCmdId.cmdidNpmOpenModuleHomepage:
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
- return VSConstants.S_OK;
- }
- }
-
- return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
- }
-
- internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmUpdateModules:
- var t = _parent.UpdateModules(AllChildren.ToList());
- return VSConstants.S_OK;
- }
- }
-
- return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
- }
-
- public override void ManageNpmModules() {
- _parent.ManageModules(isGlobal:true);
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Linq;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudioTools.Project;
+
+namespace Microsoft.NodejsTools.Project {
+ internal class GlobalModulesNode : AbstractNpmNode {
+
+ ///
+ /// The caption to display for this node
+ ///
+ private const string _cCaption = "global";
+
+ ///
+ /// The virtual name of this node.
+ ///
+ public const string GlobalModulesVirtualName = "GlobalModules";
+
+ private NodeModulesNode _parent;
+
+ public GlobalModulesNode(NodejsProjectNode root, NodeModulesNode parent)
+ : base(root) {
+ _parent = parent;
+ }
+
+ public override string Url {
+ get { return GlobalModulesVirtualName; }
+ }
+
+ public override string Caption { // TODO: stick this string in a resource, along with the NodeModulesNode caption
+ get { return _cCaption; }
+ }
+
+ public override int SortPriority {
+ get { return -1; /* DefaultSortOrderNode.FolderNode; */ }
+ }
+
+ internal IGlobalPackages GlobalPackages { get; set; }
+
+ internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmUpdateModules:
+ if (_parent.IsCurrentStateASuppressCommandsMode()) {
+ result = QueryStatusResult.SUPPORTED;
+ } else {
+ if (AllChildren.Any()) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmInstallModules:
+ case PkgCmdId.cmdidNpmInstallSingleMissingModule:
+ case PkgCmdId.cmdidNpmUninstallModule:
+ case PkgCmdId.cmdidNpmUpdateSingleModule:
+ case PkgCmdId.cmdidNpmOpenModuleHomepage:
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
+ }
+
+ internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmUpdateModules:
+ var t = _parent.UpdateModules(AllChildren.ToList());
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+ public override void ManageNpmModules() {
+ _parent.ManageModules(isGlobal:true);
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs b/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
index afb046e18..4eeeb59aa 100644
--- a/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
+++ b/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
@@ -1,692 +1,692 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.NodejsTools.NpmUI;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-using MessageBox = System.Windows.MessageBox;
-using Timer = System.Threading.Timer;
-
-namespace Microsoft.NodejsTools.Project {
- internal class NodeModulesNode : AbstractNpmNode {
- #region Constants
-
- ///
- /// The caption to display for this node
- ///
- private const string _cCaption = "npm";
-
- ///
- /// The virtual name of this node.
- ///
- public const string NodeModulesVirtualName = "NodeModules";
-
- #endregion
-
- #region Member variables
-
- private readonly GlobalModulesNode _globalModulesNode;
- private readonly LocalModulesNode _devModulesNode;
- private readonly LocalModulesNode _optionalModulesNode;
-
- private Timer _npmIdleTimer;
- private INpmController _npmController;
- private int _npmCommandsExecuting;
- private bool _suppressCommands;
- private bool _firstHierarchyLoad = true;
-
- private readonly object _commandCountLock = new object();
-
- private bool _isDisposed;
-
- #endregion
-
- #region Initialization
-
- public NodeModulesNode(NodejsProjectNode root)
- : base(root) {
- CreateNpmController();
-
- _globalModulesNode = new GlobalModulesNode(root, this);
- AddChild(_globalModulesNode);
-
- _devModulesNode = new LocalModulesNode(root, this, "dev", "DevelopmentModules", DependencyType.Development);
- AddChild(_devModulesNode);
-
- _optionalModulesNode = new LocalModulesNode(root, this, "optional", "OptionalModules", DependencyType.Optional);
- AddChild(_optionalModulesNode);
- }
-
- private void CheckNotDisposed() {
- if (_isDisposed) {
- throw new ObjectDisposedException(
- "This NodeModulesNode has been disposed of and should no longer be used.");
- }
- }
-
- protected override void Dispose(bool disposing) {
- if (!_isDisposed) {
- _npmController.Dispose();
-
- if (null != _npmIdleTimer) {
- _npmIdleTimer.Dispose();
- _npmIdleTimer = null;
- }
-
- if (null != _npmController) {
- _npmController.CommandStarted -= NpmController_CommandStarted;
- _npmController.OutputLogged -= NpmController_OutputLogged;
- _npmController.ErrorLogged -= NpmController_ErrorLogged;
- _npmController.ExceptionLogged -= NpmController_ExceptionLogged;
- _npmController.CommandCompleted -= NpmController_CommandCompleted;
- }
-
- _isDisposed = true;
- }
-
- base.Dispose(disposing);
- }
-
- #endregion
-
- #region Properties
-
- private string GetNpmPathFromNodePathInProject() {
- var props = ProjectMgr.NodeProperties as NodejsProjectNodeProperties;
- return NpmHelpers.GetPathToNpm(props != null ? props.NodeExePath : null);
- }
-
- private class NpmPathProvider : INpmPathProvider {
- private NodeModulesNode _owner;
- internal NpmPathProvider(NodeModulesNode owner) {
- _owner = owner;
- }
-
- public string PathToNpm {
- get {
- return _owner.GetNpmPathFromNodePathInProject();
- }
- }
- }
-
- private INpmController CreateNpmController() {
- if (null == _npmController) {
- _npmController = NpmControllerFactory.Create(
- _projectNode.ProjectHome,
- NodejsPackage.Instance.NpmOptionsPage.NpmCachePath,
- false,
- new NpmPathProvider(this));
- _npmController.CommandStarted += NpmController_CommandStarted;
- _npmController.OutputLogged += NpmController_OutputLogged;
- _npmController.ErrorLogged += NpmController_ErrorLogged;
- _npmController.ExceptionLogged += NpmController_ExceptionLogged;
- _npmController.CommandCompleted += NpmController_CommandCompleted;
- }
- return _npmController;
- }
-
- void NpmController_FinishedRefresh(object sender, EventArgs e) {
- ReloadHierarchySafe();
- }
-
- public INpmController NpmController {
- get {
- return _npmController;
- }
- }
-
- internal IRootPackage RootPackage {
- get {
- var controller = NpmController;
- return null == controller ? null : controller.RootPackage;
- }
- }
-
- private INodeModules RootModules {
- get {
- var root = RootPackage;
- return null == root ? null : root.Modules;
- }
- }
-
- private bool HasMissingModules {
- get {
- var modules = RootModules;
- return null != modules && modules.HasMissingModules;
- }
- }
-
- private bool HasModules {
- get {
- var modules = RootModules;
- return null != modules && modules.Count > 0;
- }
- }
-
- #endregion
-
- #region Logging and status bar updates
-
-#if DEV14_OR_LATER
- // This is the package manager pane that ships with VS2015, and we should print there if available.
- private static readonly Guid VSPackageManagerPaneGuid = new Guid("C7E31C31-1451-4E05-B6BE-D11B6829E8BB");
-#else
- private static readonly Guid NpmOutputPaneGuid = new Guid("25764421-33B8-4163-BD02-A94E299D52D8");
-#endif
-
- private OutputWindowRedirector GetNpmOutputPane() {
- try {
-#if DEV14_OR_LATER
- return OutputWindowRedirector.Get(_projectNode.Site, VSPackageManagerPaneGuid, "Bower/npm");
-#else
- return OutputWindowRedirector.Get(_projectNode.Site, NpmOutputPaneGuid, SR.GetString(SR.NpmOutputPaneTitle));
-#endif
- } catch (InvalidOperationException) {
- return null;
- }
- }
-
- private void ConditionallyShowNpmOutputPane() {
- if (NodejsPackage.Instance.NpmOptionsPage.ShowOutputWindowWhenExecutingNpm) {
- var pane = GetNpmOutputPane();
- if (null != pane) {
- pane.ShowAndActivate();
- }
- }
- }
-
-#if INTEGRATE_WITH_ERROR_LIST
-
- private ErrorListProvider _errorListProvider;
-
- private ErrorListProvider GetErrorListProvider() {
- if (null == _errorListProvider) {
- _errorListProvider = new ErrorListProvider(_projectNode.ProjectMgr.Site);
- }
- return _errorListProvider;
- }
-
- private void WriteNpmErrorsToErrorList(NpmLogEventArgs args) {
- var provider = GetErrorListProvider();
- foreach (var line in args.LogText.Split(new[] {'\n' })) {
- var trimmed = line.Trim();
- if (trimmed.StartsWith("npm ERR!")) {
- provider.Tasks.Add(new ErrorTask() {
- Category = TaskCategory.User,
- ErrorCategory = TaskErrorCategory.Error,
- Text = trimmed
- });
- } else if (trimmed.StartsWith("npm WARN")) {
- provider.Tasks.Add(new ErrorTask() {
- Category = TaskCategory.User,
- ErrorCategory = TaskErrorCategory.Warning,
- Text = trimmed
- });
- }
- }
- }
-
-#endif
-
- private void ForceUpdateStatusBarWithNpmActivity(string activity) {
- if (string.IsNullOrEmpty(activity) || string.IsNullOrEmpty(activity.Trim())) {
- return;
- }
-
- if (!activity.Contains("npm")) {
- activity = string.Format("npm: {0}", activity);
- }
-
- var statusBar = (IVsStatusbar)_projectNode.GetService(typeof(SVsStatusbar));
- if (null != statusBar) {
- statusBar.SetText(activity);
- }
- }
-
- private void ForceUpdateStatusBarWithNpmActivitySafe(string activity) {
- ProjectMgr.Site.GetUIThread().InvokeAsync(() => ForceUpdateStatusBarWithNpmActivity(activity))
- .HandleAllExceptions(SR.ProductName)
- .DoNotWait();
- }
-
- private void UpdateStatusBarWithNpmActivity(string activity) {
- lock (_commandCountLock) {
- if (_npmCommandsExecuting == 0) {
- return;
- }
- }
-
- ForceUpdateStatusBarWithNpmActivitySafe(activity);
- }
-
- private static string TrimLastNewline(string text) {
- if (string.IsNullOrEmpty(text)) {
- return string.Empty;
- }
-
- if (text.EndsWith("\r\n")) {
- return text.Remove(text.Length - 2);
- }
- if (text.EndsWith("\r") || text.EndsWith("\n")) {
- return text.Remove(text.Length - 1);
- }
-
- return text;
- }
-
- private void WriteNpmLogToOutputWindow(string logText) {
- var pane = GetNpmOutputPane();
- if (null != pane) {
- pane.WriteLine(logText);
- }
-
- UpdateStatusBarWithNpmActivity(logText);
-
-#if INTEGRATE_WITH_ERROR_LIST
- WriteNpmErrorsToErrorList(args);
-#endif
- }
-
- private void WriteNpmLogToOutputWindow(NpmLogEventArgs args) {
- WriteNpmLogToOutputWindow(TrimLastNewline(args.LogText));
- }
-
- private void NpmController_CommandStarted(object sender, EventArgs e) {
- StopNpmIdleTimer();
- lock (_commandCountLock) {
- ++_npmCommandsExecuting;
- }
- }
-
- private void NpmController_ErrorLogged(object sender, NpmLogEventArgs e) {
- WriteNpmLogToOutputWindow(e);
- }
-
- private void NpmController_OutputLogged(object sender, NpmLogEventArgs e) {
- WriteNpmLogToOutputWindow(e);
- }
-
- private void NpmController_ExceptionLogged(object sender, NpmExceptionEventArgs e) {
- WriteNpmLogToOutputWindow(ErrorHelper.GetExceptionDetailsText(e.Exception));
- }
-
- private void NpmController_CommandCompleted(object sender, NpmCommandCompletedEventArgs e) {
- lock (_commandCountLock) {
- --_npmCommandsExecuting;
- if (_npmCommandsExecuting < 0) {
- _npmCommandsExecuting = 0;
- }
- }
-
- string message;
- if (e.WithErrors) {
- message = SR.GetString(
- e.Cancelled ? SR.NpmCancelledWithErrors : SR.NpmCompletedWithErrors,
- e.CommandText
- );
- } else if (e.Cancelled) {
- message = SR.GetString(SR.NpmCancelled, e.CommandText);
- } else {
- message = SR.GetString(SR.NpmSuccessfullyCompleted, e.CommandText);
- }
-
- ForceUpdateStatusBarWithNpmActivitySafe(message);
-
- StopNpmIdleTimer();
- _npmIdleTimer = new Timer(
- _ => ProjectMgr.Site.GetUIThread().Invoke(() => _projectNode.CheckForLongPaths(e.Arguments).HandleAllExceptions(SR.ProductName).DoNotWait()),
- null, 1000, Timeout.Infinite);
- }
-
- private void StopNpmIdleTimer() {
- if (null != _npmIdleTimer) {
- _npmIdleTimer.Dispose();
- }
- }
-
-#endregion
-
-#region Updating module hierarchy
-
- internal void ReloadHierarchySafe() {
- NodejsPackage.Instance.GetUIThread().InvokeAsync(ReloadHierarchy)
- .HandleAllExceptions(SR.ProductName)
- .DoNotWait();
- }
-
- private void ReloadHierarchy() {
- if (ProjectMgr.IsClosed) {
- return;
- }
-
- var controller = _npmController;
- if (null != controller) {
- if (null != RootPackage) {
- var dev = controller.RootPackage.Modules.Where(package => package.IsDevDependency);
- _devModulesNode.Packages = dev;
- ReloadHierarchy(_devModulesNode, dev);
-
- var optional = controller.RootPackage.Modules.Where(package => package.IsOptionalDependency);
- _optionalModulesNode.Packages = optional;
- ReloadHierarchy(_optionalModulesNode, optional);
-
- var root = controller.RootPackage.Modules.Where(package =>
- package.IsDependency ||
- !package.IsListedInParentPackageJson);
-
- ReloadHierarchy(this, root);
- }
-
- var global = controller.GlobalPackages;
- if (null != global) {
- _globalModulesNode.GlobalPackages = global;
- ReloadHierarchy(_globalModulesNode, global.Modules);
- }
-
- if (_firstHierarchyLoad) {
- controller.FinishedRefresh += NpmController_FinishedRefresh;
- _firstHierarchyLoad = false;
- }
- }
- }
-
-#endregion
-
-#region HierarchyNode implementation
-
- public override int SortPriority {
- get { return DefaultSortOrderNode.ReferenceContainerNode + 1; }
- }
-
- public override string Url {
- get { return NodeModulesVirtualName; }
- }
-
- public override string Caption {
- get { return _cCaption; }
- }
-
-#endregion
-
-#region Command handling
-
- internal bool IsCurrentStateASuppressCommandsMode() {
- return _suppressCommands || ProjectMgr.IsCurrentStateASuppressCommandsMode();
- }
-
- private void SuppressCommands() {
- _suppressCommands = true;
- }
-
- private void AllowCommands() {
- _suppressCommands = false;
- }
-
- internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmInstallModules:
- if (IsCurrentStateASuppressCommandsMode()) {
- result = QueryStatusResult.SUPPORTED;
- } else {
- if (HasMissingModules) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmUpdateModules:
- if (IsCurrentStateASuppressCommandsMode()) {
- result = QueryStatusResult.SUPPORTED;
- } else {
- if (HasModules) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- } else {
- result = QueryStatusResult.SUPPORTED;
- }
- }
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmInstallSingleMissingModule:
- case PkgCmdId.cmdidNpmUninstallModule:
- case PkgCmdId.cmdidNpmUpdateSingleModule:
- case PkgCmdId.cmdidNpmOpenModuleHomepage:
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
- return VSConstants.S_OK;
- }
- }
-
- return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
- }
-
- internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmInstallModules:
- var t = InstallMissingModules();
- return VSConstants.S_OK;
-
- case PkgCmdId.cmdidNpmUpdateModules:
- UpdateModules();
- return VSConstants.S_OK;
- }
- }
-
- return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
- }
-
- public void ManageModules(DependencyType dependencyType = DependencyType.Standard, bool isGlobal = false) {
- CheckNotDisposed();
-
- if (NpmController.RootPackage == null) {
- NpmController.Refresh();
- if (NpmController.RootPackage == null) {
- MessageBox.Show(String.Format("Unable to parse {0} from your project. Please fix any errors and try again.", NodejsConstants.PackageJsonFile));
- return;
- }
- }
-
- using (var executeVm = new NpmOutputViewModel(NpmController))
- using (var manager = new NpmPackageInstallWindow(NpmController, executeVm, dependencyType, isGlobal)) {
- manager.Owner = System.Windows.Application.Current.MainWindow;
- manager.ShowModal();
- }
- ReloadHierarchy();
- }
-
- private void DoPreCommandActions() {
- CheckNotDisposed();
- SuppressCommands();
- ConditionallyShowNpmOutputPane();
- }
-
- private bool CheckValidCommandTarget(DependencyNode node) {
- if (null == node) {
- return false;
- }
- var props = node.GetPropertiesObject();
- if (null == props || props.IsSubPackage) {
- return false;
- }
- var package = node.Package;
- if (null == package) {
- return false;
- }
- return true;
- }
-
- public async System.Threading.Tasks.Task InstallMissingModules() {
- DoPreCommandActions();
- try {
- using (var commander = NpmController.CreateNpmCommander()) {
- await commander.Install();
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
- public async System.Threading.Tasks.Task InstallMissingModule(DependencyNode node) {
- if (!CheckValidCommandTarget(node)) {
- return;
- }
-
- var root = _npmController.RootPackage;
- if (null == root) {
- return;
- }
-
- var pkgJson = root.PackageJson;
- if (null == pkgJson) {
- return;
- }
-
- var package = node.Package;
- var dep = root.PackageJson.AllDependencies[package.Name];
-
- DoPreCommandActions();
- try {
- using (var commander = NpmController.CreateNpmCommander()) {
- if (node.GetPropertiesObject().IsGlobalInstall) {
- // I genuinely can't see a way this would ever happen but, just to be on the safe side...
- await commander.InstallGlobalPackageByVersionAsync(
- package.Name,
- null == dep ? "*" : dep.VersionRangeText);
- } else {
- await commander.InstallPackageByVersionAsync(
- package.Name,
- null == dep ? "*" : dep.VersionRangeText,
- DependencyType.Standard,
- false);
- }
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
- internal async System.Threading.Tasks.Task UpdateModules(IList nodes) {
- DoPreCommandActions();
- try {
- using (var commander = NpmController.CreateNpmCommander()) {
- if (nodes.Count == 1 && nodes[0] == this) {
- await commander.UpdatePackagesAsync();
- } else {
- var valid = nodes.OfType().Where(CheckValidCommandTarget).ToList();
-
- var list = valid.Where(node => node.GetPropertiesObject().IsGlobalInstall).Select(node => node.Package).ToList();
- if (list.Count > 0) {
- await commander.UpdateGlobalPackagesAsync(list);
- }
-
- list = valid.Where(node => !node.GetPropertiesObject().IsGlobalInstall).Select(node => node.Package).ToList();
- if (list.Count > 0) {
- await commander.UpdatePackagesAsync(list);
- }
- }
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
- public void UpdateModules() {
- var t = UpdateModules(_projectNode.GetSelectedNodes());
- }
-
- public async System.Threading.Tasks.Task UpdateModule(DependencyNode node) {
- if (!CheckValidCommandTarget(node)) {
- return;
- }
- DoPreCommandActions();
- try {
- using (var commander = NpmController.CreateNpmCommander()) {
- if (node.GetPropertiesObject().IsGlobalInstall) {
- await commander.UpdateGlobalPackagesAsync(new[] { node.Package });
- } else {
- await commander.UpdatePackagesAsync(new[] { node.Package });
- }
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
- public async System.Threading.Tasks.Task UninstallModules() {
- DoPreCommandActions();
- try {
- var selected = _projectNode.GetSelectedNodes();
- using (var commander = NpmController.CreateNpmCommander()) {
- foreach (var node in selected.OfType().Where(CheckValidCommandTarget)) {
- if (node.GetPropertiesObject().IsGlobalInstall) {
- await commander.UninstallGlobalPackageAsync(node.Package.Name);
- } else {
- await commander.UninstallPackageAsync(node.Package.Name);
- }
- }
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
- public async System.Threading.Tasks.Task UninstallModule(DependencyNode node) {
- if (!CheckValidCommandTarget(node)) {
- return;
- }
- DoPreCommandActions();
- try {
- using (var commander = NpmController.CreateNpmCommander()) {
- if (node.GetPropertiesObject().IsGlobalInstall) {
- await commander.UninstallGlobalPackageAsync(node.Package.Name);
- } else {
- await commander.UninstallPackageAsync(node.Package.Name);
- }
- }
- } catch (NpmNotFoundException nnfe) {
- ErrorHelper.ReportNpmNotInstalled(null, nnfe);
- } finally {
- AllowCommands();
- }
- }
-
-#endregion
-
- public override void ManageNpmModules() {
- ManageModules();
- }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.NodejsTools.NpmUI;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using MessageBox = System.Windows.MessageBox;
+using Timer = System.Threading.Timer;
+
+namespace Microsoft.NodejsTools.Project {
+ internal class NodeModulesNode : AbstractNpmNode {
+ #region Constants
+
+ ///
+ /// The caption to display for this node
+ ///
+ private const string _cCaption = "npm";
+
+ ///
+ /// The virtual name of this node.
+ ///
+ public const string NodeModulesVirtualName = "NodeModules";
+
+ #endregion
+
+ #region Member variables
+
+ private readonly GlobalModulesNode _globalModulesNode;
+ private readonly LocalModulesNode _devModulesNode;
+ private readonly LocalModulesNode _optionalModulesNode;
+
+ private Timer _npmIdleTimer;
+ private INpmController _npmController;
+ private int _npmCommandsExecuting;
+ private bool _suppressCommands;
+ private bool _firstHierarchyLoad = true;
+
+ private readonly object _commandCountLock = new object();
+
+ private bool _isDisposed;
+
+ #endregion
+
+ #region Initialization
+
+ public NodeModulesNode(NodejsProjectNode root)
+ : base(root) {
+ CreateNpmController();
+
+ _globalModulesNode = new GlobalModulesNode(root, this);
+ AddChild(_globalModulesNode);
+
+ _devModulesNode = new LocalModulesNode(root, this, "dev", "DevelopmentModules", DependencyType.Development);
+ AddChild(_devModulesNode);
+
+ _optionalModulesNode = new LocalModulesNode(root, this, "optional", "OptionalModules", DependencyType.Optional);
+ AddChild(_optionalModulesNode);
+ }
+
+ private void CheckNotDisposed() {
+ if (_isDisposed) {
+ throw new ObjectDisposedException(
+ "This NodeModulesNode has been disposed of and should no longer be used.");
+ }
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (!_isDisposed) {
+ _npmController.Dispose();
+
+ if (null != _npmIdleTimer) {
+ _npmIdleTimer.Dispose();
+ _npmIdleTimer = null;
+ }
+
+ if (null != _npmController) {
+ _npmController.CommandStarted -= NpmController_CommandStarted;
+ _npmController.OutputLogged -= NpmController_OutputLogged;
+ _npmController.ErrorLogged -= NpmController_ErrorLogged;
+ _npmController.ExceptionLogged -= NpmController_ExceptionLogged;
+ _npmController.CommandCompleted -= NpmController_CommandCompleted;
+ }
+
+ _isDisposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ #endregion
+
+ #region Properties
+
+ private string GetNpmPathFromNodePathInProject() {
+ var props = ProjectMgr.NodeProperties as NodejsProjectNodeProperties;
+ return NpmHelpers.GetPathToNpm(props != null ? props.NodeExePath : null);
+ }
+
+ private class NpmPathProvider : INpmPathProvider {
+ private NodeModulesNode _owner;
+ internal NpmPathProvider(NodeModulesNode owner) {
+ _owner = owner;
+ }
+
+ public string PathToNpm {
+ get {
+ return _owner.GetNpmPathFromNodePathInProject();
+ }
+ }
+ }
+
+ private INpmController CreateNpmController() {
+ if (null == _npmController) {
+ _npmController = NpmControllerFactory.Create(
+ _projectNode.ProjectHome,
+ NodejsPackage.Instance.NpmOptionsPage.NpmCachePath,
+ false,
+ new NpmPathProvider(this));
+ _npmController.CommandStarted += NpmController_CommandStarted;
+ _npmController.OutputLogged += NpmController_OutputLogged;
+ _npmController.ErrorLogged += NpmController_ErrorLogged;
+ _npmController.ExceptionLogged += NpmController_ExceptionLogged;
+ _npmController.CommandCompleted += NpmController_CommandCompleted;
+ }
+ return _npmController;
+ }
+
+ void NpmController_FinishedRefresh(object sender, EventArgs e) {
+ ReloadHierarchySafe();
+ }
+
+ public INpmController NpmController {
+ get {
+ return _npmController;
+ }
+ }
+
+ internal IRootPackage RootPackage {
+ get {
+ var controller = NpmController;
+ return null == controller ? null : controller.RootPackage;
+ }
+ }
+
+ private INodeModules RootModules {
+ get {
+ var root = RootPackage;
+ return null == root ? null : root.Modules;
+ }
+ }
+
+ private bool HasMissingModules {
+ get {
+ var modules = RootModules;
+ return null != modules && modules.HasMissingModules;
+ }
+ }
+
+ private bool HasModules {
+ get {
+ var modules = RootModules;
+ return null != modules && modules.Count > 0;
+ }
+ }
+
+ #endregion
+
+ #region Logging and status bar updates
+
+#if DEV14_OR_LATER
+ // This is the package manager pane that ships with VS2015, and we should print there if available.
+ private static readonly Guid VSPackageManagerPaneGuid = new Guid("C7E31C31-1451-4E05-B6BE-D11B6829E8BB");
+#else
+ private static readonly Guid NpmOutputPaneGuid = new Guid("25764421-33B8-4163-BD02-A94E299D52D8");
+#endif
+
+ private OutputWindowRedirector GetNpmOutputPane() {
+ try {
+#if DEV14_OR_LATER
+ return OutputWindowRedirector.Get(_projectNode.Site, VSPackageManagerPaneGuid, "Bower/npm");
+#else
+ return OutputWindowRedirector.Get(_projectNode.Site, NpmOutputPaneGuid, SR.GetString(SR.NpmOutputPaneTitle));
+#endif
+ } catch (InvalidOperationException) {
+ return null;
+ }
+ }
+
+ private void ConditionallyShowNpmOutputPane() {
+ if (NodejsPackage.Instance.NpmOptionsPage.ShowOutputWindowWhenExecutingNpm) {
+ var pane = GetNpmOutputPane();
+ if (null != pane) {
+ pane.ShowAndActivate();
+ }
+ }
+ }
+
+#if INTEGRATE_WITH_ERROR_LIST
+
+ private ErrorListProvider _errorListProvider;
+
+ private ErrorListProvider GetErrorListProvider() {
+ if (null == _errorListProvider) {
+ _errorListProvider = new ErrorListProvider(_projectNode.ProjectMgr.Site);
+ }
+ return _errorListProvider;
+ }
+
+ private void WriteNpmErrorsToErrorList(NpmLogEventArgs args) {
+ var provider = GetErrorListProvider();
+ foreach (var line in args.LogText.Split(new[] {'\n' })) {
+ var trimmed = line.Trim();
+ if (trimmed.StartsWith("npm ERR!")) {
+ provider.Tasks.Add(new ErrorTask() {
+ Category = TaskCategory.User,
+ ErrorCategory = TaskErrorCategory.Error,
+ Text = trimmed
+ });
+ } else if (trimmed.StartsWith("npm WARN")) {
+ provider.Tasks.Add(new ErrorTask() {
+ Category = TaskCategory.User,
+ ErrorCategory = TaskErrorCategory.Warning,
+ Text = trimmed
+ });
+ }
+ }
+ }
+
+#endif
+
+ private void ForceUpdateStatusBarWithNpmActivity(string activity) {
+ if (string.IsNullOrEmpty(activity) || string.IsNullOrEmpty(activity.Trim())) {
+ return;
+ }
+
+ if (!activity.Contains("npm")) {
+ activity = string.Format("npm: {0}", activity);
+ }
+
+ var statusBar = (IVsStatusbar)_projectNode.GetService(typeof(SVsStatusbar));
+ if (null != statusBar) {
+ statusBar.SetText(activity);
+ }
+ }
+
+ private void ForceUpdateStatusBarWithNpmActivitySafe(string activity) {
+ ProjectMgr.Site.GetUIThread().InvokeAsync(() => ForceUpdateStatusBarWithNpmActivity(activity))
+ .HandleAllExceptions(SR.ProductName)
+ .DoNotWait();
+ }
+
+ private void UpdateStatusBarWithNpmActivity(string activity) {
+ lock (_commandCountLock) {
+ if (_npmCommandsExecuting == 0) {
+ return;
+ }
+ }
+
+ ForceUpdateStatusBarWithNpmActivitySafe(activity);
+ }
+
+ private static string TrimLastNewline(string text) {
+ if (string.IsNullOrEmpty(text)) {
+ return string.Empty;
+ }
+
+ if (text.EndsWith("\r\n")) {
+ return text.Remove(text.Length - 2);
+ }
+ if (text.EndsWith("\r") || text.EndsWith("\n")) {
+ return text.Remove(text.Length - 1);
+ }
+
+ return text;
+ }
+
+ private void WriteNpmLogToOutputWindow(string logText) {
+ var pane = GetNpmOutputPane();
+ if (null != pane) {
+ pane.WriteLine(logText);
+ }
+
+ UpdateStatusBarWithNpmActivity(logText);
+
+#if INTEGRATE_WITH_ERROR_LIST
+ WriteNpmErrorsToErrorList(args);
+#endif
+ }
+
+ private void WriteNpmLogToOutputWindow(NpmLogEventArgs args) {
+ WriteNpmLogToOutputWindow(TrimLastNewline(args.LogText));
+ }
+
+ private void NpmController_CommandStarted(object sender, EventArgs e) {
+ StopNpmIdleTimer();
+ lock (_commandCountLock) {
+ ++_npmCommandsExecuting;
+ }
+ }
+
+ private void NpmController_ErrorLogged(object sender, NpmLogEventArgs e) {
+ WriteNpmLogToOutputWindow(e);
+ }
+
+ private void NpmController_OutputLogged(object sender, NpmLogEventArgs e) {
+ WriteNpmLogToOutputWindow(e);
+ }
+
+ private void NpmController_ExceptionLogged(object sender, NpmExceptionEventArgs e) {
+ WriteNpmLogToOutputWindow(ErrorHelper.GetExceptionDetailsText(e.Exception));
+ }
+
+ private void NpmController_CommandCompleted(object sender, NpmCommandCompletedEventArgs e) {
+ lock (_commandCountLock) {
+ --_npmCommandsExecuting;
+ if (_npmCommandsExecuting < 0) {
+ _npmCommandsExecuting = 0;
+ }
+ }
+
+ string message;
+ if (e.WithErrors) {
+ message = SR.GetString(
+ e.Cancelled ? SR.NpmCancelledWithErrors : SR.NpmCompletedWithErrors,
+ e.CommandText
+ );
+ } else if (e.Cancelled) {
+ message = SR.GetString(SR.NpmCancelled, e.CommandText);
+ } else {
+ message = SR.GetString(SR.NpmSuccessfullyCompleted, e.CommandText);
+ }
+
+ ForceUpdateStatusBarWithNpmActivitySafe(message);
+
+ StopNpmIdleTimer();
+ _npmIdleTimer = new Timer(
+ _ => ProjectMgr.Site.GetUIThread().Invoke(() => _projectNode.CheckForLongPaths(e.Arguments).HandleAllExceptions(SR.ProductName).DoNotWait()),
+ null, 1000, Timeout.Infinite);
+ }
+
+ private void StopNpmIdleTimer() {
+ if (null != _npmIdleTimer) {
+ _npmIdleTimer.Dispose();
+ }
+ }
+
+#endregion
+
+#region Updating module hierarchy
+
+ internal void ReloadHierarchySafe() {
+ NodejsPackage.Instance.GetUIThread().InvokeAsync(ReloadHierarchy)
+ .HandleAllExceptions(SR.ProductName)
+ .DoNotWait();
+ }
+
+ private void ReloadHierarchy() {
+ if (ProjectMgr.IsClosed) {
+ return;
+ }
+
+ var controller = _npmController;
+ if (null != controller) {
+ if (null != RootPackage) {
+ var dev = controller.RootPackage.Modules.Where(package => package.IsDevDependency);
+ _devModulesNode.Packages = dev;
+ ReloadHierarchy(_devModulesNode, dev);
+
+ var optional = controller.RootPackage.Modules.Where(package => package.IsOptionalDependency);
+ _optionalModulesNode.Packages = optional;
+ ReloadHierarchy(_optionalModulesNode, optional);
+
+ var root = controller.RootPackage.Modules.Where(package =>
+ package.IsDependency ||
+ !package.IsListedInParentPackageJson);
+
+ ReloadHierarchy(this, root);
+ }
+
+ var global = controller.GlobalPackages;
+ if (null != global) {
+ _globalModulesNode.GlobalPackages = global;
+ ReloadHierarchy(_globalModulesNode, global.Modules);
+ }
+
+ if (_firstHierarchyLoad) {
+ controller.FinishedRefresh += NpmController_FinishedRefresh;
+ _firstHierarchyLoad = false;
+ }
+ }
+ }
+
+#endregion
+
+#region HierarchyNode implementation
+
+ public override int SortPriority {
+ get { return DefaultSortOrderNode.ReferenceContainerNode + 1; }
+ }
+
+ public override string Url {
+ get { return NodeModulesVirtualName; }
+ }
+
+ public override string Caption {
+ get { return _cCaption; }
+ }
+
+#endregion
+
+#region Command handling
+
+ internal bool IsCurrentStateASuppressCommandsMode() {
+ return _suppressCommands || ProjectMgr.IsCurrentStateASuppressCommandsMode();
+ }
+
+ private void SuppressCommands() {
+ _suppressCommands = true;
+ }
+
+ private void AllowCommands() {
+ _suppressCommands = false;
+ }
+
+ internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmInstallModules:
+ if (IsCurrentStateASuppressCommandsMode()) {
+ result = QueryStatusResult.SUPPORTED;
+ } else {
+ if (HasMissingModules) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmUpdateModules:
+ if (IsCurrentStateASuppressCommandsMode()) {
+ result = QueryStatusResult.SUPPORTED;
+ } else {
+ if (HasModules) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ } else {
+ result = QueryStatusResult.SUPPORTED;
+ }
+ }
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmInstallSingleMissingModule:
+ case PkgCmdId.cmdidNpmUninstallModule:
+ case PkgCmdId.cmdidNpmUpdateSingleModule:
+ case PkgCmdId.cmdidNpmOpenModuleHomepage:
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
+ }
+
+ internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmInstallModules:
+ var t = InstallMissingModules();
+ return VSConstants.S_OK;
+
+ case PkgCmdId.cmdidNpmUpdateModules:
+ UpdateModules();
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+ public void ManageModules(DependencyType dependencyType = DependencyType.Standard, bool isGlobal = false) {
+ CheckNotDisposed();
+
+ if (NpmController.RootPackage == null) {
+ NpmController.Refresh();
+ if (NpmController.RootPackage == null) {
+ MessageBox.Show(String.Format("Unable to parse {0} from your project. Please fix any errors and try again.", NodejsConstants.PackageJsonFile));
+ return;
+ }
+ }
+
+ using (var executeVm = new NpmOutputViewModel(NpmController))
+ using (var manager = new NpmPackageInstallWindow(NpmController, executeVm, dependencyType, isGlobal)) {
+ manager.Owner = System.Windows.Application.Current.MainWindow;
+ manager.ShowModal();
+ }
+ ReloadHierarchy();
+ }
+
+ private void DoPreCommandActions() {
+ CheckNotDisposed();
+ SuppressCommands();
+ ConditionallyShowNpmOutputPane();
+ }
+
+ private bool CheckValidCommandTarget(DependencyNode node) {
+ if (null == node) {
+ return false;
+ }
+ var props = node.GetPropertiesObject();
+ if (null == props || props.IsSubPackage) {
+ return false;
+ }
+ var package = node.Package;
+ if (null == package) {
+ return false;
+ }
+ return true;
+ }
+
+ public async System.Threading.Tasks.Task InstallMissingModules() {
+ DoPreCommandActions();
+ try {
+ using (var commander = NpmController.CreateNpmCommander()) {
+ await commander.Install();
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+ public async System.Threading.Tasks.Task InstallMissingModule(DependencyNode node) {
+ if (!CheckValidCommandTarget(node)) {
+ return;
+ }
+
+ var root = _npmController.RootPackage;
+ if (null == root) {
+ return;
+ }
+
+ var pkgJson = root.PackageJson;
+ if (null == pkgJson) {
+ return;
+ }
+
+ var package = node.Package;
+ var dep = root.PackageJson.AllDependencies[package.Name];
+
+ DoPreCommandActions();
+ try {
+ using (var commander = NpmController.CreateNpmCommander()) {
+ if (node.GetPropertiesObject().IsGlobalInstall) {
+ // I genuinely can't see a way this would ever happen but, just to be on the safe side...
+ await commander.InstallGlobalPackageByVersionAsync(
+ package.Name,
+ null == dep ? "*" : dep.VersionRangeText);
+ } else {
+ await commander.InstallPackageByVersionAsync(
+ package.Name,
+ null == dep ? "*" : dep.VersionRangeText,
+ DependencyType.Standard,
+ false);
+ }
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+ internal async System.Threading.Tasks.Task UpdateModules(IList nodes) {
+ DoPreCommandActions();
+ try {
+ using (var commander = NpmController.CreateNpmCommander()) {
+ if (nodes.Count == 1 && nodes[0] == this) {
+ await commander.UpdatePackagesAsync();
+ } else {
+ var valid = nodes.OfType().Where(CheckValidCommandTarget).ToList();
+
+ var list = valid.Where(node => node.GetPropertiesObject().IsGlobalInstall).Select(node => node.Package).ToList();
+ if (list.Count > 0) {
+ await commander.UpdateGlobalPackagesAsync(list);
+ }
+
+ list = valid.Where(node => !node.GetPropertiesObject().IsGlobalInstall).Select(node => node.Package).ToList();
+ if (list.Count > 0) {
+ await commander.UpdatePackagesAsync(list);
+ }
+ }
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+ public void UpdateModules() {
+ var t = UpdateModules(_projectNode.GetSelectedNodes());
+ }
+
+ public async System.Threading.Tasks.Task UpdateModule(DependencyNode node) {
+ if (!CheckValidCommandTarget(node)) {
+ return;
+ }
+ DoPreCommandActions();
+ try {
+ using (var commander = NpmController.CreateNpmCommander()) {
+ if (node.GetPropertiesObject().IsGlobalInstall) {
+ await commander.UpdateGlobalPackagesAsync(new[] { node.Package });
+ } else {
+ await commander.UpdatePackagesAsync(new[] { node.Package });
+ }
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+ public async System.Threading.Tasks.Task UninstallModules() {
+ DoPreCommandActions();
+ try {
+ var selected = _projectNode.GetSelectedNodes();
+ using (var commander = NpmController.CreateNpmCommander()) {
+ foreach (var node in selected.OfType().Where(CheckValidCommandTarget)) {
+ if (node.GetPropertiesObject().IsGlobalInstall) {
+ await commander.UninstallGlobalPackageAsync(node.Package.Name);
+ } else {
+ await commander.UninstallPackageAsync(node.Package.Name);
+ }
+ }
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+ public async System.Threading.Tasks.Task UninstallModule(DependencyNode node) {
+ if (!CheckValidCommandTarget(node)) {
+ return;
+ }
+ DoPreCommandActions();
+ try {
+ using (var commander = NpmController.CreateNpmCommander()) {
+ if (node.GetPropertiesObject().IsGlobalInstall) {
+ await commander.UninstallGlobalPackageAsync(node.Package.Name);
+ } else {
+ await commander.UninstallPackageAsync(node.Package.Name);
+ }
+ }
+ } catch (NpmNotFoundException nnfe) {
+ ErrorHelper.ReportNpmNotInstalled(null, nnfe);
+ } finally {
+ AllowCommands();
+ }
+ }
+
+#endregion
+
+ public override void ManageNpmModules() {
+ ManageModules();
+ }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Nodejs/Project/NodejsFileNode.cs b/Nodejs/Product/Nodejs/Project/NodejsFileNode.cs
index 104ae526d..6380e5b4f 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsFileNode.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsFileNode.cs
@@ -1,209 +1,209 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.IO;
-using Microsoft.VisualStudioTools.Project;
-#if DEV14_OR_LATER
-using Microsoft.VisualStudio.Imaging.Interop;
-using Microsoft.VisualStudio.Imaging;
-#endif
-
-namespace Microsoft.NodejsTools.Project {
- class NodejsFileNode : CommonFileNode {
- private FileSystemWatcher _watcher;
-
- public NodejsFileNode(NodejsProjectNode root, ProjectElement e)
- : base(root, e) {
-#if FALSE
- CreateWatcher(Url);
-#endif
- if (Url.Contains(AnalysisConstants.NodeModulesFolder)) {
- root.EnqueueForDelayedAnalysis(this);
- } else {
- Analyze();
- }
- }
-
- internal void Analyze() {
- if (ProjectMgr != null && ProjectMgr.Analyzer != null && ShouldAnalyze) {
- ProjectMgr.Analyzer.AnalyzeFile(Url, !IsNonMemberItem);
- ProjectMgr._requireCompletionCache.Clear();
- }
- ItemNode.ItemTypeChanged += ItemNode_ItemTypeChanged;
- }
-
- internal bool ShouldAnalyze {
- get {
- // We analyze if we are a member item or the file is included
- // Also, it should either be marked as compile or not have an item type name (value is null for node_modules
- return !Url.Contains(NodejsConstants.NodeModulesStagingFolder) &&
- !ProjectMgr.DelayedAnalysisQueue.Contains(this) &&
- (!IsNonMemberItem || ProjectMgr.IncludeNodejsFile(this)) &&
- (ItemNode.ItemTypeName == ProjectFileConstants.Compile || string.IsNullOrEmpty(ItemNode.ItemTypeName));
-
- }
- }
-
-#if DEV14_OR_LATER
- protected override ImageMoniker CodeFileIconMoniker {
- get {
- return KnownMonikers.JSScript;
- }
- }
-#endif
-
- internal override int IncludeInProject(bool includeChildren) {
- // Check if parent folder is designated as containing client-side code.
- var isContent = false;
- var folderNode = this.Parent as NodejsFolderNode;
- if (folderNode != null) {
- var contentType = folderNode.ContentType;
- switch (contentType) {
- case FolderContentType.Browser:
- isContent = true;
- break;
- }
- }
-
- var includeInProject = base.IncludeInProject(includeChildren);
-
- if (isContent && Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
- this.ItemNode.ItemTypeName = ProjectFileConstants.Content;
- }
-
- ProjectMgr.Analyzer.AnalyzeFile(Url, ShouldAnalyze);
-
- UpdateParentContentType();
- ItemNode.ItemTypeChanged += ItemNode_ItemTypeChanged;
-
- return includeInProject;
- }
-
- internal override int ExcludeFromProject() {
- // Analyze on removing from a project so we have the most up to date sources for this.
- // Don't report errors since the file won't remain part of the project. This removes the errors from the list.
- ProjectMgr.Analyzer.AnalyzeFile(Url, false);
- var excludeFromProject = base.ExcludeFromProject();
-
- UpdateParentContentType();
- ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
-
- return excludeFromProject;
- }
-
- protected override void RaiseOnItemRemoved(string documentToRemove, string[] filesToBeDeleted) {
- base.RaiseOnItemRemoved(documentToRemove, filesToBeDeleted);
- foreach (var file in filesToBeDeleted) {
- if (!File.Exists(file)) {
- ProjectMgr.Analyzer.UnloadFile(file);
- }
- }
- }
-
- protected override void RenameChildNodes(FileNode parentNode) {
- base.RenameChildNodes(parentNode);
- this.ProjectMgr.Analyzer.ReloadComplete();
- }
-
- protected override NodeProperties CreatePropertiesObject() {
- if (IsLinkFile) {
- return new NodejsLinkFileNodeProperties(this);
- } else if (IsNonMemberItem) {
- return new ExcludedFileNodeProperties(this);
- }
-
- return new NodejsIncludedFileNodeProperties(this);
- }
-
- private void ItemNode_ItemTypeChanged(object sender, EventArgs e) {
- // item type node was changed...
- // if we have changed the type from compile to anything else, we should scrub
- ProjectMgr.Analyzer.AnalyzeFile(Url, ShouldAnalyze);
-
- UpdateParentContentType();
- }
-
- private void UpdateParentContentType() {
- var parent = this.Parent as NodejsFolderNode;
- if (parent != null) {
- parent.UpdateContentType();
- }
- }
-
- private void CloseWatcher() {
- if (_watcher == null) {
- ProjectMgr.UnregisterFileChangeNotification(this);
- } else {
- _watcher.EnableRaisingEvents = false;
- _watcher.Dispose();
- _watcher = null;
- }
- }
-
- // TODO: Need to update analysis for files changed outside of VS
- private void CreateWatcher(string filename) {
-#if FALSE
- if (CommonUtils.IsSubpathOf(ProjectMgr.ProjectHome, filename)) {
- // we want to subscribe to the project's file system watcher so users
- // can continue to rename the directory which contains this file.
- ProjectMgr.RegisterFileChangeNotification(this, FileContentsChanged);
- } else {
- // this is a link file which lives outside of our project directory,
- // we'll need to watch the file directly, which means we're going to
- // prevent it's parent directory from being renamed.
- _watcher = new FileSystemWatcher(Path.GetDirectoryName(filename), Path.GetFileName(filename));
- _watcher.EnableRaisingEvents = true;
- _watcher.Changed += FileContentsChanged;
- _watcher.Renamed += FileContentsChanged;
- _watcher.NotifyFilter = NotifyFilters.LastWrite;
- }
-#endif
- }
-
- internal override void RenameInStorage(string oldName, string newName) {
- CloseWatcher();
- bool renamed = false;
- try {
- base.RenameInStorage(oldName, newName);
- renamed = true;
- CreateWatcher(newName);
- } finally {
- if (!renamed) {
- CreateWatcher(oldName);
- }
- }
- }
-
- public new NodejsProjectNode ProjectMgr {
- get {
- return (NodejsProjectNode)base.ProjectMgr;
- }
- }
-
- public override void Remove(bool removeFromStorage) {
- ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
- base.Remove(removeFromStorage);
- CloseWatcher();
- }
-
- public override void Close() {
- ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
- base.Close();
- CloseWatcher();
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.IO;
+using Microsoft.VisualStudioTools.Project;
+#if DEV14_OR_LATER
+using Microsoft.VisualStudio.Imaging.Interop;
+using Microsoft.VisualStudio.Imaging;
+#endif
+
+namespace Microsoft.NodejsTools.Project {
+ class NodejsFileNode : CommonFileNode {
+ private FileSystemWatcher _watcher;
+
+ public NodejsFileNode(NodejsProjectNode root, ProjectElement e)
+ : base(root, e) {
+#if FALSE
+ CreateWatcher(Url);
+#endif
+ if (Url.Contains(AnalysisConstants.NodeModulesFolder)) {
+ root.EnqueueForDelayedAnalysis(this);
+ } else {
+ Analyze();
+ }
+ }
+
+ internal void Analyze() {
+ if (ProjectMgr != null && ProjectMgr.Analyzer != null && ShouldAnalyze) {
+ ProjectMgr.Analyzer.AnalyzeFile(Url, !IsNonMemberItem);
+ ProjectMgr._requireCompletionCache.Clear();
+ }
+ ItemNode.ItemTypeChanged += ItemNode_ItemTypeChanged;
+ }
+
+ internal bool ShouldAnalyze {
+ get {
+ // We analyze if we are a member item or the file is included
+ // Also, it should either be marked as compile or not have an item type name (value is null for node_modules
+ return !Url.Contains(NodejsConstants.NodeModulesStagingFolder) &&
+ !ProjectMgr.DelayedAnalysisQueue.Contains(this) &&
+ (!IsNonMemberItem || ProjectMgr.IncludeNodejsFile(this)) &&
+ (ItemNode.ItemTypeName == ProjectFileConstants.Compile || string.IsNullOrEmpty(ItemNode.ItemTypeName));
+
+ }
+ }
+
+#if DEV14_OR_LATER
+ protected override ImageMoniker CodeFileIconMoniker {
+ get {
+ return KnownMonikers.JSScript;
+ }
+ }
+#endif
+
+ internal override int IncludeInProject(bool includeChildren) {
+ // Check if parent folder is designated as containing client-side code.
+ var isContent = false;
+ var folderNode = this.Parent as NodejsFolderNode;
+ if (folderNode != null) {
+ var contentType = folderNode.ContentType;
+ switch (contentType) {
+ case FolderContentType.Browser:
+ isContent = true;
+ break;
+ }
+ }
+
+ var includeInProject = base.IncludeInProject(includeChildren);
+
+ if (isContent && Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
+ this.ItemNode.ItemTypeName = ProjectFileConstants.Content;
+ }
+
+ ProjectMgr.Analyzer.AnalyzeFile(Url, ShouldAnalyze);
+
+ UpdateParentContentType();
+ ItemNode.ItemTypeChanged += ItemNode_ItemTypeChanged;
+
+ return includeInProject;
+ }
+
+ internal override int ExcludeFromProject() {
+ // Analyze on removing from a project so we have the most up to date sources for this.
+ // Don't report errors since the file won't remain part of the project. This removes the errors from the list.
+ ProjectMgr.Analyzer.AnalyzeFile(Url, false);
+ var excludeFromProject = base.ExcludeFromProject();
+
+ UpdateParentContentType();
+ ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
+
+ return excludeFromProject;
+ }
+
+ protected override void RaiseOnItemRemoved(string documentToRemove, string[] filesToBeDeleted) {
+ base.RaiseOnItemRemoved(documentToRemove, filesToBeDeleted);
+ foreach (var file in filesToBeDeleted) {
+ if (!File.Exists(file)) {
+ ProjectMgr.Analyzer.UnloadFile(file);
+ }
+ }
+ }
+
+ protected override void RenameChildNodes(FileNode parentNode) {
+ base.RenameChildNodes(parentNode);
+ this.ProjectMgr.Analyzer.ReloadComplete();
+ }
+
+ protected override NodeProperties CreatePropertiesObject() {
+ if (IsLinkFile) {
+ return new NodejsLinkFileNodeProperties(this);
+ } else if (IsNonMemberItem) {
+ return new ExcludedFileNodeProperties(this);
+ }
+
+ return new NodejsIncludedFileNodeProperties(this);
+ }
+
+ private void ItemNode_ItemTypeChanged(object sender, EventArgs e) {
+ // item type node was changed...
+ // if we have changed the type from compile to anything else, we should scrub
+ ProjectMgr.Analyzer.AnalyzeFile(Url, ShouldAnalyze);
+
+ UpdateParentContentType();
+ }
+
+ private void UpdateParentContentType() {
+ var parent = this.Parent as NodejsFolderNode;
+ if (parent != null) {
+ parent.UpdateContentType();
+ }
+ }
+
+ private void CloseWatcher() {
+ if (_watcher == null) {
+ ProjectMgr.UnregisterFileChangeNotification(this);
+ } else {
+ _watcher.EnableRaisingEvents = false;
+ _watcher.Dispose();
+ _watcher = null;
+ }
+ }
+
+ // TODO: Need to update analysis for files changed outside of VS
+ private void CreateWatcher(string filename) {
+#if FALSE
+ if (CommonUtils.IsSubpathOf(ProjectMgr.ProjectHome, filename)) {
+ // we want to subscribe to the project's file system watcher so users
+ // can continue to rename the directory which contains this file.
+ ProjectMgr.RegisterFileChangeNotification(this, FileContentsChanged);
+ } else {
+ // this is a link file which lives outside of our project directory,
+ // we'll need to watch the file directly, which means we're going to
+ // prevent it's parent directory from being renamed.
+ _watcher = new FileSystemWatcher(Path.GetDirectoryName(filename), Path.GetFileName(filename));
+ _watcher.EnableRaisingEvents = true;
+ _watcher.Changed += FileContentsChanged;
+ _watcher.Renamed += FileContentsChanged;
+ _watcher.NotifyFilter = NotifyFilters.LastWrite;
+ }
+#endif
+ }
+
+ internal override void RenameInStorage(string oldName, string newName) {
+ CloseWatcher();
+ bool renamed = false;
+ try {
+ base.RenameInStorage(oldName, newName);
+ renamed = true;
+ CreateWatcher(newName);
+ } finally {
+ if (!renamed) {
+ CreateWatcher(oldName);
+ }
+ }
+ }
+
+ public new NodejsProjectNode ProjectMgr {
+ get {
+ return (NodejsProjectNode)base.ProjectMgr;
+ }
+ }
+
+ public override void Remove(bool removeFromStorage) {
+ ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
+ base.Remove(removeFromStorage);
+ CloseWatcher();
+ }
+
+ public override void Close() {
+ ItemNode.ItemTypeChanged -= ItemNode_ItemTypeChanged;
+ base.Close();
+ CloseWatcher();
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/NodejsFolderNode.cs b/Nodejs/Product/Nodejs/Project/NodejsFolderNode.cs
index da3e1a83d..fda25299b 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsFolderNode.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsFolderNode.cs
@@ -1,250 +1,250 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.IO;
-using System.Text;
-using Microsoft.NodejsTools.Options;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-using VSLangProj;
-
-namespace Microsoft.NodejsTools.Project {
- class NodejsFolderNode : CommonFolderNode {
- private readonly CommonProjectNode _project;
- private FolderContentType _contentType = FolderContentType.NotAssigned;
- private bool _containsNodeOrBrowserFiles = false;
-
- public NodejsFolderNode(CommonProjectNode root, ProjectElement element) : base(root, element) {
- _project = root;
- }
-
- public FolderContentType ContentType {
- get {
- if (_contentType == FolderContentType.NotAssigned) {
- UpdateContentType();
- }
-
- return _contentType;
- }
- }
-
- public void UpdateContentType() {
- var oldContentType = _contentType;
- _contentType = FolderContentType.None;
- var parent = Parent as NodejsFolderNode;
- _containsNodeOrBrowserFiles = false;
-
- if (ItemNode.IsExcluded || ItemNode.Url.Contains(NodejsConstants.NodeModulesFolder)) {
- _contentType = FolderContentType.None;
- } else {
- // Iterate through all of the javascript files in a directory to determine whether
- // the build actions are Content, Compile, or a mix of the two.
- var nodejsFileNodes = EnumNodesOfType();
- FolderContentType contentType = FolderContentType.None;
- foreach (var fileNode in nodejsFileNodes) {
- if (!fileNode.Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
- continue;
- }
-
- var properties = fileNode.NodeProperties as IncludedFileNodeProperties;
- if (properties != null) {
- _containsNodeOrBrowserFiles = true;
- switch (properties.BuildAction) {
- case prjBuildAction.prjBuildActionContent:
- contentType |= FolderContentType.Browser;
- break;
- case prjBuildAction.prjBuildActionCompile:
- contentType |= FolderContentType.Node;
- break;
- }
-
- if (contentType == FolderContentType.Mixed) {
- break;
- }
- }
- }
-
- // If there are no relevant javascript files in the folder, then fall back to
- // the parent type. This enables us to provide good defaults in the event that
- // an item is added to the directory later.
- if (contentType == FolderContentType.None) {
- // Set as parent content type
- if (parent != null) {
- contentType = parent.ContentType;
- }
- }
-
- _contentType = contentType;
- ProjectMgr.ReDrawNode(this, UIHierarchyElement.Caption);
- }
-
- // Update the caption of the parent folder accordingly
- if (parent != null && _contentType != oldContentType) {
- parent.UpdateContentType();
- }
- }
-
- public override string Caption {
- get {
- var res = base.Caption;
-
- if (NodejsPackage.Instance.GeneralOptionsPage.ShowBrowserAndNodeLabels &&
- NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel != AnalysisLevel.Preview &&
- _containsNodeOrBrowserFiles) {
- res = AppendLabel(res, ContentType);
- }
- return res;
- }
- }
-
- public override void RemoveChild(HierarchyNode node) {
- base.RemoveChild(node);
- UpdateContentType();
- }
-
- public override void AddChild(HierarchyNode node) {
- base.AddChild(node);
-
- // If we are adding an immediate child to a directory, then set the content type
- // acording to the content type of the folder it is being moved to.
- var nodejsFileNode = node as NodejsFileNode;
- if (nodejsFileNode != null && nodejsFileNode.Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase) && nodejsFileNode.Parent == this) {
- var properties = nodejsFileNode.NodeProperties as IncludedFileNodeProperties;
- if (properties != null) {
- switch (ContentType) {
- case FolderContentType.Browser:
- properties.ItemType = ProjectFileConstants.Content;
- break;
- case FolderContentType.Node:
- properties.ItemType = ProjectFileConstants.Compile;
- break;
- }
- }
- }
-
- UpdateContentType();
- }
-
- ///
- /// Append a label denoting browser-side code, node, or both depending on the content type
- ///
- ///
- ///
- ///
- ///
- public static string AppendLabel(string folderName, FolderContentType contentType) {
- switch (contentType) {
- case FolderContentType.Browser:
- folderName += " (browser)";
- break;
- case FolderContentType.Node:
- folderName += " (node)";
- break;
- case FolderContentType.Mixed:
- folderName += " (node, browser)";
- break;
- }
- return folderName;
- }
-
- internal override int IncludeInProject(bool includeChildren) {
- // Include node_modules folder is generally unecessary and can cause VS to hang.
- // http://nodejstools.codeplex.com/workitem/1432
- // Check if the folder is node_modules, and warn the user to ensure they don't run into this issue or at least set expectations appropriately.
- string nodeModulesPath = Path.Combine(_project.FullPathToChildren, "node_modules");
- if (CommonUtils.IsSameDirectory(nodeModulesPath, ItemNode.Url) &&
- !ShouldIncludeNodeModulesFolderInProject()) {
- return VSConstants.S_OK;
- }
- return base.IncludeInProject(includeChildren);
- }
-
- internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
- if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidSetAsContent:
- if (_containsNodeOrBrowserFiles && ContentType.HasFlag(FolderContentType.Node)) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- }
- return VSConstants.S_OK;
- case PkgCmdId.cmdidSetAsCompile:
- if (_containsNodeOrBrowserFiles && ContentType.HasFlag(FolderContentType.Browser)) {
- result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
- }
- return VSConstants.S_OK;
- }
- }
- return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
- }
-
- internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidSetAsContent:
- SetItemTypeRecursively(prjBuildAction.prjBuildActionContent);
- return VSConstants.S_OK;
- case PkgCmdId.cmdidSetAsCompile:
- SetItemTypeRecursively(prjBuildAction.prjBuildActionCompile);
- return VSConstants.S_OK;
- }
- }
- return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
- }
-
- internal void SetItemTypeRecursively(prjBuildAction buildAction) {
- var fileNodesEnumerator = this.EnumNodesOfType().GetEnumerator();
- while (fileNodesEnumerator.MoveNext()) {
- var includedFileNodeProperties = fileNodesEnumerator.Current.NodeProperties as IncludedFileNodeProperties;
- if (includedFileNodeProperties != null && includedFileNodeProperties.URL.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
- includedFileNodeProperties.BuildAction = buildAction;
- }
- }
- }
-
- private bool ShouldIncludeNodeModulesFolderInProject() {
- var includeNodeModulesButton = new TaskDialogButton(SR.GetString(SR.IncludeNodeModulesIncludeTitle), SR.GetString(SR.IncludeNodeModulesIncludeDescription));
- var cancelOperationButton = new TaskDialogButton(SR.GetString(SR.IncludeNodeModulesCancelTitle));
- var taskDialog = new TaskDialog(_project.ProjectMgr.Site) {
- AllowCancellation = true,
- EnableHyperlinks = true,
- Title = SR.ProductName,
- MainIcon = TaskDialogIcon.Warning,
- Content = SR.GetString(SR.IncludeNodeModulesContent),
- Buttons = {
- cancelOperationButton,
- includeNodeModulesButton
- },
- FooterIcon = TaskDialogIcon.Information,
- Footer = SR.GetString(SR.IncludeNodeModulesInformation),
- SelectedButton = cancelOperationButton
- };
-
- var button = taskDialog.ShowModal();
-
- return button == includeNodeModulesButton;
- }
- }
-
- internal enum FolderContentType {
- None = 0,
- Browser = 1,
- Node = 2,
- Mixed = 3,
- NotAssigned
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.IO;
+using System.Text;
+using Microsoft.NodejsTools.Options;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using VSLangProj;
+
+namespace Microsoft.NodejsTools.Project {
+ class NodejsFolderNode : CommonFolderNode {
+ private readonly CommonProjectNode _project;
+ private FolderContentType _contentType = FolderContentType.NotAssigned;
+ private bool _containsNodeOrBrowserFiles = false;
+
+ public NodejsFolderNode(CommonProjectNode root, ProjectElement element) : base(root, element) {
+ _project = root;
+ }
+
+ public FolderContentType ContentType {
+ get {
+ if (_contentType == FolderContentType.NotAssigned) {
+ UpdateContentType();
+ }
+
+ return _contentType;
+ }
+ }
+
+ public void UpdateContentType() {
+ var oldContentType = _contentType;
+ _contentType = FolderContentType.None;
+ var parent = Parent as NodejsFolderNode;
+ _containsNodeOrBrowserFiles = false;
+
+ if (ItemNode.IsExcluded || ItemNode.Url.Contains(NodejsConstants.NodeModulesFolder)) {
+ _contentType = FolderContentType.None;
+ } else {
+ // Iterate through all of the javascript files in a directory to determine whether
+ // the build actions are Content, Compile, or a mix of the two.
+ var nodejsFileNodes = EnumNodesOfType();
+ FolderContentType contentType = FolderContentType.None;
+ foreach (var fileNode in nodejsFileNodes) {
+ if (!fileNode.Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
+ continue;
+ }
+
+ var properties = fileNode.NodeProperties as IncludedFileNodeProperties;
+ if (properties != null) {
+ _containsNodeOrBrowserFiles = true;
+ switch (properties.BuildAction) {
+ case prjBuildAction.prjBuildActionContent:
+ contentType |= FolderContentType.Browser;
+ break;
+ case prjBuildAction.prjBuildActionCompile:
+ contentType |= FolderContentType.Node;
+ break;
+ }
+
+ if (contentType == FolderContentType.Mixed) {
+ break;
+ }
+ }
+ }
+
+ // If there are no relevant javascript files in the folder, then fall back to
+ // the parent type. This enables us to provide good defaults in the event that
+ // an item is added to the directory later.
+ if (contentType == FolderContentType.None) {
+ // Set as parent content type
+ if (parent != null) {
+ contentType = parent.ContentType;
+ }
+ }
+
+ _contentType = contentType;
+ ProjectMgr.ReDrawNode(this, UIHierarchyElement.Caption);
+ }
+
+ // Update the caption of the parent folder accordingly
+ if (parent != null && _contentType != oldContentType) {
+ parent.UpdateContentType();
+ }
+ }
+
+ public override string Caption {
+ get {
+ var res = base.Caption;
+
+ if (NodejsPackage.Instance.GeneralOptionsPage.ShowBrowserAndNodeLabels &&
+ NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevel != AnalysisLevel.Preview &&
+ _containsNodeOrBrowserFiles) {
+ res = AppendLabel(res, ContentType);
+ }
+ return res;
+ }
+ }
+
+ public override void RemoveChild(HierarchyNode node) {
+ base.RemoveChild(node);
+ UpdateContentType();
+ }
+
+ public override void AddChild(HierarchyNode node) {
+ base.AddChild(node);
+
+ // If we are adding an immediate child to a directory, then set the content type
+ // acording to the content type of the folder it is being moved to.
+ var nodejsFileNode = node as NodejsFileNode;
+ if (nodejsFileNode != null && nodejsFileNode.Url.EndsWith(".js", StringComparison.OrdinalIgnoreCase) && nodejsFileNode.Parent == this) {
+ var properties = nodejsFileNode.NodeProperties as IncludedFileNodeProperties;
+ if (properties != null) {
+ switch (ContentType) {
+ case FolderContentType.Browser:
+ properties.ItemType = ProjectFileConstants.Content;
+ break;
+ case FolderContentType.Node:
+ properties.ItemType = ProjectFileConstants.Compile;
+ break;
+ }
+ }
+ }
+
+ UpdateContentType();
+ }
+
+ ///
+ /// Append a label denoting browser-side code, node, or both depending on the content type
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string AppendLabel(string folderName, FolderContentType contentType) {
+ switch (contentType) {
+ case FolderContentType.Browser:
+ folderName += " (browser)";
+ break;
+ case FolderContentType.Node:
+ folderName += " (node)";
+ break;
+ case FolderContentType.Mixed:
+ folderName += " (node, browser)";
+ break;
+ }
+ return folderName;
+ }
+
+ internal override int IncludeInProject(bool includeChildren) {
+ // Include node_modules folder is generally unecessary and can cause VS to hang.
+ // http://nodejstools.codeplex.com/workitem/1432
+ // Check if the folder is node_modules, and warn the user to ensure they don't run into this issue or at least set expectations appropriately.
+ string nodeModulesPath = Path.Combine(_project.FullPathToChildren, "node_modules");
+ if (CommonUtils.IsSameDirectory(nodeModulesPath, ItemNode.Url) &&
+ !ShouldIncludeNodeModulesFolderInProject()) {
+ return VSConstants.S_OK;
+ }
+ return base.IncludeInProject(includeChildren);
+ }
+
+ internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
+ if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidSetAsContent:
+ if (_containsNodeOrBrowserFiles && ContentType.HasFlag(FolderContentType.Node)) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ }
+ return VSConstants.S_OK;
+ case PkgCmdId.cmdidSetAsCompile:
+ if (_containsNodeOrBrowserFiles && ContentType.HasFlag(FolderContentType.Browser)) {
+ result = QueryStatusResult.ENABLED | QueryStatusResult.SUPPORTED;
+ }
+ return VSConstants.S_OK;
+ }
+ }
+ return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
+ }
+
+ internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidSetAsContent:
+ SetItemTypeRecursively(prjBuildAction.prjBuildActionContent);
+ return VSConstants.S_OK;
+ case PkgCmdId.cmdidSetAsCompile:
+ SetItemTypeRecursively(prjBuildAction.prjBuildActionCompile);
+ return VSConstants.S_OK;
+ }
+ }
+ return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+ internal void SetItemTypeRecursively(prjBuildAction buildAction) {
+ var fileNodesEnumerator = this.EnumNodesOfType().GetEnumerator();
+ while (fileNodesEnumerator.MoveNext()) {
+ var includedFileNodeProperties = fileNodesEnumerator.Current.NodeProperties as IncludedFileNodeProperties;
+ if (includedFileNodeProperties != null && includedFileNodeProperties.URL.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) {
+ includedFileNodeProperties.BuildAction = buildAction;
+ }
+ }
+ }
+
+ private bool ShouldIncludeNodeModulesFolderInProject() {
+ var includeNodeModulesButton = new TaskDialogButton(SR.GetString(SR.IncludeNodeModulesIncludeTitle), SR.GetString(SR.IncludeNodeModulesIncludeDescription));
+ var cancelOperationButton = new TaskDialogButton(SR.GetString(SR.IncludeNodeModulesCancelTitle));
+ var taskDialog = new TaskDialog(_project.ProjectMgr.Site) {
+ AllowCancellation = true,
+ EnableHyperlinks = true,
+ Title = SR.ProductName,
+ MainIcon = TaskDialogIcon.Warning,
+ Content = SR.GetString(SR.IncludeNodeModulesContent),
+ Buttons = {
+ cancelOperationButton,
+ includeNodeModulesButton
+ },
+ FooterIcon = TaskDialogIcon.Information,
+ Footer = SR.GetString(SR.IncludeNodeModulesInformation),
+ SelectedButton = cancelOperationButton
+ };
+
+ var button = taskDialog.ShowModal();
+
+ return button == includeNodeModulesButton;
+ }
+ }
+
+ internal enum FolderContentType {
+ None = 0,
+ Browser = 1,
+ Node = 2,
+ Mixed = 3,
+ NotAssigned
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/NodejsGeneralPropertyPageControl.cs b/Nodejs/Product/Nodejs/Project/NodejsGeneralPropertyPageControl.cs
index 44d1c2098..3d646f5f1 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsGeneralPropertyPageControl.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsGeneralPropertyPageControl.cs
@@ -23,7 +23,7 @@
using System.Windows.Forms;
using Microsoft.VisualStudioTools;
using Microsoft.VisualStudioTools.Project;
-
+
namespace Microsoft.NodejsTools.Project {
partial class NodejsGeneralPropertyPageControl : UserControl {
private readonly NodejsGeneralPropertyPage _propPage;
diff --git a/Nodejs/Product/Nodejs/Project/NodejsProjectLauncher.cs b/Nodejs/Product/Nodejs/Project/NodejsProjectLauncher.cs
index c7ef49642..e2186f36c 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsProjectLauncher.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsProjectLauncher.cs
@@ -1,438 +1,438 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading;
-using System.Web;
-using System.Windows.Forms;
-using Microsoft.NodejsTools.Debugger;
-using Microsoft.NodejsTools.Debugger.DebugEngine;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-using Microsoft.NodejsTools.TypeScript;
-
-namespace Microsoft.NodejsTools.Project {
- class NodejsProjectLauncher : IProjectLauncher {
- private readonly NodejsProjectNode _project;
- private int? _testServerPort;
-
- public NodejsProjectLauncher(NodejsProjectNode project) {
- _project = project;
-
- var portNumber = _project.GetProjectProperty(NodejsConstants.NodejsPort);
- int portNum;
- if (Int32.TryParse(portNumber, out portNum)) {
- _testServerPort = portNum;
- }
- }
-
- #region IProjectLauncher Members
-
- public int LaunchProject(bool debug) {
- NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.Launch, debug ? 1 : 0);
- return Start(ResolveStartupFile(), debug);
- }
-
- public int LaunchFile(string file, bool debug) {
- NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.Launch, debug ? 1 : 0);
- return Start(file, debug);
- }
-
- private int Start(string file, bool debug) {
- string nodePath = GetNodePath();
- if (nodePath == null) {
- Nodejs.ShowNodejsNotInstalled();
- return VSConstants.S_OK;
- }
-
- bool startBrowser = ShouldStartBrowser();
-
- if (debug) {
- StartWithDebugger(file);
- } else {
- var psi = new ProcessStartInfo();
- psi.UseShellExecute = false;
-
- psi.FileName = nodePath;
- psi.Arguments = GetFullArguments(file);
- psi.WorkingDirectory = _project.GetWorkingDirectory();
-
- string webBrowserUrl = GetFullUrl();
- Uri uri = null;
- if (!String.IsNullOrWhiteSpace(webBrowserUrl)) {
- uri = new Uri(webBrowserUrl);
-
- psi.EnvironmentVariables["PORT"] = uri.Port.ToString();
- }
-
- foreach (var nameValue in GetEnvironmentVariables()) {
- psi.EnvironmentVariables[nameValue.Key] = nameValue.Value;
- }
-
- var process = NodeProcess.Start(
- psi,
- NodejsPackage.Instance.GeneralOptionsPage.WaitOnAbnormalExit,
- NodejsPackage.Instance.GeneralOptionsPage.WaitOnNormalExit
- );
-
- if (startBrowser && uri != null) {
- OnPortOpenedHandler.CreateHandler(
- uri.Port,
- shortCircuitPredicate: () => process.HasExited,
- action: () => {
- VsShellUtilities.OpenBrowser(webBrowserUrl, (uint)__VSOSPFLAGS.OSP_LaunchNewBrowser);
- }
- );
- }
- }
- return VSConstants.S_OK;
- }
-
- private string GetFullArguments(string file, bool includeNodeArgs = true) {
- string res = String.Empty;
- if (includeNodeArgs) {
- var nodeArgs = _project.GetProjectProperty(NodejsConstants.NodeExeArguments);
- if (!String.IsNullOrWhiteSpace(nodeArgs)) {
- res = nodeArgs + " ";
- }
- }
- res += "\"" + file + "\"";
- var scriptArgs = _project.GetProjectProperty(NodejsConstants.ScriptArguments);
- if (!String.IsNullOrWhiteSpace(scriptArgs)) {
- res += " " + scriptArgs;
- }
- return res;
- }
-
- private string GetNodePath() {
- var overridePath = _project.GetProjectProperty(NodejsConstants.NodeExePath);
- return Nodejs.GetAbsoluteNodeExePath(_project.ProjectHome, overridePath);
- }
-
- #endregion
-
- private string GetFullUrl() {
- var host = _project.GetProjectProperty(NodejsConstants.LaunchUrl);
-
- try {
- return GetFullUrl(host, TestServerPort);
- } catch (UriFormatException) {
- var output = OutputWindowRedirector.GetGeneral(NodejsPackage.Instance);
- output.WriteErrorLine(SR.GetString(SR.ErrorInvalidLaunchUrl, host));
- output.ShowAndActivate();
- return string.Empty;
- }
- }
-
- internal static string GetFullUrl(string host, int port) {
- UriBuilder builder;
- Uri uri;
- if (Uri.TryCreate(host, UriKind.Absolute, out uri)) {
- builder = new UriBuilder(uri);
- } else {
- builder = new UriBuilder();
- builder.Scheme = Uri.UriSchemeHttp;
- builder.Host = "localhost";
- builder.Path = host;
- }
-
- builder.Port = port;
-
- return builder.ToString();
- }
-
- private string TestServerPortString {
- get {
- if (!_testServerPort.HasValue) {
- _testServerPort = GetFreePort();
- }
- return _testServerPort.Value.ToString(CultureInfo.InvariantCulture);
- }
- }
-
- private int TestServerPort {
- get {
- if (!_testServerPort.HasValue) {
- _testServerPort = GetFreePort();
- }
- return _testServerPort.Value;
- }
- }
-
- ///
- /// Default implementation of the "Start Debugging" command.
- ///
- private void StartWithDebugger(string startupFile) {
- VsDebugTargetInfo dbgInfo = new VsDebugTargetInfo();
- dbgInfo.cbSize = (uint)Marshal.SizeOf(dbgInfo);
-
- if (SetupDebugInfo(ref dbgInfo, startupFile)) {
- LaunchDebugger(_project.Site, dbgInfo);
- }
- }
-
-
- private void LaunchDebugger(IServiceProvider provider, VsDebugTargetInfo dbgInfo) {
- if (!Directory.Exists(dbgInfo.bstrCurDir)) {
- MessageBox.Show(String.Format("Working directory \"{0}\" does not exist.", dbgInfo.bstrCurDir), "Node.js Tools for Visual Studio");
- } else if (!File.Exists(dbgInfo.bstrExe)) {
- MessageBox.Show(String.Format("Interpreter \"{0}\" does not exist.", dbgInfo.bstrExe), "Node.js Tools for Visual Studio");
- } else if (DoesProjectSupportDebugging()) {
- VsShellUtilities.LaunchDebugger(provider, dbgInfo);
- }
- }
-
- private bool DoesProjectSupportDebugging() {
- var typeScriptOutFile = _project.GetProjectProperty("TypeScriptOutFile");
- if (!string.IsNullOrEmpty(typeScriptOutFile)) {
- return MessageBox.Show(
- "This TypeScript project has 'Combine Javascript output into file' option enabled. This option is not supported by NTVS debugger, " +
- "and may result in erratic behavior of breakpoints, stepping, and debug tool windows. Are you sure you want to start debugging?",
- SR.ProductName,
- MessageBoxButtons.YesNo,
- MessageBoxIcon.Warning
- ) == DialogResult.Yes;
- }
-
- return true;
- }
-
- private void AppendOption(ref VsDebugTargetInfo dbgInfo, string option, string value) {
- if (!String.IsNullOrWhiteSpace(dbgInfo.bstrOptions)) {
- dbgInfo.bstrOptions += ";";
- }
-
- dbgInfo.bstrOptions += option + "=" + HttpUtility.UrlEncode(value);
- }
-
- ///
- /// Sets up debugger information.
- ///
- private bool SetupDebugInfo(ref VsDebugTargetInfo dbgInfo, string startupFile) {
- dbgInfo.dlo = DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
-
- dbgInfo.bstrExe = GetNodePath();
- dbgInfo.bstrCurDir = _project.GetWorkingDirectory();
- dbgInfo.bstrArg = GetFullArguments(startupFile, includeNodeArgs: false); // we need to supply node args via options
- dbgInfo.bstrRemoteMachine = null;
- var nodeArgs = _project.GetProjectProperty(NodejsConstants.NodeExeArguments);
- if (!String.IsNullOrWhiteSpace(nodeArgs)) {
- AppendOption(ref dbgInfo, AD7Engine.InterpreterOptions, nodeArgs);
- }
-
- var url = GetFullUrl();
- if (ShouldStartBrowser() && !String.IsNullOrWhiteSpace(url)) {
- AppendOption(ref dbgInfo, AD7Engine.WebBrowserUrl, url);
- }
-
- var debuggerPort = _project.GetProjectProperty(NodejsConstants.DebuggerPort);
- if (!String.IsNullOrWhiteSpace(debuggerPort)) {
- AppendOption(ref dbgInfo, AD7Engine.DebuggerPort, debuggerPort);
- }
-
- if (NodejsPackage.Instance.GeneralOptionsPage.WaitOnAbnormalExit) {
- AppendOption(ref dbgInfo, AD7Engine.WaitOnAbnormalExitSetting, "true");
- }
-
- if (NodejsPackage.Instance.GeneralOptionsPage.WaitOnNormalExit) {
- AppendOption(ref dbgInfo, AD7Engine.WaitOnNormalExitSetting, "true");
- }
-
- dbgInfo.fSendStdoutToOutputWindow = 0;
-
- StringDictionary env = new StringDictionary();
- if (!String.IsNullOrWhiteSpace(url)) {
- Uri webUrl = new Uri(url);
- env["PORT"] = webUrl.Port.ToString();
- }
-
- foreach (var nameValue in GetEnvironmentVariables()) {
- env[nameValue.Key] = nameValue.Value;
- }
-
- if (env.Count > 0) {
- // add any inherited env vars
- var variables = Environment.GetEnvironmentVariables();
- foreach (var key in variables.Keys) {
- string strKey = (string)key;
- if (!env.ContainsKey(strKey)) {
- env.Add(strKey, (string)variables[key]);
- }
- }
-
- //Environemnt variables should be passed as a
- //null-terminated block of null-terminated strings.
- //Each string is in the following form:name=value\0
- StringBuilder buf = new StringBuilder();
- foreach (DictionaryEntry entry in env) {
- buf.AppendFormat("{0}={1}\0", entry.Key, entry.Value);
- }
- buf.Append("\0");
- dbgInfo.bstrEnv = buf.ToString();
- }
-
- // Set the Node debugger
- dbgInfo.clsidCustom = AD7Engine.DebugEngineGuid;
- dbgInfo.grfLaunch = (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_StopDebuggingOnEnd;
- return true;
- }
-
- private bool ShouldStartBrowser() {
- var startBrowser = _project.GetProjectProperty(NodejsConstants.StartWebBrowser);
- bool fStartBrowser;
- if (!String.IsNullOrEmpty(startBrowser) &&
- Boolean.TryParse(startBrowser, out fStartBrowser)) {
- return fStartBrowser;
- }
-
- return true;
- }
-
- private IEnumerable> GetEnvironmentVariables() {
- var envVars = _project.GetProjectProperty(NodejsConstants.Environment);
- if (envVars != null) {
- foreach (var envVar in envVars.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) {
- var nameValue = envVar.Split(new[] { '=' }, 2);
- if (nameValue.Length == 2) {
- yield return new KeyValuePair(nameValue[0], nameValue[1]);
- }
- }
- }
- }
-
- private static int GetFreePort() {
- return Enumerable.Range(new Random().Next(1200, 2000), 60000).Except(
- from connection in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()
- select connection.LocalEndPoint.Port
- ).First();
- }
-
- private string ResolveStartupFile() {
- string startupFile = _project.GetStartupFile();
- if (string.IsNullOrEmpty(startupFile)) {
- throw new ApplicationException("Please select a startup file to launch by right-clicking the file in Solution Explorer and selecting 'Set as Node.js Startup File' or by modifying your configuration in project properties.");
- }
-
- if (TypeScriptHelpers.IsTypeScriptFile(startupFile)) {
- startupFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(_project, startupFile);
- }
- return startupFile;
- }
- }
-
- internal class OnPortOpenedHandler {
-
- class OnPortOpenedInfo {
- public readonly int Port;
- public readonly TimeSpan? Timeout;
- public readonly int Sleep;
- public readonly Func ShortCircuitPredicate;
- public readonly Action Action;
- public readonly DateTime StartTime;
-
- public OnPortOpenedInfo(
- int port,
- int? timeout = null,
- int? sleep = null,
- Func shortCircuitPredicate = null,
- Action action = null
- ) {
- Port = port;
- if (timeout.HasValue) {
- Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(timeout));
- }
- Sleep = sleep ?? 500; // 1/2 second sleep
- ShortCircuitPredicate = shortCircuitPredicate ?? (() => false);
- Action = action ?? (() => { });
- StartTime = System.DateTime.Now;
- }
- }
-
- internal static void CreateHandler(
- int port,
- int? timeout = null,
- int? sleep = null,
- Func shortCircuitPredicate = null,
- Action action = null
- ) {
- ThreadPool.QueueUserWorkItem(
- OnPortOpened,
- new OnPortOpenedInfo(
- port,
- timeout,
- sleep,
- shortCircuitPredicate,
- action
- )
- );
- }
-
- private static void OnPortOpened(object infoObj) {
- var info = (OnPortOpenedInfo)infoObj;
-
- using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
- socket.Blocking = true;
- try {
- while (true) {
- // Short circuit
- if (info.ShortCircuitPredicate()) {
- return;
- }
-
- // Try connect
- try {
- socket.Connect(IPAddress.Loopback, info.Port);
- break;
- } catch {
- // Connect failure
- // Fall through
- }
-
- // Timeout
- if (info.Timeout.HasValue && (System.DateTime.Now - info.StartTime) >= info.Timeout) {
- break;
- }
-
- // Sleep
- System.Threading.Thread.Sleep(info.Sleep);
- }
- } finally {
- socket.Close();
- }
- }
-
- // Launch browser (if not short-circuited)
- if (!info.ShortCircuitPredicate()) {
- info.Action();
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Web;
+using System.Windows.Forms;
+using Microsoft.NodejsTools.Debugger;
+using Microsoft.NodejsTools.Debugger.DebugEngine;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using Microsoft.NodejsTools.TypeScript;
+
+namespace Microsoft.NodejsTools.Project {
+ class NodejsProjectLauncher : IProjectLauncher {
+ private readonly NodejsProjectNode _project;
+ private int? _testServerPort;
+
+ public NodejsProjectLauncher(NodejsProjectNode project) {
+ _project = project;
+
+ var portNumber = _project.GetProjectProperty(NodejsConstants.NodejsPort);
+ int portNum;
+ if (Int32.TryParse(portNumber, out portNum)) {
+ _testServerPort = portNum;
+ }
+ }
+
+ #region IProjectLauncher Members
+
+ public int LaunchProject(bool debug) {
+ NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.Launch, debug ? 1 : 0);
+ return Start(ResolveStartupFile(), debug);
+ }
+
+ public int LaunchFile(string file, bool debug) {
+ NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.Launch, debug ? 1 : 0);
+ return Start(file, debug);
+ }
+
+ private int Start(string file, bool debug) {
+ string nodePath = GetNodePath();
+ if (nodePath == null) {
+ Nodejs.ShowNodejsNotInstalled();
+ return VSConstants.S_OK;
+ }
+
+ bool startBrowser = ShouldStartBrowser();
+
+ if (debug) {
+ StartWithDebugger(file);
+ } else {
+ var psi = new ProcessStartInfo();
+ psi.UseShellExecute = false;
+
+ psi.FileName = nodePath;
+ psi.Arguments = GetFullArguments(file);
+ psi.WorkingDirectory = _project.GetWorkingDirectory();
+
+ string webBrowserUrl = GetFullUrl();
+ Uri uri = null;
+ if (!String.IsNullOrWhiteSpace(webBrowserUrl)) {
+ uri = new Uri(webBrowserUrl);
+
+ psi.EnvironmentVariables["PORT"] = uri.Port.ToString();
+ }
+
+ foreach (var nameValue in GetEnvironmentVariables()) {
+ psi.EnvironmentVariables[nameValue.Key] = nameValue.Value;
+ }
+
+ var process = NodeProcess.Start(
+ psi,
+ NodejsPackage.Instance.GeneralOptionsPage.WaitOnAbnormalExit,
+ NodejsPackage.Instance.GeneralOptionsPage.WaitOnNormalExit
+ );
+
+ if (startBrowser && uri != null) {
+ OnPortOpenedHandler.CreateHandler(
+ uri.Port,
+ shortCircuitPredicate: () => process.HasExited,
+ action: () => {
+ VsShellUtilities.OpenBrowser(webBrowserUrl, (uint)__VSOSPFLAGS.OSP_LaunchNewBrowser);
+ }
+ );
+ }
+ }
+ return VSConstants.S_OK;
+ }
+
+ private string GetFullArguments(string file, bool includeNodeArgs = true) {
+ string res = String.Empty;
+ if (includeNodeArgs) {
+ var nodeArgs = _project.GetProjectProperty(NodejsConstants.NodeExeArguments);
+ if (!String.IsNullOrWhiteSpace(nodeArgs)) {
+ res = nodeArgs + " ";
+ }
+ }
+ res += "\"" + file + "\"";
+ var scriptArgs = _project.GetProjectProperty(NodejsConstants.ScriptArguments);
+ if (!String.IsNullOrWhiteSpace(scriptArgs)) {
+ res += " " + scriptArgs;
+ }
+ return res;
+ }
+
+ private string GetNodePath() {
+ var overridePath = _project.GetProjectProperty(NodejsConstants.NodeExePath);
+ return Nodejs.GetAbsoluteNodeExePath(_project.ProjectHome, overridePath);
+ }
+
+ #endregion
+
+ private string GetFullUrl() {
+ var host = _project.GetProjectProperty(NodejsConstants.LaunchUrl);
+
+ try {
+ return GetFullUrl(host, TestServerPort);
+ } catch (UriFormatException) {
+ var output = OutputWindowRedirector.GetGeneral(NodejsPackage.Instance);
+ output.WriteErrorLine(SR.GetString(SR.ErrorInvalidLaunchUrl, host));
+ output.ShowAndActivate();
+ return string.Empty;
+ }
+ }
+
+ internal static string GetFullUrl(string host, int port) {
+ UriBuilder builder;
+ Uri uri;
+ if (Uri.TryCreate(host, UriKind.Absolute, out uri)) {
+ builder = new UriBuilder(uri);
+ } else {
+ builder = new UriBuilder();
+ builder.Scheme = Uri.UriSchemeHttp;
+ builder.Host = "localhost";
+ builder.Path = host;
+ }
+
+ builder.Port = port;
+
+ return builder.ToString();
+ }
+
+ private string TestServerPortString {
+ get {
+ if (!_testServerPort.HasValue) {
+ _testServerPort = GetFreePort();
+ }
+ return _testServerPort.Value.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+
+ private int TestServerPort {
+ get {
+ if (!_testServerPort.HasValue) {
+ _testServerPort = GetFreePort();
+ }
+ return _testServerPort.Value;
+ }
+ }
+
+ ///
+ /// Default implementation of the "Start Debugging" command.
+ ///
+ private void StartWithDebugger(string startupFile) {
+ VsDebugTargetInfo dbgInfo = new VsDebugTargetInfo();
+ dbgInfo.cbSize = (uint)Marshal.SizeOf(dbgInfo);
+
+ if (SetupDebugInfo(ref dbgInfo, startupFile)) {
+ LaunchDebugger(_project.Site, dbgInfo);
+ }
+ }
+
+
+ private void LaunchDebugger(IServiceProvider provider, VsDebugTargetInfo dbgInfo) {
+ if (!Directory.Exists(dbgInfo.bstrCurDir)) {
+ MessageBox.Show(String.Format("Working directory \"{0}\" does not exist.", dbgInfo.bstrCurDir), "Node.js Tools for Visual Studio");
+ } else if (!File.Exists(dbgInfo.bstrExe)) {
+ MessageBox.Show(String.Format("Interpreter \"{0}\" does not exist.", dbgInfo.bstrExe), "Node.js Tools for Visual Studio");
+ } else if (DoesProjectSupportDebugging()) {
+ VsShellUtilities.LaunchDebugger(provider, dbgInfo);
+ }
+ }
+
+ private bool DoesProjectSupportDebugging() {
+ var typeScriptOutFile = _project.GetProjectProperty("TypeScriptOutFile");
+ if (!string.IsNullOrEmpty(typeScriptOutFile)) {
+ return MessageBox.Show(
+ "This TypeScript project has 'Combine Javascript output into file' option enabled. This option is not supported by NTVS debugger, " +
+ "and may result in erratic behavior of breakpoints, stepping, and debug tool windows. Are you sure you want to start debugging?",
+ SR.ProductName,
+ MessageBoxButtons.YesNo,
+ MessageBoxIcon.Warning
+ ) == DialogResult.Yes;
+ }
+
+ return true;
+ }
+
+ private void AppendOption(ref VsDebugTargetInfo dbgInfo, string option, string value) {
+ if (!String.IsNullOrWhiteSpace(dbgInfo.bstrOptions)) {
+ dbgInfo.bstrOptions += ";";
+ }
+
+ dbgInfo.bstrOptions += option + "=" + HttpUtility.UrlEncode(value);
+ }
+
+ ///
+ /// Sets up debugger information.
+ ///
+ private bool SetupDebugInfo(ref VsDebugTargetInfo dbgInfo, string startupFile) {
+ dbgInfo.dlo = DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
+
+ dbgInfo.bstrExe = GetNodePath();
+ dbgInfo.bstrCurDir = _project.GetWorkingDirectory();
+ dbgInfo.bstrArg = GetFullArguments(startupFile, includeNodeArgs: false); // we need to supply node args via options
+ dbgInfo.bstrRemoteMachine = null;
+ var nodeArgs = _project.GetProjectProperty(NodejsConstants.NodeExeArguments);
+ if (!String.IsNullOrWhiteSpace(nodeArgs)) {
+ AppendOption(ref dbgInfo, AD7Engine.InterpreterOptions, nodeArgs);
+ }
+
+ var url = GetFullUrl();
+ if (ShouldStartBrowser() && !String.IsNullOrWhiteSpace(url)) {
+ AppendOption(ref dbgInfo, AD7Engine.WebBrowserUrl, url);
+ }
+
+ var debuggerPort = _project.GetProjectProperty(NodejsConstants.DebuggerPort);
+ if (!String.IsNullOrWhiteSpace(debuggerPort)) {
+ AppendOption(ref dbgInfo, AD7Engine.DebuggerPort, debuggerPort);
+ }
+
+ if (NodejsPackage.Instance.GeneralOptionsPage.WaitOnAbnormalExit) {
+ AppendOption(ref dbgInfo, AD7Engine.WaitOnAbnormalExitSetting, "true");
+ }
+
+ if (NodejsPackage.Instance.GeneralOptionsPage.WaitOnNormalExit) {
+ AppendOption(ref dbgInfo, AD7Engine.WaitOnNormalExitSetting, "true");
+ }
+
+ dbgInfo.fSendStdoutToOutputWindow = 0;
+
+ StringDictionary env = new StringDictionary();
+ if (!String.IsNullOrWhiteSpace(url)) {
+ Uri webUrl = new Uri(url);
+ env["PORT"] = webUrl.Port.ToString();
+ }
+
+ foreach (var nameValue in GetEnvironmentVariables()) {
+ env[nameValue.Key] = nameValue.Value;
+ }
+
+ if (env.Count > 0) {
+ // add any inherited env vars
+ var variables = Environment.GetEnvironmentVariables();
+ foreach (var key in variables.Keys) {
+ string strKey = (string)key;
+ if (!env.ContainsKey(strKey)) {
+ env.Add(strKey, (string)variables[key]);
+ }
+ }
+
+ //Environemnt variables should be passed as a
+ //null-terminated block of null-terminated strings.
+ //Each string is in the following form:name=value\0
+ StringBuilder buf = new StringBuilder();
+ foreach (DictionaryEntry entry in env) {
+ buf.AppendFormat("{0}={1}\0", entry.Key, entry.Value);
+ }
+ buf.Append("\0");
+ dbgInfo.bstrEnv = buf.ToString();
+ }
+
+ // Set the Node debugger
+ dbgInfo.clsidCustom = AD7Engine.DebugEngineGuid;
+ dbgInfo.grfLaunch = (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_StopDebuggingOnEnd;
+ return true;
+ }
+
+ private bool ShouldStartBrowser() {
+ var startBrowser = _project.GetProjectProperty(NodejsConstants.StartWebBrowser);
+ bool fStartBrowser;
+ if (!String.IsNullOrEmpty(startBrowser) &&
+ Boolean.TryParse(startBrowser, out fStartBrowser)) {
+ return fStartBrowser;
+ }
+
+ return true;
+ }
+
+ private IEnumerable> GetEnvironmentVariables() {
+ var envVars = _project.GetProjectProperty(NodejsConstants.Environment);
+ if (envVars != null) {
+ foreach (var envVar in envVars.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) {
+ var nameValue = envVar.Split(new[] { '=' }, 2);
+ if (nameValue.Length == 2) {
+ yield return new KeyValuePair(nameValue[0], nameValue[1]);
+ }
+ }
+ }
+ }
+
+ private static int GetFreePort() {
+ return Enumerable.Range(new Random().Next(1200, 2000), 60000).Except(
+ from connection in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()
+ select connection.LocalEndPoint.Port
+ ).First();
+ }
+
+ private string ResolveStartupFile() {
+ string startupFile = _project.GetStartupFile();
+ if (string.IsNullOrEmpty(startupFile)) {
+ throw new ApplicationException("Please select a startup file to launch by right-clicking the file in Solution Explorer and selecting 'Set as Node.js Startup File' or by modifying your configuration in project properties.");
+ }
+
+ if (TypeScriptHelpers.IsTypeScriptFile(startupFile)) {
+ startupFile = TypeScriptHelpers.GetTypeScriptBackedJavaScriptFile(_project, startupFile);
+ }
+ return startupFile;
+ }
+ }
+
+ internal class OnPortOpenedHandler {
+
+ class OnPortOpenedInfo {
+ public readonly int Port;
+ public readonly TimeSpan? Timeout;
+ public readonly int Sleep;
+ public readonly Func ShortCircuitPredicate;
+ public readonly Action Action;
+ public readonly DateTime StartTime;
+
+ public OnPortOpenedInfo(
+ int port,
+ int? timeout = null,
+ int? sleep = null,
+ Func shortCircuitPredicate = null,
+ Action action = null
+ ) {
+ Port = port;
+ if (timeout.HasValue) {
+ Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(timeout));
+ }
+ Sleep = sleep ?? 500; // 1/2 second sleep
+ ShortCircuitPredicate = shortCircuitPredicate ?? (() => false);
+ Action = action ?? (() => { });
+ StartTime = System.DateTime.Now;
+ }
+ }
+
+ internal static void CreateHandler(
+ int port,
+ int? timeout = null,
+ int? sleep = null,
+ Func shortCircuitPredicate = null,
+ Action action = null
+ ) {
+ ThreadPool.QueueUserWorkItem(
+ OnPortOpened,
+ new OnPortOpenedInfo(
+ port,
+ timeout,
+ sleep,
+ shortCircuitPredicate,
+ action
+ )
+ );
+ }
+
+ private static void OnPortOpened(object infoObj) {
+ var info = (OnPortOpenedInfo)infoObj;
+
+ using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
+ socket.Blocking = true;
+ try {
+ while (true) {
+ // Short circuit
+ if (info.ShortCircuitPredicate()) {
+ return;
+ }
+
+ // Try connect
+ try {
+ socket.Connect(IPAddress.Loopback, info.Port);
+ break;
+ } catch {
+ // Connect failure
+ // Fall through
+ }
+
+ // Timeout
+ if (info.Timeout.HasValue && (System.DateTime.Now - info.StartTime) >= info.Timeout) {
+ break;
+ }
+
+ // Sleep
+ System.Threading.Thread.Sleep(info.Sleep);
+ }
+ } finally {
+ socket.Close();
+ }
+ }
+
+ // Launch browser (if not short-circuited)
+ if (!info.ShortCircuitPredicate()) {
+ info.Action();
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/NodejsProjectNode.cs b/Nodejs/Product/Nodejs/Project/NodejsProjectNode.cs
index 2538209c5..7c1388592 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsProjectNode.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsProjectNode.cs
@@ -1,1103 +1,1103 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.NodejsTools.Intellisense;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.NodejsTools.ProjectWizard;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudioTools;
-using Microsoft.VisualStudioTools.Project;
-using Microsoft.VisualStudioTools.Project.Automation;
-using MSBuild = Microsoft.Build.Evaluation;
-using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
-#if DEV14_OR_LATER
-using Microsoft.VisualStudio.Imaging.Interop;
-using Microsoft.VisualStudio.Imaging;
-#endif
-
-namespace Microsoft.NodejsTools.Project {
- class NodejsProjectNode : CommonProjectNode, VsWebSite.VSWebSite, INodePackageModulesCommands, IVsBuildPropertyStorage {
- private VsProjectAnalyzer _analyzer;
- private readonly HashSet _warningFiles = new HashSet();
- private readonly HashSet _errorFiles = new HashSet();
- private string[] _analysisIgnoredDirs = new string[1] { NodejsConstants.NodeModulesStagingFolder };
- private int _maxFileSize = 1024 * 512;
- internal readonly RequireCompletionCache _requireCompletionCache = new RequireCompletionCache();
- private string _intermediateOutputPath;
- private readonly Dictionary _imageIndexFromNameDictionary = new Dictionary();
-
- // We delay analysis until things calm down in the node_modules folder.
- internal Queue DelayedAnalysisQueue = new Queue();
- private object _idleNodeModulesLock = new object();
- private volatile bool _isIdleNodeModules = false;
- private Timer _idleNodeModulesTimer;
-
- public NodejsProjectNode(NodejsProjectPackage package)
- : base(
- package,
-#if DEV14_OR_LATER
- null
-#else
- Utilities.GetImageList(typeof(NodejsProjectNode).Assembly.GetManifestResourceStream("Microsoft.NodejsTools.Resources.Icons.NodejsImageList.bmp"))
-#endif
- ) {
- Type projectNodePropsType = typeof(NodejsProjectNodeProperties);
- AddCATIDMapping(projectNodePropsType, projectNodePropsType.GUID);
-#pragma warning disable 0612
- InitNodejsProjectImages();
-#pragma warning restore 0612
-
- }
-
- public VsProjectAnalyzer Analyzer {
- get {
- return _analyzer;
- }
- }
-
- private void OnIdleNodeModules(object state) {
- lock (_idleNodeModulesLock) {
- _isIdleNodeModules = true;
- }
-
- while (DelayedAnalysisQueue.Count > 0) {
- lock (_idleNodeModulesLock) {
- if (!_isIdleNodeModules) {
- return;
- }
- }
- var fileNode = DelayedAnalysisQueue.Dequeue();
- if (fileNode != null) {
- fileNode.Analyze();
- }
- }
- }
-
- internal void EnqueueForDelayedAnalysis(NodejsFileNode fileNode) {
- DelayedAnalysisQueue.Enqueue(fileNode);
- RestartIdleNodeModulesTimer();
- }
-
- private void RestartIdleNodeModulesTimer() {
- lock (_idleNodeModulesLock) {
- _isIdleNodeModules = false;
-
- // The cooldown time here is longer than the cooldown time we use in NpmController.
- // This gives the Npm component ample time to build up the npm node tree,
- // so that we can query it later for perf optimizations.
- if (_idleNodeModulesTimer != null) {
- _idleNodeModulesTimer.Change(3000, Timeout.Infinite);
- }
- }
- }
-
- private static string[] _excludedAvailableItems = new[] {
- "ApplicationDefinition",
- "Page",
- "Resource",
- "SplashScreen",
- "DesignData",
- "DesignDataWithDesignTimeCreatableTypes",
- "EntityDeploy",
- "CodeAnalysisDictionary",
- "XamlAppDef"
- };
-
- public override IEnumerable GetAvailableItemNames() {
- // Remove a couple of available item names which show up from imports we
- // can't control out of Microsoft.Common.targets.
- return base.GetAvailableItemNames().Except(_excludedAvailableItems);
- }
-
- public Dictionary ImageIndexFromNameDictionary {
- get { return _imageIndexFromNameDictionary; }
- }
-
-#if DEV14_OR_LATER
- [Obsolete]
-#endif
- private void InitNodejsProjectImages() {
- // HACK: https://nodejstools.codeplex.com/workitem/1268
-
- // Project file images
- AddProjectImage(NodejsProjectImageName.TypeScriptProjectFile, "Microsoft.VisualStudioTools.Resources.Icons.TSProject_SolutionExplorerNode.png");
-
- // Dependency images
- AddProjectImage(NodejsProjectImageName.Dependency, "Microsoft.VisualStudioTools.Resources.Icons.NodeJSPackage_16x.png");
- AddProjectImage(NodejsProjectImageName.DependencyNotListed, "Microsoft.VisualStudioTools.Resources.Icons.NodeJSPackageMissing_16x.png");
- AddProjectImage(NodejsProjectImageName.DependencyMissing, "Microsoft.VisualStudioTools.Resources.Icons.PackageWarning_16x.png");
- }
-
-#if DEV14_OR_LATER
- protected override bool SupportsIconMonikers {
- get { return true; }
- }
-
- protected override ImageMoniker GetIconMoniker(bool open) {
- if (string.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
- return KnownMonikers.TSProjectNode;
- }
- return KnownMonikers.JSProjectNode;
- }
-
- [Obsolete]
-#endif
- private void AddProjectImage(NodejsProjectImageName name, string resourceId) {
- var images = ImageHandler.ImageList.Images;
- ImageIndexFromNameDictionary.Add(name, images.Count);
- images.Add(Image.FromStream(typeof(NodejsProjectNode).Assembly.GetManifestResourceStream(resourceId)));
- }
-
- public override Guid SharedCommandGuid {
- get {
- return Guids.NodejsCmdSet;
- }
- }
-
-#if !DEV14_OR_LATER
- public override int ImageIndex {
- get {
- if (string.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
- return ImageIndexFromNameDictionary[NodejsProjectImageName.TypeScriptProjectFile];
- }
- return base.ImageIndex;
- }
- }
-#endif
- internal override string IssueTrackerUrl {
- get { return NodejsConstants.IssueTrackerUrl; }
- }
-
- protected override void FinishProjectCreation(string sourceFolder, string destFolder) {
- foreach (MSBuild.ProjectItem item in this.BuildProject.Items) {
- if (String.Equals(Path.GetExtension(item.EvaluatedInclude), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
-
- // Create the 'typings' folder
- var typingsFolder = Path.Combine(ProjectHome, "Scripts", "typings");
- if (!Directory.Exists(typingsFolder)) {
- Directory.CreateDirectory(typingsFolder);
- }
-
- // Deploy node.d.ts
- var nodeTypingsFolder = Path.Combine(typingsFolder, "node");
- if (!Directory.Exists(Path.Combine(nodeTypingsFolder))) {
- Directory.CreateDirectory(nodeTypingsFolder);
- }
-
- var nodeFolder = ((OAProject)this.GetAutomationObject()).ProjectItems
- .AddFolder("Scripts").ProjectItems
- .AddFolder("typings").ProjectItems
- .AddFolder("node");
-
- nodeFolder.ProjectItems.AddFromFileCopy(
- Path.Combine(
- Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
- "Scripts",
- "typings",
- "node",
- "node.d.ts"
- )
- );
- break;
- }
- }
-
- base.FinishProjectCreation(sourceFolder, destFolder);
- }
-
- protected override void AddNewFileNodeToHierarchy(HierarchyNode parentNode, string fileName) {
- base.AddNewFileNodeToHierarchy(parentNode, fileName);
-
- if (String.Equals(Path.GetExtension(fileName), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase) &&
- !String.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
- // enable type script on the project automatically...
- SetProjectProperty(NodejsConstants.EnableTypeScript, "true");
- SetProjectProperty(NodejsConstants.TypeScriptSourceMap, "true");
- if (String.IsNullOrWhiteSpace(GetProjectProperty(NodejsConstants.TypeScriptModuleKind))) {
- SetProjectProperty(NodejsConstants.TypeScriptModuleKind, NodejsConstants.CommonJSModuleKind);
- }
- }
- }
-
- internal static bool IsNodejsFile(string strFileName) {
- var ext = Path.GetExtension(strFileName);
-
- return String.Equals(ext, NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase);
- }
-
- internal override string GetItemType(string filename) {
- string absFileName =
- Path.IsPathRooted(filename) ?
- filename :
- Path.Combine(this.ProjectHome, filename);
-
- var node = this.FindNodeByFullPath(absFileName) as NodejsFileNode;
- if (node != null && node.ItemNode.ItemTypeName != null) {
- return node.ItemNode.ItemTypeName;
- }
-
- if (string.Equals(Path.GetExtension(filename), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
- return NodejsConstants.TypeScriptCompileItemType;
- }
- return base.GetItemType(filename);
- }
-
- protected override bool DisableCmdInCurrentMode(Guid commandGroup, uint command) {
- if (commandGroup == Guids.OfficeToolsBootstrapperCmdSet) {
- // Convert to ... commands from Office Tools don't make sense and aren't supported
- // on our project type
- const int AddOfficeAppProject = 0x0001;
- const int AddSharePointAppProject = 0x0002;
-
- if (command == AddOfficeAppProject || command == AddSharePointAppProject) {
- return true;
- }
- }
-
- if (commandGroup == VSConstants.GUID_VSStandardCommandSet97) {
- if (this.IsCurrentStateASuppressCommandsMode()) {
- switch ((VsCommands)command) {
- default:
- break;
- case VsCommands.UnloadProject:
- case VsCommands.NewFolder:
- case VsCommands.EditLabel:
- case VsCommands.Rename:
- return true;
- }
- }
- }
-
- // don't defer to base class, Node allows edits while debugging (adding new files, etc...)
- return false;
- }
-
- public override string[] CodeFileExtensions {
- get {
- return new[] { NodejsConstants.JavaScriptExtension };
- }
- }
-
- protected internal override FolderNode CreateFolderNode(ProjectElement element) {
- return new NodejsFolderNode(this, element);
- }
-
- public override CommonFileNode CreateCodeFileNode(ProjectElement item) {
- string fileName = item.Url;
- if (!String.IsNullOrWhiteSpace(fileName)
- && Path.GetExtension(fileName).Equals(NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
- return new NodejsTypeScriptFileNode(this, item);
- }
- var res = new NodejsFileNode(this, item);
- return res;
- }
-
- public override CommonFileNode CreateNonCodeFileNode(ProjectElement item) {
- string fileName = item.Url;
- if (Path.GetFileName(fileName).Equals(NodejsConstants.PackageJsonFile, StringComparison.OrdinalIgnoreCase) &&
- !fileName.Contains(NodejsConstants.NodeModulesStagingFolder)) {
- return new PackageJsonFileNode(this, item);
- }
-
- return base.CreateNonCodeFileNode(item);
- }
-
- public override string GetProjectName() {
- return "NodeProject";
- }
-
- public override Type GetProjectFactoryType() {
- return typeof(BaseNodeProjectFactory);
- }
-
- public override Type GetEditorFactoryType() {
- // Not presently used
- throw new NotImplementedException();
- }
-
- public override string GetFormatList() {
- return NodejsConstants.ProjectFileFilter;
- }
-
- protected override Guid[] GetConfigurationDependentPropertyPages() {
- var res = base.GetConfigurationDependentPropertyPages();
-
- var enableTs = GetProjectProperty(NodejsConstants.EnableTypeScript, resetCache: false);
- bool fEnableTs;
- if (enableTs != null && Boolean.TryParse(enableTs, out fEnableTs) && fEnableTs) {
- var typeScriptPages = GetProjectProperty(NodejsConstants.TypeScriptCfgProperty);
- if (typeScriptPages != null) {
- foreach (var strGuid in typeScriptPages.Split(';')) {
- Guid guid;
- if (Guid.TryParse(strGuid, out guid)) {
- res = res.Append(guid);
- }
- }
- }
- }
-
- return res;
- }
-
- public override Type GetGeneralPropertyPageType() {
- return typeof(NodejsGeneralPropertyPage);
- }
-
- public override Type GetLibraryManagerType() {
- return typeof(NodejsLibraryManager);
- }
-
- public override IProjectLauncher GetLauncher() {
- return new NodejsProjectLauncher(this);
- }
-
- protected override NodeProperties CreatePropertiesObject() {
- return new NodejsProjectNodeProperties(this);
- }
-
- protected override Stream ProjectIconsImageStripStream {
- get {
- return typeof(ProjectNode).Assembly.GetManifestResourceStream("Microsoft.VisualStudioTools.Resources.Icons.SharedProjectImageList.bmp");
- }
- }
-
- public override bool IsCodeFile(string fileName) {
- var ext = Path.GetExtension(fileName);
- return ext.Equals(NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase) ||
- ext.Equals(NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase);
- }
-
- public override int InitializeForOuter(string filename, string location, string name, uint flags, ref Guid iid, out IntPtr projectPointer, out int canceled) {
- NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevelChanged += IntellisenseOptionsPageAnalysisLevelChanged;
- NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMaximumChanged += AnalysisLogMaximumChanged;
- NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDiskChanged += IntellisenseOptionsPageSaveToDiskChanged;
- NodejsPackage.Instance.GeneralOptionsPage.ShowBrowserAndNodeLabelsChanged += ShowBrowserAndNodeLabelsChanged;
-
- return base.InitializeForOuter(filename, location, name, flags, ref iid, out projectPointer, out canceled);
- }
-
- protected override void Reload() {
- using (new DebugTimer("Project Load")) {
- // Populate values from project properties before we do anything else.
- // Otherwise we run into race conditions where, for instance, _analysisIgnoredDirectories
- // is not properly set before the FileNodes get created in base.Reload()
- UpdateProjectNodeFromProjectProperties();
-
- if (_analyzer != null && _analyzer.RemoveUser()) {
- _analyzer.Dispose();
- }
- _analyzer = new VsProjectAnalyzer(ProjectFolder);
- _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
- LogAnalysisLevel();
-
- base.Reload();
-
- SyncFileSystem();
-
- NodejsPackage.Instance.CheckSurveyNews(false);
- ModulesNode.ReloadHierarchySafe();
-
- // scan for files which were loaded from cached analysis but no longer
- // exist and remove them.
- _analyzer.ReloadComplete();
- }
- }
-
- private void UpdateProjectNodeFromProjectProperties() {
- _intermediateOutputPath = Path.Combine(ProjectHome, GetProjectProperty("BaseIntermediateOutputPath"));
-
- var ignoredPaths = GetProjectProperty(NodejsConstants.AnalysisIgnoredDirectories);
-
- if (!string.IsNullOrWhiteSpace(ignoredPaths)) {
- _analysisIgnoredDirs = _analysisIgnoredDirs.Append(ignoredPaths.Split(';').Select(x => '\\' + x + '\\').ToArray());
- }
-
- var maxFileSizeProp = GetProjectProperty(NodejsConstants.AnalysisMaxFileSize);
- int maxFileSize;
- if (maxFileSizeProp != null && Int32.TryParse(maxFileSizeProp, out maxFileSize)) {
- _maxFileSize = maxFileSize;
- }
- }
-
- private void Reanalyze(HierarchyNode node, VsProjectAnalyzer newAnalyzer) {
- if (node != null) {
- for (var child = node.FirstChild; child != null; child = child.NextSibling) {
- if (child is PackageJsonFileNode) {
- ((PackageJsonFileNode)child).AnalyzePackageJson(newAnalyzer);
- } else if (child is NodejsFileNode) {
- if (((NodejsFileNode)child).ShouldAnalyze) {
- newAnalyzer.AnalyzeFile(child.Url, !child.IsNonMemberItem);
- }
- }
-
- Reanalyze(child, newAnalyzer);
- }
- }
- }
-
- private void LogAnalysisLevel() {
- var analyzer = _analyzer;
- if (analyzer != null) {
- NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.AnalysisLevel, (int)analyzer.AnalysisLevel);
- }
- }
-
- /*
- * Needed if we switch to per project Analysis levels
- internal NodejsTools.Options.AnalysisLevel AnalysisLevel(){
- var analyzer = _analyzer;
- if (_analyzer != null) {
- return _analyzer.AnalysisLevel;
- }
- return NodejsTools.Options.AnalysisLevel.None;
- }
- */
- private void IntellisenseOptionsPageAnalysisLevelChanged(object sender, EventArgs e) {
-
- var oldAnalyzer = _analyzer;
- _analyzer = null;
-
- var analyzer = new VsProjectAnalyzer(ProjectFolder);
- Reanalyze(this, analyzer);
- if (oldAnalyzer != null) {
- analyzer.SwitchAnalyzers(oldAnalyzer);
- if (oldAnalyzer.RemoveUser()) {
- oldAnalyzer.Dispose();
- }
- }
- _analyzer = analyzer;
- _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
- LogAnalysisLevel();
- }
-
- private void AnalysisLogMaximumChanged(object sender, EventArgs e) {
- if (_analyzer != null) {
- _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
- }
- }
-
- private void IntellisenseOptionsPageSaveToDiskChanged(object sender, EventArgs e) {
- if (_analyzer != null) {
- _analyzer.SaveToDisk = NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDisk;
- }
- }
-
- private void ShowBrowserAndNodeLabelsChanged(object sender, EventArgs e) {
- var nodejsFolderNodes = this.AllDescendants.Where(item => (item as NodejsFolderNode) != null).Select(item => (NodejsFolderNode)item);
- foreach (var node in nodejsFolderNodes) {
- ProjectMgr.ReDrawNode(node, UIHierarchyElement.Caption);
- }
- }
-
- protected override void RaiseProjectPropertyChanged(string propertyName, string oldValue, string newValue) {
- base.RaiseProjectPropertyChanged(propertyName, oldValue, newValue);
-
- var propPage = GeneralPropertyPageControl;
- if (propPage != null) {
- switch (propertyName) {
- case NodejsConstants.Environment:
- propPage.Environment = newValue;
- break;
- case NodejsConstants.DebuggerPort:
- propPage.DebuggerPort = newValue;
- break;
- case NodejsConstants.NodejsPort:
- propPage.NodejsPort = newValue;
- break;
- case NodejsConstants.NodeExePath:
- propPage.NodeExePath = newValue;
- break;
- case NodejsConstants.NodeExeArguments:
- propPage.NodeExeArguments = newValue;
- break;
- case CommonConstants.StartupFile:
- propPage.ScriptFile = newValue;
- break;
- case NodejsConstants.ScriptArguments:
- propPage.ScriptArguments = newValue;
- break;
- case NodejsConstants.LaunchUrl:
- propPage.LaunchUrl = newValue;
- break;
- case NodejsConstants.StartWebBrowser:
- bool value;
- if (Boolean.TryParse(newValue, out value)) {
- propPage.StartWebBrowser = value;
- }
- break;
- case CommonConstants.WorkingDirectory:
- propPage.WorkingDirectory = newValue;
- break;
- default:
- if (propPage != null) {
- PropertyPage.IsDirty = true;
- }
- break;
- }
- }
- }
-
- private NodejsGeneralPropertyPageControl GeneralPropertyPageControl {
- get {
- if (PropertyPage != null && PropertyPage.Control != null) {
- return (NodejsGeneralPropertyPageControl)PropertyPage.Control;
- }
-
- return null;
- }
- }
-
- private static void AddFolderForFile(Dictionary> directoryPackages, FileNode rootFile, CommonFolderNode folderChild) {
- List folders;
- if (!directoryPackages.TryGetValue(rootFile, out folders)) {
- directoryPackages[rootFile] = folders = new List();
- }
- folders.Add(folderChild);
- }
-
- protected override bool IncludeNonMemberItemInProject(HierarchyNode node) {
- var fileNode = node as NodejsFileNode;
- if (fileNode != null) {
- return IncludeNodejsFile(fileNode);
- }
- return false;
- }
-
- internal bool IncludeNodejsFile(NodejsFileNode fileNode) {
- var url = fileNode.Url;
- if (CommonUtils.IsSubpathOf(_intermediateOutputPath, fileNode.Url)) {
- return false;
- }
-
- foreach (var path in _analysisIgnoredDirs) {
- if (url.IndexOf(path, 0, StringComparison.OrdinalIgnoreCase) != -1) {
- return false;
- }
- }
-
- var fileInfo = new FileInfo(fileNode.Url);
- if (!fileInfo.Exists || fileInfo.Length > _maxFileSize) {
- // skip obviously generated and missing files...
- return false;
- }
-
- int nestedModulesDepth = 0;
- if (ModulesNode.NpmController.RootPackage != null && ModulesNode.NpmController.RootPackage.Modules != null) {
- nestedModulesDepth = ModulesNode.NpmController.RootPackage.Modules.GetDepth(fileNode.Url);
- }
-
- if (_analyzer != null && _analyzer.Project != null &&
- _analyzer.Project.Limits.IsPathExceedNestingLimit(nestedModulesDepth)) {
- return false;
- }
-
- return true;
- }
-
- internal override object Object {
- get {
- return this;
- }
- }
-
- protected override ReferenceContainerNode CreateReferenceContainerNode() {
- return null;
- }
-
- public NodeModulesNode ModulesNode { get; private set; }
-
-
-
- protected internal override void ProcessReferences() {
- base.ProcessReferences();
-
- if (null == ModulesNode) {
- ModulesNode = new NodeModulesNode(this);
- AddChild(ModulesNode);
- _idleNodeModulesTimer = new Timer(OnIdleNodeModules);
- }
- }
-
- #region VSWebSite Members
-
- // This interface is just implemented so we don't get normal profiling which
- // doesn't work with our projects anyway.
-
- public EnvDTE.ProjectItem AddFromTemplate(string bstrRelFolderUrl, string bstrWizardName, string bstrLanguage, string bstrItemName, bool bUseCodeSeparation, string bstrMasterPage, string bstrDocType) {
- throw new NotImplementedException();
- }
-
- public VsWebSite.CodeFolders CodeFolders {
- get { throw new NotImplementedException(); }
- }
-
- public EnvDTE.DTE DTE {
- get { return Project.DTE; }
- }
-
- public string EnsureServerRunning() {
- throw new NotImplementedException();
- }
-
- public string GetUniqueFilename(string bstrFolder, string bstrRoot, string bstrDesiredExt) {
- throw new NotImplementedException();
- }
-
- public bool PreCompileWeb(string bstrCompilePath, bool bUpdateable) {
- throw new NotImplementedException();
- }
-
- public EnvDTE.Project Project {
- get { return (OAProject)GetAutomationObject(); }
- }
-
- public VsWebSite.AssemblyReferences References {
- get { throw new NotImplementedException(); }
- }
-
- public void Refresh() {
- }
-
- public string TemplatePath {
- get { throw new NotImplementedException(); }
- }
-
- public string URL {
- get { throw new NotImplementedException(); }
- }
-
- public string UserTemplatePath {
- get { throw new NotImplementedException(); }
- }
-
- public VsWebSite.VSWebSiteEvents VSWebSiteEvents {
- get { throw new NotImplementedException(); }
- }
-
- public void WaitUntilReady() {
- }
-
- public VsWebSite.WebReferences WebReferences {
- get { throw new NotImplementedException(); }
- }
-
- public VsWebSite.WebServices WebServices {
- get { throw new NotImplementedException(); }
- }
-
- #endregion
-
- Task INodePackageModulesCommands.InstallMissingModulesAsync() {
- //Fire off the command to update the missing modules
- // through NPM
- return ModulesNode.InstallMissingModules();
- }
-
- private void HookErrorsAndWarnings(VsProjectAnalyzer res) {
- res.ErrorAdded += OnErrorAdded;
- res.ErrorRemoved += OnErrorRemoved;
- res.WarningAdded += OnWarningAdded;
- res.WarningRemoved += OnWarningRemoved;
- }
-
- private void UnHookErrorsAndWarnings(VsProjectAnalyzer res) {
- res.ErrorAdded -= OnErrorAdded;
- res.ErrorRemoved -= OnErrorRemoved;
- res.WarningAdded -= OnWarningAdded;
- res.WarningRemoved -= OnWarningRemoved;
- }
-
- private void OnErrorAdded(object sender, FileEventArgs args) {
- if (_diskNodes.ContainsKey(args.Filename)) {
- _errorFiles.Add(args.Filename);
- }
- }
-
- private void OnErrorRemoved(object sender, FileEventArgs args) {
- _errorFiles.Remove(args.Filename);
- }
-
- private void OnWarningAdded(object sender, FileEventArgs args) {
- if (_diskNodes.ContainsKey(args.Filename)) {
- _warningFiles.Add(args.Filename);
- }
- }
-
- private void OnWarningRemoved(object sender, FileEventArgs args) {
- _warningFiles.Remove(args.Filename);
- }
-
- ///
- /// File names within the project which contain errors.
- ///
- public HashSet ErrorFiles {
- get {
- return _errorFiles;
- }
- }
-
- ///
- /// File names within the project which contain warnings.
- ///
- public HashSet WarningFiles {
- get {
- return _warningFiles;
- }
- }
-
- internal struct LongPathInfo {
- public string FullPath;
- public string RelativePath;
- public bool IsDirectory;
- }
-
- private static readonly Regex _uninstallRegex = new Regex(@"\b(uninstall|rm)\b");
- private static readonly char[] _pathSeparators = { '\\', '/' };
- private bool _isCheckingForLongPaths;
-
- public async Task CheckForLongPaths(string npmArguments = null) {
- if (_isCheckingForLongPaths || !NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths) {
- return;
- }
-
- if (npmArguments != null && _uninstallRegex.IsMatch(npmArguments)) {
- return;
- }
-
- try {
- _isCheckingForLongPaths = true;
- TaskDialogButton dedupeButton, ignoreButton, disableButton;
- var taskDialog = new TaskDialog(NodejsPackage.Instance) {
- AllowCancellation = true,
- EnableHyperlinks = true,
- Title = SR.GetString(SR.LongPathWarningTitle),
- MainIcon = TaskDialogIcon.Warning,
- Content = SR.GetString(SR.LongPathWarningText),
- CollapsedControlText = SR.GetString(SR.LongPathShowPathsExceedingTheLimit),
- ExpandedControlText = SR.GetString(SR.LongPathHidePathsExceedingTheLimit),
- Buttons = {
- (dedupeButton = new TaskDialogButton(SR.GetString(SR.LongPathNpmDedupe), SR.GetString(SR.LongPathNpmDedupeDetail))),
- (ignoreButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingButWarnNextTime))),
- (disableButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgain), SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgainDetail)))
- },
- FooterIcon = TaskDialogIcon.Information,
- Footer = SR.GetString(SR.LongPathFooter)
- };
-
- taskDialog.HyperlinkClicked += (sender, e) => {
- switch (e.Url) {
- case "#msdn":
- Process.Start("http://go.microsoft.com/fwlink/?LinkId=454508");
- break;
- case "#uservoice":
- Process.Start("http://go.microsoft.com/fwlink/?LinkID=456509");
- break;
- case "#help":
- Process.Start("http://go.microsoft.com/fwlink/?LinkId=456511");
- break;
- default:
- System.Windows.Clipboard.SetText(e.Url);
- break;
- }
- };
-
- recheck:
-
- var longPaths = await Task.Factory.StartNew(() =>
- GetLongSubPaths(ProjectHome)
- .Concat(GetLongSubPaths(_intermediateOutputPath))
- .Select(lpi => string.Format("• {1}\u00A0{2}", lpi.FullPath, lpi.RelativePath, SR.GetString(SR.LongPathClickToCopy)))
- .ToArray());
- if (longPaths.Length == 0) {
- return;
- }
- taskDialog.ExpandedInformation = string.Join("\r\n", longPaths);
-
- var button = taskDialog.ShowModal();
- if (button == dedupeButton) {
- var repl = NodejsPackage.Instance.OpenReplWindow(focus: false);
- await repl.ExecuteCommand(".npm dedupe").HandleAllExceptions(SR.ProductName);
-
- taskDialog.Content += "\r\n\r\n" + SR.GetString(SR.LongPathNpmDedupeDidNotHelp);
- taskDialog.Buttons.Remove(dedupeButton);
- goto recheck;
- } else if (button == disableButton) {
- var page = NodejsPackage.Instance.GeneralOptionsPage;
- page.CheckForLongPaths = false;
- page.SaveSettingsToStorage();
- }
- } finally {
- _isCheckingForLongPaths = false;
- }
- }
-
- internal static IEnumerable GetLongSubPaths(string basePath, string path = "") {
- const int MaxFilePathLength = 260 - 1; // account for terminating NULL
- const int MaxDirectoryPathLength = 248 - 1;
-
- basePath = CommonUtils.EnsureEndSeparator(basePath);
-
- WIN32_FIND_DATA wfd;
- IntPtr hFind = NativeMethods.FindFirstFile(basePath + path + "\\*", out wfd);
- if (hFind == NativeMethods.INVALID_HANDLE_VALUE) {
- yield break;
- }
-
- try {
- do {
- if (wfd.cFileName == "." || wfd.cFileName == "..") {
- continue;
- }
-
- bool isDirectory = (wfd.dwFileAttributes & NativeMethods.FILE_ATTRIBUTE_DIRECTORY) != 0;
-
- string childPath = path;
- if (childPath != String.Empty) {
- childPath += "\\";
- }
- childPath += wfd.cFileName;
-
- string fullChildPath = basePath + childPath;
- bool isTooLong;
- try {
- isTooLong = Path.GetFullPath(fullChildPath).Length > (isDirectory ? MaxDirectoryPathLength : MaxFilePathLength);
- } catch (PathTooLongException) {
- isTooLong = true;
- } catch (Exception) {
- continue;
- }
-
- if (isTooLong) {
- yield return new LongPathInfo { FullPath = fullChildPath, RelativePath = childPath, IsDirectory = isDirectory };
- } else if (isDirectory) {
- foreach (var item in GetLongSubPaths(basePath, childPath)) {
- yield return item;
- }
- }
- } while (NativeMethods.FindNextFile(hFind, out wfd));
- } finally {
- NativeMethods.FindClose(hFind);
- }
- }
-
- protected override void Dispose(bool disposing) {
- if (disposing) {
- if (_analyzer != null) {
- UnHookErrorsAndWarnings(_analyzer);
- if (WarningFiles.Count > 0 || ErrorFiles.Count > 0) {
- foreach (var file in WarningFiles.Concat(ErrorFiles)) {
- var node = FindNodeByFullPath(file) as NodejsFileNode;
- if (node != null) {
- //_analyzer.RemoveErrors(node.GetAnalysis(), suppressUpdate: false);
- }
- }
- }
-
- if (_analyzer.RemoveUser()) {
- _analyzer.Dispose();
- }
- _analyzer = null;
- }
-
- lock (_idleNodeModulesLock) {
- if (_idleNodeModulesTimer != null) {
- _idleNodeModulesTimer.Dispose();
- }
- _idleNodeModulesTimer = null;
- }
-
- NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDiskChanged -= IntellisenseOptionsPageSaveToDiskChanged;
- NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevelChanged -= IntellisenseOptionsPageAnalysisLevelChanged;
- NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMaximumChanged -= AnalysisLogMaximumChanged;
- }
- base.Dispose(disposing);
- }
-
- internal override async void BuildAsync(uint vsopts, string config, VisualStudio.Shell.Interop.IVsOutputWindowPane output, string target, Action uiThreadCallback) {
- try {
- await CheckForLongPaths();
- } catch (Exception) {
- uiThreadCallback(MSBuildResult.Failed, target);
- return;
- }
-
- // BuildAsync can throw on the sync path before invoking the callback. If it does, we must still invoke the callback here,
- // because by this time there's no other way to propagate the error to the caller.
- try {
- base.BuildAsync(vsopts, config, output, target, uiThreadCallback);
- } catch (Exception) {
- uiThreadCallback(MSBuildResult.Failed, target);
- }
- }
-
- internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
- if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidOpenReplWindow:
- result = QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
- return VSConstants.S_OK;
- }
- }
- return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
- }
-
- protected override QueryStatusResult QueryStatusSelectionOnNodes(IList selectedNodes, Guid cmdGroup, uint cmd, IntPtr pCmdText) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidNpmManageModules:
- if (IsCurrentStateASuppressCommandsMode()) {
- return QueryStatusResult.SUPPORTED;
- } else if (!ShowManageModulesCommandOnNode(selectedNodes)) {
- return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED | QueryStatusResult.INVISIBLE;
- }
- return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
- }
- } else if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidSetAsNodejsStartupFile:
- if (ShowSetAsStartupFileCommandOnNode(selectedNodes)) {
- // We enable "Set as StartUp File" command only on current language code files,
- // the file is in project home dir and if the file is not the startup file already.
- string startupFile = ((CommonProjectNode)ProjectMgr).GetStartupFile();
- if (!CommonUtils.IsSamePath(startupFile, selectedNodes[0].Url)) {
- return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
- }
- }
- break;
- }
- }
-
- return base.QueryStatusSelectionOnNodes(selectedNodes, cmdGroup, cmd, pCmdText);
- }
-
- internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
- if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmd) {
- case PkgCmdId.cmdidOpenReplWindow:
- NodejsPackage.Instance.OpenReplWindow();
- return VSConstants.S_OK;
- }
- } else if (cmdGroup == Guids.NodejsNpmCmdSet) {
- try {
- NpmHelpers.GetPathToNpm(
- Nodejs.GetAbsoluteNodeExePath(
- ProjectHome,
- Project.GetNodejsProject().GetProjectProperty(NodejsConstants.NodeExePath)
- ));
- } catch (NpmNotFoundException) {
- Nodejs.ShowNodejsNotInstalled();
- return VSConstants.S_OK;
- }
- }
- return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
- }
-
- protected override int ExecCommandThatDependsOnSelectedNodes(Guid cmdGroup, uint cmdId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin commandOrigin, IList selectedNodes, out bool handled) {
- if (cmdGroup == Guids.NodejsNpmCmdSet) {
- try {
- NpmHelpers.GetPathToNpm(
- Nodejs.GetAbsoluteNodeExePath(
- ProjectHome,
- Project.GetNodejsProject().GetProjectProperty(NodejsConstants.NodeExePath)
- ));
- } catch (NpmNotFoundException) {
- Nodejs.ShowNodejsNotInstalled();
- handled = true;
- return VSConstants.S_OK;
- }
-
- switch (cmdId) {
- case PkgCmdId.cmdidNpmManageModules:
- if (!ShowManageModulesCommandOnNode(selectedNodes)) {
- ModulesNode.ManageModules();
- handled = true;
- return VSConstants.S_OK;
- }
-
- var node = selectedNodes[0] as AbstractNpmNode;
- if (node != null) {
- var abstractNpmNode = node;
- abstractNpmNode.ManageNpmModules();
- handled = true;
- return VSConstants.S_OK;
- }
- break;
- }
- } else if (cmdGroup == Guids.NodejsCmdSet) {
- switch (cmdId) {
- case PkgCmdId.cmdidSetAsNodejsStartupFile:
- // Set the StartupFile project property to the Url of this node
- SetProjectProperty(
- CommonConstants.StartupFile,
- CommonUtils.GetRelativeFilePath(ProjectHome, selectedNodes[0].Url)
- );
- handled = true;
- return VSConstants.S_OK;
- }
- }
-
- return base.ExecCommandThatDependsOnSelectedNodes(cmdGroup, cmdId, cmdExecOpt, vaIn, vaOut, commandOrigin, selectedNodes, out handled);
- }
-
- private bool ShowSetAsStartupFileCommandOnNode(IList selectedNodes) {
- var selectedNodeUrl = selectedNodes[0].Url;
- return selectedNodes.Count == 1 &&
- (IsCodeFile(selectedNodeUrl) ||
- // for some reason, the default express 4 template's startup file lacks an extension.
- string.IsNullOrEmpty(Path.GetExtension(selectedNodeUrl)));
- }
-
- private static bool ShowManageModulesCommandOnNode(IList selectedNodes) {
- return selectedNodes.Count == 1 && selectedNodes[0] is AbstractNpmNode;
- }
-
- protected internal override void SetCurrentConfiguration() {
- if (!IsProjectOpened) {
- return;
- }
-
- if (this.IsPlatformAware()) {
- EnvDTE.Project automationObject = GetAutomationObject() as EnvDTE.Project;
-
- this.BuildProject.SetGlobalProperty(ProjectFileConstants.Platform, automationObject.ConfigurationManager.ActiveConfiguration.PlatformName);
- }
- base.SetCurrentConfiguration();
- }
-
- public override MSBuildResult Build(string config, string target) {
- if (this.IsPlatformAware()) {
- var platform = this.BuildProject.GetPropertyValue(GlobalProperty.Platform.ToString());
-
- if (platform == ProjectConfig.AnyCPU) {
- this.BuildProject.SetGlobalProperty(GlobalProperty.Platform.ToString(), ConfigProvider.x86Platform);
- }
- }
- return base.Build(config, target);
- }
-
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.NodejsTools.Intellisense;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.NodejsTools.ProjectWizard;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudioTools;
+using Microsoft.VisualStudioTools.Project;
+using Microsoft.VisualStudioTools.Project.Automation;
+using MSBuild = Microsoft.Build.Evaluation;
+using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
+#if DEV14_OR_LATER
+using Microsoft.VisualStudio.Imaging.Interop;
+using Microsoft.VisualStudio.Imaging;
+#endif
+
+namespace Microsoft.NodejsTools.Project {
+ class NodejsProjectNode : CommonProjectNode, VsWebSite.VSWebSite, INodePackageModulesCommands, IVsBuildPropertyStorage {
+ private VsProjectAnalyzer _analyzer;
+ private readonly HashSet _warningFiles = new HashSet();
+ private readonly HashSet _errorFiles = new HashSet();
+ private string[] _analysisIgnoredDirs = new string[1] { NodejsConstants.NodeModulesStagingFolder };
+ private int _maxFileSize = 1024 * 512;
+ internal readonly RequireCompletionCache _requireCompletionCache = new RequireCompletionCache();
+ private string _intermediateOutputPath;
+ private readonly Dictionary _imageIndexFromNameDictionary = new Dictionary();
+
+ // We delay analysis until things calm down in the node_modules folder.
+ internal Queue DelayedAnalysisQueue = new Queue();
+ private object _idleNodeModulesLock = new object();
+ private volatile bool _isIdleNodeModules = false;
+ private Timer _idleNodeModulesTimer;
+
+ public NodejsProjectNode(NodejsProjectPackage package)
+ : base(
+ package,
+#if DEV14_OR_LATER
+ null
+#else
+ Utilities.GetImageList(typeof(NodejsProjectNode).Assembly.GetManifestResourceStream("Microsoft.NodejsTools.Resources.Icons.NodejsImageList.bmp"))
+#endif
+ ) {
+ Type projectNodePropsType = typeof(NodejsProjectNodeProperties);
+ AddCATIDMapping(projectNodePropsType, projectNodePropsType.GUID);
+#pragma warning disable 0612
+ InitNodejsProjectImages();
+#pragma warning restore 0612
+
+ }
+
+ public VsProjectAnalyzer Analyzer {
+ get {
+ return _analyzer;
+ }
+ }
+
+ private void OnIdleNodeModules(object state) {
+ lock (_idleNodeModulesLock) {
+ _isIdleNodeModules = true;
+ }
+
+ while (DelayedAnalysisQueue.Count > 0) {
+ lock (_idleNodeModulesLock) {
+ if (!_isIdleNodeModules) {
+ return;
+ }
+ }
+ var fileNode = DelayedAnalysisQueue.Dequeue();
+ if (fileNode != null) {
+ fileNode.Analyze();
+ }
+ }
+ }
+
+ internal void EnqueueForDelayedAnalysis(NodejsFileNode fileNode) {
+ DelayedAnalysisQueue.Enqueue(fileNode);
+ RestartIdleNodeModulesTimer();
+ }
+
+ private void RestartIdleNodeModulesTimer() {
+ lock (_idleNodeModulesLock) {
+ _isIdleNodeModules = false;
+
+ // The cooldown time here is longer than the cooldown time we use in NpmController.
+ // This gives the Npm component ample time to build up the npm node tree,
+ // so that we can query it later for perf optimizations.
+ if (_idleNodeModulesTimer != null) {
+ _idleNodeModulesTimer.Change(3000, Timeout.Infinite);
+ }
+ }
+ }
+
+ private static string[] _excludedAvailableItems = new[] {
+ "ApplicationDefinition",
+ "Page",
+ "Resource",
+ "SplashScreen",
+ "DesignData",
+ "DesignDataWithDesignTimeCreatableTypes",
+ "EntityDeploy",
+ "CodeAnalysisDictionary",
+ "XamlAppDef"
+ };
+
+ public override IEnumerable GetAvailableItemNames() {
+ // Remove a couple of available item names which show up from imports we
+ // can't control out of Microsoft.Common.targets.
+ return base.GetAvailableItemNames().Except(_excludedAvailableItems);
+ }
+
+ public Dictionary ImageIndexFromNameDictionary {
+ get { return _imageIndexFromNameDictionary; }
+ }
+
+#if DEV14_OR_LATER
+ [Obsolete]
+#endif
+ private void InitNodejsProjectImages() {
+ // HACK: https://nodejstools.codeplex.com/workitem/1268
+
+ // Project file images
+ AddProjectImage(NodejsProjectImageName.TypeScriptProjectFile, "Microsoft.VisualStudioTools.Resources.Icons.TSProject_SolutionExplorerNode.png");
+
+ // Dependency images
+ AddProjectImage(NodejsProjectImageName.Dependency, "Microsoft.VisualStudioTools.Resources.Icons.NodeJSPackage_16x.png");
+ AddProjectImage(NodejsProjectImageName.DependencyNotListed, "Microsoft.VisualStudioTools.Resources.Icons.NodeJSPackageMissing_16x.png");
+ AddProjectImage(NodejsProjectImageName.DependencyMissing, "Microsoft.VisualStudioTools.Resources.Icons.PackageWarning_16x.png");
+ }
+
+#if DEV14_OR_LATER
+ protected override bool SupportsIconMonikers {
+ get { return true; }
+ }
+
+ protected override ImageMoniker GetIconMoniker(bool open) {
+ if (string.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
+ return KnownMonikers.TSProjectNode;
+ }
+ return KnownMonikers.JSProjectNode;
+ }
+
+ [Obsolete]
+#endif
+ private void AddProjectImage(NodejsProjectImageName name, string resourceId) {
+ var images = ImageHandler.ImageList.Images;
+ ImageIndexFromNameDictionary.Add(name, images.Count);
+ images.Add(Image.FromStream(typeof(NodejsProjectNode).Assembly.GetManifestResourceStream(resourceId)));
+ }
+
+ public override Guid SharedCommandGuid {
+ get {
+ return Guids.NodejsCmdSet;
+ }
+ }
+
+#if !DEV14_OR_LATER
+ public override int ImageIndex {
+ get {
+ if (string.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
+ return ImageIndexFromNameDictionary[NodejsProjectImageName.TypeScriptProjectFile];
+ }
+ return base.ImageIndex;
+ }
+ }
+#endif
+ internal override string IssueTrackerUrl {
+ get { return NodejsConstants.IssueTrackerUrl; }
+ }
+
+ protected override void FinishProjectCreation(string sourceFolder, string destFolder) {
+ foreach (MSBuild.ProjectItem item in this.BuildProject.Items) {
+ if (String.Equals(Path.GetExtension(item.EvaluatedInclude), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
+
+ // Create the 'typings' folder
+ var typingsFolder = Path.Combine(ProjectHome, "Scripts", "typings");
+ if (!Directory.Exists(typingsFolder)) {
+ Directory.CreateDirectory(typingsFolder);
+ }
+
+ // Deploy node.d.ts
+ var nodeTypingsFolder = Path.Combine(typingsFolder, "node");
+ if (!Directory.Exists(Path.Combine(nodeTypingsFolder))) {
+ Directory.CreateDirectory(nodeTypingsFolder);
+ }
+
+ var nodeFolder = ((OAProject)this.GetAutomationObject()).ProjectItems
+ .AddFolder("Scripts").ProjectItems
+ .AddFolder("typings").ProjectItems
+ .AddFolder("node");
+
+ nodeFolder.ProjectItems.AddFromFileCopy(
+ Path.Combine(
+ Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ "Scripts",
+ "typings",
+ "node",
+ "node.d.ts"
+ )
+ );
+ break;
+ }
+ }
+
+ base.FinishProjectCreation(sourceFolder, destFolder);
+ }
+
+ protected override void AddNewFileNodeToHierarchy(HierarchyNode parentNode, string fileName) {
+ base.AddNewFileNodeToHierarchy(parentNode, fileName);
+
+ if (String.Equals(Path.GetExtension(fileName), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase) &&
+ !String.Equals(GetProjectProperty(NodejsConstants.EnableTypeScript), "true", StringComparison.OrdinalIgnoreCase)) {
+ // enable type script on the project automatically...
+ SetProjectProperty(NodejsConstants.EnableTypeScript, "true");
+ SetProjectProperty(NodejsConstants.TypeScriptSourceMap, "true");
+ if (String.IsNullOrWhiteSpace(GetProjectProperty(NodejsConstants.TypeScriptModuleKind))) {
+ SetProjectProperty(NodejsConstants.TypeScriptModuleKind, NodejsConstants.CommonJSModuleKind);
+ }
+ }
+ }
+
+ internal static bool IsNodejsFile(string strFileName) {
+ var ext = Path.GetExtension(strFileName);
+
+ return String.Equals(ext, NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase);
+ }
+
+ internal override string GetItemType(string filename) {
+ string absFileName =
+ Path.IsPathRooted(filename) ?
+ filename :
+ Path.Combine(this.ProjectHome, filename);
+
+ var node = this.FindNodeByFullPath(absFileName) as NodejsFileNode;
+ if (node != null && node.ItemNode.ItemTypeName != null) {
+ return node.ItemNode.ItemTypeName;
+ }
+
+ if (string.Equals(Path.GetExtension(filename), NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
+ return NodejsConstants.TypeScriptCompileItemType;
+ }
+ return base.GetItemType(filename);
+ }
+
+ protected override bool DisableCmdInCurrentMode(Guid commandGroup, uint command) {
+ if (commandGroup == Guids.OfficeToolsBootstrapperCmdSet) {
+ // Convert to ... commands from Office Tools don't make sense and aren't supported
+ // on our project type
+ const int AddOfficeAppProject = 0x0001;
+ const int AddSharePointAppProject = 0x0002;
+
+ if (command == AddOfficeAppProject || command == AddSharePointAppProject) {
+ return true;
+ }
+ }
+
+ if (commandGroup == VSConstants.GUID_VSStandardCommandSet97) {
+ if (this.IsCurrentStateASuppressCommandsMode()) {
+ switch ((VsCommands)command) {
+ default:
+ break;
+ case VsCommands.UnloadProject:
+ case VsCommands.NewFolder:
+ case VsCommands.EditLabel:
+ case VsCommands.Rename:
+ return true;
+ }
+ }
+ }
+
+ // don't defer to base class, Node allows edits while debugging (adding new files, etc...)
+ return false;
+ }
+
+ public override string[] CodeFileExtensions {
+ get {
+ return new[] { NodejsConstants.JavaScriptExtension };
+ }
+ }
+
+ protected internal override FolderNode CreateFolderNode(ProjectElement element) {
+ return new NodejsFolderNode(this, element);
+ }
+
+ public override CommonFileNode CreateCodeFileNode(ProjectElement item) {
+ string fileName = item.Url;
+ if (!String.IsNullOrWhiteSpace(fileName)
+ && Path.GetExtension(fileName).Equals(NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase)) {
+ return new NodejsTypeScriptFileNode(this, item);
+ }
+ var res = new NodejsFileNode(this, item);
+ return res;
+ }
+
+ public override CommonFileNode CreateNonCodeFileNode(ProjectElement item) {
+ string fileName = item.Url;
+ if (Path.GetFileName(fileName).Equals(NodejsConstants.PackageJsonFile, StringComparison.OrdinalIgnoreCase) &&
+ !fileName.Contains(NodejsConstants.NodeModulesStagingFolder)) {
+ return new PackageJsonFileNode(this, item);
+ }
+
+ return base.CreateNonCodeFileNode(item);
+ }
+
+ public override string GetProjectName() {
+ return "NodeProject";
+ }
+
+ public override Type GetProjectFactoryType() {
+ return typeof(BaseNodeProjectFactory);
+ }
+
+ public override Type GetEditorFactoryType() {
+ // Not presently used
+ throw new NotImplementedException();
+ }
+
+ public override string GetFormatList() {
+ return NodejsConstants.ProjectFileFilter;
+ }
+
+ protected override Guid[] GetConfigurationDependentPropertyPages() {
+ var res = base.GetConfigurationDependentPropertyPages();
+
+ var enableTs = GetProjectProperty(NodejsConstants.EnableTypeScript, resetCache: false);
+ bool fEnableTs;
+ if (enableTs != null && Boolean.TryParse(enableTs, out fEnableTs) && fEnableTs) {
+ var typeScriptPages = GetProjectProperty(NodejsConstants.TypeScriptCfgProperty);
+ if (typeScriptPages != null) {
+ foreach (var strGuid in typeScriptPages.Split(';')) {
+ Guid guid;
+ if (Guid.TryParse(strGuid, out guid)) {
+ res = res.Append(guid);
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+
+ public override Type GetGeneralPropertyPageType() {
+ return typeof(NodejsGeneralPropertyPage);
+ }
+
+ public override Type GetLibraryManagerType() {
+ return typeof(NodejsLibraryManager);
+ }
+
+ public override IProjectLauncher GetLauncher() {
+ return new NodejsProjectLauncher(this);
+ }
+
+ protected override NodeProperties CreatePropertiesObject() {
+ return new NodejsProjectNodeProperties(this);
+ }
+
+ protected override Stream ProjectIconsImageStripStream {
+ get {
+ return typeof(ProjectNode).Assembly.GetManifestResourceStream("Microsoft.VisualStudioTools.Resources.Icons.SharedProjectImageList.bmp");
+ }
+ }
+
+ public override bool IsCodeFile(string fileName) {
+ var ext = Path.GetExtension(fileName);
+ return ext.Equals(NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase) ||
+ ext.Equals(NodejsConstants.TypeScriptExtension, StringComparison.OrdinalIgnoreCase);
+ }
+
+ public override int InitializeForOuter(string filename, string location, string name, uint flags, ref Guid iid, out IntPtr projectPointer, out int canceled) {
+ NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevelChanged += IntellisenseOptionsPageAnalysisLevelChanged;
+ NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMaximumChanged += AnalysisLogMaximumChanged;
+ NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDiskChanged += IntellisenseOptionsPageSaveToDiskChanged;
+ NodejsPackage.Instance.GeneralOptionsPage.ShowBrowserAndNodeLabelsChanged += ShowBrowserAndNodeLabelsChanged;
+
+ return base.InitializeForOuter(filename, location, name, flags, ref iid, out projectPointer, out canceled);
+ }
+
+ protected override void Reload() {
+ using (new DebugTimer("Project Load")) {
+ // Populate values from project properties before we do anything else.
+ // Otherwise we run into race conditions where, for instance, _analysisIgnoredDirectories
+ // is not properly set before the FileNodes get created in base.Reload()
+ UpdateProjectNodeFromProjectProperties();
+
+ if (_analyzer != null && _analyzer.RemoveUser()) {
+ _analyzer.Dispose();
+ }
+ _analyzer = new VsProjectAnalyzer(ProjectFolder);
+ _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
+ LogAnalysisLevel();
+
+ base.Reload();
+
+ SyncFileSystem();
+
+ NodejsPackage.Instance.CheckSurveyNews(false);
+ ModulesNode.ReloadHierarchySafe();
+
+ // scan for files which were loaded from cached analysis but no longer
+ // exist and remove them.
+ _analyzer.ReloadComplete();
+ }
+ }
+
+ private void UpdateProjectNodeFromProjectProperties() {
+ _intermediateOutputPath = Path.Combine(ProjectHome, GetProjectProperty("BaseIntermediateOutputPath"));
+
+ var ignoredPaths = GetProjectProperty(NodejsConstants.AnalysisIgnoredDirectories);
+
+ if (!string.IsNullOrWhiteSpace(ignoredPaths)) {
+ _analysisIgnoredDirs = _analysisIgnoredDirs.Append(ignoredPaths.Split(';').Select(x => '\\' + x + '\\').ToArray());
+ }
+
+ var maxFileSizeProp = GetProjectProperty(NodejsConstants.AnalysisMaxFileSize);
+ int maxFileSize;
+ if (maxFileSizeProp != null && Int32.TryParse(maxFileSizeProp, out maxFileSize)) {
+ _maxFileSize = maxFileSize;
+ }
+ }
+
+ private void Reanalyze(HierarchyNode node, VsProjectAnalyzer newAnalyzer) {
+ if (node != null) {
+ for (var child = node.FirstChild; child != null; child = child.NextSibling) {
+ if (child is PackageJsonFileNode) {
+ ((PackageJsonFileNode)child).AnalyzePackageJson(newAnalyzer);
+ } else if (child is NodejsFileNode) {
+ if (((NodejsFileNode)child).ShouldAnalyze) {
+ newAnalyzer.AnalyzeFile(child.Url, !child.IsNonMemberItem);
+ }
+ }
+
+ Reanalyze(child, newAnalyzer);
+ }
+ }
+ }
+
+ private void LogAnalysisLevel() {
+ var analyzer = _analyzer;
+ if (analyzer != null) {
+ NodejsPackage.Instance.Logger.LogEvent(Logging.NodejsToolsLogEvent.AnalysisLevel, (int)analyzer.AnalysisLevel);
+ }
+ }
+
+ /*
+ * Needed if we switch to per project Analysis levels
+ internal NodejsTools.Options.AnalysisLevel AnalysisLevel(){
+ var analyzer = _analyzer;
+ if (_analyzer != null) {
+ return _analyzer.AnalysisLevel;
+ }
+ return NodejsTools.Options.AnalysisLevel.None;
+ }
+ */
+ private void IntellisenseOptionsPageAnalysisLevelChanged(object sender, EventArgs e) {
+
+ var oldAnalyzer = _analyzer;
+ _analyzer = null;
+
+ var analyzer = new VsProjectAnalyzer(ProjectFolder);
+ Reanalyze(this, analyzer);
+ if (oldAnalyzer != null) {
+ analyzer.SwitchAnalyzers(oldAnalyzer);
+ if (oldAnalyzer.RemoveUser()) {
+ oldAnalyzer.Dispose();
+ }
+ }
+ _analyzer = analyzer;
+ _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
+ LogAnalysisLevel();
+ }
+
+ private void AnalysisLogMaximumChanged(object sender, EventArgs e) {
+ if (_analyzer != null) {
+ _analyzer.MaxLogLength = NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMax;
+ }
+ }
+
+ private void IntellisenseOptionsPageSaveToDiskChanged(object sender, EventArgs e) {
+ if (_analyzer != null) {
+ _analyzer.SaveToDisk = NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDisk;
+ }
+ }
+
+ private void ShowBrowserAndNodeLabelsChanged(object sender, EventArgs e) {
+ var nodejsFolderNodes = this.AllDescendants.Where(item => (item as NodejsFolderNode) != null).Select(item => (NodejsFolderNode)item);
+ foreach (var node in nodejsFolderNodes) {
+ ProjectMgr.ReDrawNode(node, UIHierarchyElement.Caption);
+ }
+ }
+
+ protected override void RaiseProjectPropertyChanged(string propertyName, string oldValue, string newValue) {
+ base.RaiseProjectPropertyChanged(propertyName, oldValue, newValue);
+
+ var propPage = GeneralPropertyPageControl;
+ if (propPage != null) {
+ switch (propertyName) {
+ case NodejsConstants.Environment:
+ propPage.Environment = newValue;
+ break;
+ case NodejsConstants.DebuggerPort:
+ propPage.DebuggerPort = newValue;
+ break;
+ case NodejsConstants.NodejsPort:
+ propPage.NodejsPort = newValue;
+ break;
+ case NodejsConstants.NodeExePath:
+ propPage.NodeExePath = newValue;
+ break;
+ case NodejsConstants.NodeExeArguments:
+ propPage.NodeExeArguments = newValue;
+ break;
+ case CommonConstants.StartupFile:
+ propPage.ScriptFile = newValue;
+ break;
+ case NodejsConstants.ScriptArguments:
+ propPage.ScriptArguments = newValue;
+ break;
+ case NodejsConstants.LaunchUrl:
+ propPage.LaunchUrl = newValue;
+ break;
+ case NodejsConstants.StartWebBrowser:
+ bool value;
+ if (Boolean.TryParse(newValue, out value)) {
+ propPage.StartWebBrowser = value;
+ }
+ break;
+ case CommonConstants.WorkingDirectory:
+ propPage.WorkingDirectory = newValue;
+ break;
+ default:
+ if (propPage != null) {
+ PropertyPage.IsDirty = true;
+ }
+ break;
+ }
+ }
+ }
+
+ private NodejsGeneralPropertyPageControl GeneralPropertyPageControl {
+ get {
+ if (PropertyPage != null && PropertyPage.Control != null) {
+ return (NodejsGeneralPropertyPageControl)PropertyPage.Control;
+ }
+
+ return null;
+ }
+ }
+
+ private static void AddFolderForFile(Dictionary> directoryPackages, FileNode rootFile, CommonFolderNode folderChild) {
+ List folders;
+ if (!directoryPackages.TryGetValue(rootFile, out folders)) {
+ directoryPackages[rootFile] = folders = new List();
+ }
+ folders.Add(folderChild);
+ }
+
+ protected override bool IncludeNonMemberItemInProject(HierarchyNode node) {
+ var fileNode = node as NodejsFileNode;
+ if (fileNode != null) {
+ return IncludeNodejsFile(fileNode);
+ }
+ return false;
+ }
+
+ internal bool IncludeNodejsFile(NodejsFileNode fileNode) {
+ var url = fileNode.Url;
+ if (CommonUtils.IsSubpathOf(_intermediateOutputPath, fileNode.Url)) {
+ return false;
+ }
+
+ foreach (var path in _analysisIgnoredDirs) {
+ if (url.IndexOf(path, 0, StringComparison.OrdinalIgnoreCase) != -1) {
+ return false;
+ }
+ }
+
+ var fileInfo = new FileInfo(fileNode.Url);
+ if (!fileInfo.Exists || fileInfo.Length > _maxFileSize) {
+ // skip obviously generated and missing files...
+ return false;
+ }
+
+ int nestedModulesDepth = 0;
+ if (ModulesNode.NpmController.RootPackage != null && ModulesNode.NpmController.RootPackage.Modules != null) {
+ nestedModulesDepth = ModulesNode.NpmController.RootPackage.Modules.GetDepth(fileNode.Url);
+ }
+
+ if (_analyzer != null && _analyzer.Project != null &&
+ _analyzer.Project.Limits.IsPathExceedNestingLimit(nestedModulesDepth)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ internal override object Object {
+ get {
+ return this;
+ }
+ }
+
+ protected override ReferenceContainerNode CreateReferenceContainerNode() {
+ return null;
+ }
+
+ public NodeModulesNode ModulesNode { get; private set; }
+
+
+
+ protected internal override void ProcessReferences() {
+ base.ProcessReferences();
+
+ if (null == ModulesNode) {
+ ModulesNode = new NodeModulesNode(this);
+ AddChild(ModulesNode);
+ _idleNodeModulesTimer = new Timer(OnIdleNodeModules);
+ }
+ }
+
+ #region VSWebSite Members
+
+ // This interface is just implemented so we don't get normal profiling which
+ // doesn't work with our projects anyway.
+
+ public EnvDTE.ProjectItem AddFromTemplate(string bstrRelFolderUrl, string bstrWizardName, string bstrLanguage, string bstrItemName, bool bUseCodeSeparation, string bstrMasterPage, string bstrDocType) {
+ throw new NotImplementedException();
+ }
+
+ public VsWebSite.CodeFolders CodeFolders {
+ get { throw new NotImplementedException(); }
+ }
+
+ public EnvDTE.DTE DTE {
+ get { return Project.DTE; }
+ }
+
+ public string EnsureServerRunning() {
+ throw new NotImplementedException();
+ }
+
+ public string GetUniqueFilename(string bstrFolder, string bstrRoot, string bstrDesiredExt) {
+ throw new NotImplementedException();
+ }
+
+ public bool PreCompileWeb(string bstrCompilePath, bool bUpdateable) {
+ throw new NotImplementedException();
+ }
+
+ public EnvDTE.Project Project {
+ get { return (OAProject)GetAutomationObject(); }
+ }
+
+ public VsWebSite.AssemblyReferences References {
+ get { throw new NotImplementedException(); }
+ }
+
+ public void Refresh() {
+ }
+
+ public string TemplatePath {
+ get { throw new NotImplementedException(); }
+ }
+
+ public string URL {
+ get { throw new NotImplementedException(); }
+ }
+
+ public string UserTemplatePath {
+ get { throw new NotImplementedException(); }
+ }
+
+ public VsWebSite.VSWebSiteEvents VSWebSiteEvents {
+ get { throw new NotImplementedException(); }
+ }
+
+ public void WaitUntilReady() {
+ }
+
+ public VsWebSite.WebReferences WebReferences {
+ get { throw new NotImplementedException(); }
+ }
+
+ public VsWebSite.WebServices WebServices {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ Task INodePackageModulesCommands.InstallMissingModulesAsync() {
+ //Fire off the command to update the missing modules
+ // through NPM
+ return ModulesNode.InstallMissingModules();
+ }
+
+ private void HookErrorsAndWarnings(VsProjectAnalyzer res) {
+ res.ErrorAdded += OnErrorAdded;
+ res.ErrorRemoved += OnErrorRemoved;
+ res.WarningAdded += OnWarningAdded;
+ res.WarningRemoved += OnWarningRemoved;
+ }
+
+ private void UnHookErrorsAndWarnings(VsProjectAnalyzer res) {
+ res.ErrorAdded -= OnErrorAdded;
+ res.ErrorRemoved -= OnErrorRemoved;
+ res.WarningAdded -= OnWarningAdded;
+ res.WarningRemoved -= OnWarningRemoved;
+ }
+
+ private void OnErrorAdded(object sender, FileEventArgs args) {
+ if (_diskNodes.ContainsKey(args.Filename)) {
+ _errorFiles.Add(args.Filename);
+ }
+ }
+
+ private void OnErrorRemoved(object sender, FileEventArgs args) {
+ _errorFiles.Remove(args.Filename);
+ }
+
+ private void OnWarningAdded(object sender, FileEventArgs args) {
+ if (_diskNodes.ContainsKey(args.Filename)) {
+ _warningFiles.Add(args.Filename);
+ }
+ }
+
+ private void OnWarningRemoved(object sender, FileEventArgs args) {
+ _warningFiles.Remove(args.Filename);
+ }
+
+ ///
+ /// File names within the project which contain errors.
+ ///
+ public HashSet ErrorFiles {
+ get {
+ return _errorFiles;
+ }
+ }
+
+ ///
+ /// File names within the project which contain warnings.
+ ///
+ public HashSet WarningFiles {
+ get {
+ return _warningFiles;
+ }
+ }
+
+ internal struct LongPathInfo {
+ public string FullPath;
+ public string RelativePath;
+ public bool IsDirectory;
+ }
+
+ private static readonly Regex _uninstallRegex = new Regex(@"\b(uninstall|rm)\b");
+ private static readonly char[] _pathSeparators = { '\\', '/' };
+ private bool _isCheckingForLongPaths;
+
+ public async Task CheckForLongPaths(string npmArguments = null) {
+ if (_isCheckingForLongPaths || !NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths) {
+ return;
+ }
+
+ if (npmArguments != null && _uninstallRegex.IsMatch(npmArguments)) {
+ return;
+ }
+
+ try {
+ _isCheckingForLongPaths = true;
+ TaskDialogButton dedupeButton, ignoreButton, disableButton;
+ var taskDialog = new TaskDialog(NodejsPackage.Instance) {
+ AllowCancellation = true,
+ EnableHyperlinks = true,
+ Title = SR.GetString(SR.LongPathWarningTitle),
+ MainIcon = TaskDialogIcon.Warning,
+ Content = SR.GetString(SR.LongPathWarningText),
+ CollapsedControlText = SR.GetString(SR.LongPathShowPathsExceedingTheLimit),
+ ExpandedControlText = SR.GetString(SR.LongPathHidePathsExceedingTheLimit),
+ Buttons = {
+ (dedupeButton = new TaskDialogButton(SR.GetString(SR.LongPathNpmDedupe), SR.GetString(SR.LongPathNpmDedupeDetail))),
+ (ignoreButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingButWarnNextTime))),
+ (disableButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgain), SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgainDetail)))
+ },
+ FooterIcon = TaskDialogIcon.Information,
+ Footer = SR.GetString(SR.LongPathFooter)
+ };
+
+ taskDialog.HyperlinkClicked += (sender, e) => {
+ switch (e.Url) {
+ case "#msdn":
+ Process.Start("http://go.microsoft.com/fwlink/?LinkId=454508");
+ break;
+ case "#uservoice":
+ Process.Start("http://go.microsoft.com/fwlink/?LinkID=456509");
+ break;
+ case "#help":
+ Process.Start("http://go.microsoft.com/fwlink/?LinkId=456511");
+ break;
+ default:
+ System.Windows.Clipboard.SetText(e.Url);
+ break;
+ }
+ };
+
+ recheck:
+
+ var longPaths = await Task.Factory.StartNew(() =>
+ GetLongSubPaths(ProjectHome)
+ .Concat(GetLongSubPaths(_intermediateOutputPath))
+ .Select(lpi => string.Format("• {1}\u00A0{2}", lpi.FullPath, lpi.RelativePath, SR.GetString(SR.LongPathClickToCopy)))
+ .ToArray());
+ if (longPaths.Length == 0) {
+ return;
+ }
+ taskDialog.ExpandedInformation = string.Join("\r\n", longPaths);
+
+ var button = taskDialog.ShowModal();
+ if (button == dedupeButton) {
+ var repl = NodejsPackage.Instance.OpenReplWindow(focus: false);
+ await repl.ExecuteCommand(".npm dedupe").HandleAllExceptions(SR.ProductName);
+
+ taskDialog.Content += "\r\n\r\n" + SR.GetString(SR.LongPathNpmDedupeDidNotHelp);
+ taskDialog.Buttons.Remove(dedupeButton);
+ goto recheck;
+ } else if (button == disableButton) {
+ var page = NodejsPackage.Instance.GeneralOptionsPage;
+ page.CheckForLongPaths = false;
+ page.SaveSettingsToStorage();
+ }
+ } finally {
+ _isCheckingForLongPaths = false;
+ }
+ }
+
+ internal static IEnumerable GetLongSubPaths(string basePath, string path = "") {
+ const int MaxFilePathLength = 260 - 1; // account for terminating NULL
+ const int MaxDirectoryPathLength = 248 - 1;
+
+ basePath = CommonUtils.EnsureEndSeparator(basePath);
+
+ WIN32_FIND_DATA wfd;
+ IntPtr hFind = NativeMethods.FindFirstFile(basePath + path + "\\*", out wfd);
+ if (hFind == NativeMethods.INVALID_HANDLE_VALUE) {
+ yield break;
+ }
+
+ try {
+ do {
+ if (wfd.cFileName == "." || wfd.cFileName == "..") {
+ continue;
+ }
+
+ bool isDirectory = (wfd.dwFileAttributes & NativeMethods.FILE_ATTRIBUTE_DIRECTORY) != 0;
+
+ string childPath = path;
+ if (childPath != String.Empty) {
+ childPath += "\\";
+ }
+ childPath += wfd.cFileName;
+
+ string fullChildPath = basePath + childPath;
+ bool isTooLong;
+ try {
+ isTooLong = Path.GetFullPath(fullChildPath).Length > (isDirectory ? MaxDirectoryPathLength : MaxFilePathLength);
+ } catch (PathTooLongException) {
+ isTooLong = true;
+ } catch (Exception) {
+ continue;
+ }
+
+ if (isTooLong) {
+ yield return new LongPathInfo { FullPath = fullChildPath, RelativePath = childPath, IsDirectory = isDirectory };
+ } else if (isDirectory) {
+ foreach (var item in GetLongSubPaths(basePath, childPath)) {
+ yield return item;
+ }
+ }
+ } while (NativeMethods.FindNextFile(hFind, out wfd));
+ } finally {
+ NativeMethods.FindClose(hFind);
+ }
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (_analyzer != null) {
+ UnHookErrorsAndWarnings(_analyzer);
+ if (WarningFiles.Count > 0 || ErrorFiles.Count > 0) {
+ foreach (var file in WarningFiles.Concat(ErrorFiles)) {
+ var node = FindNodeByFullPath(file) as NodejsFileNode;
+ if (node != null) {
+ //_analyzer.RemoveErrors(node.GetAnalysis(), suppressUpdate: false);
+ }
+ }
+ }
+
+ if (_analyzer.RemoveUser()) {
+ _analyzer.Dispose();
+ }
+ _analyzer = null;
+ }
+
+ lock (_idleNodeModulesLock) {
+ if (_idleNodeModulesTimer != null) {
+ _idleNodeModulesTimer.Dispose();
+ }
+ _idleNodeModulesTimer = null;
+ }
+
+ NodejsPackage.Instance.IntellisenseOptionsPage.SaveToDiskChanged -= IntellisenseOptionsPageSaveToDiskChanged;
+ NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLevelChanged -= IntellisenseOptionsPageAnalysisLevelChanged;
+ NodejsPackage.Instance.IntellisenseOptionsPage.AnalysisLogMaximumChanged -= AnalysisLogMaximumChanged;
+ }
+ base.Dispose(disposing);
+ }
+
+ internal override async void BuildAsync(uint vsopts, string config, VisualStudio.Shell.Interop.IVsOutputWindowPane output, string target, Action uiThreadCallback) {
+ try {
+ await CheckForLongPaths();
+ } catch (Exception) {
+ uiThreadCallback(MSBuildResult.Failed, target);
+ return;
+ }
+
+ // BuildAsync can throw on the sync path before invoking the callback. If it does, we must still invoke the callback here,
+ // because by this time there's no other way to propagate the error to the caller.
+ try {
+ base.BuildAsync(vsopts, config, output, target, uiThreadCallback);
+ } catch (Exception) {
+ uiThreadCallback(MSBuildResult.Failed, target);
+ }
+ }
+
+ internal override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) {
+ if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidOpenReplWindow:
+ result = QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
+ return VSConstants.S_OK;
+ }
+ }
+ return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
+ }
+
+ protected override QueryStatusResult QueryStatusSelectionOnNodes(IList selectedNodes, Guid cmdGroup, uint cmd, IntPtr pCmdText) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidNpmManageModules:
+ if (IsCurrentStateASuppressCommandsMode()) {
+ return QueryStatusResult.SUPPORTED;
+ } else if (!ShowManageModulesCommandOnNode(selectedNodes)) {
+ return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED | QueryStatusResult.INVISIBLE;
+ }
+ return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
+ }
+ } else if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidSetAsNodejsStartupFile:
+ if (ShowSetAsStartupFileCommandOnNode(selectedNodes)) {
+ // We enable "Set as StartUp File" command only on current language code files,
+ // the file is in project home dir and if the file is not the startup file already.
+ string startupFile = ((CommonProjectNode)ProjectMgr).GetStartupFile();
+ if (!CommonUtils.IsSamePath(startupFile, selectedNodes[0].Url)) {
+ return QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
+ }
+ }
+ break;
+ }
+ }
+
+ return base.QueryStatusSelectionOnNodes(selectedNodes, cmdGroup, cmd, pCmdText);
+ }
+
+ internal override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmd) {
+ case PkgCmdId.cmdidOpenReplWindow:
+ NodejsPackage.Instance.OpenReplWindow();
+ return VSConstants.S_OK;
+ }
+ } else if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ try {
+ NpmHelpers.GetPathToNpm(
+ Nodejs.GetAbsoluteNodeExePath(
+ ProjectHome,
+ Project.GetNodejsProject().GetProjectProperty(NodejsConstants.NodeExePath)
+ ));
+ } catch (NpmNotFoundException) {
+ Nodejs.ShowNodejsNotInstalled();
+ return VSConstants.S_OK;
+ }
+ }
+ return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
+ }
+
+ protected override int ExecCommandThatDependsOnSelectedNodes(Guid cmdGroup, uint cmdId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin commandOrigin, IList selectedNodes, out bool handled) {
+ if (cmdGroup == Guids.NodejsNpmCmdSet) {
+ try {
+ NpmHelpers.GetPathToNpm(
+ Nodejs.GetAbsoluteNodeExePath(
+ ProjectHome,
+ Project.GetNodejsProject().GetProjectProperty(NodejsConstants.NodeExePath)
+ ));
+ } catch (NpmNotFoundException) {
+ Nodejs.ShowNodejsNotInstalled();
+ handled = true;
+ return VSConstants.S_OK;
+ }
+
+ switch (cmdId) {
+ case PkgCmdId.cmdidNpmManageModules:
+ if (!ShowManageModulesCommandOnNode(selectedNodes)) {
+ ModulesNode.ManageModules();
+ handled = true;
+ return VSConstants.S_OK;
+ }
+
+ var node = selectedNodes[0] as AbstractNpmNode;
+ if (node != null) {
+ var abstractNpmNode = node;
+ abstractNpmNode.ManageNpmModules();
+ handled = true;
+ return VSConstants.S_OK;
+ }
+ break;
+ }
+ } else if (cmdGroup == Guids.NodejsCmdSet) {
+ switch (cmdId) {
+ case PkgCmdId.cmdidSetAsNodejsStartupFile:
+ // Set the StartupFile project property to the Url of this node
+ SetProjectProperty(
+ CommonConstants.StartupFile,
+ CommonUtils.GetRelativeFilePath(ProjectHome, selectedNodes[0].Url)
+ );
+ handled = true;
+ return VSConstants.S_OK;
+ }
+ }
+
+ return base.ExecCommandThatDependsOnSelectedNodes(cmdGroup, cmdId, cmdExecOpt, vaIn, vaOut, commandOrigin, selectedNodes, out handled);
+ }
+
+ private bool ShowSetAsStartupFileCommandOnNode(IList selectedNodes) {
+ var selectedNodeUrl = selectedNodes[0].Url;
+ return selectedNodes.Count == 1 &&
+ (IsCodeFile(selectedNodeUrl) ||
+ // for some reason, the default express 4 template's startup file lacks an extension.
+ string.IsNullOrEmpty(Path.GetExtension(selectedNodeUrl)));
+ }
+
+ private static bool ShowManageModulesCommandOnNode(IList selectedNodes) {
+ return selectedNodes.Count == 1 && selectedNodes[0] is AbstractNpmNode;
+ }
+
+ protected internal override void SetCurrentConfiguration() {
+ if (!IsProjectOpened) {
+ return;
+ }
+
+ if (this.IsPlatformAware()) {
+ EnvDTE.Project automationObject = GetAutomationObject() as EnvDTE.Project;
+
+ this.BuildProject.SetGlobalProperty(ProjectFileConstants.Platform, automationObject.ConfigurationManager.ActiveConfiguration.PlatformName);
+ }
+ base.SetCurrentConfiguration();
+ }
+
+ public override MSBuildResult Build(string config, string target) {
+ if (this.IsPlatformAware()) {
+ var platform = this.BuildProject.GetPropertyValue(GlobalProperty.Platform.ToString());
+
+ if (platform == ProjectConfig.AnyCPU) {
+ this.BuildProject.SetGlobalProperty(GlobalProperty.Platform.ToString(), ConfigProvider.x86Platform);
+ }
+ }
+ return base.Build(config, target);
+ }
+
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/NodejsProjectNodeProperties.cs b/Nodejs/Product/Nodejs/Project/NodejsProjectNodeProperties.cs
index 54787d697..d078e1264 100644
--- a/Nodejs/Product/Nodejs/Project/NodejsProjectNodeProperties.cs
+++ b/Nodejs/Product/Nodejs/Project/NodejsProjectNodeProperties.cs
@@ -60,8 +60,8 @@ public uint TargetFramework {
public string NodeExePath {
get {
return HierarchyNode.ProjectMgr.Site.GetUIThread().Invoke(() => {
- return Nodejs.GetAbsoluteNodeExePath(
- ProjectHome,
+ return Nodejs.GetAbsoluteNodeExePath(
+ ProjectHome,
Node.ProjectMgr.GetProjectProperty(NodejsConstants.NodeExePath, true));
});
}
diff --git a/Nodejs/Product/Nodejs/Project/NpmNodeProperties.cs b/Nodejs/Product/Nodejs/Project/NpmNodeProperties.cs
index 557696514..4508ae7f1 100644
--- a/Nodejs/Product/Nodejs/Project/NpmNodeProperties.cs
+++ b/Nodejs/Product/Nodejs/Project/NpmNodeProperties.cs
@@ -1,80 +1,80 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.VisualStudioTools.Project;
-
-namespace Microsoft.NodejsTools.Project {
- [ComVisible(true)]
- [ClassInterface(ClassInterfaceType.AutoDual)]
- [Guid("3C3BD073-2AB3-4E66-BBE9-C8B2D8A774D1")]
- public class NpmNodeProperties : NodeProperties {
- internal NpmNodeProperties(AbstractNpmNode node) : base(node) {}
-
- private AbstractNpmNode NpmNode {
- get { return Node as AbstractNpmNode; }
- }
-
- private bool IsGlobalNode {
- get { return NpmNode is GlobalModulesNode; }
- }
-
- public override string GetClassName() {
- return SR.GetString(IsGlobalNode ? SR.PropertiesClassGlobal : SR.PropertiesClassNpm);
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmNodePackageInstallation)]
- [SRDescriptionAttribute(SR.NpmNodePackageInstallationDescription)]
- public string PackageInstallation {
- get {
- return SR.GetString(IsGlobalNode ? SR.PackageInstallationGlobal : SR.PackageInstallationLocal);
- }
- }
-
- [SRCategoryAttribute(SR.General)]
- [SRDisplayName(SR.NpmNodePath)]
- [SRDescriptionAttribute(SR.NpmNodePathDescription)]
- public string Path {
- get {
- var node = NpmNode;
- if (null != node) {
- var local = node as NodeModulesNode;
- if (null != local) {
- var root = local.RootPackage;
- if (null != root) {
- return root.Path;
- }
- } else {
- var glob = node as GlobalModulesNode;
- if (null != glob) {
- var packages = glob.GlobalPackages;
- if (null != packages) {
- return packages.Path;
- }
- }
- }
- }
- return null;
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualStudioTools.Project;
+
+namespace Microsoft.NodejsTools.Project {
+ [ComVisible(true)]
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+ [Guid("3C3BD073-2AB3-4E66-BBE9-C8B2D8A774D1")]
+ public class NpmNodeProperties : NodeProperties {
+ internal NpmNodeProperties(AbstractNpmNode node) : base(node) {}
+
+ private AbstractNpmNode NpmNode {
+ get { return Node as AbstractNpmNode; }
+ }
+
+ private bool IsGlobalNode {
+ get { return NpmNode is GlobalModulesNode; }
+ }
+
+ public override string GetClassName() {
+ return SR.GetString(IsGlobalNode ? SR.PropertiesClassGlobal : SR.PropertiesClassNpm);
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmNodePackageInstallation)]
+ [SRDescriptionAttribute(SR.NpmNodePackageInstallationDescription)]
+ public string PackageInstallation {
+ get {
+ return SR.GetString(IsGlobalNode ? SR.PackageInstallationGlobal : SR.PackageInstallationLocal);
+ }
+ }
+
+ [SRCategoryAttribute(SR.General)]
+ [SRDisplayName(SR.NpmNodePath)]
+ [SRDescriptionAttribute(SR.NpmNodePathDescription)]
+ public string Path {
+ get {
+ var node = NpmNode;
+ if (null != node) {
+ var local = node as NodeModulesNode;
+ if (null != local) {
+ var root = local.RootPackage;
+ if (null != root) {
+ return root.Path;
+ }
+ } else {
+ var glob = node as GlobalModulesNode;
+ if (null != glob) {
+ var packages = glob.GlobalPackages;
+ if (null != packages) {
+ return packages.Path;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Project/ProjectResources.cs b/Nodejs/Product/Nodejs/Project/ProjectResources.cs
index 3b6b18257..3d3b3ec9f 100644
--- a/Nodejs/Product/Nodejs/Project/ProjectResources.cs
+++ b/Nodejs/Product/Nodejs/Project/ProjectResources.cs
@@ -1,205 +1,205 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Resources;
-using System.Threading;
-using CommonSR = Microsoft.VisualStudioTools.Project.SR;
-
-namespace Microsoft.NodejsTools.Project {
- internal class SR : CommonSR {
- internal const string NodejsToolsForVisualStudio = "NodejsToolsForVisualStudio";
-
- internal const string AzureToolsInstallInstructions = "AzureToolsInstallInstructions";
- internal const string AzureToolsRequired = "AzureToolsRequired";
- internal const string AzureToolsUpgradeInstructions = "AzureToolsUpgradeInstructions";
- internal const string AzureToolsUpgradeRecommended = "AzureToolsUpgradeRecommended";
- internal const string CatalogLoadingDefault = "CatalogLoadingDefault";
- internal const string CatalogLoadingNoNpm = "CatalogLoadingNoNpm";
- internal const string CategoryStatus = "CategoryStatus";
- internal const string CategoryVersion = "CategoryVersion";
- internal const string ContinueWithoutAzureToolsUpgrade = "ContinueWithoutAzureToolsUpgrade";
- internal const string DebuggerConnectionClosed = "DebuggerConnectionClosed";
- internal const string DebuggerModuleUpdateFailed = "DebuggerModuleUpdateFailed";
- internal const string DebuggerPort = "DebuggerPort";
- internal const string DontShowAgain = "DontShowAgain";
- internal const string DownloadAndInstall = "DownloadAndInstall";
- internal const string EnvironmentVariables = "EnvironmentVariables";
- internal const string ErrorNoDte = "ErrorNoDte";
- internal const string IncludeNodeModulesCancelTitle = "IncludeNodeModulesCancelTitle";
- internal const string IncludeNodeModulesContent = "IncludeNodeModulesContent";
- internal const string IncludeNodeModulesIncludeDescription = "IncludeNodeModulesIncludeDescription";
- internal const string IncludeNodeModulesIncludeTitle = "IncludeNodeModulesIncludeTitle";
- internal const string IncludeNodeModulesInformation = "IncludeNodeModulesInformation";
- internal const string InsertSnippet = "InsertSnippet";
- internal const string InvalidPortNumber = "InvalidPortNumber";
- internal const string LaunchUrlToolTip = "LaunchUrlToolTip";
- internal const string LinkStatusLinkedFromGlobal = "LinkStatusLinkedFromGlobal";
- internal const string LinkStatusLinkedToProject = "LinkStatusLinkedToProject";
- internal const string LinkStatusLocallyInstalled = "LinkStatusLocallyInstalled";
- internal const string LinkStatusNotApplicableSubPackages = "LinkStatusNotApplicableSubPackages";
- internal const string LinkStatusNotLinkedToProject = "LinkStatusNotLinkedToProject";
- internal const string LinkStatusUnknown = "LinkStatusUnknown";
- internal const string LongPathClickToCopy = "LongPathClickToCopy";
- internal const string LongPathDoNothingAndDoNotWarnAgain = "LongPathDoNothingAndDoNotWarnAgain";
- internal const string LongPathDoNothingAndDoNotWarnAgainDetail = "LongPathDoNothingAndDoNotWarnAgainDetail";
- internal const string LongPathDoNothingButWarnNextTime = "LongPathDoNothingButWarnNextTime";
- internal const string LongPathFooter = "LongPathFooter";
- internal const string LongPathHidePathsExceedingTheLimit = "LongPathHidePathsExceedingTheLimit";
- internal const string LongPathNpmDedupe = "LongPathNpmDedupe";
- internal const string LongPathNpmDedupeDetail = "LongPathNpmDedupeDetail";
- internal const string LongPathNpmDedupeDidNotHelp = "LongPathNpmDedupeDidNotHelp";
- internal const string LongPathShowPathsExceedingTheLimit = "LongPathShowPathsExceedingTheLimit";
- internal const string LongPathWarningText = "LongPathWarningText";
- internal const string LongPathWarningTitle = "LongPathWarningTitle";
- internal const string Milliseconds = "Milliseconds";
- internal const string NewVersionNo = "NewVersionNo";
- internal const string NewVersionNotApplicableSubpackage = "NewVersionNotApplicableSubpackage";
- internal const string NewVersionPackageCatalogNotRetrieved = "NewVersionPackageCatalogNotRetrieved";
- internal const string NewVersionUnknown = "NewVersionUnknown";
- internal const string NewVersionYes = "NewVersionYes";
- internal const string NodeExeArguments = "NodeExeArguments";
- internal const string NodeExeArgumentsDescription = "NodeExeArgumentsDescription";
- internal const string NodeExeArgumentsToolTip = "NodeExeArgumentsToolTip";
- internal const string NodeExeDoesntExist = "NodeExeDoesntExist";
- internal const string NodeExePath = "NodeExePath";
- internal const string NodeExePathDescription = "NodeExePathDescription";
- internal const string NodeExePathNotFound = "NodeExePathNotFound";
- internal const string NodeExePathToolTip = "NodeExePathToolTip";
- internal const string NodejsNotInstalled = "NodejsNotInstalled";
- internal const string NodejsNotInstalledShort = "NodejsNotInstalledShort";
- internal const string NodejsNotSupported = "NodejsNotSupported";
- internal const string NodejsPort = "NodejsPort";
- internal const string NodejsPortDescription = "NodejsPortDescription";
- internal const string NodejsPortToolTip = "NodejsPortToolTip";
- internal const string NoKeywordsInPackage = "NoKeywordsInPackage";
- internal const string NpmCancelled = "NpmCancelled";
- internal const string NpmCancelledWithErrors = "NpmCancelledWithErrors";
- internal const string NpmCompletedWithErrors = "NpmCompletedWithErrors";
- internal const string NpmNodePackageInstallation = "NpmNodePackageInstallation";
- internal const string NpmNodePackageInstallationDescription = "NpmNodePackageInstallationDescription";
- internal const string NpmNodePath = "NpmNodePath";
- internal const string NpmNodePathDescription = "NpmNodePathDescription";
- internal const string NpmOutputPaneTitle = "NpmOutputPaneTitle";
- internal const string NpmPackageAuthor = "NpmPackageAuthor";
- internal const string NpmPackageAuthorDescription = "NpmPackageAuthorDescription";
- internal const string NpmPackageDescription = "NpmPackageDescription";
- internal const string NpmPackageDescriptionDescription = "NpmPackageDescriptionDescription";
- internal const string NpmPackageInstallHelpMessage = "NpmPackageInstallHelpMessage";
- internal const string NpmPackageIsBundledDependency = "NpmPackageIsBundledDependency";
- internal const string NpmPackageIsBundledDependencyDescription = "NpmPackageIsBundledDependencyDescription";
- internal const string NpmPackageIsDevDependency = "NpmPackageIsDevDependency";
- internal const string NpmPackageIsDevDependencyDescription = "NpmPackageIsDevDependencyDescription";
- internal const string NpmPackageIsListedInParentPackageJson = "NpmPackageIsListedInParentPackageJson";
- internal const string NpmPackageIsListedInParentPackageJsonDescription = "NpmPackageIsListedInParentPackageJsonDescription";
- internal const string NpmPackageIsMissing = "NpmPackageIsMissing";
- internal const string NpmPackageIsMissingDescription = "NpmPackageIsMissingDescription";
- internal const string NpmPackageIsOptionalDependency = "NpmPackageIsOptionalDependency";
- internal const string NpmPackageIsOptionalDependencyDescription = "NpmPackageIsOptionalDependencyDescription";
- internal const string NpmPackageKeywords = "NpmPackageKeywords";
- internal const string NpmPackageKeywordsDescription = "NpmPackageKeywordsDescription";
- internal const string NpmPackageLinkStatus = "NpmPackageLinkStatus";
- internal const string NpmPackageLinkStatusDescription = "NpmPackageLinkStatusDescription";
- internal const string NpmPackageName = "NpmPackageName";
- internal const string NpmPackageNameDescription = "NpmPackageNameDescription";
- internal const string NpmPackageNewVersionAvailable = "NpmPackageNewVersionAvailable";
- internal const string NpmPackageNewVersionAvailableDescription = "NpmPackageNewVersionAvailableDescription";
- internal const string NpmPackagePath = "NpmPackagePath";
- internal const string NpmPackagePathDescription = "NpmPackagePathDescription";
- internal const string NpmPackageRequestedVersionRange = "NpmPackageRequestedVersionRange";
- internal const string NpmPackageRequestedVersionRangeDescription = "NpmPackageRequestedVersionRangeDescription";
- internal const string NpmPackageType = "NpmPackageType";
- internal const string NpmPackageTypeDescription = "NpmPackageTypeDescription";
- internal const string NpmPackageVersion = "NpmPackageVersion";
- internal const string NpmPackageVersionDescription = "NpmPackageVersionDescription";
- internal const string NpmReplCommandCompletedWithErrors = "NpmReplCommandCompletedWithErrors";
- internal const string NpmStatusExecuting = "NpmStatusExecuting";
- internal const string NpmStatusExecutingErrors = "NpmStatusExecutingErrors";
- internal const string NpmStatusExecutingQueued = "NpmStatusExecutingQueued";
- internal const string NpmStatusExecutingQueuedErrors = "NpmStatusExecutingQueuedErrors";
- internal const string NpmStatusReady = "NpmStatusReady";
- internal const string NpmStatusReadyWithErrors = "NpmStatusReadyWithErrors";
- internal const string NpmSuccessfullyCompleted = "NpmSuccessfullyCompleted";
- internal const string PackageCatalogRefresh0Days = "PackageCatalogRefresh0Days";
- internal const string PackageCatalogRefresh1Day = "PackageCatalogRefresh1Day";
- internal const string PackageCatalogRefresh1Month = "PackageCatalogRefresh1Month";
- internal const string PackageCatalogRefresh1Week = "PackageCatalogRefresh1Week";
- internal const string PackageCatalogRefresh2To7Days = "PackageCatalogRefresh2To7Days";
- internal const string PackageCatalogRefresh2Weeks = "PackageCatalogRefresh2Weeks";
- internal const string PackageCatalogRefresh3Months = "PackageCatalogRefresh3Months";
- internal const string PackageCatalogRefresh3Weeks = "PackageCatalogRefresh3Weeks";
- internal const string PackageCatalogRefresh6Months = "PackageCatalogRefresh6Months";
- internal const string PackageCatalogRefreshFailed = "PackageCatalogRefreshFailed";
- internal const string PackageCatalogRefreshing = "PackageCatalogRefreshing";
- internal const string PackageCount = "PackageCount";
- internal const string PackageInstallationGlobal = "PackageInstallationGlobal";
- internal const string PackageInstallationLocal = "PackageInstallationLocal";
- internal const string PackageInstalledGlobally = "PackageInstalledGlobally";
- internal const string PackageInstalledGloballyOldVersion = "PackageInstalledGloballyOldVersion";
- internal const string PackageInstalledLocally = "PackageInstalledLocally";
- internal const string PackageInstalledLocallyOldVersion = "PackageInstalledLocallyOldVersion";
- internal const string PackageMatchCount = "PackageMatchCount";
- internal const string PackageTypeGlobal = "PackageTypeGlobal";
- internal const string PackageTypeGlobalSubpackage = "PackageTypeGlobalSubpackage";
- internal const string PackageTypeLocal = "PackageTypeLocal";
- internal const string PackageTypeLocalSubpackage = "PackageTypeLocalSubpackage";
- internal const string PropertiesClassGlobal = "PropertiesClassGlobal";
- internal const string PropertiesClassGlobalPackage = "PropertiesClassGlobalPackage";
- internal const string PropertiesClassGlobalSubPackage = "PropertiesClassGlobalSubPackage";
- internal const string PropertiesClassLocalPackage = "PropertiesClassLocalPackage";
- internal const string PropertiesClassLocalSubPackage = "PropertiesClassLocalSubPackage";
- internal const string PropertiesClassNpm = "PropertiesClassNpm";
- internal const string ReplInitializationMessage = "ReplInitializationMessage";
- internal const string RequestedVersionRangeNone = "RequestedVersionRangeNone";
- internal const string ScriptArgumentsToolTip = "ScriptArgumentsToolTip";
- internal const string ScriptFileToolTip = "ScriptFileTooltip";
- internal const string Seconds = "Seconds";
- internal const string StartBrowserToolTip = "StartBrowserToolTip";
- internal const string StatusAnalysisLoaded = "StatusAnalysisLoaded";
- internal const string StatusAnalysisLoadFailed = "StatusAnalysisLoadFailed";
- internal const string StatusAnalysisLoading = "StatusAnalysisLoading";
- internal const string StatusAnalysisSaved = "StatusAnalysisSaved";
- internal const string StatusAnalysisSaving = "StatusAnalysisSaving";
- internal const string StatusAnalysisUpToDate = "StatusAnalysisUpToDate";
- internal const string SurroundWith = "SurroundWith";
- internal const string TestFramework = "TestFramework";
- internal const string TestFrameworkDescription = "TestFrameworkDescription";
- internal const string UpgradedEnvironmentVariables = "UpgradedEnvironmentVariables";
- internal const string WorkingDirInvalidOrMissing = "WorkingDirInvalidOrMissing";
- internal const string WorkingDirToolTip = "WorkingDirToolTip";
-
- private static readonly Lazy _manager = new Lazy(
- () => new System.Resources.ResourceManager("Microsoft.NodejsTools.Resources", typeof(SR).Assembly),
- LazyThreadSafetyMode.ExecutionAndPublication
- );
-
- private static ResourceManager Manager {
- get {
- return _manager.Value;
- }
- }
-
- internal static new string GetString(string value, params object[] args) {
- return GetStringInternal(Manager, value, args) ?? CommonSR.GetString(value, args);
- }
-
- internal static string ProductName {
- get {
- return GetString(NodejsToolsForVisualStudio);
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Resources;
+using System.Threading;
+using CommonSR = Microsoft.VisualStudioTools.Project.SR;
+
+namespace Microsoft.NodejsTools.Project {
+ internal class SR : CommonSR {
+ internal const string NodejsToolsForVisualStudio = "NodejsToolsForVisualStudio";
+
+ internal const string AzureToolsInstallInstructions = "AzureToolsInstallInstructions";
+ internal const string AzureToolsRequired = "AzureToolsRequired";
+ internal const string AzureToolsUpgradeInstructions = "AzureToolsUpgradeInstructions";
+ internal const string AzureToolsUpgradeRecommended = "AzureToolsUpgradeRecommended";
+ internal const string CatalogLoadingDefault = "CatalogLoadingDefault";
+ internal const string CatalogLoadingNoNpm = "CatalogLoadingNoNpm";
+ internal const string CategoryStatus = "CategoryStatus";
+ internal const string CategoryVersion = "CategoryVersion";
+ internal const string ContinueWithoutAzureToolsUpgrade = "ContinueWithoutAzureToolsUpgrade";
+ internal const string DebuggerConnectionClosed = "DebuggerConnectionClosed";
+ internal const string DebuggerModuleUpdateFailed = "DebuggerModuleUpdateFailed";
+ internal const string DebuggerPort = "DebuggerPort";
+ internal const string DontShowAgain = "DontShowAgain";
+ internal const string DownloadAndInstall = "DownloadAndInstall";
+ internal const string EnvironmentVariables = "EnvironmentVariables";
+ internal const string ErrorNoDte = "ErrorNoDte";
+ internal const string IncludeNodeModulesCancelTitle = "IncludeNodeModulesCancelTitle";
+ internal const string IncludeNodeModulesContent = "IncludeNodeModulesContent";
+ internal const string IncludeNodeModulesIncludeDescription = "IncludeNodeModulesIncludeDescription";
+ internal const string IncludeNodeModulesIncludeTitle = "IncludeNodeModulesIncludeTitle";
+ internal const string IncludeNodeModulesInformation = "IncludeNodeModulesInformation";
+ internal const string InsertSnippet = "InsertSnippet";
+ internal const string InvalidPortNumber = "InvalidPortNumber";
+ internal const string LaunchUrlToolTip = "LaunchUrlToolTip";
+ internal const string LinkStatusLinkedFromGlobal = "LinkStatusLinkedFromGlobal";
+ internal const string LinkStatusLinkedToProject = "LinkStatusLinkedToProject";
+ internal const string LinkStatusLocallyInstalled = "LinkStatusLocallyInstalled";
+ internal const string LinkStatusNotApplicableSubPackages = "LinkStatusNotApplicableSubPackages";
+ internal const string LinkStatusNotLinkedToProject = "LinkStatusNotLinkedToProject";
+ internal const string LinkStatusUnknown = "LinkStatusUnknown";
+ internal const string LongPathClickToCopy = "LongPathClickToCopy";
+ internal const string LongPathDoNothingAndDoNotWarnAgain = "LongPathDoNothingAndDoNotWarnAgain";
+ internal const string LongPathDoNothingAndDoNotWarnAgainDetail = "LongPathDoNothingAndDoNotWarnAgainDetail";
+ internal const string LongPathDoNothingButWarnNextTime = "LongPathDoNothingButWarnNextTime";
+ internal const string LongPathFooter = "LongPathFooter";
+ internal const string LongPathHidePathsExceedingTheLimit = "LongPathHidePathsExceedingTheLimit";
+ internal const string LongPathNpmDedupe = "LongPathNpmDedupe";
+ internal const string LongPathNpmDedupeDetail = "LongPathNpmDedupeDetail";
+ internal const string LongPathNpmDedupeDidNotHelp = "LongPathNpmDedupeDidNotHelp";
+ internal const string LongPathShowPathsExceedingTheLimit = "LongPathShowPathsExceedingTheLimit";
+ internal const string LongPathWarningText = "LongPathWarningText";
+ internal const string LongPathWarningTitle = "LongPathWarningTitle";
+ internal const string Milliseconds = "Milliseconds";
+ internal const string NewVersionNo = "NewVersionNo";
+ internal const string NewVersionNotApplicableSubpackage = "NewVersionNotApplicableSubpackage";
+ internal const string NewVersionPackageCatalogNotRetrieved = "NewVersionPackageCatalogNotRetrieved";
+ internal const string NewVersionUnknown = "NewVersionUnknown";
+ internal const string NewVersionYes = "NewVersionYes";
+ internal const string NodeExeArguments = "NodeExeArguments";
+ internal const string NodeExeArgumentsDescription = "NodeExeArgumentsDescription";
+ internal const string NodeExeArgumentsToolTip = "NodeExeArgumentsToolTip";
+ internal const string NodeExeDoesntExist = "NodeExeDoesntExist";
+ internal const string NodeExePath = "NodeExePath";
+ internal const string NodeExePathDescription = "NodeExePathDescription";
+ internal const string NodeExePathNotFound = "NodeExePathNotFound";
+ internal const string NodeExePathToolTip = "NodeExePathToolTip";
+ internal const string NodejsNotInstalled = "NodejsNotInstalled";
+ internal const string NodejsNotInstalledShort = "NodejsNotInstalledShort";
+ internal const string NodejsNotSupported = "NodejsNotSupported";
+ internal const string NodejsPort = "NodejsPort";
+ internal const string NodejsPortDescription = "NodejsPortDescription";
+ internal const string NodejsPortToolTip = "NodejsPortToolTip";
+ internal const string NoKeywordsInPackage = "NoKeywordsInPackage";
+ internal const string NpmCancelled = "NpmCancelled";
+ internal const string NpmCancelledWithErrors = "NpmCancelledWithErrors";
+ internal const string NpmCompletedWithErrors = "NpmCompletedWithErrors";
+ internal const string NpmNodePackageInstallation = "NpmNodePackageInstallation";
+ internal const string NpmNodePackageInstallationDescription = "NpmNodePackageInstallationDescription";
+ internal const string NpmNodePath = "NpmNodePath";
+ internal const string NpmNodePathDescription = "NpmNodePathDescription";
+ internal const string NpmOutputPaneTitle = "NpmOutputPaneTitle";
+ internal const string NpmPackageAuthor = "NpmPackageAuthor";
+ internal const string NpmPackageAuthorDescription = "NpmPackageAuthorDescription";
+ internal const string NpmPackageDescription = "NpmPackageDescription";
+ internal const string NpmPackageDescriptionDescription = "NpmPackageDescriptionDescription";
+ internal const string NpmPackageInstallHelpMessage = "NpmPackageInstallHelpMessage";
+ internal const string NpmPackageIsBundledDependency = "NpmPackageIsBundledDependency";
+ internal const string NpmPackageIsBundledDependencyDescription = "NpmPackageIsBundledDependencyDescription";
+ internal const string NpmPackageIsDevDependency = "NpmPackageIsDevDependency";
+ internal const string NpmPackageIsDevDependencyDescription = "NpmPackageIsDevDependencyDescription";
+ internal const string NpmPackageIsListedInParentPackageJson = "NpmPackageIsListedInParentPackageJson";
+ internal const string NpmPackageIsListedInParentPackageJsonDescription = "NpmPackageIsListedInParentPackageJsonDescription";
+ internal const string NpmPackageIsMissing = "NpmPackageIsMissing";
+ internal const string NpmPackageIsMissingDescription = "NpmPackageIsMissingDescription";
+ internal const string NpmPackageIsOptionalDependency = "NpmPackageIsOptionalDependency";
+ internal const string NpmPackageIsOptionalDependencyDescription = "NpmPackageIsOptionalDependencyDescription";
+ internal const string NpmPackageKeywords = "NpmPackageKeywords";
+ internal const string NpmPackageKeywordsDescription = "NpmPackageKeywordsDescription";
+ internal const string NpmPackageLinkStatus = "NpmPackageLinkStatus";
+ internal const string NpmPackageLinkStatusDescription = "NpmPackageLinkStatusDescription";
+ internal const string NpmPackageName = "NpmPackageName";
+ internal const string NpmPackageNameDescription = "NpmPackageNameDescription";
+ internal const string NpmPackageNewVersionAvailable = "NpmPackageNewVersionAvailable";
+ internal const string NpmPackageNewVersionAvailableDescription = "NpmPackageNewVersionAvailableDescription";
+ internal const string NpmPackagePath = "NpmPackagePath";
+ internal const string NpmPackagePathDescription = "NpmPackagePathDescription";
+ internal const string NpmPackageRequestedVersionRange = "NpmPackageRequestedVersionRange";
+ internal const string NpmPackageRequestedVersionRangeDescription = "NpmPackageRequestedVersionRangeDescription";
+ internal const string NpmPackageType = "NpmPackageType";
+ internal const string NpmPackageTypeDescription = "NpmPackageTypeDescription";
+ internal const string NpmPackageVersion = "NpmPackageVersion";
+ internal const string NpmPackageVersionDescription = "NpmPackageVersionDescription";
+ internal const string NpmReplCommandCompletedWithErrors = "NpmReplCommandCompletedWithErrors";
+ internal const string NpmStatusExecuting = "NpmStatusExecuting";
+ internal const string NpmStatusExecutingErrors = "NpmStatusExecutingErrors";
+ internal const string NpmStatusExecutingQueued = "NpmStatusExecutingQueued";
+ internal const string NpmStatusExecutingQueuedErrors = "NpmStatusExecutingQueuedErrors";
+ internal const string NpmStatusReady = "NpmStatusReady";
+ internal const string NpmStatusReadyWithErrors = "NpmStatusReadyWithErrors";
+ internal const string NpmSuccessfullyCompleted = "NpmSuccessfullyCompleted";
+ internal const string PackageCatalogRefresh0Days = "PackageCatalogRefresh0Days";
+ internal const string PackageCatalogRefresh1Day = "PackageCatalogRefresh1Day";
+ internal const string PackageCatalogRefresh1Month = "PackageCatalogRefresh1Month";
+ internal const string PackageCatalogRefresh1Week = "PackageCatalogRefresh1Week";
+ internal const string PackageCatalogRefresh2To7Days = "PackageCatalogRefresh2To7Days";
+ internal const string PackageCatalogRefresh2Weeks = "PackageCatalogRefresh2Weeks";
+ internal const string PackageCatalogRefresh3Months = "PackageCatalogRefresh3Months";
+ internal const string PackageCatalogRefresh3Weeks = "PackageCatalogRefresh3Weeks";
+ internal const string PackageCatalogRefresh6Months = "PackageCatalogRefresh6Months";
+ internal const string PackageCatalogRefreshFailed = "PackageCatalogRefreshFailed";
+ internal const string PackageCatalogRefreshing = "PackageCatalogRefreshing";
+ internal const string PackageCount = "PackageCount";
+ internal const string PackageInstallationGlobal = "PackageInstallationGlobal";
+ internal const string PackageInstallationLocal = "PackageInstallationLocal";
+ internal const string PackageInstalledGlobally = "PackageInstalledGlobally";
+ internal const string PackageInstalledGloballyOldVersion = "PackageInstalledGloballyOldVersion";
+ internal const string PackageInstalledLocally = "PackageInstalledLocally";
+ internal const string PackageInstalledLocallyOldVersion = "PackageInstalledLocallyOldVersion";
+ internal const string PackageMatchCount = "PackageMatchCount";
+ internal const string PackageTypeGlobal = "PackageTypeGlobal";
+ internal const string PackageTypeGlobalSubpackage = "PackageTypeGlobalSubpackage";
+ internal const string PackageTypeLocal = "PackageTypeLocal";
+ internal const string PackageTypeLocalSubpackage = "PackageTypeLocalSubpackage";
+ internal const string PropertiesClassGlobal = "PropertiesClassGlobal";
+ internal const string PropertiesClassGlobalPackage = "PropertiesClassGlobalPackage";
+ internal const string PropertiesClassGlobalSubPackage = "PropertiesClassGlobalSubPackage";
+ internal const string PropertiesClassLocalPackage = "PropertiesClassLocalPackage";
+ internal const string PropertiesClassLocalSubPackage = "PropertiesClassLocalSubPackage";
+ internal const string PropertiesClassNpm = "PropertiesClassNpm";
+ internal const string ReplInitializationMessage = "ReplInitializationMessage";
+ internal const string RequestedVersionRangeNone = "RequestedVersionRangeNone";
+ internal const string ScriptArgumentsToolTip = "ScriptArgumentsToolTip";
+ internal const string ScriptFileToolTip = "ScriptFileTooltip";
+ internal const string Seconds = "Seconds";
+ internal const string StartBrowserToolTip = "StartBrowserToolTip";
+ internal const string StatusAnalysisLoaded = "StatusAnalysisLoaded";
+ internal const string StatusAnalysisLoadFailed = "StatusAnalysisLoadFailed";
+ internal const string StatusAnalysisLoading = "StatusAnalysisLoading";
+ internal const string StatusAnalysisSaved = "StatusAnalysisSaved";
+ internal const string StatusAnalysisSaving = "StatusAnalysisSaving";
+ internal const string StatusAnalysisUpToDate = "StatusAnalysisUpToDate";
+ internal const string SurroundWith = "SurroundWith";
+ internal const string TestFramework = "TestFramework";
+ internal const string TestFrameworkDescription = "TestFrameworkDescription";
+ internal const string UpgradedEnvironmentVariables = "UpgradedEnvironmentVariables";
+ internal const string WorkingDirInvalidOrMissing = "WorkingDirInvalidOrMissing";
+ internal const string WorkingDirToolTip = "WorkingDirToolTip";
+
+ private static readonly Lazy _manager = new Lazy(
+ () => new System.Resources.ResourceManager("Microsoft.NodejsTools.Resources", typeof(SR).Assembly),
+ LazyThreadSafetyMode.ExecutionAndPublication
+ );
+
+ private static ResourceManager Manager {
+ get {
+ return _manager.Value;
+ }
+ }
+
+ internal static new string GetString(string value, params object[] args) {
+ return GetStringInternal(Manager, value, args) ?? CommonSR.GetString(value, args);
+ }
+
+ internal static string ProductName {
+ get {
+ return GetString(NodejsToolsForVisualStudio);
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/Repl/NodejsReplEvaluator.cs b/Nodejs/Product/Nodejs/Repl/NodejsReplEvaluator.cs
index 2624245f8..f91c2ea68 100644
--- a/Nodejs/Product/Nodejs/Repl/NodejsReplEvaluator.cs
+++ b/Nodejs/Product/Nodejs/Repl/NodejsReplEvaluator.cs
@@ -228,7 +228,7 @@ private string GetNodeExePath() {
var startupProject = _site.GetStartupProject();
string nodeExePath;
if (startupProject != null) {
- nodeExePath = Nodejs.GetAbsoluteNodeExePath(
+ nodeExePath = Nodejs.GetAbsoluteNodeExePath(
startupProject.ProjectHome,
startupProject.GetProjectProperty(NodejsConstants.NodeExePath)
);
diff --git a/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs b/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs
index 345089a07..7fb7c2b2d 100644
--- a/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs
+++ b/Nodejs/Product/Nodejs/Repl/NpmReplCommand.cs
@@ -1,274 +1,274 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.NodejsTools.Npm;
-using Microsoft.NodejsTools.Project;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudioTools.Project;
-using SR = Microsoft.NodejsTools.Project.SR;
-using Task = System.Threading.Tasks.Task;
-
-namespace Microsoft.NodejsTools.Repl {
-#if INTERACTIVE_WINDOW
- using IReplCommand = IInteractiveWindowCommand;
- using IReplWindow = IInteractiveWindow;
-#endif
-
- [Export(typeof(IReplCommand))]
- class NpmReplCommand : IReplCommand {
- #region IReplCommand Members
-
- public async Task Execute(IReplWindow window, string arguments) {
- string projectPath = string.Empty;
- string npmArguments = arguments.Trim(' ', '\t');
-
- // Parse project name/directory in square brackets
- if (npmArguments.StartsWith("[")) {
- var match = Regex.Match(npmArguments, @"(?:[[]\s*\""?\s*)(.*?)(?:\s*\""?\s*[]]\s*)");
- projectPath = match.Groups[1].Value;
- npmArguments = npmArguments.Substring(match.Length);
- }
-
- // Include spaces on either side of npm arguments so that we can more simply detect arguments
- // at beginning and end of string (e.g. '--global')
- npmArguments = string.Format(" {0} ", npmArguments);
-
- var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution;
- IEnumerable loadedProjects = solution.EnumerateLoadedProjects(onlyNodeProjects: true);
-
- var projectNameToDirectoryDictionary = new Dictionary>(StringComparer.OrdinalIgnoreCase);
- foreach (IVsProject project in loadedProjects) {
- var hierarchy = (IVsHierarchy)project;
- object extObject;
-
- var projectResult = hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out extObject);
- if (!ErrorHandler.Succeeded(projectResult)) {
- continue;
- }
-
- EnvDTE.Project dteProject = extObject as EnvDTE.Project;
- if (dteProject == null) {
- continue;
- }
-
- EnvDTE.Properties properties = dteProject.Properties;
- if (dteProject.Properties == null) {
- continue;
- }
-
- string projectName = dteProject.Name;
- EnvDTE.Property projectHome = properties.Item("ProjectHome");
- if (projectHome == null || projectName == null) {
- continue;
- }
-
- var projectDirectory = projectHome.Value as string;
- if (projectDirectory != null) {
- projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectDirectory, hierarchy));
- }
- }
-
- Tuple projectInfo;
- if (string.IsNullOrEmpty(projectPath) && projectNameToDirectoryDictionary.Count == 1) {
- projectInfo = projectNameToDirectoryDictionary.Values.First();
- } else {
- projectNameToDirectoryDictionary.TryGetValue(projectPath, out projectInfo);
- }
-
- NodejsProjectNode nodejsProject = null;
- if (projectInfo != null) {
- projectPath = projectInfo.Item1;
- if (projectInfo.Item2 != null) {
- nodejsProject = projectInfo.Item2.GetProject().GetNodejsProject();
- }
- }
-
- bool isGlobalCommand = false;
- if (string.IsNullOrWhiteSpace(npmArguments) ||
- npmArguments.Contains(" -g ") || npmArguments.Contains(" --global ")) {
- projectPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- isGlobalCommand = true;
- }
-
- // 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")))) {
- 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;
- }
-
- string npmPath;
- try {
- npmPath = NpmHelpers.GetPathToNpm(
- nodejsProject != null ?
- Nodejs.GetAbsoluteNodeExePath(
- nodejsProject.ProjectHome,
- nodejsProject.GetProjectProperty(NodejsConstants.NodeExePath))
- : null);
- } catch (NpmNotFoundException) {
- Nodejs.ShowNodejsNotInstalled();
- return ExecutionResult.Failure;
- }
-
- var npmReplRedirector = new NpmReplRedirector(window);
-
- await ExecuteNpmCommandAsync(
- npmReplRedirector,
- npmPath,
- projectDirectoryPath,
- new[] { npmArguments },
- null);
-
- if (npmReplRedirector.HasErrors) {
- window.WriteError(SR.GetString(SR.NpmReplCommandCompletedWithErrors, arguments));
- } else {
- window.WriteLine(SR.GetString(SR.NpmSuccessfullyCompleted, arguments));
- }
-
- if (nodejsProject != null) {
- await nodejsProject.CheckForLongPaths(npmArguments);
- }
-
- return ExecutionResult.Success;
- }
-
- public string Description {
- get { return "Executes npm command. If solution contains multiple projects, specify target project using .npm [ProjectName] "; }
- }
-
- public string Command {
- get { return "npm"; }
- }
-
- public object ButtonContent {
- get { return null; }
- }
-
- // TODO: This is duplicated from Npm project
- // We should consider using InternalsVisibleTo to avoid code duplication
- internal static async Task> ExecuteNpmCommandAsync(
- Redirector redirector,
- string pathToNpm,
- string executionDirectory,
- string[] arguments,
- ManualResetEvent cancellationResetEvent) {
-
- IEnumerable standardOutputLines = null;
-
- using (var process = ProcessOutput.Run(
- pathToNpm,
- arguments,
- executionDirectory,
- null,
- false,
- redirector,
- quoteArgs: false,
- outputEncoding: Encoding.UTF8 // npm uses UTF-8 regardless of locale if its output is redirected
- )) {
- var whnd = process.WaitHandle;
- if (whnd == null) {
- // Process failed to start, and any exception message has
- // already been sent through the redirector
- if (redirector != null) {
- redirector.WriteErrorLine("Error - cannot start npm");
- }
- } else {
- var handles = cancellationResetEvent != null ? new[] { whnd, cancellationResetEvent } : new [] { whnd };
- var i = await Task.Run(() => WaitHandle.WaitAny(handles));
- if (i == 0) {
- Debug.Assert(process.ExitCode.HasValue, "npm process has not really exited");
- process.Wait();
- if (process.StandardOutputLines != null) {
- standardOutputLines = process.StandardOutputLines.ToList();
- }
- } else {
- process.Kill();
- if (redirector != null) {
- redirector.WriteErrorLine(string.Format(
- "\r\n===={0}====\r\n\r\n",
- "npm command cancelled"));
- }
-
- if (cancellationResetEvent != null) {
- cancellationResetEvent.Reset();
- }
-
- throw new OperationCanceledException();
- }
- }
- }
- return standardOutputLines;
- }
-
- #endregion
-
- internal class NpmReplRedirector : Redirector {
-
- internal const string ErrorAnsiColor = "\x1b[31;1m";
- internal const string WarnAnsiColor = "\x1b[33;22m";
- internal const string NormalAnsiColor = "\x1b[39;49m";
-
- private const string ErrorText = "npm ERR!";
- private const string WarningText = "npm WARN";
-
- private IReplWindow _window;
-
- public NpmReplRedirector(IReplWindow window) {
- _window = window;
- HasErrors = false;
- }
- public bool HasErrors { get; set; }
-
- public override void WriteLine(string decodedString) {
- var substring = string.Empty;
- string outputString = string.Empty;
-
- if (decodedString.StartsWith(ErrorText)) {
- outputString += ErrorAnsiColor + decodedString.Substring(0, ErrorText.Length);
- substring = decodedString.Length > ErrorText.Length ? decodedString.Substring(ErrorText.Length) : string.Empty;
- this.HasErrors = true;
- } else if (decodedString.StartsWith(WarningText)) {
- outputString += WarnAnsiColor + decodedString.Substring(0, WarningText.Length);
- substring = decodedString.Length > WarningText.Length ? decodedString.Substring(WarningText.Length) : string.Empty;
- } else {
- substring = decodedString;
- }
-
- outputString += NormalAnsiColor + substring;
-
- _window.WriteLine(outputString);
- Debug.WriteLine(decodedString, "REPL npm");
- }
-
- public override void WriteErrorLine(string line) {
- _window.WriteError(line);
- }
- }
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.NodejsTools.Npm;
+using Microsoft.NodejsTools.Project;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudioTools.Project;
+using SR = Microsoft.NodejsTools.Project.SR;
+using Task = System.Threading.Tasks.Task;
+
+namespace Microsoft.NodejsTools.Repl {
+#if INTERACTIVE_WINDOW
+ using IReplCommand = IInteractiveWindowCommand;
+ using IReplWindow = IInteractiveWindow;
+#endif
+
+ [Export(typeof(IReplCommand))]
+ class NpmReplCommand : IReplCommand {
+ #region IReplCommand Members
+
+ public async Task Execute(IReplWindow window, string arguments) {
+ string projectPath = string.Empty;
+ string npmArguments = arguments.Trim(' ', '\t');
+
+ // Parse project name/directory in square brackets
+ if (npmArguments.StartsWith("[")) {
+ var match = Regex.Match(npmArguments, @"(?:[[]\s*\""?\s*)(.*?)(?:\s*\""?\s*[]]\s*)");
+ projectPath = match.Groups[1].Value;
+ npmArguments = npmArguments.Substring(match.Length);
+ }
+
+ // Include spaces on either side of npm arguments so that we can more simply detect arguments
+ // at beginning and end of string (e.g. '--global')
+ npmArguments = string.Format(" {0} ", npmArguments);
+
+ var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution;
+ IEnumerable loadedProjects = solution.EnumerateLoadedProjects(onlyNodeProjects: true);
+
+ var projectNameToDirectoryDictionary = new Dictionary>(StringComparer.OrdinalIgnoreCase);
+ foreach (IVsProject project in loadedProjects) {
+ var hierarchy = (IVsHierarchy)project;
+ object extObject;
+
+ var projectResult = hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out extObject);
+ if (!ErrorHandler.Succeeded(projectResult)) {
+ continue;
+ }
+
+ EnvDTE.Project dteProject = extObject as EnvDTE.Project;
+ if (dteProject == null) {
+ continue;
+ }
+
+ EnvDTE.Properties properties = dteProject.Properties;
+ if (dteProject.Properties == null) {
+ continue;
+ }
+
+ string projectName = dteProject.Name;
+ EnvDTE.Property projectHome = properties.Item("ProjectHome");
+ if (projectHome == null || projectName == null) {
+ continue;
+ }
+
+ var projectDirectory = projectHome.Value as string;
+ if (projectDirectory != null) {
+ projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectDirectory, hierarchy));
+ }
+ }
+
+ Tuple projectInfo;
+ if (string.IsNullOrEmpty(projectPath) && projectNameToDirectoryDictionary.Count == 1) {
+ projectInfo = projectNameToDirectoryDictionary.Values.First();
+ } else {
+ projectNameToDirectoryDictionary.TryGetValue(projectPath, out projectInfo);
+ }
+
+ NodejsProjectNode nodejsProject = null;
+ if (projectInfo != null) {
+ projectPath = projectInfo.Item1;
+ if (projectInfo.Item2 != null) {
+ nodejsProject = projectInfo.Item2.GetProject().GetNodejsProject();
+ }
+ }
+
+ bool isGlobalCommand = false;
+ if (string.IsNullOrWhiteSpace(npmArguments) ||
+ npmArguments.Contains(" -g ") || npmArguments.Contains(" --global ")) {
+ projectPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+ isGlobalCommand = true;
+ }
+
+ // 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")))) {
+ 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;
+ }
+
+ string npmPath;
+ try {
+ npmPath = NpmHelpers.GetPathToNpm(
+ nodejsProject != null ?
+ Nodejs.GetAbsoluteNodeExePath(
+ nodejsProject.ProjectHome,
+ nodejsProject.GetProjectProperty(NodejsConstants.NodeExePath))
+ : null);
+ } catch (NpmNotFoundException) {
+ Nodejs.ShowNodejsNotInstalled();
+ return ExecutionResult.Failure;
+ }
+
+ var npmReplRedirector = new NpmReplRedirector(window);
+
+ await ExecuteNpmCommandAsync(
+ npmReplRedirector,
+ npmPath,
+ projectDirectoryPath,
+ new[] { npmArguments },
+ null);
+
+ if (npmReplRedirector.HasErrors) {
+ window.WriteError(SR.GetString(SR.NpmReplCommandCompletedWithErrors, arguments));
+ } else {
+ window.WriteLine(SR.GetString(SR.NpmSuccessfullyCompleted, arguments));
+ }
+
+ if (nodejsProject != null) {
+ await nodejsProject.CheckForLongPaths(npmArguments);
+ }
+
+ return ExecutionResult.Success;
+ }
+
+ public string Description {
+ get { return "Executes npm command. If solution contains multiple projects, specify target project using .npm [ProjectName] "; }
+ }
+
+ public string Command {
+ get { return "npm"; }
+ }
+
+ public object ButtonContent {
+ get { return null; }
+ }
+
+ // TODO: This is duplicated from Npm project
+ // We should consider using InternalsVisibleTo to avoid code duplication
+ internal static async Task> ExecuteNpmCommandAsync(
+ Redirector redirector,
+ string pathToNpm,
+ string executionDirectory,
+ string[] arguments,
+ ManualResetEvent cancellationResetEvent) {
+
+ IEnumerable standardOutputLines = null;
+
+ using (var process = ProcessOutput.Run(
+ pathToNpm,
+ arguments,
+ executionDirectory,
+ null,
+ false,
+ redirector,
+ quoteArgs: false,
+ outputEncoding: Encoding.UTF8 // npm uses UTF-8 regardless of locale if its output is redirected
+ )) {
+ var whnd = process.WaitHandle;
+ if (whnd == null) {
+ // Process failed to start, and any exception message has
+ // already been sent through the redirector
+ if (redirector != null) {
+ redirector.WriteErrorLine("Error - cannot start npm");
+ }
+ } else {
+ var handles = cancellationResetEvent != null ? new[] { whnd, cancellationResetEvent } : new [] { whnd };
+ var i = await Task.Run(() => WaitHandle.WaitAny(handles));
+ if (i == 0) {
+ Debug.Assert(process.ExitCode.HasValue, "npm process has not really exited");
+ process.Wait();
+ if (process.StandardOutputLines != null) {
+ standardOutputLines = process.StandardOutputLines.ToList();
+ }
+ } else {
+ process.Kill();
+ if (redirector != null) {
+ redirector.WriteErrorLine(string.Format(
+ "\r\n===={0}====\r\n\r\n",
+ "npm command cancelled"));
+ }
+
+ if (cancellationResetEvent != null) {
+ cancellationResetEvent.Reset();
+ }
+
+ throw new OperationCanceledException();
+ }
+ }
+ }
+ return standardOutputLines;
+ }
+
+ #endregion
+
+ internal class NpmReplRedirector : Redirector {
+
+ internal const string ErrorAnsiColor = "\x1b[31;1m";
+ internal const string WarnAnsiColor = "\x1b[33;22m";
+ internal const string NormalAnsiColor = "\x1b[39;49m";
+
+ private const string ErrorText = "npm ERR!";
+ private const string WarningText = "npm WARN";
+
+ private IReplWindow _window;
+
+ public NpmReplRedirector(IReplWindow window) {
+ _window = window;
+ HasErrors = false;
+ }
+ public bool HasErrors { get; set; }
+
+ public override void WriteLine(string decodedString) {
+ var substring = string.Empty;
+ string outputString = string.Empty;
+
+ if (decodedString.StartsWith(ErrorText)) {
+ outputString += ErrorAnsiColor + decodedString.Substring(0, ErrorText.Length);
+ substring = decodedString.Length > ErrorText.Length ? decodedString.Substring(ErrorText.Length) : string.Empty;
+ this.HasErrors = true;
+ } else if (decodedString.StartsWith(WarningText)) {
+ outputString += WarnAnsiColor + decodedString.Substring(0, WarningText.Length);
+ substring = decodedString.Length > WarningText.Length ? decodedString.Substring(WarningText.Length) : string.Empty;
+ } else {
+ substring = decodedString;
+ }
+
+ outputString += NormalAnsiColor + substring;
+
+ _window.WriteLine(outputString);
+ Debug.WriteLine(decodedString, "REPL npm");
+ }
+
+ public override void WriteErrorLine(string line) {
+ _window.WriteError(line);
+ }
+ }
+ }
+}
diff --git a/Nodejs/Product/Nodejs/SourceMapping/SourceMapper.cs b/Nodejs/Product/Nodejs/SourceMapping/SourceMapper.cs
index 2661c91a4..2f34cde0c 100644
--- a/Nodejs/Product/Nodejs/SourceMapping/SourceMapper.cs
+++ b/Nodejs/Product/Nodejs/SourceMapping/SourceMapper.cs
@@ -21,8 +21,8 @@
using System.Linq;
using Microsoft.NodejsTools;
-using Microsoft.VisualStudioTools;
-
+using Microsoft.VisualStudioTools;
+
namespace Microsoft.NodejsTools.SourceMapping {
internal class SourceMapper {
private readonly Dictionary _generatedFileToSourceMap = new Dictionary(StringComparer.OrdinalIgnoreCase);
@@ -151,26 +151,26 @@ internal bool MapToJavaScript(string requestedFileName, int requestedLineNo, int
}
return false;
- }
-
- ///
- /// Get the original file name to map to.
- ///
- /// JavaScript compiled file.
+ }
+
+ ///
+ /// Get the original file name to map to.
+ ///
+ /// JavaScript compiled file.
/// Line number
/// Column number
- internal string GetOriginalFileName(string javaScriptFileName, int? line, int? column) {
- string originalFileName = null;
-
+ internal string GetOriginalFileName(string javaScriptFileName, int? line, int? column) {
+ string originalFileName = null;
+
if (line != null && column != null) {
SourceMapInfo tempMapping = this.MapToOriginal(javaScriptFileName, (int)line, (int)column);
if (tempMapping != null) {
originalFileName = tempMapping.FileName;
}
- }
-
- return originalFileName ?? this.MapToOriginal(javaScriptFileName);
+ }
+
+ return originalFileName ?? this.MapToOriginal(javaScriptFileName);
}
private static string GetFileRelativeToFile(string relativeToFile, string newFileName) {
diff --git a/Nodejs/Product/Npm/DependencyType.cs b/Nodejs/Product/Npm/DependencyType.cs
index 218baf58e..3eb8144a5 100644
--- a/Nodejs/Product/Npm/DependencyType.cs
+++ b/Nodejs/Product/Npm/DependencyType.cs
@@ -1,23 +1,23 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public enum DependencyType {
- Standard = 0,
- Development,
- Optional
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public enum DependencyType {
+ Standard = 0,
+ Development,
+ Optional
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/DependencyUrlType.cs b/Nodejs/Product/Npm/DependencyUrlType.cs
index 6d5333b9a..1cf1aeb34 100644
--- a/Nodejs/Product/Npm/DependencyUrlType.cs
+++ b/Nodejs/Product/Npm/DependencyUrlType.cs
@@ -1,27 +1,27 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public enum DependencyUrlType {
- UnsupportedProtocol,
- Http,
- Git,
- GitSsh,
- GitHttp,
- GitHttps,
- GitHub
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public enum DependencyUrlType {
+ UnsupportedProtocol,
+ Http,
+ Git,
+ GitSsh,
+ GitHttp,
+ GitHttps,
+ GitHub
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/DirectoryPackageJsonSource.cs b/Nodejs/Product/Npm/DirectoryPackageJsonSource.cs
index 478dff4a2..c6ed94eda 100644
--- a/Nodejs/Product/Npm/DirectoryPackageJsonSource.cs
+++ b/Nodejs/Product/Npm/DirectoryPackageJsonSource.cs
@@ -1,31 +1,31 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System.IO;
-
-namespace Microsoft.NodejsTools.Npm {
- public class DirectoryPackageJsonSource : IPackageJsonSource {
- private readonly FilePackageJsonSource _source;
-
- public DirectoryPackageJsonSource(string fullDirectoryPath) {
- _source = new FilePackageJsonSource(Path.Combine(fullDirectoryPath, "package.json"));
- }
-
- public dynamic Package {
- get { return _source.Package; }
- }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System.IO;
+
+namespace Microsoft.NodejsTools.Npm {
+ public class DirectoryPackageJsonSource : IPackageJsonSource {
+ private readonly FilePackageJsonSource _source;
+
+ public DirectoryPackageJsonSource(string fullDirectoryPath) {
+ _source = new FilePackageJsonSource(Path.Combine(fullDirectoryPath, "package.json"));
+ }
+
+ public dynamic Package {
+ get { return _source.Package; }
+ }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/FilePackageJsonSource.cs b/Nodejs/Product/Npm/FilePackageJsonSource.cs
index 78138cafa..194bdde03 100644
--- a/Nodejs/Product/Npm/FilePackageJsonSource.cs
+++ b/Nodejs/Product/Npm/FilePackageJsonSource.cs
@@ -1,63 +1,63 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.IO;
-using System.Threading;
-
-namespace Microsoft.NodejsTools.Npm {
- public class FilePackageJsonSource : IPackageJsonSource {
-
- private readonly ReaderPackageJsonSource _source;
-
- public FilePackageJsonSource(string fullPathToFile) {
- if (File.Exists(fullPathToFile)) {
- int retryInterval = 500;
- int attempts = 5;
-
- // populate _source with retries for recoverable errors.
- while (--attempts >= 0) {
- try {
- using (var fin = new FileStream(fullPathToFile, FileMode.Open, FileAccess.Read, FileShare.Read))
- using (var reader = new StreamReader(fin)) {
- _source = new ReaderPackageJsonSource(reader);
- break;
- }
- } catch (PackageJsonException pje) {
- WrapExceptionAndRethrow(fullPathToFile, pje);
- } catch (IOException) {
- if (attempts <= 0) { throw; }
- } catch (UnauthorizedAccessException) {
- if (attempts <= 0) { throw; }
- }
-
- Thread.Sleep(retryInterval);
- retryInterval *= 2; // exponential backoff
- }
- }
- }
-
- private void WrapExceptionAndRethrow(
- string fullPathToFile,
- Exception ex) {
- throw new PackageJsonException(
- string.Format(@"Error reading package.json at '{0}': {1}", fullPathToFile, ex.Message),
- ex);
- }
-
- public dynamic Package { get { return null == _source ? null : _source.Package; } }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.IO;
+using System.Threading;
+
+namespace Microsoft.NodejsTools.Npm {
+ public class FilePackageJsonSource : IPackageJsonSource {
+
+ private readonly ReaderPackageJsonSource _source;
+
+ public FilePackageJsonSource(string fullPathToFile) {
+ if (File.Exists(fullPathToFile)) {
+ int retryInterval = 500;
+ int attempts = 5;
+
+ // populate _source with retries for recoverable errors.
+ while (--attempts >= 0) {
+ try {
+ using (var fin = new FileStream(fullPathToFile, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (var reader = new StreamReader(fin)) {
+ _source = new ReaderPackageJsonSource(reader);
+ break;
+ }
+ } catch (PackageJsonException pje) {
+ WrapExceptionAndRethrow(fullPathToFile, pje);
+ } catch (IOException) {
+ if (attempts <= 0) { throw; }
+ } catch (UnauthorizedAccessException) {
+ if (attempts <= 0) { throw; }
+ }
+
+ Thread.Sleep(retryInterval);
+ retryInterval *= 2; // exponential backoff
+ }
+ }
+ }
+
+ private void WrapExceptionAndRethrow(
+ string fullPathToFile,
+ Exception ex) {
+ throw new PackageJsonException(
+ string.Format(@"Error reading package.json at '{0}': {1}", fullPathToFile, ex.Message),
+ ex);
+ }
+
+ public dynamic Package { get { return null == _source ? null : _source.Package; } }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IBugs.cs b/Nodejs/Product/Npm/IBugs.cs
index e45d1c899..be80b3586 100644
--- a/Nodejs/Product/Npm/IBugs.cs
+++ b/Nodejs/Product/Npm/IBugs.cs
@@ -1,22 +1,22 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IBugs {
- string Url { get; }
- string Email { get; }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IBugs {
+ string Url { get; }
+ string Email { get; }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IBundledDependencies.cs b/Nodejs/Product/Npm/IBundledDependencies.cs
index b380dbb44..287063455 100644
--- a/Nodejs/Product/Npm/IBundledDependencies.cs
+++ b/Nodejs/Product/Npm/IBundledDependencies.cs
@@ -1,19 +1,19 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IBundledDependencies : IPkgStringArray { }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IBundledDependencies : IPkgStringArray { }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IDependencies.cs b/Nodejs/Product/Npm/IDependencies.cs
index 4200d0d4c..d6533413b 100644
--- a/Nodejs/Product/Npm/IDependencies.cs
+++ b/Nodejs/Product/Npm/IDependencies.cs
@@ -1,25 +1,25 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System.Collections.Generic;
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IDependencies : IEnumerable {
- int Count { get; }
- IDependency this[string name] { get; }
- bool Contains(string name);
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System.Collections.Generic;
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IDependencies : IEnumerable {
+ int Count { get; }
+ IDependency this[string name] { get; }
+ bool Contains(string name);
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IDependency.cs b/Nodejs/Product/Npm/IDependency.cs
index 809f56d72..e48d71726 100644
--- a/Nodejs/Product/Npm/IDependency.cs
+++ b/Nodejs/Product/Npm/IDependency.cs
@@ -1,23 +1,23 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IDependency {
- string Name { get; }
- IDependencyUrl Url { get; }
- string VersionRangeText { get; }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IDependency {
+ string Name { get; }
+ IDependencyUrl Url { get; }
+ string VersionRangeText { get; }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IDependencyUrl.cs b/Nodejs/Product/Npm/IDependencyUrl.cs
index d6f6250f1..6b0c94b52 100644
--- a/Nodejs/Product/Npm/IDependencyUrl.cs
+++ b/Nodejs/Product/Npm/IDependencyUrl.cs
@@ -1,22 +1,22 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IDependencyUrl {
- string Address { get; }
- DependencyUrlType Type { get; }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IDependencyUrl {
+ string Address { get; }
+ DependencyUrlType Type { get; }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IFiles.cs b/Nodejs/Product/Npm/IFiles.cs
index 7c47d2ff4..556c7816a 100644
--- a/Nodejs/Product/Npm/IFiles.cs
+++ b/Nodejs/Product/Npm/IFiles.cs
@@ -1,19 +1,19 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IFiles : IPkgStringArray { }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IFiles : IPkgStringArray { }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IGlobalPackages.cs b/Nodejs/Product/Npm/IGlobalPackages.cs
index aa915d233..4f79306c1 100644
--- a/Nodejs/Product/Npm/IGlobalPackages.cs
+++ b/Nodejs/Product/Npm/IGlobalPackages.cs
@@ -1,19 +1,19 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IGlobalPackages : IRootPackage { }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IGlobalPackages : IRootPackage { }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IKeywords.cs b/Nodejs/Product/Npm/IKeywords.cs
index 9b0638a63..98af38e3d 100644
--- a/Nodejs/Product/Npm/IKeywords.cs
+++ b/Nodejs/Product/Npm/IKeywords.cs
@@ -1,19 +1,19 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IKeywords : IPkgStringArray { }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IKeywords : IPkgStringArray { }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/ILicense.cs b/Nodejs/Product/Npm/ILicense.cs
index b5e8e29ec..6e656929a 100644
--- a/Nodejs/Product/Npm/ILicense.cs
+++ b/Nodejs/Product/Npm/ILicense.cs
@@ -1,22 +1,22 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface ILicense {
- string Type { get; }
- string Url { get; }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface ILicense {
+ string Type { get; }
+ string Url { get; }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/ILicenses.cs b/Nodejs/Product/Npm/ILicenses.cs
index 33dbab380..64dd14a0e 100644
--- a/Nodejs/Product/Npm/ILicenses.cs
+++ b/Nodejs/Product/Npm/ILicenses.cs
@@ -1,22 +1,22 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface ILicenses {
- int Count { get; }
- ILicense this[int index] { get; }
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface ILicenses {
+ int Count { get; }
+ ILicense this[int index] { get; }
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/IMan.cs b/Nodejs/Product/Npm/IMan.cs
index 8dbbefef7..d01986280 100644
--- a/Nodejs/Product/Npm/IMan.cs
+++ b/Nodejs/Product/Npm/IMan.cs
@@ -1,19 +1,19 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-namespace Microsoft.NodejsTools.Npm {
- public interface IMan : IPkgStringArray { }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface IMan : IPkgStringArray { }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/INodeModules.cs b/Nodejs/Product/Npm/INodeModules.cs
index 2e6dfccb7..b934ce2de 100644
--- a/Nodejs/Product/Npm/INodeModules.cs
+++ b/Nodejs/Product/Npm/INodeModules.cs
@@ -1,28 +1,28 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System.Collections.Generic;
-
-namespace Microsoft.NodejsTools.Npm {
- public interface INodeModules : IEnumerable {
- int Count { get; }
- IPackage this[int index] { get; }
- IPackage this[string name] { get; }
- bool Contains(string name);
- bool HasMissingModules { get; }
- int GetDepth(string filepath);
- }
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System.Collections.Generic;
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface INodeModules : IEnumerable {
+ int Count { get; }
+ IPackage this[int index] { get; }
+ IPackage this[string name] { get; }
+ bool Contains(string name);
+ bool HasMissingModules { get; }
+ int GetDepth(string filepath);
+ }
}
\ No newline at end of file
diff --git a/Nodejs/Product/Npm/INpmCommander.cs b/Nodejs/Product/Npm/INpmCommander.cs
index 443548521..7af5919cf 100644
--- a/Nodejs/Product/Npm/INpmCommander.cs
+++ b/Nodejs/Product/Npm/INpmCommander.cs
@@ -1,100 +1,100 @@
-//*********************************************************//
-// Copyright (c) Microsoft. All rights reserved.
-//
-// Apache 2.0 License
-//
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-//
-//*********************************************************//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Microsoft.NodejsTools.Npm {
- public interface INpmCommander : INpmLogSource, IDisposable {
-
- ///
- /// Cancels the currently running command
- ///
- void CancelCurrentCommand();
-
- ///
- /// Executes npm install to install all packages in package.json.
- ///
- ///
- Task Install();
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- /// If there is an error reading a package.json file when modules are refreshed.
- ///
- Task InstallPackageByVersionAsync(
- string packageName,
- string versionRange,
- DependencyType type,
- bool saveToPackageJson);
-
- ///
- ///
- ///
- ///
- ///
- /// If there is an error reading a package.json file when modules are refreshed.
- ///
- Task InstallGlobalPackageByVersionAsync(
- string packageName,
- string versionRange);
-
- ///
- ///
- ///
- ///
- /// If there is an error reading a package.json file when modules are refreshed.
- ///
- Task UninstallPackageAsync(string packageName);
-
- Task UninstallGlobalPackageAsync(string packageName);
-
- Task GetCatalogAsync(bool forceDownload, IProgress progress);
-
- Task UpdatePackagesAsync();
-
- ///
- ///
- ///
- ///
- /// If there is an error reading a package.json file when modules are refreshed.
- ///
- Task UpdatePackagesAsync(IEnumerable packages);
-
- ///
- ///
- ///
- ///
- /// If there is an error reading a package.json file when modules are refreshed.
- ///
- Task UpdateGlobalPackagesAsync(IEnumerable packages);
-
- ///
- ///
- ///
- ///
- ///
- Task ExecuteNpmCommandAsync(string arguments);
- }
-}
+//*********************************************************//
+// Copyright (c) Microsoft. All rights reserved.
+//
+// Apache 2.0 License
+//
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+//
+//*********************************************************//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.NodejsTools.Npm {
+ public interface INpmCommander : INpmLogSource, IDisposable {
+
+ ///