Ejemplo n.º 1
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)
                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))
Ejemplo n.º 2
0
def patch(tree):
    qxnode = treeutil.findQxDefine(tree)

    processBlock(
        treeutil.selectNode(qxnode,
                            "params/map/keyvalue[@key='statics']/value/map"))
    processBlock(
        treeutil.selectNode(qxnode,
                            "params/map/keyvalue[@key='members']/value/map"))
Ejemplo n.º 3
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 '{}'")
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
    def checkFields(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)
        if not classMap.has_key("members"):
            return

        members = treeutil.mapNodeToMap(classMap["members"].children[0])
        restricted = [key for key in members if key.startswith("_")]

        assignNodes = [
            node for node in nodeIterator(classMap["members"], "assignment")
        ]
        if classMap.has_key("construct"):
            for node in nodeIterator(classMap["construct"], "assignment"):
                assignNodes.append(node)

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

            field = treeutil.selectNode(node,
                                        "left/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 fileds in combination with getter and setter methods."
                    % field)
            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))
Ejemplo n.º 7
0
def optimizeConstruct(node, superClass, methodName, classDefNodes):
    patchCount = 0

    # Need to run through all the nodes, to skip embedded qx.*.define(),
    # which will be treated separately

    # Handle Node

    # skip embedded qx.*.define()
    if node in classDefNodes:
        return 0

    elif node.type == "variable" and node.hasParentContext("call/operand"):

        varName, complete = treeutil.assembleVariable(node)
        if not (complete and varName == "this.base"):
            return 0

        call = node.parent.parent

        try:
            firstArgName = treeutil.selectNode(call,
                                               "params/1/identifier/@name")
        except tree.NodeAccessException:
            return 0

        if firstArgName != "arguments":
            return 0

        # "construct"
        if methodName == "construct":
            newCall = treeutil.compileString("%s.call()" % superClass)
        # "member"
        else:
            newCall = treeutil.compileString("%s.prototype.%s.call()" %
                                             (superClass, methodName))
        newCall.replaceChild(
            newCall.getChild("params"),
            call.getChild("params"))  # replace with old arglist
        treeutil.selectNode(newCall, "params/1/identifier").set(
            "name", "this")  # arguments -> this
        call.parent.replaceChild(call, newCall)
        patchCount += 1

    # Handle Children
    if node.hasChildren():
        for child in node.children:
            patchCount += optimizeConstruct(child, superClass, methodName,
                                            classDefNodes)

    return patchCount
Ejemplo n.º 8
0
 def _variantsFromTree(self, node):
     console = self.context['console']
     #config  = self.context['jobconf'] - TODO: this can yield job 'apiconf::build-resources' when running 'apiconf::build-data'!?
     config = Context.jobconf
     warn_non_literal_keys = "non-literal-keys" not in config.get(
         "config-warnings/environment", [])
     classvariants = set()
     for variantNode in variantoptimizer.findVariantNodes(node):
         firstParam = treeutil.selectNode(variantNode, "../../params/1")
         if firstParam:
             if treeutil.isStringLiteral(firstParam):
                 classvariants.add(firstParam.get("value"))
             elif firstParam.isVar():
                 if warn_non_literal_keys:
                     console.warn(
                         "qx.core.Environment call with non-literal key (%s:%s)"
                         % (self.id, variantNode.get("line", False)))
             elif firstParam.type == "map":  # e.g. .filter() method
                 mapMap = treeutil.mapNodeToMap(firstParam)
                 classvariants.update(mapMap.keys())
             else:
                 console.warn(
                     "qx.core.Environment call with alien first argument (%s:%s)"
                     % (self.id, variantNode.get("line", False)))
     return classvariants
Ejemplo n.º 9
0
def patch(tree, id, feature_names):

    # get class map
    qxDefine = treeutil.findQxDefine(tree)
    classMap = treeutil.getClassMap(qxDefine)
    # go through features in 'members' and 'statics'
    for section in ("statics", "members"):
        if section in classMap:
            for key, node in classMap[section].items():
                # skip registered keys
                if key in feature_names:
                    continue
                # skip non-function attribs
                meth = None
                if node.type == 'function':
                    meth = node
                else:
                    meth = treeutil.selectNode(node, "function")
                if not meth:
                    continue
                # prune
                else:
                    parent = node.parent
                    assert parent.type == "keyvalue"
                    #print "pruning: %s#%s" % (id, key)
                    parent.parent.removeChild(
                        parent)  # remove the entire key from the map
