public static void AddToDoComment(DTE dte) { ThreadHelper.ThrowIfNotOnUIThread(); TextDocumentHandler handler = new(dte); if (handler.TextDocument != null) { TextPoint bottomPoint = handler.Selection.BottomPoint; bool isAtEndOfLine = bottomPoint.AtEndOfLine || IsAtVisibleEndOfLine(bottomPoint); Language language = handler.Language; GetCommentStyle(language, false, !isAtEndOfLine, out string beginDelimiter, out string endDelimiter); StringBuilder sb = new(); sb.Append(beginDelimiter); if (sb.Length > 0) { sb.Append(' '); } Tasks.Options options = MainPackage.TaskOptions; sb.Append(options.AddTodoPrefix); int noteStartIndex = sb.Length; string memberName = GetMemberName(handler, language); sb.Append("Finish ").Append(memberName ?? "implementation").Append('.'); int noteLength = sb.Length - noteStartIndex; if (options.AddTodoSuffix != TodoSuffix.None) { sb.Append(" ["); switch (options.AddTodoSuffix) { case TodoSuffix.User: sb.Append(Environment.UserName); break; case TodoSuffix.UserDate: sb.Append(Environment.UserName).Append(", "); goto case TodoSuffix.Date; case TodoSuffix.Date: sb.Append(DateTime.UtcNow.ToLocalTime().ToShortDateString()); break; } sb.Append(']'); } if (!string.IsNullOrEmpty(endDelimiter)) { sb.Append(' ').Append(endDelimiter); } string comment = sb.ToString(); handler.SetSelectedText(comment, "Add TODO Comment"); // Select the note portion in case the user wants to edit it immediately. handler.Selection.MoveToAbsoluteOffset(handler.Selection.ActivePoint.AbsoluteCharOffset - comment.Length + noteStartIndex, false); handler.Selection.MoveToAbsoluteOffset(handler.Selection.ActivePoint.AbsoluteCharOffset + noteLength, true); } }
/// <summary> /// 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. /// </summary> protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress <ServiceProgressData> progress) { LogMessage(string.Format("Entering {0}.Initialize()", this.ToString())); try { await base.InitializeAsync(cancellationToken, progress).ConfigureAwait(true); LogMessage(string.Format("After {0}'s base.Initialize()", this.ToString())); // Set the ApplicationInfo's main assembly so IsDebugBuild will work correctly. ApplicationInfo.Initialize(Title, this.GetType().Assembly); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); ScanInfo.GetUserRegistryRoot = () => this.UserRegistryRoot; // Ryan Molden from Microsoft says that GetDialogPage caches the result, so we're going to cache it too. // I've also verified GetDialogPage's caching implementation in VS11 by looking at it with Reflector. // http://social.msdn.microsoft.com/Forums/eu/vsx/thread/303fce01-dfc0-43b3-a578-8b3258c0b83f // From http://msdn.microsoft.com/en-us/library/bb165039.aspx baseConverterOptions = this.GetDialogPage(typeof(BaseConverter.Options)) as BaseConverter.Options; generalOptions = this.GetDialogPage(typeof(Options)) as Options; highlightOptions = this.GetDialogPage(typeof(HighlightOptions)) as HighlightOptions; projectOptions = this.GetDialogPage(typeof(Projects.Options)) as Projects.Options; regionOptions = this.GetDialogPage(typeof(Regions.Options)) as Regions.Options; sortOptions = this.GetDialogPage(typeof(Sort.Options)) as Sort.Options; taskOptions = this.GetDialogPage(typeof(Tasks.Options)) as Tasks.Options; this.processor = new CommandProcessor(this); // Add our command handlers. Commands must exist in the .vsct file. if (await this.GetServiceAsync(typeof(IMenuCommandService)).ConfigureAwait(true) is OleMenuCommandService mcs) { foreach (Command id in Enum.GetValues(typeof(Command))) { CommandID commandId = new(Guids.MeneesVsToolsCommandSet, (int)id); // OleMenuCommand extends the base MenuCommand to add BeforeQueryStatus. // http://msdn.microsoft.com/en-us/library/bb165468.aspx OleMenuCommand menuItem = new(this.Command_Execute, commandId); menuItem.BeforeQueryStatus += this.Command_QueryStatus; mcs.AddCommand(menuItem); } } // To make our font and color formats customizable in non-TextEditor windows, // (e.g., Output) we have to hook some old-school TextManager COM events. this.formatManager = new ClassificationFormatManager(this.ServiceProvider); this.formatManager.UpdateFormats(); // This option requires a restart if changed because the CommentTaskProvider and various // XxxMonitor classes attach to too many events and register too many things to easily // detach/unregister and clean them all up if this is toggled interactively. if (TaskOptions.EnableCommentScans) { this.commentTaskProvider = new CommentTaskProvider(this); } this.buildTimer = new BuildTimer(this); } catch (Exception ex) { LogMessage(string.Format("An unhandled exception occurred in {0}.Initialize().", this.ToString()), ex); throw; } LogMessage(string.Format("Exiting {0}.Initialize()", this.ToString())); }