/// <summary> /// Inserts a #region tag for the specified region preceding the specified start point. /// </summary> /// <param name="region">The region to start.</param> /// <param name="startPoint">The starting point.</param> /// <returns>The updated cursor.</returns> public EditPoint InsertRegionTag(CodeItemRegion region, EditPoint startPoint) { var cursor = startPoint.CreateEditPoint(); // If the cursor is not preceeded only by whitespace, insert a new line. var firstNonWhitespaceIndex = cursor.GetLine().TakeWhile(char.IsWhiteSpace).Count(); if (cursor.DisplayColumn > firstNonWhitespaceIndex + 1) { cursor.Insert(Environment.NewLine); } cursor.Insert($"{RegionHelper.GetRegionTagText(cursor, region.Name)}{Environment.NewLine}"); startPoint.SmartFormat(cursor); region.StartPoint = cursor.CreateEditPoint(); region.StartPoint.LineUp(); region.StartPoint.StartOfLine(); var regionWrapper = new[] { region }; _insertBlankLinePaddingLogic.InsertPaddingBeforeRegionTags(regionWrapper); _insertBlankLinePaddingLogic.InsertPaddingAfterRegionTags(regionWrapper); return(cursor); }
/// <summary> /// Inserts an #endregion tag for the specified region following the specified end point. /// </summary> /// <param name="region">The region to end.</param> /// <param name="endPoint">The end point.</param> /// <returns>The updated cursor.</returns> private EditPoint InsertEndRegionTag(CodeItemRegion region, EditPoint endPoint) { var cursor = endPoint.CreateEditPoint(); // If the cursor is not preceeded only by whitespace, insert a new line. var firstNonWhitespaceIndex = cursor.GetLine().TakeWhile(char.IsWhiteSpace).Count(); if (cursor.DisplayColumn > firstNonWhitespaceIndex + 1) { cursor.Insert(Environment.NewLine); } cursor.Insert("#endregion " + region.Name); // If the cursor is not followed only by whitespace, insert a new line. var lastNonWhitespaceIndex = cursor.GetLine().TrimEnd().Length; if (cursor.DisplayColumn < lastNonWhitespaceIndex + 1) { cursor.Insert(Environment.NewLine); cursor.LineUp(); cursor.EndOfLine(); } endPoint.SmartFormat(cursor); region.EndPoint = cursor.CreateEditPoint(); var regionWrapper = new[] { region }; _insertBlankLinePaddingLogic.InsertPaddingBeforeEndRegionTags(regionWrapper); _insertBlankLinePaddingLogic.InsertPaddingAfterEndRegionTags(regionWrapper); return(cursor); }
/// <summary> /// Called to execute the command. /// </summary> protected override void OnExecute() { base.OnExecute(); var spade = Package.Spade; if (spade != null) { var region = new CodeItemRegion { Name = "New Region" }; var startPoint = spade.SelectedItems.OrderBy(x => x.StartOffset).First().StartPoint; var endPoint = spade.SelectedItems.OrderBy(x => x.EndOffset).Last().EndPoint; _undoTransactionHelper.Run(() => { // Create the new region. _generateRegionLogic.InsertEndRegionTag(region, endPoint); _generateRegionLogic.InsertRegionTag(region, startPoint); // Move to that element. TextDocumentHelper.MoveToCodeItem(spade.Document, region, Settings.Default.Digging_CenterOnWhole); // Highlight the line of text for renaming. var textDocument = spade.Document.GetTextDocument(); textDocument.Selection.EndOfLine(true); textDocument.Selection.SwapAnchor(); }); spade.Refresh(); } }
/// <summary> /// Retrieves code regions based on the specified edit points. /// </summary> /// <param name="editPoints">The edit points to walk.</param> /// <returns>An enumerable collection of regions.</returns> private static IEnumerable <CodeItemRegion> RetrieveCodeRegions(IEnumerable <EditPoint> editPoints) { var regionStack = new Stack <CodeItemRegion>(); var codeItems = new List <CodeItemRegion>(); foreach (var cursor in editPoints) { // Create a pointer to capture the text for this line. EditPoint eolCursor = cursor.CreateEditPoint(); eolCursor.EndOfLine(); string regionText = cursor.GetText(eolCursor).TrimStart(new[] { ' ', '\t' }); if (regionText.StartsWith("#region ")) // Space required by compiler. { // Get the region name. string regionName = regionText.Substring(8).Trim(); // Push the parsed region info onto the top of the stack. regionStack.Push(new CodeItemRegion { Name = regionName, StartLine = cursor.Line, StartOffset = cursor.AbsoluteCharOffset, StartPoint = cursor.CreateEditPoint() }); } else if (regionText.StartsWith("#endregion")) { if (regionStack.Count > 0) { CodeItemRegion region = regionStack.Pop(); region.EndLine = eolCursor.Line; region.EndOffset = eolCursor.AbsoluteCharOffset; region.EndPoint = eolCursor.CreateEditPoint(); codeItems.Add(region); } else { // This document is improperly formatted, abort. return(Enumerable.Empty <CodeItemRegion>()); } } } return(codeItems); }
/// <summary> /// Recursively groups the children within the specified item based on their type. /// </summary> /// <param name="codeItem">The code item.</param> private static void RecursivelyGroupByType(ICodeItemParent codeItem) { // Skip any code item that is already a region or does not have children. if (codeItem.Kind == KindCodeItem.Region || !codeItem.Children.Any()) { return; } // Capture the current children, then clear them out so they can be re-added. var children = codeItem.Children.ToArray(); codeItem.Children.Clear(); CodeItemRegion group = null; int groupOrder = -1; foreach (var child in children) { var memberTypeSetting = MemberTypeSettingHelper.LookupByKind(child.Kind); // Create a new group unless the right kind has already been defined. if (group == null || memberTypeSetting.Order != groupOrder) { group = new CodeItemRegion { Name = memberTypeSetting.EffectiveName, IsPseudoGroup = true }; if (Settings.Default.Digging_TrackExpandedStateOfSpadeNodes) { group.IsExpanded = CodeItemRegionGlobals.GetIsExpandedFor(group.Name); } groupOrder = memberTypeSetting.Order; codeItem.Children.Add(group); } // Add the child to the group and recurse. group.Children.Add(child); var childAsParent = child as ICodeItemParent; if (childAsParent != null) { RecursivelyGroupByType(childAsParent); } } }
/// <summary> /// Inserts an #endregion tag for the specified region following the specified end point. /// </summary> /// <param name="region">The region to end.</param> /// <param name="endPoint">The end point.</param> /// <returns>The updated cursor.</returns> public EditPoint InsertEndRegionTag(CodeItemRegion region, EditPoint endPoint) { var cursor = endPoint.CreateEditPoint(); // If the cursor is not preceeded only by whitespace, insert a new line. var firstNonWhitespaceIndex = cursor.GetLine().TakeWhile(char.IsWhiteSpace).Count(); if (cursor.DisplayColumn > firstNonWhitespaceIndex + 1) { cursor.Insert(Environment.NewLine); } cursor.Insert(RegionHelper.GetEndRegionTagText(cursor)); if (Settings.Default.Cleaning_UpdateEndRegionDirectives && RegionHelper.LanguageSupportsUpdatingEndRegionDirectives(cursor)) { cursor.Insert(" " + region.Name); } // If the cursor is not followed only by whitespace, insert a new line. var lastNonWhitespaceIndex = cursor.GetLine().TrimEnd().Length; if (cursor.DisplayColumn < lastNonWhitespaceIndex + 1) { cursor.Insert(Environment.NewLine); cursor.LineUp(); cursor.EndOfLine(); } endPoint.SmartFormat(cursor); region.EndPoint = cursor.CreateEditPoint(); var regionWrapper = new[] { region }; _insertBlankLinePaddingLogic.InsertPaddingBeforeEndRegionTags(regionWrapper); _insertBlankLinePaddingLogic.InsertPaddingAfterEndRegionTags(regionWrapper); return(cursor); }
/// <summary> /// Removes the region tags from the specified region. /// </summary> /// <param name="region">The region to update.</param> internal void RemoveRegion(CodeItemRegion region) { if (region == null || region.IsInvalidated || region.IsPseudoGroup || region.StartLine <= 0 || region.EndLine <= 0) { return; } new UndoTransactionHelper(_package, "CodeMaid Remove Region " + region.Name).Run(() => { var end = region.EndPoint.CreateEditPoint(); end.StartOfLine(); end.Delete(end.LineLength); end.DeleteWhitespace(vsWhitespaceOptions.vsWhitespaceOptionsVertical); end.Insert(Environment.NewLine); var start = region.StartPoint.CreateEditPoint(); start.StartOfLine(); start.Delete(start.LineLength); start.DeleteWhitespace(vsWhitespaceOptions.vsWhitespaceOptionsVertical); start.Insert(Environment.NewLine); region.IsInvalidated = true; }); }
/// <summary> /// Determines if the specified code item belongs in the specified region. /// </summary> /// <param name="codeItem">The code item.</param> /// <param name="region">The region.</param> /// <returns>True if the specified code item belongs in the specified region, otherwise false.</returns> private bool CodeItemBelongsInRegion(BaseCodeItem codeItem, CodeItemRegion region) { return(codeItem != null && _regionComparerByName.Equals(region, ComposeRegionForCodeItem(codeItem))); }
/// <summary> /// Determines if the specified region is a candidate for removal. /// </summary> /// <param name="region">The region.</param> /// <returns>True if the region can be removed, otherwise false.</returns> private static bool IsRemoveableRegion(CodeItemRegion region) { return(!region.IsPseudoGroup && region.StartLine > 0 && region.EndLine > 0); }