Ejemplo n.º 10
0
def patch(tree, id, feature_names):
    
    # get class map
    qxDefine = treeutil.findQxDefine(tree)
    classMap = treeutil.getClassMap(qxDefine)
    # go through features in 'members' and 'statics'
    for section in ("statics", "members"):
        if section in classMap:
            for key, node in classMap[section].items():
                # skip registered keys
                if key in feature_names:
                    continue
                # skip non-function attribs
                meth = None
                if node.type == 'function':
                    meth = node
                else:
                    meth = treeutil.selectNode(node, "function")
                if not meth:
                    continue
                # prune
                else:
                    parent = node.parent
                    assert parent.type == "keyvalue"
                    #print "pruning: %s#%s" % (id, key)
                    parent.parent.removeChild(parent)  # remove the entire key from the map
Ejemplo n.º 11
0
 def _variantsFromTree(self, node):
     console = self.context["console"]
     config = self.context["jobconf"]
     warn_non_literal_keys = "non-literal-keys" not in config.get("config-warnings/environment", [])
     classvariants = set()
     for variantNode in variantoptimizer.findVariantNodes(node):
         firstParam = treeutil.selectNode(variantNode, "../../params/1")
         if firstParam:
             if treeutil.isStringLiteral(firstParam):
                 classvariants.add(firstParam.get("value"))
             elif firstParam.type == "variable":
                 if warn_non_literal_keys:
                     console.warn(
                         "qx.core.Environment call with non-literal key (%s:%s)"
                         % (self.id, variantNode.get("line", False))
                     )
             elif firstParam.type == "map":  # e.g. .filter() method
                 mapMap = treeutil.mapNodeToMap(firstParam)
                 classvariants.update(mapMap.keys())
             else:
                 console.warn(
                     "qx.core.Environment call with alien first argument (%s:%s)"
                     % (self.id, variantNode.get("line", False))
                 )
     return classvariants
Ejemplo n.º 12
0
        def checkNodeContext(node):
            context = 'interesting' # every context is interesting, mybe we get more specific
            #context = ''

            # filter out the occurrences like 'c' in a.b().c
            myFirst = node.getFirstChild(mandatory=False, ignoreComments=True)
            if not treeutil.checkFirstChainChild(myFirst): # see if myFirst is the first identifier in a chain
                context = ''

            # filter out variable in lval position -- Nope! (qx.ui.form.ListItem.prototype.setValue = 
            # function(..){...};)
            #elif (node.hasParentContext("assignment/left")):
            #    context = ''

            # fitler out a.b[c] -- Nope! E.g. foo.ISO_8601_FORMAT might carry further dependencies
            # (like 'new qx.util.format.DateFormat("yyyy-MM-dd")')
            elif (treeutil.selectNode(node, "accessor")):
                context = 'accessor'

            # check name in 'new ...' position
            elif (node.hasParentContext("instantiation/*/*/operand")):
                context = 'new'

            # check name in call position
            elif (node.hasParentContext("call/operand")):
                context = 'call'

            # check name in "'extend' : ..." position
            elif (node.hasParentContext("keyvalue/*") and node.parent.parent.get('key') in ['extend']): #, 'include']):
                #print "-- found context: %s" % node.parent.parent.get('key')
                context = 'extend'

            return context
Ejemplo n.º 13
0
 def _getExceptionVariables(self):
     identifier = treeutil.selectNode(self.node,
                                      "expression/variable/identifier")
     return [
         VariableDefinition(identifier.get("name", None), identifier, False,
                            self)
     ]
Ejemplo n.º 14
0
def search(node, variantMap, fileId_="", verb=False):
    if not variantMap:
        return False

    global verbose
    global fileId
    verbose = verb
    fileId = fileId_
    modified = False

    variantNodes = findVariantNodes(node)
    for variantNode in variantNodes:
        variantMethod = variantNode.toJS(pp).rsplit('.', 1)[1]
        callNode = treeutil.selectNode(variantNode, "../..")
        if variantMethod in ["select"]:
            modified = processVariantSelect(callNode, variantMap) or modified
        elif variantMethod in ["get"]:
            modified = processVariantGet(callNode, variantMap) or modified
        elif variantMethod in ["filter"]:
            modified = processVariantFilter(callNode, variantMap) or modified

    # reduce decidable subtrees
    if modified:
        for cld in node.children[:]:
            new_cld = reducer.ast_reduce(cld)
            node.replaceChild(cld, new_cld)

    return modified
