def _analyzeClassDepsNode_1(self, node, depsList, inLoadContext, inDefer=False):
        if node.type in ("file", "function", "catch"):
            top_scope = node.scope
        else:
            top_scope = scopes.find_enclosing(node)  # get enclosing scope of node
        # import pydb; pydb.debugger()
        for scope in top_scope.scope_iterator():  # walk through this and all nested scopes
            for global_name, scopeVar in scope.globals().items():  # get the global symbols { sym_name: ScopeVar }
                for node in scopeVar.uses:  # create a depsItem for all its uses
                    depsItem = self.qualify_deps_item(node, scope.is_load_time, scope.is_defer)
                    depsList.append(depsItem)  # and qualify them

        # Augment with feature dependencies introduces with qx.core.Environment.get("...") calls
        for envCall in variantoptimizer.findVariantNodes(node):
            className, classAttribute = self.getClassNameFromEnvKey(
                envCall.getChild("arguments").children[0].get("value", "")
            )
            if className:
                depsItem = DependencyItem(className, classAttribute, self.id, envCall.get("line", -1))
                depsItem.isCall = True  # treat as if actual call, to collect recursive deps
                # .inLoadContext
                # get 'qx' node of 'qx.core.Environment....'
                call_operand = envCall.getChild("operand").children[0]
                qx_idnode = treeutil.findFirstChainChild(call_operand)
                scope = qx_idnode.scope
                inLoadContext = scope.is_load_time  # get its scope's .is_load_time
                depsItem.isLoadDep = inLoadContext
                if inLoadContext:
                    depsItem.needsRecursion = True
                depsList.append(depsItem)

        return
Ejemplo n.º 2
0
 def dependencies_from_envcalls(self, node):
     depsList = []
     if 'qx.core.Environment' not in ClassesAll:
         self.context['console'].warn(
             "No qx.core.Environment available to extract feature keys from"
         )
         return depsList
     qcEnvClass = ClassesAll['qx.core.Environment']
     for env_operand in variantoptimizer.findVariantNodes(node):
         call_node = env_operand.parent.parent
         env_key = call_node.getChild("arguments").children[0].get(
             "value", "")
         className, classAttribute = qcEnvClass.classNameFromEnvKey(env_key)
         if className and className in ClassesAll:
             #print className
             depsItem = DependencyItem(className, classAttribute, self.id,
                                       env_operand.get('line', -1))
             depsItem.isCall = True  # treat as if actual call, to collect recursive deps
             depsItem.node = call_node
             # .inLoadContext
             qx_idnode = treeutil.findFirstChainChild(
                 env_operand)  # 'qx' node of 'qx.core.Environment....'
             scope = qx_idnode.scope
             depsItem.isLoadDep = scope.is_load_time
             if depsItem.isLoadDep:
                 depsItem.needsRecursion = True
             depsList.append(depsItem)
     return depsList
