Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from .info import *
from .llm import ask
from .graph import *
from .project import *
from .entities import *
from .git_utils import *
from .code_coverage import *
from .index import create_app
from .analyzers.source_analyzer import *
from .auto_complete import prefix_search
90 changes: 82 additions & 8 deletions api/analyzers/analyzer.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,102 @@
import io
from pathlib import Path
from typing import Optional

from tree_sitter import Language, Node, Parser, Point
from api.entities.entity import Entity
from api.entities.file import File
from abc import ABC, abstractmethod
from multilspy import SyncLanguageServer

class AbstractAnalyzer(ABC):
def __init__(self, language: Language) -> None:
self.language = language
self.parser = Parser(language)

def find_parent(self, node: Node, parent_types: list) -> Node:
while node and node.type not in parent_types:
node = node.parent
return node

def resolve(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[tuple[File, Node]]:
try:
return [(files[Path(location['absolutePath'])], files[Path(location['absolutePath'])].tree.root_node.descendant_for_point_range(Point(location['range']['start']['line'], location['range']['start']['character']), Point(location['range']['end']['line'], location['range']['end']['character']))) for location in lsp.request_definition(str(path), node.start_point.row, node.start_point.column) if location and Path(location['absolutePath']) in files]
except Exception as e:
return []

@abstractmethod
def get_entity_label(self, node: Node) -> str:
"""
Get the entity label from the node.

Args:
node (Node): The node.

Returns:
str: The entity label.
"""
pass

@abstractmethod
def get_entity_name(self, node: Node) -> str:
"""
Get the entity name from the node.

Args:
node (Node): The node.

Returns:
str: The entity name.
"""
pass

@abstractmethod
def get_entity_docstring(self, node: Node) -> Optional[str]:
"""
Get the entity docstring from the node.

Args:
node (Node): The node.

Returns:
Optional[str]: The entity docstring.
"""
pass

@abstractmethod
def first_pass(self, path: Path, f: io.TextIOWrapper) -> None:
def get_entity_types(self) -> list[str]:
"""
Perform the first pass of analysis on the given file.
Get the top level entity types for the language.

Returns:
list[str]: The list of top level entity types.
"""

pass

@abstractmethod
def add_symbols(self, entity: Entity) -> None:
"""
Add symbols to the entity.

Args:
path (Path): The path to the file being processed.
f (io.TextIOWrapper): The file object.
entity (Entity): The entity to add symbols to.
"""

pass

@abstractmethod
def second_pass(self, path: Path, f: io.TextIOWrapper) -> None:
def resolve_symbol(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, key: str, symbol: Node) -> Entity:
"""
Perform a second pass analysis on the given source file.
Resolve a symbol to an entity.

Args:
lsp (SyncLanguageServer): The language server.
path (Path): The path to the file.
f (io.TextIOWrapper): The file handle of the file to be processed.
key (str): The symbol key.
symbol (Node): The symbol node.

Returns:
Entity: The entity.
"""

pass
Expand Down
Loading
Loading