Ejemplo n.º 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)
Ejemplo n.º 16
0
def search(node, variantMap, fileId_="", verb=False):
    if not variantMap:
        return False

    global verbose
    global fileId
    verbose = verb
    fileId = fileId_
    modified = False

    variantNodes = findVariantNodes(node)
    for variantNode in variantNodes:
        variantMethod = variantNode.toJS(pp).rsplit(".", 1)[1]
        callNode = treeutil.selectNode(variantNode, "../..")
        if variantMethod in ["select"]:
            modified = processVariantSelect(callNode, variantMap) or modified
        elif variantMethod in ["get"]:
            modified = processVariantGet(callNode, variantMap) or modified
        elif variantMethod in ["filter"]:
            modified = processVariantFilter(callNode, variantMap) or modified

    # reduce decidable subtrees
    if modified:
        for cld in node.children[:]:
            new_cld = reducer.ast_reduce(cld)
            node.replaceChild(cld, new_cld)

    return modified
Ejemplo n.º 17
0
        def checkNodeContext(node):
            context = 'interesting' # every context is interesting, mybe we get more specific
            #context = ''

            # filter out the occurrences like 'c' in a.b().c
            myFirst = node.getFirstChild(mandatory=False, ignoreComments=True)
            if not treeutil.checkFirstChainChild(myFirst): # see if myFirst is the first identifier in a chain
                context = ''

            # filter out variable in lval position -- Nope! (qx.ui.form.ListItem.prototype.setValue = 
            # function(..){...};)
            #elif (node.hasParentContext("assignment/left")):
            #    context = ''

            # fitler out a.b[c] -- Nope! E.g. foo.ISO_8601_FORMAT might carry further dependencies
            # (like 'new qx.util.format.DateFormat("yyyy-MM-dd")')
            elif (treeutil.selectNode(node, "accessor")):
                context = 'accessor'

            # check name in 'new ...' position
            elif (node.hasParentContext("instantiation/*/*/operand")):
                context = 'new'

            # check name in call position
            elif (node.hasParentContext("call/operand")):
                context = 'call'

            # check name in "'extend' : ..." position
            elif (node.hasParentContext("keyvalue/*") and node.parent.parent.get('key') in ['extend']): #, 'include']):
                #print "-- found context: %s" % node.parent.parent.get('key')
                context = 'extend'

            return context
def patch(tree, classObj, featureMap):
    
    # change this to 'False' if you want logging instead of function removal
    prune_dont_log = True

    feature_names = featureMap[classObj.id]
    # get class map
    qxDefine = treeutil.findQxDefine(tree)
    classMap = treeutil.getClassMap(qxDefine)
    # go through features in 'members' and 'statics'
    for section in ("statics", "members"):
        if section in classMap:
            for feature, node in classMap[section].items():
                # skip registered and used keys
                if feature in feature_names and feature_names[feature].hasref():
                    continue
                else:
                    parent = node.parent
                    assert parent.type == "keyvalue"
                    #print "static optimizing: %s#%s" % (classObj.id, feature)
                    if prune_dont_log:
                        # remove sub tree
                        parent.parent.removeChild(parent)  # remove the entire feature from the map
                        # remove from featureMap
                        if feature in feature_names:
                            del featureMap[classObj.id][feature]
                        # decrease the ref counts of the contained dependees
                        decrementFromCode(classObj, node, featureMap)
                    else:
                        # OR: only add runtime logging to functions
                        block = treeutil.selectNode(node, 'function/body/block/statements')
                        if block:
                            LogStmt = treegenerator.parse("console.warn('Static optimization would have removed: " + classObj.id + '#' + feature + "');")
                            block.addChild(LogStmt, 0)