Ejemplo n.º 3
0
    def depsItem_from_node(self, node):
        scope = node.scope
        # some initializations (might get refined later)
        depsItem = DependencyItem('', '', '')
        depsItem.name           = ''
        depsItem.attribute      = ''
        depsItem.requestor      = self.id
        depsItem.line           = node.get("line", -1)
        depsItem.isLoadDep      = scope.is_load_time
        depsItem.needsRecursion = False
        depsItem.isCall         = False
        depsItem.node           = node
        var_root = treeutil.findVarRoot(node)  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if treeutil.isCallOperand(var_root): # it's a function call or new op.
            depsItem.isCall = True  # interesting when following transitive deps

        # .name, .attribute
        assembled = (treeutil.assembleVariable(node))[0]
        #className, classAttribute = self._splitQxClass(assembled)
        className = gs.test_for_libsymbol(assembled, ClassesAll, []) # TODO: no namespaces!?
        if not className: 
            is_lib_class = False
            className = assembled
            classAttribute = ''
        else:
            is_lib_class = True
            if len(assembled) > len(className):
                classAttribute = assembled[len(className)+1:]
            else:
                classAttribute = ''
        # we allow self-references, to be able to track method dependencies within the same class
        assembled_parts = assembled.split('.')
        if assembled_parts[0] == 'this':
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        elif scope.is_defer and assembled_parts[0] in DEFER_ARGS:
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        if is_lib_class and not classAttribute:  # see if we have to provide 'construct'
            if treeutil.isNEWoperand(var_root):
                classAttribute = 'construct'
        depsItem.name = className
        depsItem.attribute = classAttribute

        # .needsRecursion
        # Mark items that need recursive analysis of their dependencies (bug#1455)
        if (is_lib_class and
            scope.is_load_time and
            (treeutil.isCallOperand(var_root) or 
             treeutil.isNEWoperand(var_root))):
            depsItem.needsRecursion = True

        return depsItem
    def depsItem_from_node(self, node):
        scope = node.scope
        # some initializations (might get refined later)
        depsItem = DependencyItem('', '', '')
        depsItem.name           = ''
        depsItem.attribute      = ''
        depsItem.requestor      = self.id
        depsItem.line           = node.get("line", -1)
        depsItem.isLoadDep      = scope.is_load_time
        depsItem.needsRecursion = False
        depsItem.isCall         = False
        depsItem.node           = node
        is_lib_class             = False
        var_root = treeutil.findVarRoot(node)  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if treeutil.isCallOperand(var_root): # it's a function call or new op.
            depsItem.isCall = True  # interesting when following transitive deps

        # .name, .attribute
        assembled = (treeutil.assembleVariable(node))[0]
        className, classAttribute = self._splitQxClass(assembled)
        if not className: 
            if "." in assembled:
                className, classAttribute = assembled.split('.')[:2]
            else:
                className = assembled
        else:
            is_lib_class = True
        # we allow self-references, to be able to track method dependencies within the same class
        if self.is_this(className):
            if className.find('.')>-1:
                classAttribute = className.split('.')[1]
            className = self.id
            is_lib_class = True
        elif scope.is_defer and className in DEFER_ARGS:
            className = self.id
            is_lib_class = True
        if is_lib_class and not classAttribute:  # see if we have to provide 'construct'
            if treeutil.isNEWoperand(var_root):
                classAttribute = 'construct'
        depsItem.name = className
        depsItem.attribute = classAttribute

        # .needsRecursion
        # Mark items that need recursive analysis of their dependencies (bug#1455)
        #if self.followCallDeps(var_root, self.id, className, isLoadTime):
        #if self.id=='qx.bom.element.Style' and depsItem.attribute=='__detectVendorProperties':
        #    import pydb; pydb.debugger()
        if (is_lib_class and
            scope.is_load_time and
            (treeutil.isCallOperand(var_root) or 
             treeutil.isNEWoperand(var_root))):
            depsItem.needsRecursion = True

        return depsItem
Ejemplo n.º 5
0
 def depsItems_from_Json(self, deps_json):
     result = {'run':[], 'load':[], 'ignore':[]}
     for category in ('run', 'load'):
         for classId in deps_json[category]:
             if any([classId.startswith(x) for x in ('/resource/', '/translation/', '/locale/')]):
                 continue  # sorting out resource, locale and msgid dependencies
             depsItem = DependencyItem(classId, '', '|dependency.json|')
             depsItem.isLoadDep = category == 'load'
             result[category].append(depsItem)
     return result
Ejemplo n.º 6
0
 def depsItems_from_Json(self, deps_json):
     result = {'run':[], 'load':[], 'ignore':[]}
     for category in ('run', 'load'):
         for classId in deps_json[category]:
             if any([classId.startswith(x) for x in ('/resource/', '/translation/', '/locale/')]):
                 continue  # sorting out resource, locale and msgid dependencies
             depsItem = DependencyItem(classId, '', '|dependency.json|')
             depsItem.isLoadDep = category == 'load'
             result[category].append(depsItem)
     return result
