My favorites | Sign in
Project Home Downloads Wiki Issues
Search
for
WindowsVisualStudioMacros  
Visual Studio macros to help debug Chromium
Updated Oct 5, 2011 by sch...@chromium.org

Random Visual Studio macros

Note: Syntax highlighting is wrong, there's nothing to do about it.

How to install one

  • Verify that you have the non-Express version of Visual Studio
  • Menu: Tools, Macros, Macro Explorer
  • Double click on MyMacros
  • Double click on Module1, that will open the Macros editor
  • Paste whatever code you want there inside the Module section. You may want to create one module per macro to keep it sane.

How to bind

Once you've added a macro, you can double click it in the Macro Explorer to execute it, but it's often convenient to bind it.

  • Keyboard
    • Menu Tools, Options
    • Navigate to Environment, Keyboard
    • Type MyMacros or your macro name, select the one you want.
    • Press the key to bind in the bottom, press Assign.
  • Toolbar
    • Menu Tools, Customize
    • Tab Commands
    • Select Macros on the left
    • Drag the macro name on the right to a toolbar
    • The text will be awfully long, right click on the new button and edit the Name property

Automatically grab chromium child processes

Hint: Bind AttachChromium() to a toolbar button and enable the "Debug Location" toolbar to navigate between processes.

Public Sub AttachToProcesses(ByVal process_name As String, ByVal AttachIfCmdLineContains As String)
	' Attaches to a process by its name. If a command line argument is needed, looks for it.'
	Dim pids As New System.Collections.Generic.List(Of Integer)
	Dim pids_debugged As New System.Collections.Generic.List(Of Integer)
	For Each debugged As EnvDTE.Process In DTE.Debugger.DebuggedProcesses
		pids_debugged.Add(debugged.ProcessID)
	Next
	Dim processes As System.Diagnostics.Process() = System.Diagnostics.Process.GetProcessesByName(process_name)
	For Each proc As System.Diagnostics.Process In processes
		If proc.MainModule.FileName().ToLower().Contains(AttachIfCmdLineContains.ToLower()) Then
			pids.Add(proc.Id)
		End If
	Next
	For Each proc As EnvDTE.Process In DTE.Debugger.LocalProcesses
		If Not pids_debugged.Contains(proc.ProcessID) And pids.Contains(proc.ProcessID) Then
			proc.Attach()
		End If
	Next
End Sub