Ejemplo n.º 19
0
    def visit(self, scopeNode):
        # go through globals
        for name, scopeVar in scopeNode.globals().iteritems():
            # name might be as little as 'qx'
            for node in scopeVar.occurrences():
                # assemble var
                var_node = treeutil.findVarRoot(node)
                var_name = var_node.toJS(
                    None)  # e.g. "qx.util.ResourceManager.getInstance"
                if var_name in lang.QX_CLASS_FACTORIES:  # capture qx.*.define() calls
                    succ, class_name, _ = treeutil.isQxDefine(var_node)
                    if succ and class_name:
                        self.new_qx_classes.append(class_name)
                # lookup in globals_map
                sKnown_global = self.globals_map.longest_match(
                    var_name)  # -> "qx.util.ResourceManager"
                if sKnown_global:
                    sReplacement = self.globals_map[sKnown_global]
                    # find node in tree
                    dot_number = sKnown_global.count(".")
                    uptimes = u'/'.join(['..'] * dot_number)
                    source_node = treeutil.selectNode(
                        node, uptimes) if uptimes else node
                    # construct replacement
                    repl_node = treegenerator.parse(
                        sReplacement,
                        expr=True)  # could be "foo.bar" or "qx.$g['bNq']"
                    # replace known symbol in tree
                    source_node.parent.replaceChild(source_node, repl_node)
                    # update scopeVar.occurrences??!!

        for child in scopeNode.children:
            self.visit(child)
Ejemplo n.º 20
0
    def visit(self, scopeNode):
        # go through globals
        for name,scopeVar in scopeNode.globals().iteritems():
            # name might be as little as 'qx'
            for node in scopeVar.occurrences():
                # assemble var
                var_node = treeutil.findVarRoot(node)
                var_name = var_node.toJS(None) # e.g. "qx.util.ResourceManager.getInstance"
                if var_name in lang.QX_CLASS_FACTORIES: # capture qx.*.define() calls
                    succ, class_name, _ = treeutil.isQxDefine(var_node)
                    if succ and class_name: self.new_qx_classes.append(class_name)
                # lookup in globals_map
                sKnown_global = self.globals_map.longest_match(var_name)  # -> "qx.util.ResourceManager"
                if sKnown_global:
                    sReplacement = self.globals_map[sKnown_global]
                    # find node in tree
                    dot_number = sKnown_global.count(".")
                    uptimes = u'/'.join(['..'] * dot_number)
                    source_node = treeutil.selectNode(node, uptimes) if uptimes else node
                    # construct replacement
                    repl_node = treegenerator.parse(sReplacement, expr=True)  # could be "foo.bar" or "qx.$g['bNq']"
                    # replace known symbol in tree
                    source_node.parent.replaceChild(source_node, repl_node)
                    # update scopeVar.occurrences??!!

        for child in scopeNode.children:
            self.visit(child)
Ejemplo n.º 21
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 '{}'"
             )
Ejemplo n.º 22
0
def getClassVariantsFromTree(node, console):
    classvariants = set([])
    # mostly taken from ecmascript.transform.optimizer.variantoptimizer
    variants = treeutil.findVariablePrefix(node, "qx.core.Variant")
    for variant in variants:
        if not variant.hasParentContext("call/operand"):
            continue
        variantMethod = treeutil.selectNode(variant, "identifier[4]/@name")
        if variantMethod not in ["select", "isSet", "compilerIsSet"]:
            continue
        firstParam = treeutil.selectNode(variant, "../../params/1")
        if firstParam and treeutil.isStringLiteral(firstParam):
            classvariants.add(firstParam.get("value"))
        else:
            console.warn("! qx.core.Variant call without literal argument")

    return classvariants
Ejemplo n.º 23
0
def findVariantNodes(node):
    for callnode in list(
        treeutil.nodeIterator(node, ["call"])
    ):  # enforce eagerness so nodes that are moved are still handled
        if isEnvironmentCall(callnode):
            yield treeutil.selectNode(callnode, "operand").getFirstChild()
        else:
            continue
Ejemplo n.º 24
0
 def checkRequiredBlocks(self):
     for node in nodeIterator(self.tree, "loop"):
         block = treeutil.selectNode(node, "statement/block")
         if not block:
             self.log(
                 node,
                 "The statement of loops and conditions must be enclosed by a block in braces '{}'"
             )
Ejemplo n.º 25
0
 def _getExceptionVariables(self):
     assert self.node.type == "catch"
     identifier = treeutil.selectNode(self.node, "params/identifier")
     assert identifier and identifier.type == "identifier", "Unable to retrieve 'catch' parameter"
     return [
         VariableDefinition(identifier.get("value", ""), identifier, False,
                            self)
     ]