Ejemplo n.º 7
0
 def depsItems_from_Json(self, deps_json):
     result = {"run": [], "load": [], "ignore": []}
     for category in ("run", "load"):
         for classId in deps_json[category]:
             if any([classId.startswith(x) for x in ("/resource/", "/translation/", "/locale/")]):
                 continue  # sorting out resource, locale and msgid dependencies
             depsItem = DependencyItem(classId, "", "|dependency.json|")
             depsItem.isLoadDep = category == "load"
             result[category].append(depsItem)
     return result
Ejemplo n.º 8
0
    def qualify_deps_item(self, node, isLoadTime, inDefer, depsItem=None):
        if not depsItem:
            depsItem = DependencyItem('', '', '')
        depsItem.name = ''
        depsItem.attribute = ''
        depsItem.requestor = self.id
        depsItem.line = node.get("line", -1)
        depsItem.isLoadDep = isLoadTime
        depsItem.needsRecursion = False
        depsItem.isCall = False
        var_root = treeutil.findVarRoot(
            node
        )  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if var_root.hasParentContext("call/operand"):  # it's a function call
            depsItem.isCall = True  # interesting when following transitive deps

        # .name
        assembled = (treeutil.assembleVariable(node))[0]
        _, className, classAttribute = self._isInterestingReference(
            assembled, var_root, self.id, inDefer)
        # postcond:
        # - className != '' must always be true, as we know it is an interesting reference
        # - might be a known qooxdoo class, or an unknown class (use 'className in self._classes')
        # - if assembled contained ".", classAttribute will contain approx. non-class part

        if className:
            # we allow self-references, to be able to track method dependencies within the same class
            if className == 'this':
                className = self.id
            elif inDefer and className in DEFER_ARGS:
                className = self.id
            if not classAttribute:  # see if we have to provide 'construct'
                if treeutil.isNEWoperand(node):
                    classAttribute = 'construct'
            # Can't do the next; it's catching too many occurrences of 'getInstance' that have
            # nothing to do with the singleton 'getInstance' method (just grep in the framework)
            #elif classAttribute == 'getInstance':  # erase 'getInstance' and introduce 'construct' dependency
            #    classAttribute = 'construct'
            depsItem.name = className
            depsItem.attribute = classAttribute

            # .needsRecursion
            # Mark items that need recursive analysis of their dependencies (bug#1455)
            if self.followCallDeps(var_root, self.id, className, isLoadTime):
                depsItem.needsRecursion = True

        if depsItem.name:
            return depsItem
        else:
            return None
Ejemplo n.º 9
0
    def qualify_deps_item(self, node, isLoadTime, inDefer, depsItem=None):
        if not depsItem:
            depsItem = DependencyItem('', '', '')
        depsItem.name = ''
        depsItem.attribute = ''
        depsItem.requestor = self.id
        depsItem.line = node.get("line", -1)
        depsItem.isLoadDep = isLoadTime
        depsItem.needsRecursion = False
        depsItem.isCall = False
        var_root = treeutil.findVarRoot(node)  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if var_root.hasParentContext("call/operand"): # it's a function call
            depsItem.isCall = True  # interesting when following transitive deps

        # .name
        assembled = (treeutil.assembleVariable(node))[0]
        _, className, classAttribute = self._isInterestingReference(assembled, var_root, self.id, inDefer)
        # postcond: 
        # - className != '' must always be true, as we know it is an interesting reference
        # - might be a known qooxdoo class, or an unknown class (use 'className in self._classes')
        # - if assembled contained ".", classAttribute will contain approx. non-class part

        if className:
            # we allow self-references, to be able to track method dependencies within the same class
            if className == 'this':
                className = self.id
            elif inDefer and className in DEFER_ARGS:
                className = self.id
            if not classAttribute:  # see if we have to provide 'construct'
                if treeutil.isNEWoperand(node):
                    classAttribute = 'construct'
            # Can't do the next; it's catching too many occurrences of 'getInstance' that have
            # nothing to do with the singleton 'getInstance' method (just grep in the framework)
            #elif classAttribute == 'getInstance':  # erase 'getInstance' and introduce 'construct' dependency
            #    classAttribute = 'construct'
            depsItem.name = className
            depsItem.attribute = classAttribute

            # .needsRecursion
            # Mark items that need recursive analysis of their dependencies (bug#1455)
            if self.followCallDeps(var_root, self.id, className, isLoadTime):
                depsItem.needsRecursion = True

        if depsItem.name:
            return depsItem
        else:
            return None