Sub AttachChromium()
	' Attaches to the chrome.exe processes that has \code\ in their command line'
	' argument or binary path.'
	AttachToProcesses("chrome", System.IO.Path.GetDirectoryName(System.IO.Path.GetDirectoryName(DTE.Solution.FullName)) & "\build\")
End Sub

Format comments to 80 cols

Hint: Bind FormatComment() to Alt-F.

Sub FormatComment()
	' Make comments fit 80 cols.'
	Dim sel As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
	Dim text As String = sel.Text
	Dim CommentMarker As String = "//"

	' InStr() is one-based'
	Dim commentColumn As Integer = InStr(text, CommentMarker)
	' Substring() is zero-based'
	Dim prefix As String = text.Substring(0, commentColumn - 1) + CommentMarker + " "
	' Take in account the length of the comment marker and the space. The maximum is 81'
	' and not 80; column starts at 1 and not 0. InStr() is 1 based too.'
	Dim maxline As Integer = 81 - commentColumn - CommentMarker.Length

	' Remove comment marker'
	text = System.Text.RegularExpressions.Regex.Replace(text, "^ *// *", "", System.Text.RegularExpressions.RegexOptions.Multiline)
	' Remove \r\n to put all the text on one line'
	text = System.Text.RegularExpressions.Regex.Replace(text, " *[" + vbLf + "]+ *", " ")
	text = text.Trim()

	Dim newtext As String = ""

	While text <> ""
		' InStrRev() is one-based'
		Dim pos As Integer = InStrRev(text, " ", maxline)
		If pos = 0 Then
			pos = text.Length
		End If

		' Substring() is zero-based'
		Dim line As String = text.Substring(0, pos).Trim()
		newtext += prefix + line + vbLf
		text = text.Substring(pos)
	End While

	sel.Insert(newtext, vsInsertFlags.vsInsertFlagsContainNewText)
End Sub

Remove trailing white spaces

Add this sub to your EnvironmentEvents. When your .cc/.cpp/.c/.h is saved, trailing white spaces are removed automatically. No longer need to worry about presubmit giving nits.

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
    Handles DocumentEvents.DocumentSaved
    Dim fileName As String
    Dim result As vsFindResult

    Try
        fileName = document.Name.ToLower()

        If fileName.EndsWith(".cc") _
        Or fileName.EndsWith(".cpp") _
        Or fileName.EndsWith(".c") _
        Or fileName.EndsWith(".h") Then
            ' Remove trailing whitespace'
            result = DTE.Find.FindReplace( _
                vsFindAction.vsFindActionReplaceAll, _
                "{:b}+$", _
                vsFindOptions.vsFindOptionsRegularExpression, _
                String.Empty, _
                vsFindTarget.vsFindTargetFiles, _
                document.FullName, _
                "", _
                vsFindResultsLocation.vsFindResultsNone)

            If result = vsFindResult.vsFindResultReplaced Then
                ' Triggers DocumentEvents_DocumentSaved event again'
                document.Save()
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub

Alternate between source and header file

Hint: Bind SwitchOfSourceFile() to Alt-O.

Function TryOpenProjectItem(ByVal project_items As ProjectItems, ByVal item As String) As Boolean
	TryOpenProjectItem = False
	If project_items Is Nothing Then
		Exit Function
	End If
	For Each project_item As EnvDTE.ProjectItem In project_items
		If Strings.StrComp(project_item.Name, item, CompareMethod.Text) = 0 Then
			' Found!'
			project_item.Open().Activate()
			TryOpenProjectItem = True
		End If
		If project_item.SubProject Is Nothing Then
			TryOpenProjectItem = TryOpenProjectItem(project_item.ProjectItems, item)
		Else
			TryOpenProjectItem = TryOpenProjectItem(project_item.SubProject.ProjectItems, item)
		End If
		If TryOpenProjectItem = True Then
			Exit Function
		End If
	Next
End Function

' Will find the file if it is:'
' - beside in the same directory,'
' - in "opened documents",'
' - in the same project'
' - TODO(maruel): Try in includes?'
Public Function TryOpen(ByVal FileName As String, ByVal Path As String, ByVal project As EnvDTE.Project) As Boolean
	TryOpen = False
	' Try to open the file in same folder.'
	Try
		DTE.Documents.Open(Path + FileName, "Text")
		TryOpen = True
		Exit Function
	Catch
	End Try

	' Search document in the same project.'
	If Not project Is Nothing Then
		TryOpen = TryOpenProjectItem(project.ProjectItems, FileName)
	End If

	' Search opened documents.'
	For Each myDocument As EnvDTE.Document In DTE.Documents
		If Strings.StrComp(myDocument.Name, FileName, CompareMethod.Text) = 0 Then
			Try
				myDocument.Activate()
				TryOpen = True
				Exit Function
			Catch
			End Try
		End If
	Next
End Function

' Shortcut.'
Public Function TryOpen(ByVal FilePathName As String) As Boolean
	TryOpen = TryOpen(System.IO.Path.GetFileName(FilePathName), System.IO.Path.GetFullPath(FilePathName), Nothing)
End Function

' Will cycle thru .cc, .cpp, .h and .inl file extensions'
Public Sub SwitchOfSourceFile()
	' For source looping. It\'s not extension in the true meaning.'
	Dim supportedExts As String() = {"-inl.h", ".cc", ".cpp", ".h", ".hpp", ".inl"}

	Dim origFile As String
	Dim origFilePath As String
	Dim project As EnvDTE.Project
	Try
		origFile = DTE.ActiveDocument.Name
		origFilePath = DTE.ActiveDocument.Path
		project = DTE.ActiveDocument.ProjectItem.ContainingProject
	Catch
		Exit Sub
	End Try

	' This is touchy here because we want to support both ".h" and "-inl.h" so we have to find the right extension first.'
	For indexExt As Integer = 0 To supportedExts.Length - 1
		Dim ext As String = supportedExts(indexExt)
		If origFile.Length > ext.Length Then
			If origFile.Substring(origFile.Length - ext.Length) = ext Then
				Dim FileToOpen As String = origFile.Substring(0, origFile.Length - ext.Length)
				' Try the rest'
				For indexTry As Integer = 0 To supportedExts.Length - 2
					Dim trueIndex As Integer = (indexExt + indexTry + 1) Mod supportedExts.Length
					If TryOpen(FileToOpen + supportedExts(trueIndex), origFilePath, project) Then
						' We succeeded'
						Exit Sub
					End If
				Next
				' We failed.'
				Exit For
			End If
		End If
	Next
	' We failed.'
End Sub

Run the currently selected google test

See the function's description.

Sub RunCurrentGTest()
	' From the active source file, find the test that the user wants to run'
	' based on the current cursor position. Set the project containing this'
	' source file as the startup project, changes the command line to run'
	' only this test, compile the project and starts it under the debugger.'
	' Doesn\'t change any breakpoint.'
	Dim ActiveDoc As Document = DTE.ActiveDocument

	' Try to guess the test to run.'
	Dim TestGroup As String = ""
	Dim TestName As String = ""
	Dim selection As TextSelection = CType(ActiveDoc.Selection(), TextSelection)
	Dim toppoint As EditPoint = selection.TopPoint.CreateEditPoint()
	Dim bottompoint As EditPoint = selection.BottomPoint.CreateEditPoint()
	Dim ranges As TextRanges = selection.TextRanges
	Dim line As Integer = selection.TopPoint.Line
	' selection.FindPattern() is crummy.'
	While line <> 0
		selection.GotoLine(line)
		selection.SelectLine()
		Dim match As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(selection.Text, "TEST[_F]*\((.*),(.*)\)")
		If Not match Is System.Text.RegularExpressions.Match.Empty Then
			TestGroup = match.Groups.Item(1).Value.Trim()
			TestName = match.Groups.Item(2).Value.Trim()
			Exit While
		End If
		line = line - 1
	End While
	' Cheap way to try to restore the old selection. Isn\'t 100% correct.'
	selection.MoveToLineAndOffset(toppoint.Line, toppoint.LineCharOffset)
	selection.MoveToLineAndOffset(bottompoint.Line, bottompoint.LineCharOffset, True)

	' From the current active document, find the project and the active configuration.'
	Dim Proj As Project = ActiveDoc.ProjectItem.ContainingProject
	Dim config As Configuration = Proj.ConfigurationManager.ActiveConfiguration

	' Fix the command line argument.'
	Dim CmdLine As EnvDTE.Property = config.Properties.Item("CommandArguments")
	If TestGroup <> "" Then
		CmdLine.Value = "--gtest_filter=" & TestGroup & "." & TestName
	Else
		' Run all'
		CmdLine.Value = ""
	End If

	' Set it as startup project.'
	Dim SoluBuild As SolutionBuild = DTE.Solution.SolutionBuild
	Dim StartupProject As String
	StartupProject = Proj.UniqueName
	SoluBuild.StartupProjects = StartupProject

	' Build it.'
	SoluBuild.BuildProject(config.ConfigurationName, Proj.UniqueName, True)

	' Start it.'
	DTE.Debugger.Go()
End Sub

Add a definition in a .cc file for the currently selected method/variable declarations.

Select a class method or member variable declaration, then run this macro to add empty definitions in the corresponding .cc file. Hint: Bind AddDefinitionForSelectedDeclaration() to Alt-D

Public Sub AddDefinitionForSelectedDeclaration()
    ' Get the function declaration text.'
    Dim sel As TextSelection = DTE.ActiveDocument.Selection
    Dim text = sel.Text.Trim()

    Dim className = ClassNameFinder()

    Dim funcDef = text
    ' Remove comments first, since they mess up the rest of the regexes.'
    funcDef = Regex.Replace(funcDef, "//.*$", "", RegexOptions.Multiline)
    ' Try to put declarations all on the same line.'
    funcDef = Regex.Replace(funcDef, "([^;]) *\n *", "$1 ", RegexOptions.Singleline)
    ' Replace the identifier with ClassName::identifier.'
    funcDef = Regex.Replace(funcDef, "^(.*) ([^ ()]+;|[^ ()]+ *\()", _
                                "$1 " + className + "::$2", RegexOptions.Multiline)
    ' Convert ; to {} for functions.'
    funcDef = Regex.Replace(funcDef, "\) *;", ") {" + vbLf + "}" + vbLf)
    ' Remove leading whitespace, static/virtual.'
    funcDef = Regex.Replace(funcDef, "^ *", "", RegexOptions.Multiline)
    funcDef = Regex.Replace(funcDef, "static *", "// static" + vbLf)
    funcDef = Regex.Replace(funcDef, "virtual *", "")
    ' Collapse empty lines.'
    funcDef = Regex.Replace(funcDef, vbLf + vbLf + "+", vbLf + vbLf)

    ' Switch to source file and append defs at the end.'
    GoToCCFile()
    sel = DTE.ActiveDocument.Selection
    sel.EndOfDocument()
    sel.Insert(funcDef)
End Sub

' If the current document is an .h file, try to switch to the .cc file of the same name.'
Sub GoToCCFile()
    Dim origFile = DTE.ActiveDocument.FullName()
    If Regex.IsMatch(origFile, "\.h$") Then
        Dim altFile = Regex.Replace(origFile, "\.h$", ".cpp")
        If Not My.Computer.FileSystem.FileExists(altFile) Then
            altFile = Regex.Replace(origFile, "\.h$", ".cc")
        End If
        DTE.Documents.Open(altFile, "Text")
    End If
End Sub

' Finds which class the cursor is inside of, and returns the class name.'
' Note: This is indent based.  Your class bodies must be indented, and the closing'
' "};" must line up with the initial "class".'
' ex: class Foo {\nclass Bar {\n <cursor>...'
' returns: "Foo::Bar"''
Private Function ClassNameFinder() As String
    Dim sel As TextSelection = DTE.ActiveDocument.Selection
    Dim origPos = sel.ActivePoint.AbsoluteCharOffset
    Dim endLine = sel.CurrentLine

    sel.MoveToAbsoluteOffset(1, True)
    Dim pos = 0
    Dim text = sel.Text
    Dim className = ClassNameFinderInternal(text)
    sel.MoveToAbsoluteOffset(origPos)

    If className.Length > 0 Then
        className = className.Substring(2)
    End If
    Return className
End Function

' Helper function for ClassNameFinder.  Returns the full class name that doesn\'t'
' have matching close braces in the given text string.'
Private Function ClassNameFinderInternal(ByRef text As String) As String
    Dim className = ""
    While text.Length > 0
        Dim match = Regex.Match(text, "^( *)class ([^ \n\r{:;]+)[^\n\r;]*$", RegexOptions.Multiline)
        If match.Success Then
            Dim indentString = match.Groups.Item(1).Value
            Dim newClass = "::" + match.Groups.Item(2).Value
            text = text.Substring(match.Index + match.Length)

            match = Regex.Match(text, "^" + indentString + "};", RegexOptions.Multiline)
            If match.Success Then
                text = text.Substring(match.Index + match.Length)
            Else
                className += newClass + ClassNameFinderInternal(text)
            End If
        Else
            text = ""
            Exit While
        End If
    End While

    Return className
End Function

Open all the files of a given change list.

Specify which change list you want to open all files of, and this macro will find it if it lies in the same svn repository as the currently opened solution. If it can't find it there, it will prompt you to specify the path of the root of your client view.

Sub OpenChangeListFiles()
    ' Open all the files of a given change list.'
    Dim change_list_name As String = InputBox("Enter the change list name." + vbNewLine + "(with an optional repo folder path prefix)")
    If String.IsNullOrEmpty(change_list_name) Then
        Exit Sub
    End If
    Dim solution As Solution = DTE.Solution
    ' Try to get the source root path starting from the solution path and search upward in the folder hierarchy.'
    Dim source_root_path As String
    If Not solution Is Nothing And Not String.IsNullOrEmpty(solution.FullName) Then
        source_root_path = GetRepositoryRootFolder(solution.FullName)
    End If
    If source_root_path Is Nothing Or String.IsNullOrEmpty(source_root_path) Then
        ' We couldn\'t find the root ourselves, ask the user.'
        source_root_path = InputBox("Can't find a solution file path." + vbNewLine + "Please specify the root of your source tree.")
        If String.IsNullOrEmpty(source_root_path) Then
            Exit Sub
        End If
    End If
    ' If we provided one or more \ in change_list_name, we want to check a subdirectory of the root path.'
    ' This is useful if we have another repository in our solution.'
    Dim change_list_path() As String = Split(change_list_name, "\")
    If change_list_path.Length > 1 Then
        source_root_path += "\" + String.Join("\", change_list_path, 0, change_list_path.Length - 1)
        change_list_name = change_list_path(change_list_path.Length - 1)
    End If
    ' Look for the CL file in the appropriate folder.'
    Dim change_list_file As String = source_root_path + "\.svn\gcl_info\changes\" + change_list_name
    If Not IO.File.Exists(change_list_file) Then
        ' OK, give one last chance to the user to specify the appropriate path for the CL.'
        source_root_path = InputBox("Can't find CL: '" + change_list_name + "', under " + source_root_path + vbNewLine + "Specify the proper root folder one last time:")
        If String.IsNullOrEmpty(source_root_path) Then
            Exit Sub
        End If
        change_list_file = source_root_path + "\.svn\gcl_info\changes\" + change_list_name
        If Not IO.File.Exists(change_list_file) Then
            MsgBox("Can't find CL: '" + change_list_name + "', under " + source_root_path)
            Exit Sub
        End If
    End If
    ' Now load its content.'
    Dim change_list_content As String
    Try
        change_list_content = IO.File.ReadAllText(change_list_file, Text.Encoding.GetEncoding(1252))
    Catch e As Exception
        MsgBox("Exception: " + e.Message())
        Exit Sub
    End Try
    ' Match the lines where the paths of the opened files can be found.'
    Dim pattern As String = "M\s*(.*)$"
    Dim regex As New Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.Multiline)
    Dim matches As Text.RegularExpressions.MatchCollection = regex.Matches(change_list_content)
    Dim match
    For Each match In matches
        ' And now we can open each and everyone of them.'
        Dim file_path As String = match.Groups(1).ToString()
        Dim full_path As String = source_root_path + "\" + Left(file_path, file_path.Length() - 1)
        If IO.File.Exists(full_path) Then
            DTE.ItemOperations.OpenFile(full_path)
        End If
    Next
End Sub

Private Function GetRepositoryRootFolder(ByVal solution_path As String) As String
    Try
        ' We look for a change in the svn: root path in the .svn/entries file.'
        ' This means we have reached view root or changed repo.'
        Dim solution_folder As String = IO.Directory.GetParent(solution_path).ToString()
        Dim svn_root_path As String = GetSvnRootPath(solution_folder)
        If String.IsNullOrEmpty(svn_root_path) Then
            ' We don'\t seem to be within a repo if we can\'t get the SVN root path.'
            Return ""
        End If
        ' We need to keep the previous path, since we need to stop once we found a bad parent.'
        Dim previous_path As String = solution_folder
        While True
            Dim next_path As String = IO.Directory.GetParent(previous_path).ToString()
            Dim current_svn_root_path As String = GetSvnRootPath(next_path)
            ' As long as we have the same svn root path, we are in the same repo, continue.'
            If current_svn_root_path = svn_root_path Then
                previous_path = next_path
            Else
                Exit While
            End If
        End While
        Return previous_path
    Catch e As Exception
        MsgBox("Exception: " + e.Message())
    End Try
    Return Nothing
End Function

Private Function GetSvnRootPath(ByVal client_path As String) As String
    ' First make sure we are within a repo.'
    Dim svn_folder As String = client_path + "\.svn"
    If Not IO.Directory.Exists(svn_folder) Then
        Return ""
    End If
    ' Then there MUST be an entries file in there.'
    Dim entries_file As String = svn_folder + "\entries"
    If Not IO.File.Exists(entries_file) Then
        Return ""
    End If
    ' Read the content of the file and find the svn root, and return it.'
    Dim entries_content As String = IO.File.ReadAllText(entries_file, Text.Encoding.GetEncoding(1252))
    Dim pattern As String = "svn:(.*)$"
    Dim regex As New Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.Multiline)
    Dim matches As Text.RegularExpressions.MatchCollection = regex.Matches(entries_content)
    Return matches.Item(1).ToString()