Ejemplo n.º 26
0
def optimizeConstruct(node, superClass, methodName, classDefNodes):
    patchCount = 0

    # Need to run through all the nodes, to skip embedded qx.*.define(),
    # which will be treated separately

    # Handle Node

    # skip embedded qx.*.define()
    if node in classDefNodes:
        return 0

    elif node.type == "variable" and node.hasParentContext("call/operand"):

        varName, complete = treeutil.assembleVariable(node)
        if not (complete and varName == "this.base"):
            return 0

        call = node.parent.parent

        try:
            firstArgName = treeutil.selectNode(call, "params/1/identifier/@name")
        except tree.NodeAccessException:
            return 0

        if firstArgName != "arguments":
            return 0

        # "construct"
        if methodName == "construct":
            newCall = treeutil.compileString("%s.call()" % superClass)
        # "member"
        else:
            newCall = treeutil.compileString("%s.prototype.%s.call()" % (superClass, methodName))
        newCall.replaceChild(newCall.getChild("params"), call.getChild("params"))  # replace with old arglist
        treeutil.selectNode(newCall, "params/1/identifier").set("name", "this")  # arguments -> this
        call.parent.replaceChild(call, newCall)
        patchCount += 1

    # Handle Children
    if node.hasChildren():
        for child in node.children:
            patchCount += optimizeConstruct(child, superClass, methodName, classDefNodes)

    return patchCount
Ejemplo n.º 27
0
 def checkDeferNode(self, assembled, node):
     deferNode = None
     if assembled in lang.QX_CLASS_FACTORIES:
         if node.hasParentContext("call/operand"):
             deferNode = treeutil.selectNode(
                 node,
                 "../../arguments/2/keyvalue[@key='defer']/value/function/body/block"
             )
     return deferNode
Ejemplo n.º 28
0
 def checkDeferNode(self, assembled, node):
     deferNode = None
     if assembled == "qx.Class.define" or assembled == "qx.Bootstrap.define" or assembled == "q.define":
         if node.hasParentContext("call/operand"):
             deferNode = treeutil.selectNode(
                 node,
                 "../../arguments/2/keyvalue[@key='defer']/value/function/body/block"
             )
     return deferNode
Ejemplo n.º 29
0
def findVariantNodes(node):
    for callnode in list(treeutil.nodeIterator(
            node,
        ['call'
         ])):  # enforce eagerness so nodes that are moved are still handled
        if isEnvironmentCall(callnode):
            yield treeutil.selectNode(callnode, "operand").getFirstChild()
        else:
            continue
Ejemplo n.º 30
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
Ejemplo n.º 31
0
 def environment_check_calls(self, node):
     for env_call in variantoptimizer.findVariantNodes(node):
         variantMethod = env_call.toJS(treegenerator.PackerFlags).rsplit('.',1)[1]
         callNode = treeutil.selectNode(env_call, "../..")
         if variantMethod in ["select"]:
             self.environment_check_select(callNode)
         elif variantMethod in ["get"]:
             self.environment_check_get(callNode)
         elif variantMethod in ["filter"]:
             self.environment_check_filter(callNode)
Ejemplo n.º 32
0
def patch(node):
    patchCount = 0

    this_base_vars = treeutil.findVariable(node, "this.base")
    for var in this_base_vars:
        if var.parent.type == "operand" and var.parent.parent.type == "call":
            call = var.parent.parent
            try:
                firstArgName = treeutil.selectNode(
                    call, "params/1/identifier/@name")
            except tree.NodeAccessException:
                continue

            if firstArgName != "arguments":
                continue

            newCall = treeutil.compileString(
                "arguments.callee.base.call(this)")
            newCall.replaceChild(newCall.getChild("params"),
                                 call.getChild("params"))
            treeutil.selectNode(newCall,
                                "params/1/identifier").set("name", "this")
            call.parent.replaceChild(call, newCall)
            patchCount += 1

    this_self_vars = treeutil.findVariable(node, "this.self")
    for var in this_self_vars:
        if var.parent.type == "operand" and var.parent.parent.type == "call":
            call = var.parent.parent
            try:
                firstArgName = treeutil.selectNode(
                    call, "params/1/identifier/@name")
            except tree.NodeAccessException:
                continue

            if firstArgName != "arguments":
                continue

            newCall = treeutil.compileString("arguments.callee.self")
            call.parent.replaceChild(call, newCall)
            patchCount += 1

    return patchCount
Ejemplo n.º 33
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
Ejemplo n.º 34
0
 def _variantsFromTree(self, node):
     console = self.context['console']
     classvariants = set([])
     for variantNode in variantoptimizer.findVariantNodes(node):
         firstParam = treeutil.selectNode(variantNode, "../../params/1")
         if firstParam and treeutil.isStringLiteral(firstParam):
             classvariants.add(firstParam.get("value"))
         else:
             console.warn("qx.core.Environment call without literal argument (%s:%s)" % (self.id, variantNode.get("line", False)))
     return classvariants
