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.
 
 
 
 
 
 

175 lines
4.0 KiB

  1. from ..languages import LANGS
  2. __all__ = ["String", "Regex", "Text", "Language", "Date", "Author", "Symbol",
  3. "BinaryOp", "UnaryOp"]
  4. class _Node(object):
  5. """Represents a single node in a query tree.
  6. Generally speaking, a node is a constraint applied to the database. Thus,
  7. a :py:class:`~.Language` node represents a constraint where only codelets
  8. of a specific language are selected.
  9. """
  10. pass
  11. class _Literal(object):
  12. """Represents a literal component of a search query, present at the leaves.
  13. A literal might be a string or a regular expression.
  14. """
  15. pass
  16. class String(_Literal):
  17. """Represents a string literal."""
  18. def __init__(self, string):
  19. """
  20. :type string: unicode
  21. """
  22. self.string = string
  23. def __repr__(self):
  24. return "String({0!r})".format(self.string)
  25. class Regex(_Literal):
  26. """Represents a regular expression literal."""
  27. def __init__(self, regex):
  28. """
  29. :type string: unicode
  30. """
  31. self.regex = regex
  32. def __repr__(self):
  33. return "Regex({0!r})".format(self.regex)
  34. class Text(_Node):
  35. """Represents a text node.
  36. Searches in codelet names (full-text search), symbols (equality), and
  37. source code (full-text search).
  38. """
  39. def __init__(self, text):
  40. """
  41. :type text: :py:class:`._Literal`
  42. """
  43. self.text = text
  44. def __repr__(self):
  45. return "Text({0})".format(self.text)
  46. class Language(_Node):
  47. """Represents a language node.
  48. Searches in the code_lang field.
  49. """
  50. def __init__(self, lang):
  51. """
  52. :type lang: int
  53. """
  54. self.lang = lang
  55. def __repr__(self):
  56. return "Language({0})".format(LANGS[self.lang])
  57. class Date(_Node):
  58. """Represents a date node.
  59. Searches in the codelet_date_created or codelet_date_modified fields.
  60. """
  61. CREATE = 1
  62. MODIFY = 2
  63. BEFORE = 1
  64. AFTER = 2
  65. def __init__(self, type_, relation, date):
  66. """
  67. :type type_: int (``CREATE`` or ``MODIFY``)
  68. :type relation: int (``BEFORE``, ``AFTER``)
  69. :type date: datetime.datetime
  70. """
  71. self.type = type_
  72. self.relation = relation
  73. self.date = date
  74. def __repr__(self):
  75. types = {self.CREATE: "CREATE", self.MODIFY: MODIFY}
  76. relations = {self.BEFORE: "BEFORE", self.AFTER: "AFTER"}
  77. tm = "Date({0}, {1}, {2})"
  78. return tm.format(types[self.type], relations[self.relation], self.date)
  79. class Author(_Node):
  80. """Represents a author node.
  81. Searches in the author_name field (full-text search).
  82. """
  83. def __init__(self, name):
  84. self.name = name
  85. def __repr__(self):
  86. return "Author({0})".format(self.name)
  87. class Symbol(_Node):
  88. """Represents a symbol node.
  89. Searches in symbol_type and symbol_name.
  90. """
  91. ALL = 0
  92. FUNCTION = 1
  93. CLASS = 2
  94. VARIABLE = 3
  95. def __init__(self, type_, name):
  96. """
  97. :type type_: int (``ALL``, ``FUNCTION``, ``CLASS``, etc.)
  98. :type name: :py:class:`.Literal`
  99. """
  100. self.type = type_
  101. self.name = name
  102. def __repr__(self):
  103. types = {self.ALL: "ALL", self.FUNCTION: "FUNCTION",
  104. self.CLASS: "CLASS", self.VARIABLE: "VARIABLE"}
  105. return "Symbol({0}, {1})".format(types[self.type], name)
  106. class BinaryOp(_Node):
  107. """Represents a relationship between two nodes: ``and``, ``or``."""
  108. AND = 1
  109. OR = 2
  110. def __init__(self, left, op, right):
  111. self.left = left
  112. self.op = op
  113. self.right = right
  114. def __repr__(self):
  115. ops = {self.AND: "AND", self.OR: "OR"}
  116. tmpl = "BinaryOp({0}, {1}, {2})"
  117. return tmpl.format(self.left, ops[self.op], self.right)
  118. class UnaryOp(_Node):
  119. """Represents a transformation applied to one node: ``not``."""
  120. NOT = 1
  121. def __init__(self, op, node):
  122. self.op = op
  123. self.node = node
  124. def __repr__(self):
  125. ops = {self.NOT: "NOT"}
  126. return "UnaryOp({0}, {1})".format(ops[self.op], self.node)