End Function

Only build startup project

Stolen from Boris, thanks!

Sub BuildStartupProject()
    Dim sb As SolutionBuild = DTE.Solution.SolutionBuild
    Dim projName As String = sb.StartupProjects(0)
    DTE.ExecuteCommand("View.Output")
    sb.BuildProject(sb.ActiveConfiguration.Name, projName, False)
End Sub

Use WinDbg as your debugger

I fully regret writing this macro as it didn't pass the "time wasted to write it"/"utility" ratio. But I'm really too proud.

Sub WinbgStartupProject()
    ' Use the right one:
    Dim windbg As String = "C:\program files\Debugging Tools for Windows (x86)\windbg.exe"
    'Dim windbg As String = "C:\program files\Debugging Tools for Windows (x64)\windbg.exe"

    Dim project_name As String = CType(DTE.Solution.SolutionBuild.StartupProjects(0), String)
    Dim project As EnvDTE.Project = FindProjects(DTE.Solution.Projects, project_name)
    Dim config As Configuration = project.ConfigurationManager.ActiveConfiguration
    ' Hack to remove file:///
    Dim target_path As String = config.OutputGroups.Item(1).FileURLs(0).ToString().Remove(0, 8)
    Dim arguments As String = config.Properties.Item("CommandArguments").Value
    'MsgBox(windbg & " -o " & target_path & " " & arguments)
    System.Diagnostics.Process.Start(windbg, "-o " & target_path & " " & arguments)
