Esempio n. 1
0
def prettyNode(node, opts, rslt, enableBreaks=False, enableVerbose=False):
    global indent
    global result
    global pretty
    global verbose
    global breaks
    global afterLine
    global afterBreak
    global afterDoc
    global afterDivider
    global afterArea
    global options

    result = rslt

    options = opts
    opts.prettypIndentString = eval("'" + opts.prettypIndentString + "'")
    opts.prettypCommentsInlinePadding = eval(
        "'" + opts.prettypCommentsInlinePadding + "'")
    # allow for escapes like "\t"
    # split trailing comment cols into an array
    if (opts.prettypCommentsTrailingCommentCols and isinstance(
            opts.prettypCommentsTrailingCommentCols, basestring)):
        opts.prettypCommentsTrailingCommentCols = [
            int(column.strip())
            for column in opts.prettypCommentsTrailingCommentCols.split(",")
        ]
        opts.prettypCommentsTrailingCommentCols.sort(
        )  # make sure they are ascending!
    # or make sure it's a list of int's
    elif (isinstance(opts.prettypCommentsTrailingCommentCols, list) and reduce(
            lambda y, z: y and z,
        [isinstance(x, int)
         for x in opts.prettypCommentsTrailingCommentCols], True)):
        opts.prettypCommentsTrailingCommentCols.sort(
        )  # make sure they are ascending!
    # or pass
    else:
        #raise TypeError, "Unsuitable type for option --pretty-print-comments-trailing-commentCols"
        pass

    if opts.prettypCommentsBlockAdd:
        Comment.fill(node)

    indent = 0
    result = [u""]
    pretty = opts.prettyPrint
    verbose = enableVerbose
    breaks = enableBreaks
    afterLine = False
    afterBreak = False
    afterDoc = False
    afterDivider = False
    afterArea = False

    return _prettyNode(node, opts, result)
Esempio n. 2
0
def prettyNode(node, opts, rslt, enableBreaks=False, enableVerbose=False):
    global indent
    global result
    global pretty
    global verbose
    global breaks
    global afterLine
    global afterBreak
    global afterDoc
    global afterDivider
    global afterArea
    global options

    result = rslt

    options = opts
    opts.prettypIndentString          = eval("'" + opts.prettypIndentString + "'")
    opts.prettypCommentsInlinePadding = eval("'" + opts.prettypCommentsInlinePadding + "'")
                                                              # allow for escapes like "\t"
    # split trailing comment cols into an array
    if (opts.prettypCommentsTrailingCommentCols and
        isinstance(opts.prettypCommentsTrailingCommentCols, basestring)):
        opts.prettypCommentsTrailingCommentCols = [int(column.strip()) for column in opts.prettypCommentsTrailingCommentCols.split(",")]
        opts.prettypCommentsTrailingCommentCols.sort() # make sure they are ascending!
    # or make sure it's a list of int's
    elif (isinstance(opts.prettypCommentsTrailingCommentCols, list) and
        reduce(lambda y,z: y and z,
               [isinstance(x,int) for x in opts.prettypCommentsTrailingCommentCols],
               True)):
        opts.prettypCommentsTrailingCommentCols.sort() # make sure they are ascending!
    # or pass
    else:
        #raise TypeError, "Unsuitable type for option --pretty-print-comments-trailing-commentCols"
        pass

    if opts.prettypCommentsBlockAdd:
        Comment.fill(node)

    indent       = 0
    result       = [u""]
    pretty       = opts.prettyPrint
    verbose      = enableVerbose
    breaks       = enableBreaks
    afterLine    = False
    afterBreak   = False
    afterDoc     = False
    afterDivider = False
    afterArea    = False

    return _prettyNode(node,opts,result)
Esempio n. 3
0
    def _shouldPrintVariableWarning(self, node, docCommand, variableName):
        comments = Comment.findComment(node)
        if comments is None:
            return True

        lintAttribs = [x for x in comments if x["category"] == "lint"]

        unused_re = re.compile("<p>\s*%s\s*\(\s*((?:[\w\$]+)\s*(?:,\s*(?:[\w\$]+)\s*)*)\)" % docCommand)
        for attrib in lintAttribs:
            match = unused_re.match(attrib["text"])
            if match:
                variables = [var.strip() for var in match.group(1).split(",")]
                return not variableName in variables
        return True
