Example #1
0
 def checkRequiredBlocks(self):
     for node in treeutil.nodeIterator(self.tree, "loop"):
         block = treeutil.selectNode(node, "statement/block")
         if not block:
             self.log(node, "The statement of loops and conditions should be enclosed by a block in braces '{}'")
     for node in treeutil.nodeIterator(self.tree, "elseStatement"):
         block = treeutil.selectNode(node, "block")
         if not block:
             block = treeutil.selectNode(node, "loop[@loopType='IF']")
         if not block:
             self.log(node, "The statement of loops and conditions should be enclosed by a block in braces '{}'")
Example #2
0
def isEnvironmentCall(callNode):
    if callNode.type != "call":
        return False
    operandNode = treeutil.selectNode(callNode, "operand")
    environNodes = treeutil.findVariablePrefix(operandNode, "qx.core.Environment")
    if len(environNodes) != 1:
        return False
    environMethod = treeutil.selectNode(environNodes[0], "identifier[4]/@name")
    if environMethod in InterestingEnvMethods:
        return True
    return False
Example #3
0
def isEnvironmentCall(callNode):
    if callNode.type != "call":
        return False
    operandNode = treeutil.selectNode(callNode, "operand")
    environNodes = treeutil.findVariablePrefix(operandNode,
                                               "qx.core.Environment")
    if len(environNodes) != 1:
        return False
    environMethod = treeutil.selectNode(environNodes[0], "identifier[4]/@name")
    if environMethod in InterestingEnvMethods:
        return True
    return False
Example #4
0
    def checkUndefinedVariables(self, globals):

        # check whether this is a qooxdoo class and extract the top level namespace
        define = treeutil.findQxDefine(self.tree)
        if define:
            className = treeutil.selectNode(define, "params/1").get("value")
            globals.append(className.split(".")[0])

        globalScope = self.script.getGlobalScope()
        for scope in self.script.iterScopes():
            for use in scope.uses:

                if use.name in globals:
                    continue

                if not use.definition:
                    if self.isBadGlobal(use.name) and self._shouldPrintDeprecatedWarning(use.node, use.name):
                        self.log(use.node, "Use of deprecated global identifier '%s'" % use.name)
                    elif (
                        not self.isBadGlobal(use.name)
                        and not self.isGoodGlobal(use.name)
                        and self._shouldPrintUndefinedWarning(use.node, use.name)
                    ):
                        self.log(use.node, "Use of undefined or global identifier '%s'" % use.name)

                elif use.definition.scope == globalScope and self._shouldPrintUndefinedWarning(use.node, use.name):
                    self.log(use.node, "Use of global identifier '%s'" % use.name)
Example #5
0
 def checkRequiredBlocks(self):
     for node in treeutil.nodeIterator(self.tree, "loop"):
         block = treeutil.selectNode(node, "statement/block")
         if not block:
             self.log(
                 node,
                 "The statement of loops and conditions should be enclosed by a block in braces '{}'"
             )
     for node in treeutil.nodeIterator(self.tree, "elseStatement"):
         block = treeutil.selectNode(node, "block")
         if not block:
             block = treeutil.selectNode(node, "loop[@loopType='IF']")
         if not block:
             self.log(
                 node,
                 "The statement of loops and conditions should be enclosed by a block in braces '{}'"
             )
Example #6
0
 def protectedIsLastVarChild(var):
     lastChild = var.getLastChild(ignoreComments=True)  # like "this.a.b" -> b
     if lastChild.type != "identifier":  # rules out this.a._prot[0] which isn't a call anyway
         return False
     name = treeutil.selectNode(lastChild, "@name")
     if name and protectedElement.match(name):
         return True
     else:
         return False
Example #7
0
 def protectedIsLastVarChild(var):
     lastChild = var.getLastChild(
         ignoreComments=True)  # like "this.a.b" -> b
     if lastChild.type != "identifier":  # rules out this.a._prot[0] which isn't a call anyway
         return False
     name = treeutil.selectNode(lastChild, "@name")
     if name and protectedElement.match(name):
         return True
     else:
         return False
Example #8
0
def findVariantNodes(node):
    variantNodes = treeutil.findVariablePrefix(node, "qx.core.Environment")
    for variantNode in variantNodes:
        if not variantNode.hasParentContext("call/operand"):
            continue
        variantMethod = treeutil.selectNode(variantNode, "identifier[4]/@name")
        if variantMethod in InterestingEnvMethods:
            yield variantNode
        else:
            continue