End Sub

Function FindProjectItems(ByVal project_items As EnvDTE.ProjectItems, ByVal project_name As String) As EnvDTE.Project
    FindProjectItems = Nothing
    For Each project_item As EnvDTE.ProjectItem In project_items
        If Not project_item.SubProject Is Nothing Then
            FindProjectItems = FindProject(project_item.SubProject, project_name)
            If Not FindProjectItems Is Nothing Then Exit Function
        End If
    Next
End Function

Function FindProject(ByVal project As EnvDTE.Project, ByVal project_name As String) As EnvDTE.Project
    If project.UniqueName = project_name Then
        FindProject = project
        Exit Function
    End If
    If Not project.ProjectItems Is Nothing Then
        FindProject = FindProjectItems(project.ProjectItems, project_name)
        If Not FindProject Is Nothing Then Exit Function
    End If
End Function

Function FindProjects(ByVal projects As EnvDTE.Projects, ByVal project_name As String) As EnvDTE.Project
    ' You never thought it'd be so complex to find a project. The VS extensibility team
    ' stole me an hour of my life I will never get back.
    FindProjects = Nothing
    For Each project As EnvDTE.Project In projects
        FindProjects = FindProject(project, project_name)
        If Not FindProjects Is Nothing Then Exit Function
    Next