Ejemplo n.º 35
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
Ejemplo n.º 36
0
 def environment_check_calls(self, node):
     for env_call in variantoptimizer.findVariantNodes(node):
         variantMethod = env_call.toJS(treegenerator.PackerFlags).rsplit('.',1)[1]
         callNode = treeutil.selectNode(env_call, "../..")
         if variantMethod in ["select"]:
             self.environment_check_select(callNode)
         elif variantMethod in ["get"]:
             self.environment_check_get(callNode)
         elif variantMethod in ["filter"]:
             self.environment_check_filter(callNode)
Ejemplo n.º 37
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
Ejemplo n.º 38
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
Ejemplo n.º 39
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
Ejemplo n.º 40
0
    def createEnvKeyProviderIndex(self, classesAll):
        envProviders = {}
        providingEnvClasses = [className for className in classesAll.keys() if className.startswith("qx.bom.client")]
        for className in providingEnvClasses:
            tree = classesAll[className].tree()
            for callnode in list(treeutil.nodeIterator(tree, ['call'])):
                if callnode.toJS(pp).startswith("qx.core.Environment.add"):
                    envKey = treeutil.selectNode(callnode, "arguments/constant/@value")
                    envProviders[envKey] = className

        return envProviders
def findVariantNodes(node):
    variantNodes = treeutil.findVariablePrefix(node, "qx.core.Variant")
    variantNodes.extend(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 not in ["select", "isSet", "compilerIsSet", "get"]:
            continue
        else:
            yield variantNode
Ejemplo n.º 42
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))
Ejemplo n.º 43
0
    def checkFields(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)
        if not classMap.has_key("members"):
            return

        members = treeutil.mapNodeToMap(classMap["members"].children[0])
        restricted = [key for key in members if key.startswith("_")]

        assignNodes = [node for node in treeutil.nodeIterator(classMap["members"], "assignment")]
        if classMap.has_key("construct"):
            for node in treeutil.nodeIterator(classMap["construct"], "assignment"):
                assignNodes.append(node)

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

            field = treeutil.selectNode(node, "left/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)
            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))
