A semantic search engine for source code https://bitshift.benkurtovic.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

94 rivejä
2.9 KiB

  1. import ast
  2. def _serialize(tree):
  3. """
  4. Private function to serialize an abstract syntax tree so it is indexable by the database.
  5. :param tree: The syntax tree to be serialized.
  6. :type tree: list or ast.AST
  7. """
  8. def _start_n_end(big_node):
  9. """
  10. Helper function to get the start and end lines of a code node.
  11. :param big_node: The node.
  12. :type big_node: ast.FunctionDef, ast.ClassDef, ast.Module
  13. """
  14. start_line = big_node.lineno
  15. temp_node = big_node
  16. while 'body' in temp_node.__dict__:
  17. temp_node = temp_node.body[-1]
  18. end_line = temp_node.lineno
  19. return (start_line, end_line)
  20. def _helper(cur_node, accum):
  21. """
  22. Helper function for _serialize which recursively updates the 'vars', 'functions', and 'classes' in the parsed version of the tree.
  23. :param cur_node: The node in the syntax tree currently being parsed.
  24. :param accum: Dicitonary holding parsed version of the tree.
  25. :type cur_node: list or ast.AST
  26. :type accum: dict
  27. """
  28. if isinstance(cur_node, list):
  29. for node in cur_node:
  30. _helper(node, accum)
  31. elif isinstance(cur_node, ast.Assign):
  32. # return name
  33. # return col and line offset
  34. # in the future add value and type metadata
  35. for t in cur_node.targets:
  36. if isinstance(t, ast.Tuple):
  37. for n in t.elts:
  38. line, col = n.lineno, n.col_offset
  39. accum['vars'][n.id] = {'ln': line, 'col': col}
  40. else:
  41. line, col = t.lineno, t.col_offset
  42. accum['vars'][t.id] = {'ln': line, 'col': col}
  43. elif isinstance(cur_node, ast.FunctionDef):
  44. # return name
  45. # return start and end of the function
  46. # in the future add arguments and decorators metadata
  47. start_line, end_line = _start_n_end(cur_node)
  48. accum['functions'][cur_node.name] = {'start_ln': start_line , 'end_ln': end_line}
  49. elif isinstance(cur_node, ast.ClassDef):
  50. # return name
  51. # return start and end of the class
  52. # in the future add arguments, inherits, and decorators metadata
  53. start_line, end_line = _start_n_end(cur_node)
  54. accum['classes'][cur_node.name] = {'start_ln': start_line , 'end_ln': end_line}
  55. elif isinstance(cur_node, ast.AST):
  56. for k in cur_node.__dict__.keys():
  57. node = node.__dict__[k]
  58. _helper(node, accum)
  59. accum = {}
  60. _helper(tree, accum)
  61. return accum
  62. def parse_py(codelet):
  63. """
  64. Adds 'symbols' field to the codelet after parsing the code.
  65. :param codelet: The codelet object to parsed.
  66. :type code: Codelet
  67. """
  68. tree = ast.parse(codelet.code)
  69. symbols = _serialize(tree)
  70. codelet.symbols = symbols
  71. print symbols