Ejemplo n.º 10
0
    def _analyzeClassDepsNode_2(self,
                                node,
                                depsList,
                                inLoadContext,
                                inDefer=False):
        if node.type in ('file', 'function', 'catch'):
            top_scope = node.scope
        else:
            top_scope = scopes.find_enclosing(
                node)  # get enclosing scope of node
        for scope in top_scope.scope_iterator(
        ):  # walk through this and all nested scopes
            for global_name, scopeVar in scope.globals().items(
            ):  # get the global symbols { sym_name: ScopeVar }
                for var_node in scopeVar.uses:  # create a depsItem for all its uses
                    if treeutil.hasAncestor(
                            var_node, node
                    ):  # var_node is not disconnected through optimization
                        depsItem = self.qualify_deps_item(
                            var_node, scope.is_load_time, scope.is_defer)
                        # as this also does filtering
                        if depsItem:
                            depsList.append(depsItem)  # and qualify them
                            #if depsItem.name == "qx.log.appender.Console":
                            #    import pydb; pydb.debugger()

        # Augment with feature dependencies introduces with qx.core.Environment.get("...") calls
        for env_operand in variantoptimizer.findVariantNodes(node):
            call_node = env_operand.parent.parent
            env_key = call_node.getChild("arguments").children[0].get(
                "value", "")
            className, classAttribute = self.getClassNameFromEnvKey(env_key)
            if className:
                #print className
                depsItem = DependencyItem(className, classAttribute, self.id,
                                          env_operand.get('line', -1))
                depsItem.isCall = True  # treat as if actual call, to collect recursive deps
                # .inLoadContext
                # get 'qx' node of 'qx.core.Environment....'
                qx_idnode = treeutil.findFirstChainChild(env_operand)
                scope = qx_idnode.scope
                inLoadContext = scope.is_load_time  # get its scope's .is_load_time
                depsItem.isLoadDep = inLoadContext
                if inLoadContext:
                    depsItem.needsRecursion = True
                depsList.append(depsItem)

        return
Ejemplo n.º 11
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.º 12
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)
 def dependencies_from_envcalls(self, node):
     depsList = []
     qcEnvClass = ClassesAll['qx.core.Environment']
     for env_operand in variantoptimizer.findVariantNodes(node):
         call_node = env_operand.parent.parent
         env_key = call_node.getChild("arguments").children[0].get("value", "")
         className, classAttribute = qcEnvClass.classNameFromEnvKey(env_key)
         if className and className in ClassesAll:
             #print className
             depsItem = DependencyItem(className, classAttribute, self.id, env_operand.get('line', -1))
             depsItem.isCall = True  # treat as if actual call, to collect recursive deps
             # .inLoadContext
             qx_idnode = treeutil.findFirstChainChild(env_operand) # 'qx' node of 'qx.core.Environment....'
             scope = qx_idnode.scope
             depsItem.isLoadDep = scope.is_load_time
             if depsItem.isLoadDep:
                 depsItem.needsRecursion = True
             depsList.append(depsItem)
     return depsList