Ejemplo n.º 44
0
def findVariantNodes(node):
    variantNodes = treeutil.findVariablePrefix(node, "qx.core.Variant")
    variantNodes.extend(
        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 not in ["select", "isSet", "compilerIsSet", "get"]:
            continue
        else:
            yield variantNode
Ejemplo n.º 45
0
 def checkDeferNode(self, assembled, node):
     deferNode = None
     if (
         assembled == "qx.Class.define"
         or assembled == "qx.Bootstrap.define"
         or assembled == "q.define"
         or assembled == "qxWeb.define"
     ):
         if node.hasParentContext("call/operand"):
             deferNode = treeutil.selectNode(
                 node, "../../arguments/2/keyvalue[@key='defer']/value/function/body/block"
             )
     return deferNode
Ejemplo n.º 46
0
def patch(node):
    patchCount = 0

    this_base_vars = treeutil.findVariable(node, "this.base")
    for var in this_base_vars:
        if var.parent.type == "operand" and var.parent.parent.type == "call":
            call = var.parent.parent
            try:
                firstArgName = treeutil.selectNode(call, "params/1/identifier/@name")
            except tree.NodeAccessException:
                continue

            if firstArgName != "arguments":
                continue

            newCall = treeutil.compileString("arguments.callee.base.call(this)")
            newCall.replaceChild(newCall.getChild("params"), call.getChild("params"))
            treeutil.selectNode(newCall, "params/1/identifier").set("name", "this")
            call.parent.replaceChild(call, newCall)
            patchCount += 1

    this_self_vars = treeutil.findVariable(node, "this.self")
    for var in this_self_vars:
        if var.parent.type == "operand" and var.parent.parent.type == "call":
            call = var.parent.parent
            try:
                firstArgName = treeutil.selectNode(call, "params/1/identifier/@name")
            except tree.NodeAccessException:
                continue

            if firstArgName != "arguments":
                continue

            newCall = treeutil.compileString("arguments.callee.self")
            call.parent.replaceChild(call, newCall)
            patchCount += 1

    return patchCount
Ejemplo n.º 47
0
 def _variantsFromTree(self, node):
     console = self.context['console']
     classvariants = set()
     for variantNode in variantoptimizer.findVariantNodes(node):
         firstParam = treeutil.selectNode(variantNode, "../../params/1")
         if firstParam:
             if treeutil.isStringLiteral(firstParam):
                 classvariants.add(firstParam.get("value"))
             elif firstParam.type == "map": # e.g. .filter() method
                 mapMap = treeutil.mapNodeToMap(firstParam)
                 classvariants.update(mapMap.keys())
             else:
                 console.warn("qx.core.Environment call with alien first argument (%s:%s)" % (self.id, variantNode.get("line", False)))
     return classvariants
Ejemplo n.º 48
0
def isEnvironmentCall(callNode):
    if callNode.type != "call":
        return False
    operandNode = treeutil.selectNode(callNode, "operand")
    operand = operandNode.toJS(pp)
    environParts = operand.rsplit(".", 1)
    if len(environParts) != 2:
        return False
    elif environParts[0] not in InterestingEnvClasses:
        return False
    elif environParts[1] not in InterestingEnvMethods:
        return False
    else:
        return operand
Ejemplo n.º 49
0
def isEnvironmentCall(callNode):
    if callNode.type != "call":
        return False
    operandNode = treeutil.selectNode(callNode, "operand")
    operand = operandNode.toJS(pp)
    environParts = operand.rsplit('.', 1)
    if len(environParts) != 2:
        return False
    elif environParts[0] not in InterestingEnvClasses:
        return False
    elif environParts[1] not in InterestingEnvMethods:
        return False
    else:
        return operand
Ejemplo n.º 50
0
 def extractChecksMap(self):
     tree = self.tree()
     checksMap = None
     for node in treeutil.nodeIterator(tree, "keyvalue"):
         if node.get("key", "") == "_checksMap":
             checksMap = node
             break
     assert checksMap
     assert checksMap.hasParentContext("keyvalue/value/map")  # 'statics/_checksMap'
     checksMap = treeutil.selectNode(checksMap, "value/map")
     checksMap = treeutil.mapNodeToMap(checksMap)
     # stringify map values
     for key in checksMap:
         checksMap[key] = checksMap[key].children[0].get("value")
     return checksMap
Ejemplo n.º 51
0
    def createEnvKeyProviderIndex(self, classesAll):
        envProviders = {}
        providingEnvClasses = [
            className for className in classesAll.keys()
            if className.startswith("qx.bom.client")
        ]
        for className in providingEnvClasses:
            tree = classesAll[className].tree()
            for callnode in list(treeutil.nodeIterator(tree, ['call'])):
                if callnode.toJS(pp).startswith("qx.core.Environment.add"):
                    envKey = treeutil.selectNode(callnode,
                                                 "arguments/constant/@value")
                    envProviders[envKey] = className

        return envProviders
Ejemplo n.º 52
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
Ejemplo n.º 53
0
 def visit_call(self, node):
     #print "visiting", node.type
     if variantoptimizer.isEnvironmentCall(node):
         assert self.opts.envmappings
         key = treeutil.selectNode(node, "arguments/1")
         classname, methname = self.getClassNameFromEnvKey(key, self.opts.envmappings)
         if classname:
             depsItem = DependencyItem(classname, methname, self.file_name, 
                                       node.get('line',0) or -1)
             depsItem.isCall = True  # treat as if actual call, to collect recursive deps
             # check phase
             functor = node.getChild("operand")  # get the "qx.core.Environment" symbol
             if self.is_static_loaddep(functor):
                 depsItem.isLoadDep = True
                 depsItem.needsRecursion = True
             self.deps.append(depsItem)
Ejemplo n.º 54
0
Archivo: Scope.py Proyecto: lite/empweb
    def usedVariablesIterator(node):

        # Switch on node context:
        # "function", "catch":
        if node.type in ["function", "catch"]:
            return

        # "catch": skip the identifier of catch clauses, e.g. the 'e' in 'catch(e)'
        # (it belongs to the catch scope)
        if node.parent and node.parent.type == "catch" and node == node.parent.children[
                0]:
            return

        # "for-in": treat variables used in for-in loops as used variables (why?)
        # (undeclared variables are handled by the normal "identifier" rule
        # further down)
        if (node.type == "first" and node.parent.type == "operation"
                and node.parent.get("operator") == "IN"):
            use = treeutil.selectNode(node, "var/definition/identifier")
            if use:
                name = use.get("value", False)
                yield (name, use)
                return

        # "identifier":
        if node.type == "identifier":
            isFirstChild = False
            isVariableMember = False

            if node.parent.parent.isVar(
            ):  # (the old code added "accessor" for the types to check)
                isVariableMember = True
                isFirstChild = treeutil.checkFirstChainChild(node)

            # inside a variable only respect the first member
            if not isVariableMember or isFirstChild:
                name = node.get("value", False)
                if name:
                    yield (name, node)

        # -- Recurse over children
        if node.children:
            for child in node.children:
                for (name, use) in Scope.usedVariablesIterator(child):
                    yield (name, use)

        return
Ejemplo n.º 55
0
def collectCalls(node, calls):
    if node.hasChildren():
        for child in node.children:
            collectCalls(child, calls)

    # looking out for classic function calls like
    # this.foo() or obj.hello(). Interesting here are
    # all methods which are called on "this".
    if node.type == "call":
        var = treeutil.selectNode(node, "operand/variable")
        if var:
            name = detectCallName(var)
            if name:
                if name in calls:
                    calls[name].append(node)
                else:
                    calls[name] = [node]
Ejemplo n.º 56
0
def collectCalls(node, calls):
    if node.hasChildren():
        for child in node.children:
            collectCalls(child, calls)    
            
    # looking out for classic function calls like
    # this.foo() or obj.hello(). Interesting here are
    # all methods which are called on "this".
    if node.type == "call":
        var = treeutil.selectNode(node, "operand/variable")
        if var:
            name = detectCallName(var)
            if name:
                if name in calls:
                    calls[name].append(node)
                else:
                    calls[name] = [node]
Ejemplo n.º 57
0
    def _analyzeClassDepsNode(self, fileId, node, loadtime, runtime,
                              inFunction):
        if node.type == "variable":
            assembled = (treeutil.assembleVariable(node))[0]

            # treat dependencies in defer as requires
            if assembled == "qx.Class.define" or assembled == "qx.Bootstrap.define":
                if node.parent.type == "operand" and node.parent.parent.type == "call":
                    deferNode = treeutil.selectNode(
                        node,
                        "../../params/2/keyvalue[@key='defer']/value/function/body/block"
                    )
                    if deferNode != None:
                        self._analyzeClassDepsNode(fileId, deferNode, loadtime,
                                                   runtime, False)

            # try to reduce to a class name
            assembledId = None
            if self._classes.has_key(assembled):
                assembledId = assembled

            elif "." in assembled:
                for entryId in self._classes:
                    if assembled.startswith(entryId) and re.match(
                            "%s\W" % entryId, assembled):
                        assembledId = entryId
                        break

            if assembledId and assembledId != fileId and self._classes.has_key(
                    assembledId):
                if inFunction:
                    target = runtime
                else:
                    target = loadtime

                if not assembledId in target:
                    target.append(assembledId)

        elif node.type == "body" and node.parent.type == "function":
            inFunction = True

        if node.hasChildren():
            for child in node.children:
                self._analyzeClassDepsNode(fileId, child, loadtime, runtime,
                                           inFunction)
Ejemplo n.º 58
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):
        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