Example #9
0
def findVariantNodes(node):
    variantNodes = treeutil.findVariablePrefix(node, "qx.core.Environment")
    for variantNode in variantNodes:
        if not variantNode.hasParentContext("call/operand"):
            continue
        variantMethod = treeutil.selectNode(variantNode, "identifier[4]/@name")
        if variantMethod in InterestingEnvMethods:
            yield variantNode
        else:
            continue
Example #10
0
    def _getClassMap(self):
        define = treeutil.findQxDefine(self.tree)
        if not define:
            return {}

        classMapNode = treeutil.selectNode(define, "params/2")
        if classMapNode is None:
            return {}

        classMap = treeutil.mapNodeToMap(classMapNode)
        return classMap
Example #11
0
    def _getClassMap(self):
        define = treeutil.findQxDefine(self.tree)
        if not define:
            return {}

        classMapNode = treeutil.selectNode(define, "params/2")
        if classMapNode is None:
            return {}

        classMap = treeutil.mapNodeToMap(classMapNode)
        return classMap
Example #12
0
        def checkAll():
            def findVariables(rootNode):
                variables = []
                for node in treeutil.nodeIterator(rootNode,
                                                  ["assignment", "call"]):
                    if node.type == "assignment":
                        variables.append(node.getChild("left"))
                    elif node.type == "call":
                        variables.append(node.getChild("operand"))
                return variables

            variables = findVariables(classMap["members"])
            if "construct" in classMap:
                variables.extend(findVariables(classMap["construct"]))

            for node in variables:
                this = treeutil.selectNode(node,
                                           "variable/identifier[1]/@name")
                if this != "this":
                    continue

                field = treeutil.selectNode(node,
                                            "variable/identifier[2]/@name")
                if field is None:
                    continue

                if field[0] != "_":
                    continue
                elif field[1] == "_":
                    prot = "private"
                else:
                    prot = "protected"

                if prot == "protected":
                    #self.log(node, "Protected data field '%s'. Protected fields are deprecated. Better use private fields in combination with getter and setter methods." % field)
                    pass  # protected data fields are ok
                elif not field in restricted:
                    self.log(
                        node,
                        "Implicit declaration of %s field '%s'. You should list this field in the members section."
                        % (prot, field))
Example #13
0
        def checkAll():
            def findVariables(rootNode):
                variables = []
                for node in treeutil.nodeIterator(rootNode, ["assignment", "call"]):
                    if node.type == "assignment":
                        variables.append(node.getChild("left"))
                    elif node.type == "call":
                        variables.append(node.getChild("operand"))
                return variables

            variables = findVariables(classMap["members"])
            if "construct" in classMap:
                variables.extend(findVariables(classMap["construct"]))

            for node in variables:
                this = treeutil.selectNode(node, "variable/identifier[1]/@name")
                if this != "this":
                    continue

                field = treeutil.selectNode(node, "variable/identifier[2]/@name")
                if field is None:
                    continue

                if field[0] != "_":
                    continue
                elif field[1] == "_":
                    prot = "private"
                else:
                    prot = "protected"

                if prot == "protected":
                    # self.log(node, "Protected data field '%s'. Protected fields are deprecated. Better use private fields in combination with getter and setter methods." % field)
                    pass  # protected data fields are ok
                elif not field in restricted:
                    self.log(
                        node,
                        "Implicit declaration of %s field '%s'. You should list this field in the members section."
                        % (prot, field),
                    )
Example #14
0
def processVariantGet(callNode, variantMap):

    treeModified = False

    # Simple sanity checks
    params = callNode.getChild("params")
    if len(params.children) != 1:
        log("Warning", "Expecting exactly one argument for qx.core.Environment.get. Ignoring this occurrence.", params)
        return treeModified

    firstParam = params.getChildByPosition(0)
    if not isStringLiteral(firstParam):
        # warning is currently covered in parsing code
        #log("Warning", "First argument must be a string literal! Ignoring this occurrence.", firstParam)
        return treeModified

    # skipping "relative" calls like "a.b.qx.core.Environment.get()"
    qxIdentifier = treeutil.selectNode(callNode, "operand/variable/identifier[1]")
    if not treeutil.checkFirstChainChild(qxIdentifier):
        log("Warning", "Skipping relative qx.core.Environment.get call. Ignoring this occurrence ('%s')." % treeutil.findChainRoot(qxIdentifier).toJavascript())
        return treeModified

    variantKey = firstParam.get("value");
    if variantKey in variantMap:
        confValue = variantMap[variantKey]
    else:
        return treeModified

    # Replace the .get() with its value
    resultNode = reduceCall(callNode, confValue)
    treeModified = True

    # Reduce any potential operations with literals (+3, =='hugo', ?a:b, ...)
    treeMod = True
    while treeMod:
        resultNode, treeMod = reduceOperation(resultNode)

    # Reduce a potential condition
    _ = reduceLoop(resultNode)

    return treeModified