Ejemplo n.º 14
0
    def dependencies_from_envcalls(self, node):

        depsList = []
        if 'qx.core.Environment' not in ClassesAll:
            self.context['console'].warn("No qx.core.Environment available to extract feature keys from")
            return depsList
        qcEnvClass = ClassesAll['qx.core.Environment']

        for env_operand in variantoptimizer.findVariantNodes(node):
            call_node = env_operand.parent.parent
            env_key = call_node.getChild("arguments").children[0].get("value", "")
            # Without qx.core.Environment._checksMap:
            # ---------------------------------------
            className = qcEnvClass.classNameFromEnvKeyByIndex(env_key)
            if className and className in ClassesAll:
                #print className
                depsItem = DependencyItem(className, "", self.id, env_operand.get('line', -1))
                depsItem.isCall = True  # treat as if actual call, to collect recursive deps
                depsItem.node = call_node
                # .inLoadContext
                qx_idnode = treeutil.findFirstChainChild(env_operand) # 'qx' node of 'qx.core.Environment....'
                scope = qx_idnode.scope
                depsItem.isLoadDep = scope.is_load_time
                if depsItem.isLoadDep:
                    depsItem.needsRecursion = True
                depsList.append(depsItem)
            # With qx.core.Environment._checksMap:
            # ------------------------------------
            # className, classAttribute = qcEnvClass.classNameFromEnvKey(env_key)
            # if className and className in ClassesAll:
            #     #print className
            #     depsItem = DependencyItem(className, classAttribute, self.id, env_operand.get('line', -1))
            #     depsItem.isCall = True  # treat as if actual call, to collect recursive deps
            #     depsItem.node = call_node
            #     # .inLoadContext
            #     qx_idnode = treeutil.findFirstChainChild(env_operand) # 'qx' node of 'qx.core.Environment....'
            #     scope = qx_idnode.scope
            #     depsItem.isLoadDep = scope.is_load_time
            #     if depsItem.isLoadDep:
            #         depsItem.needsRecursion = True
            #     depsList.append(depsItem)
        return depsList
Ejemplo n.º 15
0
    def _analyzeClassDepsNode_2(self, node, depsList, inLoadContext, inDefer=False):
        if node.type in ('file', 'function', 'catch'):
            top_scope = node.scope
        else:
            top_scope = scopes.find_enclosing(node)  # get enclosing scope of node
        for scope in top_scope.scope_iterator(): # walk through this and all nested scopes
            for global_name, scopeVar in scope.globals().items():  # get the global symbols { sym_name: ScopeVar }
                for var_node in scopeVar.uses:       # create a depsItem for all its uses
                    if treeutil.hasAncestor(var_node, node): # var_node is not disconnected through optimization
                        depsItem = self.qualify_deps_item(var_node, scope.is_load_time, scope.is_defer)
                        # as this also does filtering
                        if depsItem:
                            depsList.append(depsItem)    # and qualify them
                            #if depsItem.name == "qx.log.appender.Console":
                            #    import pydb; pydb.debugger()

        # Augment with feature dependencies introduces with qx.core.Environment.get("...") calls
        for env_operand in variantoptimizer.findVariantNodes(node):
            call_node = env_operand.parent.parent
            env_key = call_node.getChild("arguments").children[0].get("value", "")
            className, classAttribute = self.getClassNameFromEnvKey(env_key)
            if className:
                #print className
                depsItem = DependencyItem(className, classAttribute, self.id, env_operand.get('line', -1))
                depsItem.isCall = True  # treat as if actual call, to collect recursive deps
                # .inLoadContext
                # get 'qx' node of 'qx.core.Environment....'
                qx_idnode = treeutil.findFirstChainChild(env_operand)
                scope = qx_idnode.scope
                inLoadContext = scope.is_load_time # get its scope's .is_load_time
                depsItem.isLoadDep = inLoadContext
                if inLoadContext:
                    depsItem.needsRecursion = True
                depsList.append(depsItem)

        return
