def METHOD_NAME(out, file, extra_args, break_on):
	args = extra_args + ["-Isrc"]
	if file.endswith(".c"):
		header = f"{file[:-2]}.h"
	elif file.endswith(".cpp"):
		header = f"{file[:-4]}.h"
	else:
		raise ValueError(f"unrecognized source file: {file}")
	index = clang.cindex.Index.create()
	unit = index.parse(file, args=args)
	errors = list(unit.diagnostics)
	if errors:
		for error in errors:
			print(f"{file}: {error.format()}", file=sys.stderr)
		print(args, file=sys.stderr)
		raise ParseError(f"failed parsing {file}")
	filter_files = frozenset([file, header])
	for namespace, node in traverse_namespaced(unit.cursor, filter_files=filter_files):
		cur_file = None
		if node.location.file is not None:
			cur_file = node.location.file.name
		if cur_file is None or cur_file not in (file, header):
			continue
		if node.kind in INTERESTING_NODE_KINDS and node.spelling:
			typ = get_complex_type(node.type)
			qualifiers = ""
			if INTERESTING_NODE_KINDS[node.kind] in {"variable", "function"}:
				is_member = node.semantic_parent.kind in {CursorKind.CLASS_DECL, CursorKind.CLASS_TEMPLATE, CursorKind.STRUCT_DECL, CursorKind.UNION_DECL}
				is_static = node.storage_class == StorageClass.STATIC or is_static_member_definition_hack(node)
				if is_static:
					qualifiers = "s" + qualifiers
				if is_member:
					qualifiers = "m" + qualifiers
				if is_static and not is_member and is_const(node.type):
					qualifiers = "c" + qualifiers
				if node.linkage == LinkageKind.EXTERNAL and not is_member:
					qualifiers = "g" + qualifiers
			out.writerow({
				"file": cur_file,
				"line": node.location.line,
				"column": node.location.column,
				"kind": INTERESTING_NODE_KINDS[node.kind],
				"path": "::".join(namespace),
				"qualifiers": qualifiers,
				"type": typ,
				"name": node.spelling,
			})
			if node.spelling == break_on:
				breakpoint() # pylint: disable=forgotten-debug-statement