Module refinery.lib.scripts.vba.synth

Expand source code Browse git
from __future__ import annotations

import io

from refinery.lib.scripts import Node, Visitor
from refinery.lib.scripts.vba.model import (
    Statement,
    VbaBangAccess,
    VbaBinaryExpression,
    VbaBooleanLiteral,
    VbaByValArgument,
    VbaCallExpression,
    VbaCallStatement,
    VbaCaseClause,
    VbaConstDeclaration,
    VbaConstDeclarator,
    VbaDateLiteral,
    VbaDebugPrintStatement,
    VbaDeclareStatement,
    VbaDoLoopStatement,
    VbaElseIfClause,
    VbaEmptyLiteral,
    VbaEndStatement,
    VbaEnumDefinition,
    VbaEnumMember,
    VbaEraseStatement,
    VbaErrorNode,
    VbaEventDeclaration,
    VbaExitStatement,
    VbaExpressionStatement,
    VbaFloatLiteral,
    VbaForEachStatement,
    VbaForStatement,
    VbaFunctionDeclaration,
    VbaGosubStatement,
    VbaGotoStatement,
    VbaIdentifier,
    VbaIfStatement,
    VbaImplementsStatement,
    VbaIndexExpression,
    VbaIntegerLiteral,
    VbaLabelStatement,
    VbaLetStatement,
    VbaLoopConditionPosition,
    VbaMeExpression,
    VbaMemberAccess,
    VbaModule,
    VbaNamedArgument,
    VbaNewExpression,
    VbaNothingLiteral,
    VbaNullLiteral,
    VbaOnBranchStatement,
    VbaOnErrorAction,
    VbaOnErrorStatement,
    VbaOptionStatement,
    VbaParameter,
    VbaParameterPassing,
    VbaParenExpression,
    VbaPropertyDeclaration,
    VbaRaiseEventStatement,
    VbaRangeExpression,
    VbaRedimStatement,
    VbaResumeStatement,
    VbaReturnStatement,
    VbaScopeModifier,
    VbaSelectCaseStatement,
    VbaSetStatement,
    VbaStopStatement,
    VbaStringLiteral,
    VbaSubDeclaration,
    VbaTypeDefinition,
    VbaTypedIdentifier,
    VbaTypeOfIsExpression,
    VbaUnaryExpression,
    VbaVariableDeclaration,
    VbaVariableDeclarator,
    VbaWhileStatement,
    VbaWithStatement,
)