Ejemplo n.º 16
0
    def depsItem_from_node(self, node):
        scope = node.scope
        # some initializations (might get refined later)
        depsItem = DependencyItem('', '', '')
        depsItem.name           = ''
        depsItem.attribute      = ''
        depsItem.requestor      = self.id
        depsItem.line           = node.get("line", -1)
        depsItem.isLoadDep      = scope.is_load_time
        depsItem.needsRecursion = False
        depsItem.isCall         = False
        depsItem.node           = node
        var_root = treeutil.findVarRoot(node)  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if treeutil.isCallOperand(var_root): # it's a function call or new op.
            depsItem.isCall = True  # interesting when following transitive deps

        # .name, .attribute
        assembled = (treeutil.assembleVariable(node))[0]
        className = gs.test_for_libsymbol(assembled, ClassesAll, []) # TODO: no namespaces!?
        if not className:
            is_lib_class = False
            className = assembled
            classAttribute = ''
        else:
            is_lib_class = True
            if len(assembled) > len(className):
                classAttribute = assembled[len(className)+1:]
                dotidx = classAttribute.find(".") # see if classAttribute is chained too
                if dotidx > -1:
                    classAttribute = classAttribute[:dotidx]    # only use the first component
            else:
                classAttribute = ''
        # we allow self-references, to be able to track method dependencies within the same class
        assembled_parts = assembled.split('.')
        if assembled_parts[0] == 'this':
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        elif scope.is_defer and assembled_parts[0] in DEFER_ARGS:
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        if is_lib_class and not classAttribute:  # see if we have to provide 'construct'
            if treeutil.isNEWoperand(var_root):
                classAttribute = 'construct'
        depsItem.name = className
        depsItem.attribute = classAttribute

        # .needsRecursion
        # Mark items that need recursive analysis of their dependencies (bug#1455)
        if (is_lib_class and
            scope.is_load_time and
            (treeutil.isCallOperand(var_root) or
             treeutil.isNEWoperand(var_root))):
            depsItem.needsRecursion = True

        return depsItem
Ejemplo n.º 17
0
    def depsItem_from_node(self, node):
        scope = node.scope
        # some initializations (might get refined later)
        depsItem = DependencyItem('', '', '')
        depsItem.name = ''
        depsItem.attribute = ''
        depsItem.requestor = self.id
        depsItem.line = node.get("line", -1)
        depsItem.isLoadDep = scope.is_load_time
        depsItem.needsRecursion = False
        depsItem.isCall = False
        depsItem.node = node
        is_lib_class = False
        var_root = treeutil.findVarRoot(
            node
        )  # various of the tests need the var (dot) root, rather than the head symbol (like 'qx')

        # .isCall
        if treeutil.isCallOperand(var_root):  # it's a function call or new op.
            depsItem.isCall = True  # interesting when following transitive deps

        # .name, .attribute
        assembled = (treeutil.assembleVariable(node))[0]
        className, classAttribute = self._splitQxClass(assembled)
        assembled_parts = assembled.split('.')
        if not className:
            if "." in assembled:
                className = '.'.join(assembled_parts[:-1])
                classAttribute = assembled_parts[-1]
                #className, classAttribute = assembled.split('.')[:2]
            else:
                className = assembled
        else:
            is_lib_class = True
        # we allow self-references, to be able to track method dependencies within the same class
        if assembled_parts[0] == 'this':
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        elif scope.is_defer and assembled_parts[0] in DEFER_ARGS:
            className = self.id
            is_lib_class = True
            if '.' in assembled:
                classAttribute = assembled_parts[1]
        if is_lib_class and not classAttribute:  # see if we have to provide 'construct'
            if treeutil.isNEWoperand(var_root):
                classAttribute = 'construct'
        depsItem.name = className
        depsItem.attribute = classAttribute

        # .needsRecursion
        # Mark items that need recursive analysis of their dependencies (bug#1455)
        #if self.followCallDeps(var_root, self.id, className, isLoadTime):
        #if self.id=='qx.bom.element.Style' and depsItem.attribute=='__detectVendorProperties':
        #    import pydb; pydb.debugger()
        if (is_lib_class and scope.is_load_time
                and (treeutil.isCallOperand(var_root)
                     or treeutil.isNEWoperand(var_root))):
            depsItem.needsRecursion = True

        return depsItem