2012-07-16 105 views
0

如果我有这样的:的Visual Studio宏崩溃定制节点

namespace SomeNameSpace 
{ 
    #region Usings 

    using System.Collections.Generic; 
    using System.Security; 

    #endregion 

    /// <summary> Implements a dictionary with several keys.        </summary> 
    /// <typeparam name="Value"> What type of elements we will be storing in the dictionary</typeparam> 
    public class MultiKeyDic<Value> 
    { 

     /// <summary> a very long summary that can be 
     /// collapsed and expanded. </summary> 
     public int SomeInt {get;set;} 


     public void someMethod() 
     { 

     } 
    } 
} 

如何创建一个宏,将找到所有可以扩充(节点)的地方。如果我想折叠所有节点,我将不得不折叠节点的顺序为someMethod(),summary of SomeInt,class MultiKeyDic,summary of class MultiKeyDic,#region Usings,最后是namespace

我知道命令CTRL +中号 + Ø倒塌的一切,但我不想崩溃的一切。例如,我可能不想折叠评论。如果我折叠一切,然后展开扩展父节点的注释。


到目前为止,我已经创造了这个宏,会发现大部分的节点:

Sub VisitAllNodes() 
    Dim i As Integer 
    Dim fileCM As FileCodeModel 
    Dim elts As EnvDTE.CodeElements 
    Dim elt As EnvDTE.CodeElement 

    fileCM = DTE.ActiveDocument.ProjectItem.FileCodeModel 
    elts = fileCM.CodeElements 
    For i = 1 To elts.Count 
     elt = elts.Item(i) 
     CollapseE(elt, elts, i) 
    Next 
End Sub 

'' Helper to OutlineCode. Recursively outlines members of elt. 
'' 
Sub CollapseE(ByVal elt As EnvDTE.CodeElement, ByVal elts As EnvDTE.CodeElements, ByVal loc As Integer) 
    Dim epStart As EnvDTE.EditPoint 
    Dim epEnd As EnvDTE.EditPoint 

    epStart = elt.GetStartPoint(vsCMPart.vsCMPartWholeWithAttributes).CreateEditPoint() 
    epEnd = elt.GetEndPoint(vsCMPart.vsCMPartWholeWithAttributes).CreateEditPoint() ' Copy it because we move it later. 
    epStart.EndOfLine() 
    If ((elt.IsCodeType()) And (elt.Kind <> EnvDTE.vsCMElement.vsCMElementDelegate)) Then 
     Dim i As Integer 
     Dim mems As EnvDTE.CodeElements 

     mems = elt.Members 
     For i = 1 To mems.Count 

      Dim temp As EnvDTE.CodeElement = mems.Item(i) 
      Dim t As String = [Enum].GetName(GetType(EnvDTE.vsCMElement), temp.Kind) 
      MsgBox("Found member (" & t & ") at line# " & temp.StartPoint.Line) 

      CollapseE(mems.Item(i), mems, i) 
     Next 
    ElseIf (elt.Kind = EnvDTE.vsCMElement.vsCMElementNamespace) Then 
     Dim i As Integer 
     Dim mems As EnvDTE.CodeElements 

     mems = elt.Members 
     For i = 1 To mems.Count 

      Dim temp As EnvDTE.CodeElement = mems.Item(i) 
      Dim t As String = [Enum].GetName(GetType(EnvDTE.vsCMElement), temp.Kind) 
      MsgBox("Found member (" & t & ") at line# " & temp.StartPoint.Line) 

      CollapseE(mems.Item(i), mems, i) 
     Next 
    End If 

    'Return 
    ' collapse the element 

    If (epStart.LessThan(epEnd)) Then 
     loc = loc + 1 
     If (loc <= elts.Count) Then 
      epEnd.MoveToPoint(elts.Item(loc).GetStartPoint(vsCMPart.vsCMPartHeader)) 
      epEnd.LineUp() 
      epEnd.EndOfLine() 
     End If 
     epStart.OutlineSection(epEnd) 
    End If 
End Sub 

它看起来比它是什么更复杂。它运行在任何文件上,它会显示所有属性,类,枚举等,但由于某种原因,没有找到意见也不区域。

回答

0

第一功能IncludeMember用于确定排除什么类型的构件。例如,在这个例子中,我不塌陷的命名空间和使用指令:

' filter some mebers. for example using statemets cannot be collapsed so exclude them. 
    Function IncludeMember(ByVal member As EnvDTE.CodeElement) 

     If member.Kind = vsCMElement.vsCMElementIDLImport Then 
      Return False 
     ElseIf member.Kind = vsCMElement.vsCMElementNamespace Then 
      Return False ' I do not want to colapse enums 
     End If 

     Return True 

    End Function 

    Sub CollapseNodes() 

     ' activate working window 
     DTE.Windows.Item(DTE.ActiveDocument.Name).Activate() 

     ' expand everything to start 

     Try 
      DTE.ExecuteCommand("Edit.StopOutlining") 
     Catch 
     End Try 

     Try 
      DTE.ExecuteCommand("Edit.StartAutomaticOutlining") 
     Catch 
     End Try 


     ' get text of document and replace all new lines with \r\n 
     Dim objTextDoc As TextDocument 
     Dim objEditPt As EnvDTE.EditPoint 
     Dim text As String 
     ' Get a handle to the new document and create an EditPoint. 
     objTextDoc = DTE.ActiveDocument.Object("TextDocument") 
     objEditPt = objTextDoc.StartPoint.CreateEditPoint 
     ' Get all Text of active document 
     text = objEditPt.GetText(objTextDoc.EndPoint) 
     text = System.Text.RegularExpressions.Regex.Replace(_ 
         text, _ 
         "(\r\n?|\n\r?)", ChrW(13) & ChrW(10) _ 
        ) 

     ' add new line to text so that lines of visual studio match with index of array 
     Dim lines As String() = System.Text.RegularExpressions.Regex.Split(vbCrLf & text, vbCrLf) 

     ' list where whe will place all colapsable items 
     Dim targetLines As New System.Collections.Generic.List(Of Integer) 

     ' regex that we will use to check if a line contains a #region 
     Dim reg As New System.Text.RegularExpressions.Regex(" *#region(|$)") 

     Dim i As Integer 
     For i = 1 To lines.Length - 1 

      If reg.Match(lines(i)).Success Then 
       targetLines.Add(i) 
      End If 

     Next 


     Dim fileCM As FileCodeModel 
     Dim elts As EnvDTE.CodeElements 
     Dim elt As EnvDTE.CodeElement 

     Dim projectItem = DTE.ActiveDocument.ProjectItem 

     Dim temp = projectItem.Collection.Count 

     Dim b = DirectCast(DirectCast(projectItem.Document, EnvDTE.Document).ActiveWindow, EnvDTE.Window).ContextAttributes 

     fileCM = projectItem.FileCodeModel 
     elts = fileCM.CodeElements 
     For i = 1 To elts.Count 
      elt = elts.Item(i) 
      CollapseE(elt, elts, i, targetLines) 
     Next 

     ' now that we have the lines that we will plan to collapse sort them. it is important to go in order 
     targetLines.Sort() 

     ActivateWorkingWindow() 

     ' go in reverse order so that we can collapse nested regions 
     For i = targetLines.Count - 1 To 0 Step -1 


      DTE.ExecuteCommand("Edit.Goto", targetLines(i)) 

      DTE.ExecuteCommand("Edit.ToggleOutliningExpansion") 

     Next 


    End Sub 

    '' Helper to OutlineCode. Recursively outlines members of elt. 
    '' 
    Sub CollapseE(ByVal elt As EnvDTE.CodeElement, ByVal elts As EnvDTE.CodeElements, ByVal loc As Integer, ByRef targetLines As System.Collections.Generic.List(Of Integer)) 
     Dim epStart As EnvDTE.EditPoint 
     Dim epEnd As EnvDTE.EditPoint 

     epStart = elt.GetStartPoint(vsCMPart.vsCMPartWholeWithAttributes).CreateEditPoint() 
     epEnd = elt.GetEndPoint(vsCMPart.vsCMPartWholeWithAttributes).CreateEditPoint() ' Copy it because we move it later. 
     epStart.EndOfLine() 
     If ((elt.IsCodeType()) And (elt.Kind <> EnvDTE.vsCMElement.vsCMElementDelegate) Or elt.Kind = EnvDTE.vsCMElement.vsCMElementNamespace) Then 
      Dim i As Integer 
      Dim mems As EnvDTE.CodeElements 

      mems = elt.Members 
      For i = 1 To mems.Count 

       CollapseE(mems.Item(i), mems, i, targetLines) 

      Next 

     End If 


     If (epStart.LessThan(epEnd)) Then 
      If IncludeMember(elt) Then 
       targetLines.Add(epStart.Line) 
      End If 
     End If 



    End Sub