End Function

Indent to open-paren on line-wrap

This macro is slightly different than the rest. You'll need to put it in your EnvironmentEvents project rather than Module, since it runs on every keypress.

What it does is indent your cursor up to the level of the open-paren on the previous line when you hit Enter.

    Public Sub keypress(ByVal key As String, ByVal sel As TextSelection, ByVal completion As Boolean, ByRef cancel As Boolean) _
            Handles TextDocumentKeyPressEvents.BeforeKeyPress
        If (Not completion And key = vbCr) Then
            Dim textDocument As TextDocument = DTE.ActiveDocument.Object("TextDocument")
            Dim startPoint As EditPoint = textDocument.StartPoint.CreateEditPoint()
            startPoint.MoveToLineAndOffset(sel.ActivePoint.Line, 1)
            Dim text = startPoint.GetText(sel.ActivePoint.LineCharOffset - 1)
            Dim pos = findUnclosedParenIndent(text)

            If pos <> -1 Then
                Dim commentPos = text.IndexOf("//")
                If commentPos = -1 Or commentPos > pos Then
                    sel.Insert(vbLf)
                    sel.DeleteWhitespace()
                    sel.PadToColumn(pos + 2)
                    cancel = True
                End If
            End If
        End If
    End Sub

    Public Function findUnclosedParenIndent(ByRef text As String) As Integer
        findUnclosedParenIndent = -1

        Dim parens As Char() = "()".ToCharArray()
        Dim lastPos = text.Length
        Dim numClosed = 0

        While True
            Dim pos = text.LastIndexOfAny(parens, lastPos - 1)

            If pos = -1 Then
                Exit While
            End If

            If text(pos) = ")" Then
                numClosed += 1
            Else
                If numClosed = 0 Then
                    findUnclosedParenIndent = pos
                    Exit While
                End If
                numClosed -= 1
            End If

            lastPos = pos
        End While
    End Function

Add other useful macros here

Feel free to edit this page to add other useful macros.

Comment by fenghaungyuyicon@gmail.com, May 22, 2011

it should be "Use WinDbg? as your debugger" instead of "Use as your debugger" in Index Table.

Comment by manputra...@gmail.com, May 31, 2011

i feel good

Comment by w.r.bedz...@gmail.com, Jul 7, 2011

wrbedzinski:#!>short>if>>


Sign in to add a comment
Powered by Google Project Hosting