class VbaSynthesizer(Visitor):

    _BLOCK_TYPES = (
        VbaSubDeclaration,
        VbaFunctionDeclaration,
        VbaPropertyDeclaration,
        VbaTypeDefinition,
        VbaEnumDefinition,
    )

    def __init__(self, indent: str = '  '):
        super().__init__()
        self._indent = indent
        self._depth = 0
        self._parts = io.StringIO()

    def convert(self, node: Node) -> str:
        self._parts.seek(0)
        self._parts.truncate(0)
        self._depth = 0
        self.visit(node)
        return self._parts.getvalue()

    def _write(self, text: str):
        self._parts.write(text)

    def _newline(self):
        self._parts.write('\n')
        self._parts.write(self._indent * self._depth)

    def _emit_body(self, body: list[Statement]):
        self._depth += 1
        for stmt in body:
            self._newline()
            self.visit(stmt)
        self._depth -= 1

    def _comma_separated(self, nodes: list):
        for i, node in enumerate(nodes):
            if i > 0:
                self._write(', ')
            if node is None:
                continue
            self.visit(node)

    def _emit_params(self, params: list[VbaParameter]):
        self._write('(')
        for i, p in enumerate(params):
            if i > 0:
                self._write(', ')
            self.visit(p)
        self._write(')')

    def generic_visit(self, node: Node):
        self._write(F'<{type(node).__name__}>')

    def visit_VbaIntegerLiteral(self, node: VbaIntegerLiteral):
        self._write(node.raw)

    def visit_VbaFloatLiteral(self, node: VbaFloatLiteral):
        self._write(node.raw)

    def visit_VbaStringLiteral(self, node: VbaStringLiteral):
        self._write(node.raw)

    def visit_VbaDateLiteral(self, node: VbaDateLiteral):
        self._write(node.raw)

    def visit_VbaBooleanLiteral(self, node: VbaBooleanLiteral):
        self._write('True' if node.value else 'False')

    def visit_VbaNothingLiteral(self, node: VbaNothingLiteral):
        self._write('Nothing')

    def visit_VbaNullLiteral(self, node: VbaNullLiteral):
        self._write('Null')

    def visit_VbaEmptyLiteral(self, node: VbaEmptyLiteral):
        self._write('Empty')

    def visit_VbaMeExpression(self, node: VbaMeExpression):
        self._write('Me')

    def visit_VbaIdentifier(self, node: VbaIdentifier):
        self._write(node.name)

    def visit_VbaTypedIdentifier(self, node: VbaTypedIdentifier):
        self._write(F'{node.name}{node.suffix}')

    def visit_VbaErrorNode(self, node: VbaErrorNode):
        self._write(node.text)

    def visit_VbaBinaryExpression(self, node: VbaBinaryExpression):
        if node.left:
            self.visit(node.left)
        self._write(F' {node.operator} ')
        if node.right:
            self.visit(node.right)

    def visit_VbaUnaryExpression(self, node: VbaUnaryExpression):
        op = node.operator
        self._write(op)
        if op.isalpha():
            self._write(' ')
        if node.operand:
            self.visit(node.operand)

    def visit_VbaByValArgument(self, node: VbaByValArgument):
        self._write('ByVal ')
        if node.expression:
            self.visit(node.expression)

    def visit_VbaNamedArgument(self, node: VbaNamedArgument):
        self._write(F'{node.name}:=')
        if node.expression:
            self.visit(node.expression)

    def visit_VbaCallExpression(self, node: VbaCallExpression):
        if node.callee:
            self.visit(node.callee)
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')

    def visit_VbaMemberAccess(self, node: VbaMemberAccess):
        if node.object:
            self.visit(node.object)
        self._write(F'.{node.member}')

    def visit_VbaBangAccess(self, node: VbaBangAccess):
        if node.object:
            self.visit(node.object)
        self._write(F'!{node.member}')

    def visit_VbaIndexExpression(self, node: VbaIndexExpression):
        if node.object:
            self.visit(node.object)
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')

    def visit_VbaNewExpression(self, node: VbaNewExpression):
        self._write('New ')
        if node.class_name:
            self.visit(node.class_name)

    def visit_VbaTypeOfIsExpression(self, node: VbaTypeOfIsExpression):
        self._write('TypeOf ')
        if node.operand:
            self.visit(node.operand)
        self._write(' Is ')
        if node.type_name:
            self.visit(node.type_name)

    def visit_VbaParenExpression(self, node: VbaParenExpression):
        self._write('(')
        if node.expression:
            self.visit(node.expression)
        self._write(')')

    def visit_VbaRangeExpression(self, node: VbaRangeExpression):
        if node.start:
            self.visit(node.start)
        self._write(' To ')
        if node.end:
            self.visit(node.end)

    def visit_VbaModule(self, node: VbaModule):
        prev_group = None
        for i, stmt in enumerate(node.body):
            group = self._stmt_group(stmt)
            if i > 0:
                if group != prev_group or group == 'block':
                    self._write('\n')
                self._newline()
            self.visit(stmt)
            prev_group = group

    @classmethod
    def _stmt_group(cls, stmt: Statement) -> str:
        if isinstance(stmt, cls._BLOCK_TYPES):
            return 'block'
        if isinstance(stmt, VbaDeclareStatement):
            return 'declare'
        if isinstance(stmt, VbaOptionStatement):
            return 'option'
        if isinstance(stmt, (VbaVariableDeclaration, VbaConstDeclaration)):
            return 'variable'
        if isinstance(stmt, VbaEventDeclaration):
            return 'event'
        if isinstance(stmt, VbaImplementsStatement):
            return 'implements'
        return 'other'

    def visit_VbaOptionStatement(self, node: VbaOptionStatement):
        self._write(F'Option {node.keyword}')
        if node.value:
            self._write(F' {node.value}')

    def visit_VbaDeclareStatement(self, node: VbaDeclareStatement):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        kind = 'Function' if node.is_function else 'Sub'
        self._write(F'Declare {kind} {node.name}')
        if node.lib:
            self._write(F' Lib {node.lib}')
        if node.alias:
            self._write(F' Alias {node.alias}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')

    def visit_VbaTypeDefinition(self, node: VbaTypeDefinition):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Type {node.name}')
        self._depth += 1
        for m in node.members:
            self._newline()
            self._write(m.name)
            if m.bounds:
                self._write('(')
                self._comma_separated(m.bounds)
                self._write(')')
            if m.type_name:
                self._write(F' As {m.type_name}')
        self._depth -= 1
        self._newline()
        self._write('End Type')

    def visit_VbaEnumDefinition(self, node: VbaEnumDefinition):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Enum {node.name}')
        self._depth += 1
        for m in node.members:
            self._newline()
            self.visit(m)
        self._depth -= 1
        self._newline()
        self._write('End Enum')

    def visit_VbaEnumMember(self, node: VbaEnumMember):
        self._write(node.name)
        if node.value is not None:
            self._write(' = ')
            self.visit(node.value)

    def visit_VbaConstDeclaration(self, node: VbaConstDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write('Const ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaConstDeclarator(self, node: VbaConstDeclarator):
        self._write(node.name)
        if node.type_name:
            self._write(F' As {node.type_name}')
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaVariableDeclaration(self, node: VbaVariableDeclaration):
        self._write(F'{node.scope.value} ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaVariableDeclarator(self, node: VbaVariableDeclarator):
        if node.with_events:
            self._write('WithEvents ')
        self._write(node.name)
        if node.is_array or node.bounds:
            self._write('(')
            self._comma_separated(node.bounds)
            self._write(')')
        if node.type_name:
            if node.is_new:
                self._write(F' As New {node.type_name}')
            else:
                self._write(F' As {node.type_name}')

    def visit_VbaEventDeclaration(self, node: VbaEventDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Event {node.name}')
        self._emit_params(node.params)

    def visit_VbaParameter(self, node: VbaParameter):
        if node.is_optional:
            self._write('Optional ')
        if node.passing is not VbaParameterPassing.NONE:
            self._write(F'{node.passing.value} ')
        if node.is_paramarray:
            self._write('ParamArray ')
        self._write(node.name)
        if node.is_array:
            self._write('()')
        if node.type_name:
            self._write(F' As {node.type_name}')
        if node.default is not None:
            self._write(' = ')
            self.visit(node.default)

    def visit_VbaSubDeclaration(self, node: VbaSubDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Sub {node.name}')
        self._emit_params(node.params)
        self._emit_body(node.body)
        self._newline()
        self._write('End Sub')

    def visit_VbaFunctionDeclaration(self, node: VbaFunctionDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Function {node.name}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')
        self._emit_body(node.body)
        self._newline()
        self._write('End Function')

    def visit_VbaPropertyDeclaration(self, node: VbaPropertyDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Property {node.kind.value} {node.name}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')
        self._emit_body(node.body)
        self._newline()
        self._write('End Property')

    def visit_VbaExpressionStatement(self, node: VbaExpressionStatement):
        if node.expression:
            self.visit(node.expression)
        if node.arguments:
            self._write(' ')
            self._comma_separated(node.arguments)

    def visit_VbaCallStatement(self, node: VbaCallStatement):
        self._write('Call ')
        if node.callee:
            self.visit(node.callee)
        if node.arguments:
            self._write('(')
            self._comma_separated(node.arguments)
            self._write(')')

    def visit_VbaLetStatement(self, node: VbaLetStatement):
        if node.explicit:
            kw = node.keyword if node.keyword else 'Let'
            self._write(F'{kw} ')
        if node.target:
            self.visit(node.target)
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaSetStatement(self, node: VbaSetStatement):
        self._write('Set ')
        if node.target:
            self.visit(node.target)
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaIfStatement(self, node: VbaIfStatement):
        if node.single_line:
            self._write('If ')
            if node.condition:
                self.visit(node.condition)
            self._write(' Then ')
            for i, stmt in enumerate(node.body):
                if i > 0:
                    self._write(': ')
                self.visit(stmt)
            if node.else_body:
                self._write(' Else ')
                for i, stmt in enumerate(node.else_body):
                    if i > 0:
                        self._write(': ')
                    self.visit(stmt)
            return
        self._write('If ')
        if node.condition:
            self.visit(node.condition)
        self._write(' Then')
        self._emit_body(node.body)
        for clause in node.elseif_clauses:
            self._newline()
            self.visit(clause)
        if node.else_body:
            self._newline()
            self._write('Else')
            self._emit_body(node.else_body)
        self._newline()
        self._write('End If')

    def visit_VbaElseIfClause(self, node: VbaElseIfClause):
        self._write('ElseIf ')
        if node.condition:
            self.visit(node.condition)
        self._write(' Then')
        self._emit_body(node.body)

    def visit_VbaForStatement(self, node: VbaForStatement):
        self._write('For ')
        if node.variable:
            self.visit(node.variable)
        self._write(' = ')
        if node.start:
            self.visit(node.start)
        self._write(' To ')
        if node.end:
            self.visit(node.end)
        if node.step:
            self._write(' Step ')
            self.visit(node.step)
        self._emit_body(node.body)
        self._newline()
        self._write('Next')

    def visit_VbaForEachStatement(self, node: VbaForEachStatement):
        self._write('For Each ')
        if node.variable:
            self.visit(node.variable)
        self._write(' In ')
        if node.collection:
            self.visit(node.collection)
        self._emit_body(node.body)
        self._newline()
        self._write('Next')

    def visit_VbaDoLoopStatement(self, node: VbaDoLoopStatement):
        self._write('Do')
        if (
            node.condition_position is VbaLoopConditionPosition.PRE
            and node.condition_type
            and node.condition
        ):
            self._write(F' {node.condition_type.value} ')
            self.visit(node.condition)
        self._emit_body(node.body)
        self._newline()
        self._write('Loop')
        if (
            node.condition_position is VbaLoopConditionPosition.POST
            and node.condition_type
            and node.condition
        ):
            self._write(F' {node.condition_type.value} ')
            self.visit(node.condition)

    def visit_VbaWhileStatement(self, node: VbaWhileStatement):
        self._write('While ')
        if node.condition:
            self.visit(node.condition)
        self._emit_body(node.body)
        self._newline()
        self._write('Wend')

    def visit_VbaSelectCaseStatement(self, node: VbaSelectCaseStatement):
        self._write('Select Case ')
        if node.expression:
            self.visit(node.expression)
        self._depth += 1
        for c in node.cases:
            self._newline()
            self.visit(c)
        self._depth -= 1
        self._newline()
        self._write('End Select')

    def visit_VbaCaseClause(self, node: VbaCaseClause):
        if node.is_else:
            self._write('Case Else')
        else:
            self._write('Case ')
            self._comma_separated(node.tests)
        self._emit_body(node.body)

    def visit_VbaWithStatement(self, node: VbaWithStatement):
        self._write('With ')
        if node.object:
            self.visit(node.object)
        self._emit_body(node.body)
        self._newline()
        self._write('End With')

    def visit_VbaGotoStatement(self, node: VbaGotoStatement):
        self._write(F'GoTo {node.label}')

    def visit_VbaGosubStatement(self, node: VbaGosubStatement):
        self._write(F'GoSub {node.label}')

    def visit_VbaOnErrorStatement(self, node: VbaOnErrorStatement):
        if node.action is VbaOnErrorAction.RESUME_NEXT:
            self._write('On Error Resume Next')
        elif node.action is VbaOnErrorAction.GOTO:
            self._write(F'On Error GoTo {node.label}')
        else:
            self._write('On Error')

    def visit_VbaOnBranchStatement(self, node: VbaOnBranchStatement):
        self._write('On ')
        self.visit(node.expression)
        labels = ', '.join(node.labels)
        self._write(F' {node.kind.value} {labels}')

    def visit_VbaExitStatement(self, node: VbaExitStatement):
        self._write(F'Exit {node.kind.value}')

    def visit_VbaReturnStatement(self, node: VbaReturnStatement):
        self._write('Return')

    def visit_VbaRedimStatement(self, node: VbaRedimStatement):
        self._write('ReDim ')
        if node.preserve:
            self._write('Preserve ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaEraseStatement(self, node: VbaEraseStatement):
        self._write('Erase ')
        self._comma_separated(node.targets)

    def visit_VbaRaiseEventStatement(self, node: VbaRaiseEventStatement):
        self._write(F'RaiseEvent {node.name}')
        if node.arguments:
            self._write('(')
            self._comma_separated(node.arguments)
            self._write(')')

    def visit_VbaLabelStatement(self, node: VbaLabelStatement):
        self._write(F'{node.label}:')

    def visit_VbaStopStatement(self, node: VbaStopStatement):
        self._write('Stop')

    def visit_VbaEndStatement(self, node: VbaEndStatement):
        self._write('End')

    def visit_VbaDebugPrintStatement(self, node: VbaDebugPrintStatement):
        self._write(F'Debug.{node.method}')
        if node.arguments:
            self._write(' ')
            for i, arg in enumerate(node.arguments):
                if i > 0:
                    sep = node.separators[i - 1] if i - 1 < len(node.separators) else ';'
                    self._write(F'{sep} ')
                self.visit(arg)
            if len(node.separators) >= len(node.arguments):
                self._write(node.separators[-1])

    def visit_VbaResumeStatement(self, node: VbaResumeStatement):
        self._write('Resume')
        if node.label:
            self._write(F' {node.label}')

    def visit_VbaImplementsStatement(self, node: VbaImplementsStatement):
        self._write(F'Implements {node.name}')

Classes

class VbaSynthesizer (indent=' ')

Dispatch-based tree walker. Subclasses define visit_ClassName methods; unhandled nodes fall through to generic_visit.

Expand source code Browse git
class VbaSynthesizer(Visitor):

    _BLOCK_TYPES = (
        VbaSubDeclaration,
        VbaFunctionDeclaration,
        VbaPropertyDeclaration,
        VbaTypeDefinition,
        VbaEnumDefinition,
    )

    def __init__(self, indent: str = '  '):
        super().__init__()
        self._indent = indent
        self._depth = 0
        self._parts = io.StringIO()

    def convert(self, node: Node) -> str:
        self._parts.seek(0)
        self._parts.truncate(0)
        self._depth = 0
        self.visit(node)
        return self._parts.getvalue()

    def _write(self, text: str):
        self._parts.write(text)

    def _newline(self):
        self._parts.write('\n')
        self._parts.write(self._indent * self._depth)

    def _emit_body(self, body: list[Statement]):
        self._depth += 1
        for stmt in body:
            self._newline()
            self.visit(stmt)
        self._depth -= 1

    def _comma_separated(self, nodes: list):
        for i, node in enumerate(nodes):
            if i > 0:
                self._write(', ')
            if node is None:
                continue
            self.visit(node)

    def _emit_params(self, params: list[VbaParameter]):
        self._write('(')
        for i, p in enumerate(params):
            if i > 0:
                self._write(', ')
            self.visit(p)
        self._write(')')

    def generic_visit(self, node: Node):
        self._write(F'<{type(node).__name__}>')

    def visit_VbaIntegerLiteral(self, node: VbaIntegerLiteral):
        self._write(node.raw)

    def visit_VbaFloatLiteral(self, node: VbaFloatLiteral):
        self._write(node.raw)

    def visit_VbaStringLiteral(self, node: VbaStringLiteral):
        self._write(node.raw)

    def visit_VbaDateLiteral(self, node: VbaDateLiteral):
        self._write(node.raw)

    def visit_VbaBooleanLiteral(self, node: VbaBooleanLiteral):
        self._write('True' if node.value else 'False')

    def visit_VbaNothingLiteral(self, node: VbaNothingLiteral):
        self._write('Nothing')

    def visit_VbaNullLiteral(self, node: VbaNullLiteral):
        self._write('Null')

    def visit_VbaEmptyLiteral(self, node: VbaEmptyLiteral):
        self._write('Empty')

    def visit_VbaMeExpression(self, node: VbaMeExpression):
        self._write('Me')

    def visit_VbaIdentifier(self, node: VbaIdentifier):
        self._write(node.name)

    def visit_VbaTypedIdentifier(self, node: VbaTypedIdentifier):
        self._write(F'{node.name}{node.suffix}')

    def visit_VbaErrorNode(self, node: VbaErrorNode):
        self._write(node.text)

    def visit_VbaBinaryExpression(self, node: VbaBinaryExpression):
        if node.left:
            self.visit(node.left)
        self._write(F' {node.operator} ')
        if node.right:
            self.visit(node.right)

    def visit_VbaUnaryExpression(self, node: VbaUnaryExpression):
        op = node.operator
        self._write(op)
        if op.isalpha():
            self._write(' ')
        if node.operand:
            self.visit(node.operand)

    def visit_VbaByValArgument(self, node: VbaByValArgument):
        self._write('ByVal ')
        if node.expression:
            self.visit(node.expression)

    def visit_VbaNamedArgument(self, node: VbaNamedArgument):
        self._write(F'{node.name}:=')
        if node.expression:
            self.visit(node.expression)

    def visit_VbaCallExpression(self, node: VbaCallExpression):
        if node.callee:
            self.visit(node.callee)
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')

    def visit_VbaMemberAccess(self, node: VbaMemberAccess):
        if node.object:
            self.visit(node.object)
        self._write(F'.{node.member}')

    def visit_VbaBangAccess(self, node: VbaBangAccess):
        if node.object:
            self.visit(node.object)
        self._write(F'!{node.member}')

    def visit_VbaIndexExpression(self, node: VbaIndexExpression):
        if node.object:
            self.visit(node.object)
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')

    def visit_VbaNewExpression(self, node: VbaNewExpression):
        self._write('New ')
        if node.class_name:
            self.visit(node.class_name)

    def visit_VbaTypeOfIsExpression(self, node: VbaTypeOfIsExpression):
        self._write('TypeOf ')
        if node.operand:
            self.visit(node.operand)
        self._write(' Is ')
        if node.type_name:
            self.visit(node.type_name)

    def visit_VbaParenExpression(self, node: VbaParenExpression):
        self._write('(')
        if node.expression:
            self.visit(node.expression)
        self._write(')')

    def visit_VbaRangeExpression(self, node: VbaRangeExpression):
        if node.start:
            self.visit(node.start)
        self._write(' To ')
        if node.end:
            self.visit(node.end)

    def visit_VbaModule(self, node: VbaModule):
        prev_group = None
        for i, stmt in enumerate(node.body):
            group = self._stmt_group(stmt)
            if i > 0:
                if group != prev_group or group == 'block':
                    self._write('\n')
                self._newline()
            self.visit(stmt)
            prev_group = group

    @classmethod
    def _stmt_group(cls, stmt: Statement) -> str:
        if isinstance(stmt, cls._BLOCK_TYPES):
            return 'block'
        if isinstance(stmt, VbaDeclareStatement):
            return 'declare'
        if isinstance(stmt, VbaOptionStatement):
            return 'option'
        if isinstance(stmt, (VbaVariableDeclaration, VbaConstDeclaration)):
            return 'variable'
        if isinstance(stmt, VbaEventDeclaration):
            return 'event'
        if isinstance(stmt, VbaImplementsStatement):
            return 'implements'
        return 'other'

    def visit_VbaOptionStatement(self, node: VbaOptionStatement):
        self._write(F'Option {node.keyword}')
        if node.value:
            self._write(F' {node.value}')

    def visit_VbaDeclareStatement(self, node: VbaDeclareStatement):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        kind = 'Function' if node.is_function else 'Sub'
        self._write(F'Declare {kind} {node.name}')
        if node.lib:
            self._write(F' Lib {node.lib}')
        if node.alias:
            self._write(F' Alias {node.alias}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')

    def visit_VbaTypeDefinition(self, node: VbaTypeDefinition):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Type {node.name}')
        self._depth += 1
        for m in node.members:
            self._newline()
            self._write(m.name)
            if m.bounds:
                self._write('(')
                self._comma_separated(m.bounds)
                self._write(')')
            if m.type_name:
                self._write(F' As {m.type_name}')
        self._depth -= 1
        self._newline()
        self._write('End Type')

    def visit_VbaEnumDefinition(self, node: VbaEnumDefinition):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Enum {node.name}')
        self._depth += 1
        for m in node.members:
            self._newline()
            self.visit(m)
        self._depth -= 1
        self._newline()
        self._write('End Enum')

    def visit_VbaEnumMember(self, node: VbaEnumMember):
        self._write(node.name)
        if node.value is not None:
            self._write(' = ')
            self.visit(node.value)

    def visit_VbaConstDeclaration(self, node: VbaConstDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write('Const ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaConstDeclarator(self, node: VbaConstDeclarator):
        self._write(node.name)
        if node.type_name:
            self._write(F' As {node.type_name}')
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaVariableDeclaration(self, node: VbaVariableDeclaration):
        self._write(F'{node.scope.value} ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaVariableDeclarator(self, node: VbaVariableDeclarator):
        if node.with_events:
            self._write('WithEvents ')
        self._write(node.name)
        if node.is_array or node.bounds:
            self._write('(')
            self._comma_separated(node.bounds)
            self._write(')')
        if node.type_name:
            if node.is_new:
                self._write(F' As New {node.type_name}')
            else:
                self._write(F' As {node.type_name}')

    def visit_VbaEventDeclaration(self, node: VbaEventDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        self._write(F'Event {node.name}')
        self._emit_params(node.params)

    def visit_VbaParameter(self, node: VbaParameter):
        if node.is_optional:
            self._write('Optional ')
        if node.passing is not VbaParameterPassing.NONE:
            self._write(F'{node.passing.value} ')
        if node.is_paramarray:
            self._write('ParamArray ')
        self._write(node.name)
        if node.is_array:
            self._write('()')
        if node.type_name:
            self._write(F' As {node.type_name}')
        if node.default is not None:
            self._write(' = ')
            self.visit(node.default)

    def visit_VbaSubDeclaration(self, node: VbaSubDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Sub {node.name}')
        self._emit_params(node.params)
        self._emit_body(node.body)
        self._newline()
        self._write('End Sub')

    def visit_VbaFunctionDeclaration(self, node: VbaFunctionDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Function {node.name}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')
        self._emit_body(node.body)
        self._newline()
        self._write('End Function')

    def visit_VbaPropertyDeclaration(self, node: VbaPropertyDeclaration):
        if node.scope is not VbaScopeModifier.NONE:
            self._write(F'{node.scope.value} ')
        if node.is_static:
            self._write('Static ')
        self._write(F'Property {node.kind.value} {node.name}')
        self._emit_params(node.params)
        if node.return_type:
            self._write(F' As {node.return_type}')
        self._emit_body(node.body)
        self._newline()
        self._write('End Property')

    def visit_VbaExpressionStatement(self, node: VbaExpressionStatement):
        if node.expression:
            self.visit(node.expression)
        if node.arguments:
            self._write(' ')
            self._comma_separated(node.arguments)

    def visit_VbaCallStatement(self, node: VbaCallStatement):
        self._write('Call ')
        if node.callee:
            self.visit(node.callee)
        if node.arguments:
            self._write('(')
            self._comma_separated(node.arguments)
            self._write(')')

    def visit_VbaLetStatement(self, node: VbaLetStatement):
        if node.explicit:
            kw = node.keyword if node.keyword else 'Let'
            self._write(F'{kw} ')
        if node.target:
            self.visit(node.target)
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaSetStatement(self, node: VbaSetStatement):
        self._write('Set ')
        if node.target:
            self.visit(node.target)
        self._write(' = ')
        if node.value:
            self.visit(node.value)

    def visit_VbaIfStatement(self, node: VbaIfStatement):
        if node.single_line:
            self._write('If ')
            if node.condition:
                self.visit(node.condition)
            self._write(' Then ')
            for i, stmt in enumerate(node.body):
                if i > 0:
                    self._write(': ')
                self.visit(stmt)
            if node.else_body:
                self._write(' Else ')
                for i, stmt in enumerate(node.else_body):
                    if i > 0:
                        self._write(': ')
                    self.visit(stmt)
            return
        self._write('If ')
        if node.condition:
            self.visit(node.condition)
        self._write(' Then')
        self._emit_body(node.body)
        for clause in node.elseif_clauses:
            self._newline()
            self.visit(clause)
        if node.else_body:
            self._newline()
            self._write('Else')
            self._emit_body(node.else_body)
        self._newline()
        self._write('End If')

    def visit_VbaElseIfClause(self, node: VbaElseIfClause):
        self._write('ElseIf ')
        if node.condition:
            self.visit(node.condition)
        self._write(' Then')
        self._emit_body(node.body)

    def visit_VbaForStatement(self, node: VbaForStatement):
        self._write('For ')
        if node.variable:
            self.visit(node.variable)
        self._write(' = ')
        if node.start:
            self.visit(node.start)
        self._write(' To ')
        if node.end:
            self.visit(node.end)
        if node.step:
            self._write(' Step ')
            self.visit(node.step)
        self._emit_body(node.body)
        self._newline()
        self._write('Next')

    def visit_VbaForEachStatement(self, node: VbaForEachStatement):
        self._write('For Each ')
        if node.variable:
            self.visit(node.variable)
        self._write(' In ')
        if node.collection:
            self.visit(node.collection)
        self._emit_body(node.body)
        self._newline()
        self._write('Next')

    def visit_VbaDoLoopStatement(self, node: VbaDoLoopStatement):
        self._write('Do')
        if (
            node.condition_position is VbaLoopConditionPosition.PRE
            and node.condition_type
            and node.condition
        ):
            self._write(F' {node.condition_type.value} ')
            self.visit(node.condition)
        self._emit_body(node.body)
        self._newline()
        self._write('Loop')
        if (
            node.condition_position is VbaLoopConditionPosition.POST
            and node.condition_type
            and node.condition
        ):
            self._write(F' {node.condition_type.value} ')
            self.visit(node.condition)

    def visit_VbaWhileStatement(self, node: VbaWhileStatement):
        self._write('While ')
        if node.condition:
            self.visit(node.condition)
        self._emit_body(node.body)
        self._newline()
        self._write('Wend')

    def visit_VbaSelectCaseStatement(self, node: VbaSelectCaseStatement):
        self._write('Select Case ')
        if node.expression:
            self.visit(node.expression)
        self._depth += 1
        for c in node.cases:
            self._newline()
            self.visit(c)
        self._depth -= 1
        self._newline()
        self._write('End Select')

    def visit_VbaCaseClause(self, node: VbaCaseClause):
        if node.is_else:
            self._write('Case Else')
        else:
            self._write('Case ')
            self._comma_separated(node.tests)
        self._emit_body(node.body)

    def visit_VbaWithStatement(self, node: VbaWithStatement):
        self._write('With ')
        if node.object:
            self.visit(node.object)
        self._emit_body(node.body)
        self._newline()
        self._write('End With')

    def visit_VbaGotoStatement(self, node: VbaGotoStatement):
        self._write(F'GoTo {node.label}')

    def visit_VbaGosubStatement(self, node: VbaGosubStatement):
        self._write(F'GoSub {node.label}')

    def visit_VbaOnErrorStatement(self, node: VbaOnErrorStatement):
        if node.action is VbaOnErrorAction.RESUME_NEXT:
            self._write('On Error Resume Next')
        elif node.action is VbaOnErrorAction.GOTO:
            self._write(F'On Error GoTo {node.label}')
        else:
            self._write('On Error')

    def visit_VbaOnBranchStatement(self, node: VbaOnBranchStatement):
        self._write('On ')
        self.visit(node.expression)
        labels = ', '.join(node.labels)
        self._write(F' {node.kind.value} {labels}')

    def visit_VbaExitStatement(self, node: VbaExitStatement):
        self._write(F'Exit {node.kind.value}')

    def visit_VbaReturnStatement(self, node: VbaReturnStatement):
        self._write('Return')

    def visit_VbaRedimStatement(self, node: VbaRedimStatement):
        self._write('ReDim ')
        if node.preserve:
            self._write('Preserve ')
        for i, d in enumerate(node.declarators):
            if i > 0:
                self._write(', ')
            self.visit(d)

    def visit_VbaEraseStatement(self, node: VbaEraseStatement):
        self._write('Erase ')
        self._comma_separated(node.targets)

    def visit_VbaRaiseEventStatement(self, node: VbaRaiseEventStatement):
        self._write(F'RaiseEvent {node.name}')
        if node.arguments:
            self._write('(')
            self._comma_separated(node.arguments)
            self._write(')')

    def visit_VbaLabelStatement(self, node: VbaLabelStatement):
        self._write(F'{node.label}:')

    def visit_VbaStopStatement(self, node: VbaStopStatement):
        self._write('Stop')

    def visit_VbaEndStatement(self, node: VbaEndStatement):
        self._write('End')

    def visit_VbaDebugPrintStatement(self, node: VbaDebugPrintStatement):
        self._write(F'Debug.{node.method}')
        if node.arguments:
            self._write(' ')
            for i, arg in enumerate(node.arguments):
                if i > 0:
                    sep = node.separators[i - 1] if i - 1 < len(node.separators) else ';'
                    self._write(F'{sep} ')
                self.visit(arg)
            if len(node.separators) >= len(node.arguments):
                self._write(node.separators[-1])

    def visit_VbaResumeStatement(self, node: VbaResumeStatement):
        self._write('Resume')
        if node.label:
            self._write(F' {node.label}')

    def visit_VbaImplementsStatement(self, node: VbaImplementsStatement):
        self._write(F'Implements {node.name}')

Ancestors

Methods

def convert(self, node)
Expand source code Browse git
def convert(self, node: Node) -> str:
    self._parts.seek(0)
    self._parts.truncate(0)
    self._depth = 0
    self.visit(node)
    return self._parts.getvalue()
def generic_visit(self, node)
Expand source code Browse git
def generic_visit(self, node: Node):
    self._write(F'<{type(node).__name__}>')
def visit_VbaIntegerLiteral(self, node)
Expand source code Browse git
def visit_VbaIntegerLiteral(self, node: VbaIntegerLiteral):
    self._write(node.raw)
def visit_VbaFloatLiteral(self, node)
Expand source code Browse git
def visit_VbaFloatLiteral(self, node: VbaFloatLiteral):
    self._write(node.raw)
def visit_VbaStringLiteral(self, node)
Expand source code Browse git
def visit_VbaStringLiteral(self, node: VbaStringLiteral):
    self._write(node.raw)
def visit_VbaDateLiteral(self, node)
Expand source code Browse git
def visit_VbaDateLiteral(self, node: VbaDateLiteral):
    self._write(node.raw)
def visit_VbaBooleanLiteral(self, node)
Expand source code Browse git
def visit_VbaBooleanLiteral(self, node: VbaBooleanLiteral):
    self._write('True' if node.value else 'False')
def visit_VbaNothingLiteral(self, node)
Expand source code Browse git
def visit_VbaNothingLiteral(self, node: VbaNothingLiteral):
    self._write('Nothing')
def visit_VbaNullLiteral(self, node)
Expand source code Browse git
def visit_VbaNullLiteral(self, node: VbaNullLiteral):
    self._write('Null')
def visit_VbaEmptyLiteral(self, node)
Expand source code Browse git
def visit_VbaEmptyLiteral(self, node: VbaEmptyLiteral):
    self._write('Empty')
def visit_VbaMeExpression(self, node)
Expand source code Browse git
def visit_VbaMeExpression(self, node: VbaMeExpression):
    self._write('Me')
def visit_VbaIdentifier(self, node)
Expand source code Browse git
def visit_VbaIdentifier(self, node: VbaIdentifier):
    self._write(node.name)
def visit_VbaTypedIdentifier(self, node)
Expand source code Browse git
def visit_VbaTypedIdentifier(self, node: VbaTypedIdentifier):
    self._write(F'{node.name}{node.suffix}')
def visit_VbaErrorNode(self, node)
Expand source code Browse git
def visit_VbaErrorNode(self, node: VbaErrorNode):
    self._write(node.text)
def visit_VbaBinaryExpression(self, node)
Expand source code Browse git
def visit_VbaBinaryExpression(self, node: VbaBinaryExpression):
    if node.left:
        self.visit(node.left)
    self._write(F' {node.operator} ')
    if node.right:
        self.visit(node.right)
def visit_VbaUnaryExpression(self, node)
Expand source code Browse git
def visit_VbaUnaryExpression(self, node: VbaUnaryExpression):
    op = node.operator
    self._write(op)
    if op.isalpha():
        self._write(' ')
    if node.operand:
        self.visit(node.operand)
def visit_VbaByValArgument(self, node)
Expand source code Browse git
def visit_VbaByValArgument(self, node: VbaByValArgument):
    self._write('ByVal ')
    if node.expression:
        self.visit(node.expression)
def visit_VbaNamedArgument(self, node)
Expand source code Browse git
def visit_VbaNamedArgument(self, node: VbaNamedArgument):
    self._write(F'{node.name}:=')
    if node.expression:
        self.visit(node.expression)
def visit_VbaCallExpression(self, node)
Expand source code Browse git
def visit_VbaCallExpression(self, node: VbaCallExpression):
    if node.callee:
        self.visit(node.callee)
    self._write('(')
    self._comma_separated(node.arguments)
    self._write(')')
def visit_VbaMemberAccess(self, node)
Expand source code Browse git
def visit_VbaMemberAccess(self, node: VbaMemberAccess):
    if node.object:
        self.visit(node.object)
    self._write(F'.{node.member}')
def visit_VbaBangAccess(self, node)
Expand source code Browse git
def visit_VbaBangAccess(self, node: VbaBangAccess):
    if node.object:
        self.visit(node.object)
    self._write(F'!{node.member}')
def visit_VbaIndexExpression(self, node)
Expand source code Browse git
def visit_VbaIndexExpression(self, node: VbaIndexExpression):
    if node.object:
        self.visit(node.object)
    self._write('(')
    self._comma_separated(node.arguments)
    self._write(')')
def visit_VbaNewExpression(self, node)
Expand source code Browse git
def visit_VbaNewExpression(self, node: VbaNewExpression):
    self._write('New ')
    if node.class_name:
        self.visit(node.class_name)
def visit_VbaTypeOfIsExpression(self, node)
Expand source code Browse git
def visit_VbaTypeOfIsExpression(self, node: VbaTypeOfIsExpression):
    self._write('TypeOf ')
    if node.operand:
        self.visit(node.operand)
    self._write(' Is ')
    if node.type_name:
        self.visit(node.type_name)
def visit_VbaParenExpression(self, node)
Expand source code Browse git
def visit_VbaParenExpression(self, node: VbaParenExpression):
    self._write('(')
    if node.expression:
        self.visit(node.expression)
    self._write(')')
def visit_VbaRangeExpression(self, node)
Expand source code Browse git
def visit_VbaRangeExpression(self, node: VbaRangeExpression):
    if node.start:
        self.visit(node.start)
    self._write(' To ')
    if node.end:
        self.visit(node.end)
def visit_VbaModule(self, node)
Expand source code Browse git
def visit_VbaModule(self, node: VbaModule):
    prev_group = None
    for i, stmt in enumerate(node.body):
        group = self._stmt_group(stmt)
        if i > 0:
            if group != prev_group or group == 'block':
                self._write('\n')
            self._newline()
        self.visit(stmt)
        prev_group = group
def visit_VbaOptionStatement(self, node)
Expand source code Browse git
def visit_VbaOptionStatement(self, node: VbaOptionStatement):
    self._write(F'Option {node.keyword}')
    if node.value:
        self._write(F' {node.value}')
def visit_VbaDeclareStatement(self, node)
Expand source code Browse git
def visit_VbaDeclareStatement(self, node: VbaDeclareStatement):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    kind = 'Function' if node.is_function else 'Sub'
    self._write(F'Declare {kind} {node.name}')
    if node.lib:
        self._write(F' Lib {node.lib}')
    if node.alias:
        self._write(F' Alias {node.alias}')
    self._emit_params(node.params)
    if node.return_type:
        self._write(F' As {node.return_type}')
def visit_VbaTypeDefinition(self, node)
Expand source code Browse git
def visit_VbaTypeDefinition(self, node: VbaTypeDefinition):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    self._write(F'Type {node.name}')
    self._depth += 1
    for m in node.members:
        self._newline()
        self._write(m.name)
        if m.bounds:
            self._write('(')
            self._comma_separated(m.bounds)
            self._write(')')
        if m.type_name:
            self._write(F' As {m.type_name}')
    self._depth -= 1
    self._newline()
    self._write('End Type')
def visit_VbaEnumDefinition(self, node)
Expand source code Browse git
def visit_VbaEnumDefinition(self, node: VbaEnumDefinition):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    self._write(F'Enum {node.name}')
    self._depth += 1
    for m in node.members:
        self._newline()
        self.visit(m)
    self._depth -= 1
    self._newline()
    self._write('End Enum')
def visit_VbaEnumMember(self, node)
Expand source code Browse git
def visit_VbaEnumMember(self, node: VbaEnumMember):
    self._write(node.name)
    if node.value is not None:
        self._write(' = ')
        self.visit(node.value)
def visit_VbaConstDeclaration(self, node)
Expand source code Browse git
def visit_VbaConstDeclaration(self, node: VbaConstDeclaration):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    self._write('Const ')
    for i, d in enumerate(node.declarators):
        if i > 0:
            self._write(', ')
        self.visit(d)
def visit_VbaConstDeclarator(self, node)
Expand source code Browse git
def visit_VbaConstDeclarator(self, node: VbaConstDeclarator):
    self._write(node.name)
    if node.type_name:
        self._write(F' As {node.type_name}')
    self._write(' = ')
    if node.value:
        self.visit(node.value)
def visit_VbaVariableDeclaration(self, node)
Expand source code Browse git
def visit_VbaVariableDeclaration(self, node: VbaVariableDeclaration):
    self._write(F'{node.scope.value} ')
    for i, d in enumerate(node.declarators):
        if i > 0:
            self._write(', ')
        self.visit(d)
def visit_VbaVariableDeclarator(self, node)
Expand source code Browse git
def visit_VbaVariableDeclarator(self, node: VbaVariableDeclarator):
    if node.with_events:
        self._write('WithEvents ')
    self._write(node.name)
    if node.is_array or node.bounds:
        self._write('(')
        self._comma_separated(node.bounds)
        self._write(')')
    if node.type_name:
        if node.is_new:
            self._write(F' As New {node.type_name}')
        else:
            self._write(F' As {node.type_name}')
def visit_VbaEventDeclaration(self, node)
Expand source code Browse git
def visit_VbaEventDeclaration(self, node: VbaEventDeclaration):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    self._write(F'Event {node.name}')
    self._emit_params(node.params)
def visit_VbaParameter(self, node)
Expand source code Browse git
def visit_VbaParameter(self, node: VbaParameter):
    if node.is_optional:
        self._write('Optional ')
    if node.passing is not VbaParameterPassing.NONE:
        self._write(F'{node.passing.value} ')
    if node.is_paramarray:
        self._write('ParamArray ')
    self._write(node.name)
    if node.is_array:
        self._write('()')
    if node.type_name:
        self._write(F' As {node.type_name}')
    if node.default is not None:
        self._write(' = ')
        self.visit(node.default)
def visit_VbaSubDeclaration(self, node)
Expand source code Browse git
def visit_VbaSubDeclaration(self, node: VbaSubDeclaration):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    if node.is_static:
        self._write('Static ')
    self._write(F'Sub {node.name}')
    self._emit_params(node.params)
    self._emit_body(node.body)
    self._newline()
    self._write('End Sub')
def visit_VbaFunctionDeclaration(self, node)
Expand source code Browse git
def visit_VbaFunctionDeclaration(self, node: VbaFunctionDeclaration):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    if node.is_static:
        self._write('Static ')
    self._write(F'Function {node.name}')
    self._emit_params(node.params)
    if node.return_type:
        self._write(F' As {node.return_type}')
    self._emit_body(node.body)
    self._newline()
    self._write('End Function')
def visit_VbaPropertyDeclaration(self, node)
Expand source code Browse git
def visit_VbaPropertyDeclaration(self, node: VbaPropertyDeclaration):
    if node.scope is not VbaScopeModifier.NONE:
        self._write(F'{node.scope.value} ')
    if node.is_static:
        self._write('Static ')
    self._write(F'Property {node.kind.value} {node.name}')
    self._emit_params(node.params)
    if node.return_type:
        self._write(F' As {node.return_type}')
    self._emit_body(node.body)
    self._newline()
    self._write('End Property')
def visit_VbaExpressionStatement(self, node)
Expand source code Browse git
def visit_VbaExpressionStatement(self, node: VbaExpressionStatement):
    if node.expression:
        self.visit(node.expression)
    if node.arguments:
        self._write(' ')
        self._comma_separated(node.arguments)
def visit_VbaCallStatement(self, node)
Expand source code Browse git
def visit_VbaCallStatement(self, node: VbaCallStatement):
    self._write('Call ')
    if node.callee:
        self.visit(node.callee)
    if node.arguments:
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')
def visit_VbaLetStatement(self, node)
Expand source code Browse git
def visit_VbaLetStatement(self, node: VbaLetStatement):
    if node.explicit:
        kw = node.keyword if node.keyword else 'Let'
        self._write(F'{kw} ')
    if node.target:
        self.visit(node.target)
    self._write(' = ')
    if node.value:
        self.visit(node.value)
def visit_VbaSetStatement(self, node)
Expand source code Browse git
def visit_VbaSetStatement(self, node: VbaSetStatement):
    self._write('Set ')
    if node.target:
        self.visit(node.target)
    self._write(' = ')
    if node.value:
        self.visit(node.value)
def visit_VbaIfStatement(self, node)
Expand source code Browse git
def visit_VbaIfStatement(self, node: VbaIfStatement):
    if node.single_line:
        self._write('If ')
        if node.condition:
            self.visit(node.condition)
        self._write(' Then ')
        for i, stmt in enumerate(node.body):
            if i > 0:
                self._write(': ')
            self.visit(stmt)
        if node.else_body:
            self._write(' Else ')
            for i, stmt in enumerate(node.else_body):
                if i > 0:
                    self._write(': ')
                self.visit(stmt)
        return
    self._write('If ')
    if node.condition:
        self.visit(node.condition)
    self._write(' Then')
    self._emit_body(node.body)
    for clause in node.elseif_clauses:
        self._newline()
        self.visit(clause)
    if node.else_body:
        self._newline()
        self._write('Else')
        self._emit_body(node.else_body)
    self._newline()
    self._write('End If')
def visit_VbaElseIfClause(self, node)
Expand source code Browse git
def visit_VbaElseIfClause(self, node: VbaElseIfClause):
    self._write('ElseIf ')
    if node.condition:
        self.visit(node.condition)
    self._write(' Then')
    self._emit_body(node.body)
def visit_VbaForStatement(self, node)
Expand source code Browse git
def visit_VbaForStatement(self, node: VbaForStatement):
    self._write('For ')
    if node.variable:
        self.visit(node.variable)
    self._write(' = ')
    if node.start:
        self.visit(node.start)
    self._write(' To ')
    if node.end:
        self.visit(node.end)
    if node.step:
        self._write(' Step ')
        self.visit(node.step)
    self._emit_body(node.body)
    self._newline()
    self._write('Next')
def visit_VbaForEachStatement(self, node)
Expand source code Browse git
def visit_VbaForEachStatement(self, node: VbaForEachStatement):
    self._write('For Each ')
    if node.variable:
        self.visit(node.variable)
    self._write(' In ')
    if node.collection:
        self.visit(node.collection)
    self._emit_body(node.body)
    self._newline()
    self._write('Next')
def visit_VbaDoLoopStatement(self, node)
Expand source code Browse git
def visit_VbaDoLoopStatement(self, node: VbaDoLoopStatement):
    self._write('Do')
    if (
        node.condition_position is VbaLoopConditionPosition.PRE
        and node.condition_type
        and node.condition
    ):
        self._write(F' {node.condition_type.value} ')
        self.visit(node.condition)
    self._emit_body(node.body)
    self._newline()
    self._write('Loop')
    if (
        node.condition_position is VbaLoopConditionPosition.POST
        and node.condition_type
        and node.condition
    ):
        self._write(F' {node.condition_type.value} ')
        self.visit(node.condition)
def visit_VbaWhileStatement(self, node)
Expand source code Browse git
def visit_VbaWhileStatement(self, node: VbaWhileStatement):
    self._write('While ')
    if node.condition:
        self.visit(node.condition)
    self._emit_body(node.body)
    self._newline()
    self._write('Wend')
def visit_VbaSelectCaseStatement(self, node)
Expand source code Browse git
def visit_VbaSelectCaseStatement(self, node: VbaSelectCaseStatement):
    self._write('Select Case ')
    if node.expression:
        self.visit(node.expression)
    self._depth += 1
    for c in node.cases:
        self._newline()
        self.visit(c)
    self._depth -= 1
    self._newline()
    self._write('End Select')
def visit_VbaCaseClause(self, node)
Expand source code Browse git
def visit_VbaCaseClause(self, node: VbaCaseClause):
    if node.is_else:
        self._write('Case Else')
    else:
        self._write('Case ')
        self._comma_separated(node.tests)
    self._emit_body(node.body)
def visit_VbaWithStatement(self, node)
Expand source code Browse git
def visit_VbaWithStatement(self, node: VbaWithStatement):
    self._write('With ')
    if node.object:
        self.visit(node.object)
    self._emit_body(node.body)
    self._newline()
    self._write('End With')
def visit_VbaGotoStatement(self, node)
Expand source code Browse git
def visit_VbaGotoStatement(self, node: VbaGotoStatement):
    self._write(F'GoTo {node.label}')
def visit_VbaGosubStatement(self, node)
Expand source code Browse git
def visit_VbaGosubStatement(self, node: VbaGosubStatement):
    self._write(F'GoSub {node.label}')
def visit_VbaOnErrorStatement(self, node)
Expand source code Browse git
def visit_VbaOnErrorStatement(self, node: VbaOnErrorStatement):
    if node.action is VbaOnErrorAction.RESUME_NEXT:
        self._write('On Error Resume Next')
    elif node.action is VbaOnErrorAction.GOTO:
        self._write(F'On Error GoTo {node.label}')
    else:
        self._write('On Error')
def visit_VbaOnBranchStatement(self, node)
Expand source code Browse git
def visit_VbaOnBranchStatement(self, node: VbaOnBranchStatement):
    self._write('On ')
    self.visit(node.expression)
    labels = ', '.join(node.labels)
    self._write(F' {node.kind.value} {labels}')
def visit_VbaExitStatement(self, node)
Expand source code Browse git
def visit_VbaExitStatement(self, node: VbaExitStatement):
    self._write(F'Exit {node.kind.value}')
def visit_VbaReturnStatement(self, node)
Expand source code Browse git
def visit_VbaReturnStatement(self, node: VbaReturnStatement):
    self._write('Return')
def visit_VbaRedimStatement(self, node)
Expand source code Browse git
def visit_VbaRedimStatement(self, node: VbaRedimStatement):
    self._write('ReDim ')
    if node.preserve:
        self._write('Preserve ')
    for i, d in enumerate(node.declarators):
        if i > 0:
            self._write(', ')
        self.visit(d)
def visit_VbaEraseStatement(self, node)
Expand source code Browse git
def visit_VbaEraseStatement(self, node: VbaEraseStatement):
    self._write('Erase ')
    self._comma_separated(node.targets)
def visit_VbaRaiseEventStatement(self, node)
Expand source code Browse git
def visit_VbaRaiseEventStatement(self, node: VbaRaiseEventStatement):
    self._write(F'RaiseEvent {node.name}')
    if node.arguments:
        self._write('(')
        self._comma_separated(node.arguments)
        self._write(')')
def visit_VbaLabelStatement(self, node)
Expand source code Browse git
def visit_VbaLabelStatement(self, node: VbaLabelStatement):
    self._write(F'{node.label}:')
def visit_VbaStopStatement(self, node)
Expand source code Browse git
def visit_VbaStopStatement(self, node: VbaStopStatement):
    self._write('Stop')
def visit_VbaEndStatement(self, node)
Expand source code Browse git
def visit_VbaEndStatement(self, node: VbaEndStatement):
    self._write('End')
def visit_VbaDebugPrintStatement(self, node)
Expand source code Browse git
def visit_VbaDebugPrintStatement(self, node: VbaDebugPrintStatement):
    self._write(F'Debug.{node.method}')
    if node.arguments:
        self._write(' ')
        for i, arg in enumerate(node.arguments):
            if i > 0:
                sep = node.separators[i - 1] if i - 1 < len(node.separators) else ';'
                self._write(F'{sep} ')
            self.visit(arg)
        if len(node.separators) >= len(node.arguments):
            self._write(node.separators[-1])
def visit_VbaResumeStatement(self, node)
Expand source code Browse git
def visit_VbaResumeStatement(self, node: VbaResumeStatement):
    self._write('Resume')
    if node.label:
        self._write(F' {node.label}')
def visit_VbaImplementsStatement(self, node)
Expand source code Browse git
def visit_VbaImplementsStatement(self, node: VbaImplementsStatement):
    self._write(F'Implements {node.name}')