/// <summary> /// Composes a region based on the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>A region.</returns> private CodeItemRegion ComposeRegionForCodeItem(BaseCodeItem codeItem) { if (codeItem == null) { return(null); } var setting = MemberTypeSettingHelper.LookupByKind(codeItem.Kind); if (setting == null) { return(null); } var regionName = string.Empty; if (Settings.Default.Reorganizing_RegionsIncludeAccessLevel) { var element = codeItem as BaseCodeItemElement; if (element != null && (!Settings.Default.Reorganizing_RegionsIncludeAccessLevelForMethodsOnly || element is CodeItemMethod)) { var accessModifier = CodeElementHelper.GetAccessModifierKeyword(element.Access); if (accessModifier != null) { regionName = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(accessModifier) + " "; } } } regionName += setting.EffectiveName; return(new CodeItemRegion { Name = regionName }); }
/// <summary> /// Gets the text and removes the specified item. /// </summary> /// <param name="itemToRemove">The item to remove.</param> /// <param name="cursorOffset"> /// The cursor's offset within the item being removed, otherwise -1. /// </param> private static string GetTextAndRemoveItem(BaseCodeItem itemToRemove, out int cursorOffset) { // Refresh the code item and capture its end points. itemToRemove.RefreshCachedPositionAndName(); var removeStartPoint = itemToRemove.StartPoint; var removeEndPoint = itemToRemove.EndPoint; // Determine the cursor's offset if within the item being removed. var cursorAbsoluteOffset = removeStartPoint.Parent.Selection.ActivePoint.AbsoluteCharOffset; if (cursorAbsoluteOffset >= removeStartPoint.AbsoluteCharOffset && cursorAbsoluteOffset <= removeEndPoint.AbsoluteCharOffset) { cursorOffset = cursorAbsoluteOffset - removeStartPoint.AbsoluteCharOffset; } else { cursorOffset = -1; } // Capture the text. var text = removeStartPoint.GetText(removeEndPoint); // Remove the text and cleanup whitespace. removeStartPoint.Delete(removeEndPoint); removeStartPoint.DeleteWhitespace(vsWhitespaceOptions.vsWhitespaceOptionsVertical); return(text); }
/// <summary> /// Repositions the specified item into the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> private void RepositionItemIntoBase(BaseCodeItem itemToMove, ICodeItemParent baseItem) { if (itemToMove == baseItem) { return; } bool padWithNewLine = _insertBlankLinePaddingLogic.ShouldBeFollowedByBlankLine(itemToMove); int cursorOffset; var text = GetTextAndRemoveItem(itemToMove, out cursorOffset); baseItem.RefreshCachedPositionAndName(); var baseInsertPoint = baseItem.InsertPoint; var pastePoint = baseInsertPoint.CreateEditPoint(); pastePoint.Insert(text); pastePoint.Insert(Environment.NewLine); if (padWithNewLine) { pastePoint.Insert(Environment.NewLine); } pastePoint.EndOfLine(); baseInsertPoint.SmartFormat(pastePoint); if (cursorOffset >= 0) { baseInsertPoint.Parent.Selection.MoveToAbsoluteOffset(baseInsertPoint.AbsoluteCharOffset + cursorOffset); } itemToMove.RefreshCachedPositionAndName(); baseItem.RefreshCachedPositionAndName(); }
/// <summary> /// Repositions the specified item above the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> private void RepositionItemAboveBase(BaseCodeItem itemToMove, BaseCodeItem baseItem) { if (itemToMove == baseItem) { return; } bool separateWithNewLine = ShouldBeSeparatedByNewLine(itemToMove, baseItem); int cursorOffset; var text = GetTextAndRemoveItem(itemToMove, out cursorOffset); baseItem.RefreshCachedPositionAndName(); var baseStartPoint = baseItem.StartPoint; var pastePoint = baseStartPoint.CreateEditPoint(); pastePoint.Insert(text); pastePoint.Insert(Environment.NewLine); if (separateWithNewLine) { pastePoint.Insert(Environment.NewLine); } pastePoint.EndOfLine(); baseStartPoint.SmartFormat(pastePoint); if (cursorOffset >= 0) { baseStartPoint.Parent.Selection.MoveToAbsoluteOffset(baseStartPoint.AbsoluteCharOffset + cursorOffset); } itemToMove.RefreshCachedPositionAndName(); baseItem.RefreshCachedPositionAndName(); }
/// <summary> /// Attempts to select the text of the specified code item. /// </summary> /// <param name="document">The document.</param> /// <param name="codeItem">The code item.</param> internal static void SelectCodeItem(Document document, BaseCodeItem codeItem) { var textDocument = document.GetTextDocument(); if (textDocument == null) { return; } try { codeItem.RefreshCachedPositionAndName(); textDocument.Selection.MoveToPoint(codeItem.StartPoint, false); textDocument.Selection.MoveToPoint(codeItem.EndPoint, true); textDocument.Selection.SwapAnchor(); } catch (Exception) { // Select operation may fail if element is no longer available. } finally { // Always set focus within the code editor window. document.Activate(); } }
/// <summary> /// Determines if the specified code item instance should be preceded by a blank line. /// Defaults to false for unknown kinds or null objects. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>True if code item should be preceded by a blank line, otherwise false.</returns> internal bool ShouldBePrecededByBlankLine(BaseCodeItem codeItem) { if (codeItem == null) { return(false); } switch (codeItem.Kind) { case KindCodeItem.Class: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeClasses); case KindCodeItem.Delegate: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeDelegates); case KindCodeItem.Enum: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeEnumerations); case KindCodeItem.Event: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeEvents); case KindCodeItem.Field: return(codeItem.IsMultiLine ? Settings.Default.Cleaning_InsertBlankLinePaddingBeforeFieldsMultiLine : Settings.Default.Cleaning_InsertBlankLinePaddingBeforeFieldsSingleLine); case KindCodeItem.Interface: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeInterfaces); case KindCodeItem.Namespace: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeNamespaces); case KindCodeItem.Constructor: case KindCodeItem.Destructor: case KindCodeItem.Method: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeMethods); case KindCodeItem.Indexer: case KindCodeItem.Property: return(codeItem.IsMultiLine ? Settings.Default.Cleaning_InsertBlankLinePaddingBeforePropertiesMultiLine : Settings.Default.Cleaning_InsertBlankLinePaddingBeforePropertiesSingleLine); case KindCodeItem.Region: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeRegionTags); case KindCodeItem.Struct: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeStructs); case KindCodeItem.Using: return(Settings.Default.Cleaning_InsertBlankLinePaddingBeforeUsingStatementBlocks); default: return(false); } }
public void ShouldSortByGroupType() { BaseCodeItem method = Create <CodeItemMethod>("a", 1); BaseCodeItem field = Create <CodeItemField>("z", 2); var comparer = new CodeItemTypeComparer(sortByName: true); int result = comparer.Compare(field, method); Assert.IsTrue(result < 0); }
public void ShouldSortItemsOfTheSameTypeByOffset() { BaseCodeItem itemB = Create <CodeItemField>("b", 1); BaseCodeItem itemA = Create <CodeItemField>("a", 2); var comparer = new CodeItemTypeComparer(sortByName: false); int result = comparer.Compare(itemA, itemB); Assert.IsTrue(result > 0); }
public void ShouldPlaceExplicitInterfaceMembersAtTheEndOfTheGroup() { CodeItemMethod methodA = CreateExplicitMethod("Interface", "A", 1); BaseCodeItem methodB = Create <CodeItemMethod>("B", 2); var comparer = new CodeItemTypeComparer(sortByName: true); Settings.Default.Reorganizing_ExplicitMembersAtEnd = true; int result = comparer.Compare(methodB, methodA); Assert.IsTrue(result < 0); }
public void ShouldSortByExplicitInterfaceMemberName() { CodeItemMethod methodZ = CreateExplicitMethod("Interface", "Z", 1); BaseCodeItem methodX = Create <CodeItemMethod>("X", 2); var comparer = new CodeItemTypeComparer(sortByName: true); Settings.Default.Reorganizing_ExplicitMembersAtEnd = false; int result = comparer.Compare(methodX, methodZ); Assert.IsTrue(result < 0); }
/// <summary> /// Selects the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> private void SelectCodeItem(BaseCodeItem codeItem) { var viewModel = ViewModel; if (codeItem == null || viewModel == null || codeItem.StartOffset <= 0) { return; } Dispatcher.BeginInvoke( new Action(() => TextDocumentHelper.SelectCodeItem(viewModel.Document, codeItem))); }
/// <summary> /// Jumps to the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> private void JumpToCodeItem(BaseCodeItem codeItem) { var viewModel = ViewModel; if (codeItem == null || viewModel == null || codeItem.StartOffset <= 0) { return; } Dispatcher.BeginInvoke( new Action(() => TextDocumentHelper.MoveToCodeItem(viewModel.Document, codeItem, Settings.Default.Digging_CenterOnWhole))); }
/// <summary> /// Determines if the specified item is an ancestor of the specified base. /// </summary> /// <param name="item">The item.</param> /// <param name="baseItem">The base item.</param> /// <returns>True if item is an ancestor of the specified base, otherwise false.</returns> private static bool IsItemAncestorOfBase(BaseCodeItem item, BaseCodeItem baseItem) { var itemAsParent = item as ICodeItemParent; if (itemAsParent == null) { return(false); } return(itemAsParent.Children.Contains(baseItem) || itemAsParent.Children.Any(x => IsItemAncestorOfBase(x, baseItem))); }
/// <summary> /// Attempts to build an image URI from the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>The built URI, otherwise null.</returns> private string BuildImageURIString(BaseCodeItem codeItem) { string typeComponent = GetTypeComponentString(codeItem); string accessComponent = GetAccessString(codeItem as BaseCodeItemElement); if (typeComponent == null) { return(null); } string uriString = $"/Waodng.CodeMaid;component/UI/ToolWindows/Spade/Images/{ImagePath}/{typeComponent}{accessComponent}.png"; return(uriString); }
/// <summary> /// Attempts to build an image URI from the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>The built URI, otherwise null.</returns> private string BuildImageURIString(BaseCodeItem codeItem) { string typeComponent = GetTypeComponentString(codeItem); string accessComponent = GetAccessString(codeItem as BaseCodeItemElement); if (typeComponent == null) { return(null); } string uriString = string.Format("/SteveCadwallader.CodeMaid;component/UI/ToolWindows/Spade/Images/{0}/{1}{2}.png", ImagePath, typeComponent, accessComponent); return(uriString); }
/// <summary> /// Attempts to move the cursor to the specified code item. /// </summary> /// <param name="document">The document.</param> /// <param name="codeItem">The code item.</param> /// <param name="centerOnWhole">True if the whole element should be used for centering.</param> internal static void MoveToCodeItem(Document document, BaseCodeItem codeItem, bool centerOnWhole) { var textDocument = document.GetTextDocument(); if (textDocument == null) { return; } try { object viewRangeEnd = null; TextPoint navigatePoint = null; codeItem.RefreshCachedPositionAndName(); textDocument.Selection.MoveToPoint(codeItem.StartPoint, false); if (centerOnWhole) { viewRangeEnd = codeItem.EndPoint; } var codeItemElement = codeItem as BaseCodeItemElement; if (codeItemElement != null) { navigatePoint = codeItemElement.CodeElement.GetStartPoint(vsCMPart.vsCMPartNavigate); } textDocument.Selection.AnchorPoint.TryToShow(vsPaneShowHow.vsPaneShowCentered, viewRangeEnd); if (navigatePoint != null) { textDocument.Selection.MoveToPoint(navigatePoint, false); } else { textDocument.Selection.FindText(codeItem.Name, (int)vsFindOptions.vsFindOptionsMatchInHiddenText); textDocument.Selection.MoveToPoint(textDocument.Selection.AnchorPoint, false); } } catch (Exception) { // Move operation may fail if element is no longer available. } finally { // Always set focus within the code editor window. document.Activate(); } }
/// <summary> /// Determines the drop position for the specified drag event and the drop target. /// </summary> /// <param name="e"> /// The <see cref="System.Windows.DragEventArgs" /> instance containing the event data. /// </param> /// <param name="targetItem">The target item.</param> /// <param name="targetElement">The target element.</param> /// <returns>The drop position.</returns> private static DropPosition GetDropPosition(DragEventArgs e, BaseCodeItem targetItem, TreeViewItem targetElement) { var header = targetElement.Template.FindName("PART_HeaderBorder", targetElement) as FrameworkElement; var targetHeight = header?.ActualHeight ?? targetElement.ActualHeight; var dropPoint = e.GetPosition(targetElement); bool canDropOn = targetItem is ICodeItemParent; if (canDropOn) { bool isTopThird = dropPoint.Y <= targetHeight / 3; bool isBottomThird = dropPoint.Y > targetHeight * 2 / 3; return(isTopThird ? DropPosition.Above : (isBottomThird ? DropPosition.Below : DropPosition.On)); } bool isTopHalf = dropPoint.Y <= targetHeight / 2; return(isTopHalf ? DropPosition.Above : DropPosition.Below); }
/// <summary> /// Determines if the specified code item instance should be followed by a blank line. /// Defaults to false for unknown kinds or null objects. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>True if code item should be followed by a blank line, otherwise false.</returns> internal bool ShouldInstanceBeFollowedByBlankLine(BaseCodeItem codeItem) { if (codeItem == null) { return(false); } bool shouldKindBeFollowedByBlankLine = ShouldKindBeFollowedByBlankLine(codeItem.Kind); if (shouldKindBeFollowedByBlankLine) { if (codeItem.Kind == KindCodeItem.Field && codeItem.StartPoint.Line == codeItem.EndPoint.Line) { return(false); } } return(shouldKindBeFollowedByBlankLine); }
/// <summary> /// Attempts to get the type component string based on the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>The type component of the partial image name, otherwise null.</returns> private static string GetTypeComponentString(BaseCodeItem codeItem) { switch (codeItem.Kind) { case KindCodeItem.Class: return("Class"); case KindCodeItem.Constructor: return("MethodConstructor"); case KindCodeItem.Delegate: return("Delegate"); case KindCodeItem.Destructor: return("MethodDestructor"); case KindCodeItem.Enum: return("Enum"); case KindCodeItem.Event: return("Event"); case KindCodeItem.Field: var codeItemField = (CodeItemField)codeItem; if (codeItemField.IsEnumItem) { return("EnumItem"); } if (codeItemField.IsConstant) { return("Constant"); } return("Field"); case KindCodeItem.Interface: return("Interface"); case KindCodeItem.Method: return("Method"); case KindCodeItem.Indexer: case KindCodeItem.Property: return("Property"); case KindCodeItem.Region: return("Region"); case KindCodeItem.Struct: return("Structure"); default: return(null); } }
/// <summary> /// Shows a context menu for the specified code item. /// </summary> /// <param name="codeItem">The code item.</param> /// <param name="point">The point where the context menu should be shown.</param> private void ShowContextMenu(BaseCodeItem codeItem, Point point) { var viewModel = ViewModel; if (codeItem == null || viewModel == null) { return; } var menuCommandService = viewModel.Package.MenuCommandService; if (menuCommandService != null) { var contextMenuCommandID = new CommandID(GuidList.GuidCodeMaidContextSpadeBaseGroup, PkgCmdIDList.MenuIDCodeMaidContextSpade); viewModel.SelectedItem = codeItem; menuCommandService.ShowContextMenu(contextMenuCommandID, (int)point.X, (int)point.Y); viewModel.SelectedItem = null; } }
/// <summary> /// Moves the specified item below the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> internal void MoveItemBelowBase(BaseCodeItem itemToMove, BaseCodeItem baseItem) { _undoTransactionHelper.Run(() => RepositionItemBelowBase(itemToMove, baseItem)); }
/// <summary> /// Moves the specified item into the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> internal void MoveItemIntoBase(BaseCodeItem itemToMove, ICodeItemParent baseItem) { new UndoTransactionHelper(_package, "CodeMaid Move Item Into").Run( () => RepositionItemIntoBase(itemToMove, baseItem)); }
/// <summary> /// Moves the specified item below the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> internal void MoveItemBelowBase(BaseCodeItem itemToMove, BaseCodeItem baseItem) { new UndoTransactionHelper(_package, "CodeMaid Move Item Below").Run( () => RepositionItemBelowBase(itemToMove, baseItem)); }
/// <summary> /// Moves the specified item above the specified base within an undo transaction. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> internal void MoveItemAboveBase(BaseCodeItem itemToMove, BaseCodeItem baseItem) { new UndoTransactionHelper(_package, Resources.CodeMaidMoveItemAbove).Run( () => RepositionItemAboveBase(itemToMove, baseItem)); }
/// <summary> /// Determines if the two specified items should be separated by a newline. /// </summary> /// <param name="firstItem">The first item.</param> /// <param name="secondItem">The second item.</param> /// <returns>True if the items should be separated by a newline, otherwise false.</returns> private bool ShouldBeSeparatedByNewLine(BaseCodeItem firstItem, BaseCodeItem secondItem) { return(_insertBlankLinePaddingLogic.ShouldBeFollowedByBlankLine(firstItem) || _insertBlankLinePaddingLogic.ShouldBePrecededByBlankLine(secondItem)); }
/// <summary> /// Determines if the specified item is a candidate for deletion. /// </summary> /// <param name="codeItem">The code item.</param> /// <returns>True if the code item can be deleted, otherwise false.</returns> private static bool IsDeletable(BaseCodeItem codeItem) { return(!(codeItem is CodeItemRegion) || !((CodeItemRegion)codeItem).IsPseudoGroup); }
/// <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> /// Moves the specified item into the specified base. /// </summary> /// <param name="itemToMove">The item to move.</param> /// <param name="baseItem">The base item.</param> internal void MoveItemIntoBase(BaseCodeItem itemToMove, ICodeItemParent baseItem) { _undoTransactionHelper.Run(() => RepositionItemIntoBase(itemToMove, baseItem)); }