def enter_ClassDef(self, node): class_name = node_utils.get_name(node, self._ast) last_line = max(node.lineno, node.body[0].lineno - 1) # Python2 ops = match_opcodes_multiline(self.traces, node.lineno, last_line, [("BUILD_CLASS", class_name)]) d = None if ops: _, _, data = ops[0] d = _unwrap(data) else: # Python3 ops = match_opcodes_multiline(self.traces, node.lineno, last_line, [("LOAD_BUILD_CLASS", None), ("STORE_NAME", class_name)]) if len(ops) == 2: _, _, data = ops[1] d = _unwrap(data) assert d, "Did not get pytype data for class %s" % class_name defn = self.add_local_def(node, data=data, doc=DocString.from_node(self._ast, node)) self.classmap[d[0]] = defn super(IndexVisitor, self).enter_ClassDef(node)
def enter_ClassDef(self, node): class_name = node_utils.get_name(node, self._ast) last_line = max(node.lineno, node.body[0].lineno - 1) # Python2 ops = match_opcodes_multiline(self.traces, node.lineno, last_line, [("BUILD_CLASS", class_name)]) d = None if ops: _, _, data = ops[0] d = _unwrap(data) else: # Python3 ops = match_opcodes_multiline( self.traces, node.lineno, last_line, [ ("LOAD_BUILD_CLASS", None), ("STORE_NAME", class_name), # Classes defined within a function generate a STORE_FAST op. ("STORE_FAST", class_name), ]) # pytype sometimes analyses this twice, leading to duplicate opcode # traces. We only want the first two in the list. if (len(ops) >= 2 and ops[0][0] == "LOAD_BUILD_CLASS" and ops[1][0] in ("STORE_NAME", "STORE_FAST")): _, _, data = ops[1] d = _unwrap(data) assert d, "Did not get pytype data for class %s" % class_name defn = self.add_local_def(node, data=data, doc=DocString.from_node(self._ast, node)) self.classmap[d[0]] = defn super(IndexVisitor, self).enter_ClassDef(node)
def enter_ClassDef(self, node): class_name = node_utils.get_name(node, self._ast) last_line = max(node.lineno, node.body[0].lineno - 1) ops = match_opcodes_multiline( self.traces, node.lineno, last_line, [ ("LOAD_BUILD_CLASS", None), ("STORE_NAME", class_name), # Classes defined within a function generate a STORE_FAST or # STORE_DEREF op. ("STORE_FAST", class_name), ("STORE_DEREF", class_name), # A class being declared global anywhere generates a STORE_GLOBAL op. ("STORE_GLOBAL", class_name), ]) # pytype sometimes analyses this twice, leading to duplicate opcode # traces. We only want the first two in the list. if (len(ops) >= 2 and ops[0][0] == "LOAD_BUILD_CLASS" and ops[1][0] in ("STORE_NAME", "STORE_FAST", "STORE_DEREF", "STORE_GLOBAL")): _, _, data = ops[1] d = _unwrap(data) assert d, "Did not get pytype data for class %s at line %d" % ( class_name, node.lineno) defn = self.add_local_def(node, data=data, doc=DocString.from_node(self._ast, node)) self.classmap[d[0]] = defn super().enter_ClassDef(node)
def make_ref(self, node, **kwargs): """Make a reference from a node.""" assert "data" in kwargs # required kwarg args = { "name": node_utils.get_name(node, self._ast), "scope": self.scope_id(), "ref_scope": None, "typ": node_utils.typename(node), "location": get_location(node), "target": None, } args.update(kwargs) return Reference(**args)
def add_closure_ref(self, node, **kwargs): """Look for node.name up the chain of scopes.""" name = node_utils.get_name(node, self._ast) env, _ = self.current_env.lookup(name) if env: kwargs.update({"ref_scope": env.scope}) else: # This should never happen! If python has generated a LOAD_DEREF bytecode # then we do have the name defined in a parent scope. However, in the # interests of not crashing the indexer, fall back to the current scope. # TODO(mdemello): We need error logs. pass ref = self.make_ref(node, **kwargs) self.refs.append(ref) return ref
def make_def(self, node, **kwargs): """Make a definition from a node.""" if isinstance(node, self._ast.Name): t = node_utils.typename(node.ctx) elif isinstance(node, self._ast.arg): t = "Param" else: t = node_utils.typename(node) args = { "name": node_utils.get_name(node, self._ast), "scope": self.scope_id(), "typ": t, "data": None, "target": None, "doc": None, } args.update(kwargs) defn = Definition(**args) line, col = self._get_location(node, args) assert line is not None defloc = DefLocation(defn.id, source.Location(line, col)) return (defn, defloc)