
I have implemented a method that uses the AstNodes provided by your .Net Addon. It is almost finished the only problem is that it is very slow. I think it is slow because i am updating every lines TabStopLevel. Should i be calling a PauseUpdate on the document and then ResumeUpdate or should make all my changes in a buffer and then replace the formatted area with the buffer?
Thank you
Leif
I am not done with the code, i know of a few indenting bugs. for VB only
Thank you
Leif
I am not done with the code, i know of a few indenting bugs. for VB only
Imports ActiproSoftware.SyntaxEditor
Imports ActiproSoftware.SyntaxEditor.Addons.VB
Imports ActiproSoftware.SyntaxEditor.Addons.DotNet.Ast
Public Class FormattingASTVisitor
Inherits AstVisitor
Private Document As Document
Private IndentLevel As Integer
Private IndentationOffsetSum As Integer
Private LastFormattedLine As Integer
#Region " Public "
Public Overridable Sub VisitCompilationUnit(ByVal CompilationUnit As ActiproSoftware.SyntaxEditor.Addons.DotNet.Ast.CompilationUnit, ByVal Document As Document)
IndentationOffsetSum = 0
IndentLevel = 0
LastFormattedLine = -1
_Regions = Nothing
Me.Document = Document
CompilationUnit.Accept(Me)
End Sub
#End Region
#Region " Step Left or Right in Indentation "
Private Sub Left()
IndentLevel = IndentLevel - 1
If IndentLevel < 0 Then
IndentLevel = 0
'BCAM.GeneralCore.Services.EventLogger.Warn("Auto Indenting Error")
End If
End Sub
Private Sub Right()
IndentLevel = IndentLevel + 1
End Sub
#End Region
#Region " Adjust Line Indentation "
Private Sub AdjustLine(ByVal Line As Integer, ByVal IndentLevel As Integer)
If Document.Lines(Line).TabStopLevel <> IndentLevel Then
IndentationOffsetSum = IndentationOffsetSum + (IndentLevel - Document.Lines(Line).TabStopLevel)
'If Document.Lines(Line).Text = "" And IndentLevel > 0 Then IndentationOffsetSum = IndentationOffsetSum
Document.Lines(Line).TabStopLevel = IndentLevel
End If
End Sub
#End Region
#Region " Adjust Line with Relation to AstNode "
Private Sub AdjustOnPreVisiting(ByVal Node As AstNode)
AdjustAstNode(Node, True)
End Sub
Private Sub AdjustOnPostVisiting(ByVal Node As AstNode)
AdjustAstNode(Node, False)
End Sub
Private Sub AdjustAstNode(ByVal Node As AstNode, ByVal UseStartOffset As Boolean)
Dim LineOffset As Integer = 0
If UseStartOffset Then
AdjustMissedLines(Document.OffsetToPosition(Node.TextRange.StartOffset + IndentationOffsetSum).Line)
LineOffset = Node.TextRange.StartOffset + IndentationOffsetSum
Else
LineOffset = Node.TextRange.EndOffset + IndentationOffsetSum
End If
Dim DP As ActiproSoftware.SyntaxEditor.DocumentPosition = Document.OffsetToPosition(LineOffset)
AdjustLine(DP.Line, IndentLevel)
LastFormattedLine = DP.Line
End Sub
#End Region
#Region " Adjust Line with out Relation to AstNode "
Private Sub AdjustMissedLines(ByVal NextLine As Integer)
For Line As Integer = LastFormattedLine + 1 To NextLine - 1
If IsLineRegionDirective(Line) Then
AdjustLine(Line, 0)
Else
AdjustLine(Line, IndentLevel)
End If
Next
End Sub
Private Sub AdjustMissedLines(ByVal NextNode As AstNode)
AdjustMissedLines(Document.OffsetToPosition(NextNode.TextRange.EndOffset + IndentationOffsetSum).Line)
End Sub
#End Region
#Region " Else Help "
''' <summary>
''' This whole region isnt very good
''' Help???
''' </summary>
''' <param name="Node"></param>
''' <remarks></remarks>
Private Sub AdjustIfElseLine(ByVal Node As IfStatement)
Dim Line As Integer = FindElseLine(Node)
If Line = -1 Then Exit Sub
Me.AdjustLine(Line, Me.IndentLevel)
End Sub
Private Function FindElseLine(ByVal Node As IfStatement) As Integer
If Node.FalseStatement Is Nothing Then Return -1
Dim TrueStatmentLastLine As Integer = Document.OffsetToPosition(Node.TrueStatement.TextRange.EndOffset + Me.IndentationOffsetSum).Line
Dim FalseStatmentFirstLine As Integer = Document.OffsetToPosition(Node.FalseStatement.TextRange.StartOffset + Me.IndentationOffsetSum).Line
If FalseStatmentFirstLine - TrueStatmentLastLine = 1 Then
Return FalseStatmentFirstLine - 1
ElseIf FalseStatmentFirstLine - TrueStatmentLastLine > 1 Then
For I As Integer = TrueStatmentLastLine To FalseStatmentFirstLine - 1
If Document.Lines(I).Text.Trim(" ").Trim(vbTab).ToString = "Else" Then
Return I
End If
Next
Return ((FalseStatmentFirstLine + TrueStatmentLastLine) / 2) - 1
End If
Return -1
End Function
#End Region
#Region " Regions Directive Help "
Private _Regions As Collections.IList
Private ReadOnly Property Regions() As Collections.IList
Get
Return _Regions
End Get
End Property
Private Function IsLineRegionDirective(ByVal Line As Integer) As Boolean
If Regions Is Nothing Then Return False
For Each Range As ActiproSoftware.SyntaxEditor.TextRange In Regions
If Document.OffsetToPosition(Range.StartOffset + IndentationOffsetSum).Line = Line Then
Return True
ElseIf Document.OffsetToPosition(Range.EndOffset + IndentationOffsetSum).Line = Line Then
Return True
End If
Next
Return False
End Function
#End Region
#Region " Ast Visiters "
Public Overrides Function OnPreVisiting(ByVal node As ActiproSoftware.SyntaxEditor.Addons.DotNet.Ast.AstNode) As Boolean
If TypeOf node Is CompilationUnit Then
_Regions = CType(node, CompilationUnit).RegionTextRanges
ElseIf TypeOf node Is TypeDeclaration Then
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is IfStatement Then
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is ElseIfSection Then
Left()
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is TypeMemberDeclaration Then
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is NamespaceDeclaration Then
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is ChildStatementStatement Then
AdjustOnPreVisiting(node)
Right()
ElseIf TypeOf node Is BlockStatement Then
ElseIf TypeOf node Is LocalVariableDeclaration Then
ElseIf TypeOf node Is Statement Then
AdjustOnPreVisiting(node)
Else
Return False
End If
Return True
'Return MyBase.OnPreVisiting(node)
End Function
Public Overrides Sub OnPostVisited(ByVal node As ActiproSoftware.SyntaxEditor.Addons.DotNet.Ast.AstNode)
If TypeOf node Is CompilationUnit Then
_Regions = Nothing
ElseIf TypeOf node Is TypeDeclaration Then
AdjustMissedLines(node)
Left()
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is IfStatement Then
AdjustMissedLines(node)
Left()
AdjustIfElseLine(node)
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is ElseIfSection Then
AdjustMissedLines(node)
'Left()
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is TypeMemberDeclaration Then
AdjustMissedLines(node)
Left()
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is NamespaceDeclaration Then
AdjustMissedLines(node)
Left()
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is ChildStatementStatement Then
AdjustMissedLines(node)
Left()
AdjustOnPostVisiting(node)
ElseIf TypeOf node Is LocalVariableDeclaration Then
ElseIf TypeOf node Is BlockStatement Then
ElseIf TypeOf node Is Statement Then
End If
MyBase.OnPostVisited(node)
End Sub
#End Region
End Class