Esempio n. 4
0
    def _shouldPrintVariableWarning(self, node, docCommand, variableName):
        comments = Comment.findComment(node)
        if comments is None:
            return True

        lintAttribs = [x for x in comments if x["category"] == "lint"]

        unused_re = re.compile(
            "<p>\s*%s\s*\(\s*((?:[\w\$]+)\s*(?:,\s*(?:[\w\$]+)\s*)*)\)" %
            docCommand)
        for attrib in lintAttribs:
            match = unused_re.match(attrib["text"])
            if match:
                variables = [var.strip() for var in match.group(1).split(",")]
                return not variableName in variables
        return True
Esempio n. 5
0
def createBlockComment(txt):
    l = "*****************************************************************************"

    s = ""
    s += "/*\n"
    s += "%s\n" % l
    s += "   %s\n" % txt.upper()
    s += "%s\n" % l
    s += "*/"

    bef = tree.Node("commentsBefore")
    com = tree.Node("comment")

    bef.addChild(com)

    com.set("multiline", True)
    com.set("connection", "before")
    com.set("text", s)
    com.set("detail", Comment.Comment(s).getFormat())

    return bef
Esempio n. 6
0
def _prettyNode(node, optns, result):

    global pretty
    global indent

    #####################################################################################################################
    # Recover styling
    #####################################################################################################################

    if pretty:
        # Recover exclicit breaks
        if node.get("breakBefore", False) and not node.isFirstChild(True):
            sep()

        # Additional explicit break before complex blocks
        if node.hasParent() and not node.isFirstChild(
                True) and node.parent.type in ["block", "file"
                                               ] and node.isComplex():
            sep()

    #####################################################################################################################
    # Insert comments before
    #####################################################################################################################

    if pretty:
        if node.getChild("commentsBefore", False) != None:
            commentCounter = 0
            commentsBefore = node.getChild("commentsBefore")
            isFirst = node.isFirstChild()
            previous = node.getPreviousSibling(False, True)

            if previous and previous.type in ["case", "default"]:
                inCase = True
            else:
                inCase = False

            inOperation = node.parent.type in [
                "first", "second", "third"
            ] and node.parent.parent.type == "operation"

            for child in commentsBefore.children:
                docComment = child.get("detail") in ["javadoc", "qtdoc"]
                headComment = child.get("detail") == "header"
                areaComment = child.get("detail") == "area"
                divComment = child.get("detail") == "divider"
                blockComment = child.get("detail") == "block"
                singleLineBlock = child.get(
                    "detail") != "inline" and child.get("multiline") == False

                if not child.isFirstChild():
                    pass

                elif inCase:
                    pass

                elif singleLineBlock:
                    if child.get("begin"):
                        sep()
                    else:
                        space()

                elif areaComment and not isFirst:
                    area()

                elif divComment and not isFirst:
                    divide()

                elif not isFirst:
                    if docComment:
                        doc()
                    else:
                        if child.get("text") in ("//", "/*"):
                            nosep(
                            )  # the blank comment provides a blank line, so don't put a separator in
                            line(
                            )  # make sure there is a new line after whatever has gone before
                        else:
                            sep()

                elif inOperation:
                    sep()

                elif not headComment:
                    line()

                # reindenting first
                text = child.get("text")

                if child.get("detail") == "qtdoc":
                    text = Comment.Comment(text).qt2javadoc()

                #write(comment.indent(text, INDENTSPACES * indent))
                write(
                    Comment.Text(text).indent(optns.prettypIndentString *
                                              indent))

                if singleLineBlock:
                    if docComment:
                        line()
                    elif child.get("end"):
                        sep()
                    else:
                        space()

                # separator after divider/head comments and after block comments which are not for documentation
                elif headComment or areaComment or divComment or blockComment:
                    sep()

                else:
                    line()
                    # the next two: bugzilla#454
                    #global result
                    #result += "\n"

    #####################################################################################################################
    # Opening...
    #####################################################################################################################

    #
    # OPEN: FINALLY
    ##################################

    if node.type == "finally":
        write("finally")

    #
    # OPEN: DELETE
    ##################################

    elif node.type == "delete":
        write("delete")
        space()

    #
    # OPEN: THROW
    ##################################

    elif node.type == "throw":
        write("throw")
        space()

    #
    # OPEN: NEW
    ##################################

    elif node.type == "instantiation":
        write("new")
        space()

    #
    # OPEN: RETURN
    ##################################

    elif node.type == "return":
        write("return")

        if node.hasChildren():
            space()

    #
    # OPEN: DEFINITION LIST
    ##################################

    elif node.type == "definitionList":
        write("var")
        space()

    #
    # OPEN: BREAK
    ##################################

    elif node.type == "break":
        write("break")

        if node.get("label", False):
            space()
            write(node.get("label", False))

    #
    # OPEN: CONTINUE
    ##################################

    elif node.type == "continue":
        write("continue")

        if node.get("label", False):
            space()
            write(node.get("label", False))

    #
    # OPEN: FUNCTION
    ##################################

    elif node.type == "function":
        write("function")

        if node.getChild("identifier", False):
            functionName = node.getChild("identifier", False).get("value")
            space()
            write(functionName)

    #
    # OPEN: IDENTIFIER
    ##################################

    elif node.type == "identifier":
        name = node.get("value", False)
        if name != None:
            write(name)

    #
    # OPEN: DEFINITION
    ##################################

    elif node.type == "definition":
        if node.parent.type != "definitionList":
            write("var")
            space()

        write(node.get("identifier"))

    #
    # OPEN: CONSTANT
    ##################################

    elif node.type == "constant":
        if node.get("constantType") == "string":
            if node.get("detail") == "singlequotes":
                write("'")
            else:
                write('"')

            write(node.get("value"))

            if node.get("detail") == "singlequotes":
                write("'")
            else:
                write('"')

        else:
            write(node.get("value"))

    #
    # OPEN: COMMENT
    ##################################

    elif node.type == "comment":
        if pretty:
            commentText = node.get("text")
            # insert appropriate spaces before and no newline in the case of after comments
            if node.get("connection") == "after":
                noline()
                padding = getInlineCommentPadding(optns, node.get("column"))
                if padding:
                    commentText = padding + commentText.strip()
                else:
                    space()
                ##space()

            ##write(node.get("text"))
            write(commentText)

            # new line after inline comment (for example for syntactical reasons)
            #if (node.get("detail") == "inline") or (node.get("multiline") == False):
            if (node.get("detail") == "inline") or (node.get("end") == True):
                line()
            else:
                space()

    #
    # OPEN: RIGHT
    ##################################

    elif node.type == "right":
        if node.parent.type == "accessor":
            write(".")

    #
    # OPEN: ASSIGNMENT
    ##################################

    elif node.type == "assignment":
        if node.parent.type == "definition":
            oper = node.get("operator", False)

            # be compact in for-loops
            compact = inForLoop(node)
            compileToken(oper, compact)

    #
    # OPEN: KEY
    ##################################

    elif node.type == "key":
        if node.parent.type == "accessor":
            write("[")

    #
    # OPEN: GROUP
    ##################################

    elif node.type == "group":
        write("(")

    #
    # OPEN: VOID
    ##################################

    elif node.type == "void":
        write("void")
        write("(")

    #
    # OPEN: ARRAY
    ##################################

    elif node.type == "array":
        write("[")

        if node.hasChildren(True):
            space(False)

    #
    # OPEN: PARAMS
    ##################################

    elif node.type in ("params", "arguments"):
        noline()
        write("(")

    #
    # OPEN: CASE
    ##################################

    elif node.type == "case":
        if pretty:
            # force double new lines
            if not node.isFirstChild():
                sep()
                dec_indent()

            line()

        write("case")
        space()

    #
    # OPEN: DEFAULT
    ##################################

    elif node.type == "default":
        if pretty:
            dec_indent()

            # force double new lines
            if (node.getPreviousSibling(False)
                    and not node.getPreviousSibling(True).type == "case"):
                sep()

        write("default")
        write(":")

        if pretty:
            inc_indent()
            line()

    #
    # OPEN: TRY
    ##################################

    elif node.type == "switch":
        # Additional new line before each switch/try
        if not node.isFirstChild(True) and not node.getChild(
                "commentsBefore", False):
            prev = node.getPreviousSibling(False, True)

            # No separation after case statements
            if prev != None and prev.type in ["case", "default"]:
                pass
            else:
                sep()

        if node.get("switchType") == "catch":
            write("try")
        elif node.get("switchType") == "case":
            write("switch")

    #
    # OPEN: CATCH
    ##################################

    elif node.type == "catch":
        if pretty:
            # If this statement block or the previous try were not complex, be not complex here, too
            if not node.getChild("statement").getChild(
                    "block").isComplex() and not node.parent.getChild(
                        "statement").getChild("block").isComplex():
                noline()
                space()
            # the next two: bugzilla#454
            if node.getFirstChild(
            ).type == "commentsBefore" and not result[-1].endswith("\n"):
                line()

        write("catch")

    #
    # OPEN: MAP
    ##################################

    elif node.type == "map":
        par = node.parent

        if pretty:
            postProcessMap(node)

        if pretty:
            # No break before return statement
            if node.hasParent(
            ) and node.parent.type == "expression" and node.parent.parent.type == "return":
                pass

            elif ((node.isComplex()
                   and not (optns.prettypOpenCurlyNewlineBefore in "nN"))
                  or (optns.prettypOpenCurlyNewlineBefore in "aA")):
                line()
                if optns.prettypOpenCurlyIndentBefore:
                    inc_indent()

        write("{")

        if pretty:
            if node.isComplex():
                line()
                if not optns.prettypAlignBlockWithCurlies:
                    inc_indent()

            elif node.hasChildren(True):
                space()

    #
    # OPEN: KEYVALUE
    ##################################

    elif node.type == "keyvalue":
        keyString = node.get("key")
        keyQuote = node.get("quote", False)

        if keyQuote != None:
            # print "USE QUOTATION"
            if keyQuote == "doublequotes":
                keyString = '"' + keyString + '"'
            else:
                keyString = "'" + keyString + "'"

        elif keyString in lang.RESERVED or not KEY.match(keyString):
            print "Warning: Auto protect key: %s" % keyString
            keyString = "\"" + keyString + "\""

        if pretty and not node.isFirstChild(True) and not node.hasChild(
                "commentsBefore") and node.getChild("value").isComplex():
            sep()

        write(keyString)
        space(False)

        # Fill with spaces
        # Do this only if the parent is complex (many entries)
        # But not if the value itself is complex
        if pretty and node.parent.isComplex() and node.parent.get(
                "alignValues"):
            write(" " * (node.parent.get("maxKeyLength") - len(keyString)))

        write(":")
        space(False)

    #
    # OPEN: BLOCK
    ##################################

    elif node.type == "block":
        if pretty:
            if ((node.isComplex()
                 and not (optns.prettypOpenCurlyNewlineBefore in "nN"))
                    or (optns.prettypOpenCurlyNewlineBefore in "aA")):
                line()
                nl = True
                if optns.prettypOpenCurlyIndentBefore:
                    inc_indent()
            else:
                space()
                nl = False

        write("{")

        if pretty:
            if node.hasChildren():
                line()
                if (not nl) or (nl and not optns.prettypAlignBlockWithCurlies):
                    inc_indent()

    #
    # OPEN: LOOP
    ##################################

    elif node.type == "loop":
        # Additional new line before each loop
        if not node.isFirstChild(True) and not node.getChild(
                "commentsBefore", False):
            prev = node.getPreviousSibling(False, True)

            # No separation after case statements
            if prev != None and prev.type in ["case", "default"]:
                pass
            elif node.hasChild("elseStatement") or node.getChild(
                    "statement").hasBlockChildren():
                sep()
            else:
                line()

        loopType = node.get("loopType")

        if loopType == "IF":
            write("if")
            space(False)

        elif loopType == "WHILE":
            write("while")
            space(False)

        elif loopType == "FOR":
            write("for")
            space(False)

        elif loopType == "DO":
            write("do")
            space(False)

        elif loopType == "WITH":
            write("with")
            space(False)

        else:
            print "Warning: Unknown loop type: %s" % loopType

    #
    # OPEN: ELSE
    ##################################

    elif node.type == "elseStatement":
        if node.hasChild("commentsBefore"):
            pass

        elif pretty:
            if not node.hasChild("block") and not node.hasChild("loop"):
                pass

            elif not node.isComplex():
                noline()
                space()

        write("else")

        # This is a elseStatement without a block around (a set of {})
        if not node.hasChild("block"):
            space()

    #
    # OPEN: EXPRESSION
    ##################################

    elif node.type == "expression":
        if node.parent.type == "loop":
            loopType = node.parent.get("loopType")

            # only do-while loops
            if loopType == "DO":
                if pretty:
                    stmnt = node.parent.getChild("statement")
                    compact = stmnt.hasChild(
                        "block") and not stmnt.getChild("block").isComplex()

                    if compact:
                        noline()
                        space()

                write("while")

                if pretty:
                    space()

            # open expression block of IF/WHILE/DO-WHILE/FOR statements
            write("(")

        elif node.parent.type == "catch":
            # open expression block of CATCH statement
            write("(")

        elif node.parent.type == "switch" and node.parent.get(
                "switchType") == "case":
            # open expression block of SWITCH statement
            write("(")

    #
    # OPEN: FIRST
    ##################################

    elif node.type == "first":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            write("(")

        # operation
        elif node.parent.type == "operation":
            # operation (var a = -1)
            if node.parent.get("left", False) == True:
                compileToken(node.parent.get("operator"), True)

    #
    # OPEN: SECOND
    ##################################

    elif node.type == "second":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            if not node.parent.hasChild("first"):
                write("(;")

        # operation
        elif node.parent.type == "operation":
            if node.isComplex():
                # (?: hook operation)
                if node.parent.get("operator") == "HOOK":
                    sep()
                else:
                    line()

    #
    # OPEN: THIRD
    ##################################

    elif node.type == "third":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            if not node.parent.hasChild("second"):
                if node.parent.hasChild("first"):
                    write(";")
                    space(False)
                else:
                    write("(;;")

        # operation
        elif node.parent.type == "operation":
            # (?: hook operation)
            if node.parent.get("operator") == "HOOK":
                if node.isComplex():
                    sep()

    #
    # OPEN: STATEMENT
    ##################################

    elif node.type == "statement":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            if node.parent.get("forVariant") == "iter":
                if not node.parent.hasChild(
                        "first") and not node.parent.hasChild(
                            "second") and not node.parent.hasChild("third"):
                    write("(;;")

                elif not node.parent.hasChild(
                        "second") and not node.parent.hasChild("third"):
                    write(";")

            write(")")

            if not node.hasChild("block"):
                space(False)

    #####################################################################################################################
    # Children content
    #####################################################################################################################

    if node.hasChildren():
        for child in node.children:
            if not node.type in ["commentsBefore", "commentsAfter"]:
                _prettyNode(child, optns, result)

    #####################################################################################################################
    # Closing node
    #####################################################################################################################

    #
    # CLOSE: IDENTIFIER
    ##################################

    if node.type == "identifier":
        if node.hasParent(
        ) and node.parent.type == "variable" and not node.isLastChild(True):
            write(".")
        elif node.hasParent() and node.parent.type == "label":
            write(":")

    #
    # CLOSE: ACCESSOR
    ##################################

    elif node.type == "accessor":
        if node.hasParent(
        ) and node.parent.type == "variable" and not node.isLastChild(True):
            write(".")

    #
    # CLOSE: KEYVALUE
    ##################################

    elif node.type == "keyvalue":
        if node.hasParent(
        ) and node.parent.type == "map" and not node.isLastChild(True):
            noline()
            comma()

            if pretty:
                commentNode(node)

                if node.getChild("value").isComplex():
                    sep()
                elif node.parent.isComplex():
                    line()
                else:
                    space()

    #
    # CLOSE: DEFINITION
    ##################################

    elif node.type == "definition":
        if node.hasParent(
        ) and node.parent.type == "definitionList" and not node.isLastChild(
                True):
            comma()

            if pretty:
                commentNode(node)

                if node.hasComplexChildren():
                    line()
                else:
                    space()

    #
    # CLOSE: LEFT
    ##################################

    elif node.type == "left":
        if node.hasParent() and node.parent.type == "assignment":
            oper = node.parent.get("operator", False)

            # be compact in for-loops
            compact = inForLoop(node)
            compileToken(oper, compact)

    #
    # CLOSE: KEY
    ##################################

    elif node.type == "key":
        if node.hasParent() and node.parent.type == "accessor":
            write("]")

    #
    # CLOSE: GROUP
    ##################################

    elif node.type == "group":
        if node.getChildrenLength(True) == 1:
            #noline()  # commented out due to bug#811
            pass

        write(")")

    #
    # CLOSE: VOID
    ##################################

    elif node.type == "void":
        if node.getChildrenLength(True) == 1:
            noline()

        write(")")

    #
    # CLOSE: ARRAY
    ##################################

    elif node.type == "array":
        if node.hasChildren(True):
            space(False)

        write("]")

    #
    # CLOSE: PARAMS
    ##################################

    elif node.type in ("params", "arguments"):
        write(")")

    #
    # CLOSE: MAP
    ##################################

    elif node.type == "map":
        if pretty:
            if node.isComplex():
                line()
                if not optns.prettypAlignBlockWithCurlies:
                    dec_indent()

            elif node.hasChildren(True):
                space()

        write("}")

        if pretty:
            #if node.isComplex() and optns.prettypOpenCurlyIndentBefore:
            #    dec_indent()
            if node.hasParent(
            ) and node.parent.type == "expression" and node.parent.parent.type == "return":
                pass

            elif ((node.isComplex()
                   and not (optns.prettypOpenCurlyNewlineBefore in "nN")
                   )  # means: opening "{" on new line
                  or (optns.prettypOpenCurlyNewlineBefore in "aA")):
                if optns.prettypOpenCurlyIndentBefore:
                    dec_indent()

    #
    # CLOSE: SWITCH
    ##################################

    elif node.type == "switch":
        if node.get("switchType") == "case":
            if pretty:
                dec_indent()
                if not options.prettypAlignBlockWithCurlies:
                    dec_indent()
                line()

            write("}")

            if pretty:
                commentNode(node)
                line()
                if optns.prettypOpenCurlyIndentBefore:
                    dec_indent()

        # Force a additinal line feed after each switch/try
        if pretty and not node.isLastChild():
            sep()

    #
    # CLOSE: CASE
    ##################################

    elif node.type == "case":
        write(":")

        if pretty:
            commentNode(node)
            inc_indent()
            line()

    #
    # CLOSE: BLOCK
    ##################################

    elif node.type == "block":
        if pretty and node.hasChildren():
            line()
            if not optns.prettypAlignBlockWithCurlies:
                dec_indent()

        write("}")

        if pretty:
            commentNode(node)

            if node.hasChildren():
                # Newline afterwards
                if node.parent.type == "body" and node.parent.parent.type == "function":

                    # But only when this isn't a function block inside a assignment
                    if node.parent.parent.parent.type in [
                            "right", "params", "arguments"
                    ]:
                        pass

                    elif node.parent.parent.parent.type == "value" and node.parent.parent.parent.parent.type == "keyvalue":
                        pass

                    else:
                        line()

                else:
                    line()

            # to get the next statement after the block aligned with the parent of the block, you have to
            # unindent after "}" if:
            # - the opening "{" was on a new line AND was indented
            #   OR
            # - the opending "{" was inline AND align-with-curlies is active
            if ((node.isComplex()
                 and not (optns.prettypOpenCurlyNewlineBefore in "nN")
                 )  # means: opening "{" on new line
                    or (optns.prettypOpenCurlyNewlineBefore in "aA")):
                if optns.prettypOpenCurlyIndentBefore:
                    dec_indent()
            else:
                if optns.prettypAlignBlockWithCurlies:
                    dec_indent()

    #
    # CLOSE: LOOP
    ##################################

    elif node.type == "loop":
        if node.get("loopType") == "DO":
            semicolon()

        if pretty:
            commentNode(node)

            # Force a additinal line feed after each loop
            if not node.isLastChild():
                if node.hasChild("elseStatement"):
                    sep()
                elif node.getChild("statement").hasBlockChildren():
                    sep()
                else:
                    line()

    #
    # CLOSE: FUNCTION
    ##################################

    elif node.type == "function":
        if pretty:
            #commentNode(node) # commented out due to bug#942

            if not node.isLastChild() and node.hasParent(
            ) and node.parent.type in ["block", "file"]:
                sep()

    #
    # CLOSE: EXPRESSION
    ##################################

    elif node.type == "expression":
        if node.parent.type == "loop":
            write(")")

            # e.g. a if-construct without a block {}
            if node.parent.getChild("statement").hasChild("block"):
                pass

            elif node.parent.getChild("statement").hasChild("emptyStatement"):
                pass

            elif node.parent.type == "loop" and node.parent.get(
                    "loopType") == "DO":
                pass

            else:
                space(False)

        elif node.parent.type == "catch":
            write(")")

        elif node.parent.type == "switch" and node.parent.get(
                "switchType") == "case":
            write(")")

            if pretty:
                commentNode(node)
                line()
                if optns.prettypOpenCurlyIndentBefore:
                    inc_indent()

            write("{")

            if pretty:
                if not options.prettypAlignBlockWithCurlies:
                    inc_indent()

    #
    # CLOSE: FIRST
    ##################################

    elif node.type == "first":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            if node.parent.get("forVariant") == "iter":
                write(";")

                if node.parent.hasChild("second"):
                    space(False)

        # operation
        elif node.parent.type == "operation" and node.parent.get(
                "left", False) != True:
            oper = node.parent.get("operator")

            # be compact in for loops
            compact = inForLoop(node)
            compileToken(oper, compact)

    #
    # CLOSE: SECOND
    ##################################

    elif node.type == "second":
        # for loop
        if node.parent.type == "loop" and node.parent.get("loopType") == "FOR":
            write(";")

            if node.parent.hasChild("third"):
                space(False)

        # operation
        elif node.parent.type == "operation":
            # (?: hook operation)
            if node.parent.get("operator") == "HOOK":
                #noline()  # commented out due to bug#3415
                space(False)
                write(":")
                space(False)

    #
    # CLOSE: OTHER
    ##################################

    if node.hasParent() and not node.type in [
            "comment", "commentsBefore", "commentsAfter"
    ]:

        # Add comma dividers between statements in these parents
        if node.parent.type in [
                "array", "params", "arguments", "expressionList"
        ]:
            if not node.isLastChild(True):
                comma()

                if pretty:
                    commentNode(node)

                    if node.isComplex():
                        line()
                    else:
                        space()

        # Semicolon handling
        elif node.type in [
                "group", "block", "assignment", "call", "operation",
                "definitionList", "return", "break", "continue", "delete",
                "accessor", "instantiation", "throw", "variable",
                "emptyStatement"
        ]:

            # Default semicolon handling
            if node.parent.type in ["block", "file"]:
                semicolon()

                if pretty:
                    commentNode(node)
                    line()

                    if node.isComplex() and not node.isLastChild():
                        sep()

            # Special handling for switch statements
            elif node.parent.type == "statement" and node.parent.parent.type == "switch" and node.parent.parent.get(
                    "switchType") == "case":
                semicolon()

                if pretty:
                    commentNode(node)
                    line()

                    if node.isComplex() and not node.isLastChild():
                        sep()

            # Special handling for loops (e.g. if) without blocks {}
            elif (node.parent.type in ["statement", "elseStatement"]
                  and not node.parent.hasChild("block")
                  and node.parent.parent.type == "loop"):
                semicolon()

                if pretty:
                    commentNode(node)
                    line()

                    if node.isComplex() and not node.isLastChild():
                        sep()

    #
    # CLOSE: OTHER
    ##################################

    if pretty:
        # Rest of the after comments (not inserted previously)
        commentNode(node)

    return result