Example #15
0
    def checkUndefinedVariables(self, globals):

        # check whether this is a qooxdoo class and extract the top level namespace
        define = treeutil.findQxDefine(self.tree)
        if define:
            className = treeutil.selectNode(define, "params/1").get("value")
            globals.append(className.split(".")[0])

        globalScope = self.script.getGlobalScope()
        for scope in self.script.iterScopes():
            for use in scope.uses:

                if use.name in globals:
                    continue

                if not use.definition:
                    if self.isBadGlobal(
                            use.name) and self._shouldPrintDeprecatedWarning(
                                use.node, use.name):
                        self.log(
                            use.node,
                            "Use of deprecated global identifier '%s'" %
                            use.name)
                    elif not self.isBadGlobal(
                            use.name) and not self.isGoodGlobal(
                                use.name
                            ) and self._shouldPrintUndefinedWarning(
                                use.node, use.name):
                        self.log(
                            use.node,
                            "Use of undefined or global identifier '%s'" %
                            use.name)

                elif use.definition.scope == globalScope and self._shouldPrintUndefinedWarning(
                        use.node, use.name):
                    self.log(use.node,
                             "Use of global identifier '%s'" % use.name)
Example #16
0
def reduceOperation(literalNode): 

    resultNode = None
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False
    else:
        literalValue = constNodeToPyValue(literalNode)

    # check if we're in an operation
    ngParent = nextNongroupParent(literalNode) # could be "first", "second" etc. in ops
    if not ngParent or not ngParent.parent or ngParent.parent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent.parent
    # get operator
    operator = operationNode.get("operator")

    # normalize expression
    noperationNode = normalizeExpression(operationNode)
    # re-gain knownn literal node
    for node in treeutil.nodeIterator(noperationNode, [literalNode.type]):
        if literalNode.attributes == node.attributes:
            nliteralNode = node
            break

    # equal, unequal
    if operator in ["EQ", "SHEQ", "NE", "SHNE"]:
        otherOperand, _ = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator in ["EQ", "SHEQ"]:
            cmpFcn = operators.eq
        elif operator in ["NE", "SHNE"]:
            cmpFcn = operators.ne

        operands = [literalValue]
        otherVal = constNodeToPyValue(otherOperand)
        operands.append(otherVal)
         
        result = cmpFcn(operands[0],operands[1])
        resultNode = tree.Node("constant")
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # order compares <, =<, ...
    elif operator in ["LT", "LE", "GT", "GE"]:
        otherOperand, otherPosition = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator == "LT":
            cmpFcn = operators.lt
        elif operator == "LE":
            cmpFcn = operators.le
        elif operator == "GT":
            cmpFcn = operators.gt
        elif operator == "GE":
            cmpFcn = operators.ge

        operands = {}
        operands[1 - otherPosition] = literalValue
        otherVal = constNodeToPyValue(otherOperand)
        operands[otherPosition] = otherVal

        result = cmpFcn(operands[0], operands[1])
        resultNode = tree.Node("constant")
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # logical ! (not)
    elif operator in ["NOT"]:
        result = not literalValue
        resultNode = tree.Node("constant")
        resultNode.set("constantType","boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # logical operators &&, || -- Currently disabled, s. bug#4856
    elif False and operator in ["AND", "OR"]:
        result = None
        otherOperand, otherPosition = getOtherOperand(noperationNode, nliteralNode)
        if operator == "AND":
            #if otherPosition==1 and not literalValue:  # short circuit
            #    result = False
            #else:
            cmpFcn = (lambda x,y: x and y)
        elif operator == "OR":
            #if otherPosition==1 and literalValue:  # short circuit
            #    result = True
            #else:
            cmpFcn = (lambda x,y: x or y)

        if result == None:
            if otherOperand.type != "constant":
                return literalNode, False
            operands = {}
            operands[1 - otherPosition] = literalValue
            otherVal = constNodeToPyValue(otherOperand)
            operands[otherPosition] = otherVal
            result = cmpFcn(operands[0], operands[1])
            resultNode = {literalValue:literalNode, otherVal:otherOperand}[result]

    # hook ?: operator
    elif operator in ["HOOK"]:
        if ngParent.type == "first": # optimize a literal condition
            if bool(literalValue):
                resultNode = treeutil.selectNode(noperationNode, "second/1", True)
            else:
                resultNode = treeutil.selectNode(noperationNode, "third/1", True)

    # unsupported operation
    else:
        pass

    if resultNode != None:
        #print "optimizing: operation"
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True
    else:
        resultNode = literalNode
        treeModified = False

    return resultNode, treeModified
Example #17
0
def reduceOperation(literalNode):

    resultNode = None
    treeModified = False

    # can only reduce with constants
    if literalNode.type != "constant":
        return literalNode, False
    else:
        literalValue = constNodeToPyValue(literalNode)

    # check if we're in an operation
    ngParent = nextNongroupParent(
        literalNode)  # could be "first", "second" etc. in ops
    if not ngParent or not ngParent.parent or ngParent.parent.type != "operation":
        return literalNode, False
    else:
        operationNode = ngParent.parent
    # get operator
    operator = operationNode.get("operator")

    # normalize expression
    noperationNode = normalizeExpression(operationNode)
    # re-gain knownn literal node
    for node in treeutil.nodeIterator(noperationNode, [literalNode.type]):
        if literalNode.attributes == node.attributes:
            nliteralNode = node
            break

    # equal, unequal
    if operator in ["EQ", "SHEQ", "NE", "SHNE"]:
        otherOperand, _ = getOtherOperand(noperationNode, nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator in ["EQ", "SHEQ"]:
            cmpFcn = operators.eq
        elif operator in ["NE", "SHNE"]:
            cmpFcn = operators.ne

        operands = [literalValue]
        otherVal = constNodeToPyValue(otherOperand)
        operands.append(otherVal)

        result = cmpFcn(operands[0], operands[1])
        resultNode = tree.Node("constant")
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # order compares <, =<, ...
    elif operator in ["LT", "LE", "GT", "GE"]:
        otherOperand, otherPosition = getOtherOperand(noperationNode,
                                                      nliteralNode)
        if otherOperand.type != "constant":
            return literalNode, False
        if operator == "LT":
            cmpFcn = operators.lt
        elif operator == "LE":
            cmpFcn = operators.le
        elif operator == "GT":
            cmpFcn = operators.gt
        elif operator == "GE":
            cmpFcn = operators.ge

        operands = {}
        operands[1 - otherPosition] = literalValue
        otherVal = constNodeToPyValue(otherOperand)
        operands[otherPosition] = otherVal

        result = cmpFcn(operands[0], operands[1])
        resultNode = tree.Node("constant")
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # logical ! (not)
    elif operator in ["NOT"]:
        result = not literalValue
        resultNode = tree.Node("constant")
        resultNode.set("constantType", "boolean")
        resultNode.set("value", str(result).lower())
        resultNode.set("line", noperationNode.get("line"))

    # logical operators &&, || -- Currently disabled, s. bug#4856
    elif False and operator in ["AND", "OR"]:
        result = None
        otherOperand, otherPosition = getOtherOperand(noperationNode,
                                                      nliteralNode)
        if operator == "AND":
            #if otherPosition==1 and not literalValue:  # short circuit
            #    result = False
            #else:
            cmpFcn = (lambda x, y: x and y)
        elif operator == "OR":
            #if otherPosition==1 and literalValue:  # short circuit
            #    result = True
            #else:
            cmpFcn = (lambda x, y: x or y)

        if result == None:
            if otherOperand.type != "constant":
                return literalNode, False
            operands = {}
            operands[1 - otherPosition] = literalValue
            otherVal = constNodeToPyValue(otherOperand)
            operands[otherPosition] = otherVal
            result = cmpFcn(operands[0], operands[1])
            resultNode = {
                literalValue: literalNode,
                otherVal: otherOperand
            }[result]

    # hook ?: operator
    elif operator in ["HOOK"]:
        if ngParent.type == "first":  # optimize a literal condition
            if bool(literalValue):
                resultNode = treeutil.selectNode(noperationNode, "second/1",
                                                 True)
            else:
                resultNode = treeutil.selectNode(noperationNode, "third/1",
                                                 True)

    # unsupported operation
    else:
        pass

    if resultNode != None:
        #print "optimizing: operation"
        operationNode.parent.replaceChild(operationNode, resultNode)
        treeModified = True
    else:
        resultNode = literalNode
        treeModified = False

    return resultNode, treeModified