Ejemplo n.º 59
0
def detectDeps(node, optionalDeps, loadtimeDeps, runtimeDeps, fileId, fileDb, inFunction):
    if node.type == "variable":
        if node.hasChildren:
            assembled = ""
            first = True

            for child in node.children:
                if child.type == "identifier":
                    if not first:
                        assembled += "."

                    assembled += child.get("name")
                    first = False

                    if assembled != fileId and fileDb.has_key(assembled) and not assembled in optionalDeps:
                        if inFunction:
                            targetDeps = runtimeDeps
                        else:
                            targetDeps = loadtimeDeps

                        if assembled in targetDeps:
                            return

                        targetDeps.append(assembled)

                else:
                    assembled = ""
                    break

                # treat dependencies in defer as requires
                if assembled == "qx.Class.define" or assembled == "qx.Bootstrap.define":
                    if node.parent.type == "operand" and node.parent.parent.type == "call":
                        deferNode = treeutil.selectNode(
                            node, "../../params/2/keyvalue[@key='defer']/value/function/body/block"
                        )
                        if deferNode != None:
                            detectDeps(deferNode, optionalDeps, loadtimeDeps, runtimeDeps, fileId, fileDb, False)

    elif node.type == "body" and node.parent.type == "function":
        inFunction = True

    if node.hasChildren():
        for child in node.children:
            detectDeps(child, optionalDeps, loadtimeDeps, runtimeDeps, fileId, fileDb, inFunction)