Skip to content

Commit 5829481

Browse files
authored
Merge pull request #79 from FalkorDB/staging
Staging
2 parents 673db14 + 0fbc545 commit 5829481

13 files changed

+192
-219
lines changed

api/analyzers/analyzer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def resolve(self, files: dict[Path, File], lsp: SyncLanguageServer, file_path: P
5454
return []
5555

5656
@abstractmethod
57-
def add_dependencies(self, path: Path, files: dict[Path, File]):
57+
def add_dependencies(self, path: Path, files: list[Path]):
5858
"""
5959
Add dependencies to the files.
6060

api/analyzers/java/analyzer.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class JavaAnalyzer(AbstractAnalyzer):
1919
def __init__(self) -> None:
2020
super().__init__(Language(tsjava.language()))
2121

22-
def add_dependencies(self, path: Path, files: dict[Path, File]):
22+
def add_dependencies(self, path: Path, files: list[Path]):
2323
# if not Path("java-decompiler-engine-243.23654.153.jar").is_file():
2424
# subprocess.run(["wget", "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/java/java-decompiler-engine/243.23654.153/java-decompiler-engine-243.23654.153.jar"])
2525
subprocess.run(["rm", "-rf", f"{path}/temp_deps"])
@@ -35,6 +35,7 @@ def add_dependencies(self, path: Path, files: dict[Path, File]):
3535
# subprocess.run(["java", "-jar", "java-decompiler-engine-243.23654.153.jar", "-hdc=0 -iib=1 -rsy=1 -rbr=1 -dgs=1 -din=1 -den=1 -asc=1 -bsm=1", jar_path, f"{path}/temp_deps/{artifactId}-{version}"])
3636
subprocess.run(["cp", jar_path, f"{artifactId}-{version}.jar"], cwd=f"{path}/temp_deps/{artifactId}-{version}")
3737
subprocess.run(["unzip", f"{artifactId}-{version}.jar"], cwd=f"{path}/temp_deps/{artifactId}-{version}")
38+
files.extend(Path(f"{path}/temp_deps").rglob("*.java"))
3839

3940
def get_entity_label(self, node: Node) -> str:
4041
if node.type == 'class_declaration':

api/analyzers/python/analyzer.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import os
12
import subprocess
23
from multilspy import SyncLanguageServer
34
from pathlib import Path
5+
6+
import toml
47
from ...entities import *
58
from typing import Optional
69
from ..analyzer import AbstractAnalyzer
@@ -15,15 +18,23 @@ class PythonAnalyzer(AbstractAnalyzer):
1518
def __init__(self) -> None:
1619
super().__init__(Language(tspython.language()))
1720

18-
def add_dependencies(self, path: Path, files: dict[Path, File]):
21+
def add_dependencies(self, path: Path, files: list[Path]):
1922
if Path(f"{path}/venv").is_dir():
2023
return
21-
subprocess.run(["python3", "-m", "venv", f"{path}/venv"])
22-
if Path(f"{path}/requirements.txt").is_file():
23-
subprocess.run([f"{path}/venv/bin/pip", "install", "-r", "requirements.txt"])
24+
subprocess.run(["python3", "-m", "venv", "venv"], cwd=str(path))
2425
if Path(f"{path}/pyproject.toml").is_file():
25-
subprocess.run([f"{path}/venv/bin/pip", "install", "poetry"])
26-
subprocess.run([f"{path}/venv/bin/poetry", "install"])
26+
subprocess.run(["pip", "install", "poetry"], cwd=str(path), env={"VIRTUAL_ENV": f"{path}/venv", "PATH": f"{path}/venv/bin:{os.environ['PATH']}"})
27+
subprocess.run(["poetry", "install"], cwd=str(path), env={"VIRTUAL_ENV": f"{path}/venv", "PATH": f"{path}/venv/bin:{os.environ['PATH']}"})
28+
with open(f"{path}/pyproject.toml", 'r') as file:
29+
pyproject_data = toml.load(file)
30+
for requirement in pyproject_data.get("tool").get("poetry").get("dependencies"):
31+
files.extend(Path(f"{path}/venv/lib").rglob(f"**/site-packages/{requirement}/*.py"))
32+
elif Path(f"{path}/requirements.txt").is_file():
33+
subprocess.run(["pip", "install", "-r", "requirements.txt"], cwd=str(path), env={"VIRTUAL_ENV": f"{path}/venv", "PATH": f"{path}/venv/bin:{os.environ['PATH']}"})
34+
with open(f"{path}/requirements.txt", 'r') as file:
35+
requirements = [line.strip().split("==") for line in file if line.strip()]
36+
for requirement in requirements:
37+
files.extend(Path(f"{path}/venv/lib/").rglob(f"**/site-packages/{requirement}/*.py"))
2738

2839
def get_entity_label(self, node: Node) -> str:
2940
if node.type == 'class_definition':

api/analyzers/source_analyzer.py

+18-24
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def supported_types(self) -> list[str]:
3838
"""
3939
"""
4040
return list(analyzers.keys())
41-
41+
4242
def create_entity_hierarchy(self, entity: Entity, file: File, analyzer: AbstractAnalyzer, graph: Graph):
4343
types = analyzer.get_entity_types()
4444
stack = list(entity.node.children)
@@ -72,7 +72,7 @@ def create_hierarchy(self, file: File, analyzer: AbstractAnalyzer, graph: Graph)
7272
else:
7373
stack.extend(node.children)
7474

75-
def first_pass(self, path: Path, ignore: list[str], graph: Graph) -> None:
75+
def first_pass(self, path: Path, files: list[Path], ignore: list[str], graph: Graph) -> None:
7676
"""
7777
Perform the first pass analysis on source files in the given directory tree.
7878
@@ -81,12 +81,10 @@ def first_pass(self, path: Path, ignore: list[str], graph: Graph) -> None:
8181
executor (concurrent.futures.Executor): The executor to run tasks concurrently.
8282
"""
8383

84-
if any(path.rglob('*.java')):
85-
analyzers[".java"].add_dependencies(path, self.files)
86-
if any(path.rglob('*.py')):
87-
analyzers[".py"].add_dependencies(path, self.files)
88-
89-
files = list(path.rglob('*.*'))
84+
supoorted_types = self.supported_types()
85+
for ext in set([file.suffix for file in files if file.suffix in supoorted_types]):
86+
analyzers[ext].add_dependencies(path, files)
87+
9088
files_len = len(files)
9189
for i, file_path in enumerate(files):
9290
# Skip none supported files
@@ -115,7 +113,7 @@ def first_pass(self, path: Path, ignore: list[str], graph: Graph) -> None:
115113
graph.add_file(file)
116114
self.create_hierarchy(file, analyzer, graph)
117115

118-
def second_pass(self, graph: Graph, path: Path) -> None:
116+
def second_pass(self, graph: Graph, files: list[Path], path: Path) -> None:
119117
"""
120118
Recursively analyze the contents of a directory.
121119
@@ -140,7 +138,8 @@ def second_pass(self, graph: Graph, path: Path) -> None:
140138
lsps[".py"] = NullLanguageServer()
141139
with lsps[".java"].start_server(), lsps[".py"].start_server():
142140
files_len = len(self.files)
143-
for i, (file_path, file) in enumerate(self.files.items()):
141+
for i, file_path in enumerate(files):
142+
file = self.files[file_path]
144143
logging.info(f'Processing file ({i + 1}/{files_len}): {file_path}')
145144
for _, entity in file.entities.items():
146145
entity.resolved_symbol(lambda key, symbol: analyzers[file_path.suffix].resolve_symbol(self.files, lsps[file_path.suffix], file_path, path, key, symbol))
@@ -159,22 +158,17 @@ def second_pass(self, graph: Graph, path: Path) -> None:
159158
elif key == "parameters":
160159
graph.connect_entities("PARAMETERS", entity.id, symbol.id)
161160

162-
def analyze_file(self, file_path: Path, path: Path, graph: Graph) -> None:
163-
ext = file_path.suffix
164-
logging.info(f"analyze_file: path: {file_path}")
165-
logging.info(f"analyze_file: ext: {ext}")
166-
if ext not in analyzers:
167-
return
168-
169-
self.first_pass(file_path, [], graph)
170-
self.second_pass(graph, path)
161+
def analyze_files(self, files: list[Path], path: Path, graph: Graph) -> None:
162+
self.first_pass(path, files, [], graph)
163+
self.second_pass(graph, files, path)
171164

172165
def analyze_sources(self, path: Path, ignore: list[str], graph: Graph) -> None:
166+
files = list(path.rglob("*.java")) + list(path.rglob("*.py"))
173167
# First pass analysis of the source code
174-
self.first_pass(path, ignore, graph)
168+
self.first_pass(path, files, ignore, graph)
175169

176170
# Second pass analysis of the source code
177-
self.second_pass(graph, path)
171+
self.second_pass(graph, files, path)
178172

179173
def analyze_local_folder(self, path: str, g: Graph, ignore: Optional[list[str]] = []) -> None:
180174
"""
@@ -203,14 +197,14 @@ def analyze_local_repository(self, path: str, ignore: Optional[list[str]] = None
203197
path (str): Path to a local git repository
204198
ignore (List(str)): List of paths to skip
205199
"""
206-
from git import Repo
200+
from pygit2.repository import Repository
207201

208202
self.analyze_local_folder(path, ignore)
209203

210204
# Save processed commit hash to the DB
211-
repo = Repo(path)
205+
repo = Repository(path)
212206
head = repo.commit("HEAD")
213-
self.graph.set_graph_commit(head.hexsha)
207+
self.graph.set_graph_commit(head.short_id)
214208

215209
return self.graph
216210

api/auto_complete.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .graph import Graph
22

33
def prefix_search(repo: str, prefix: str) -> str:
4+
""" Returns a list of all entities in the repository that start with the given prefix. """
45
g = Graph(repo)
56
return g.prefix_search(prefix)
6-

api/git_utils/git_graph.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def add_commit(self, commit: Commit) -> None:
4646
"""
4747
Add a new commit to the graph
4848
"""
49-
date = commit.committed_date
49+
date = commit.commit_time
5050
author = commit.author.name
51-
hexsha = commit.hexsha
51+
hexsha = commit.short_id
5252
message = commit.message
5353
logging.info(f"Adding commit {hexsha}: {message}")
5454

0 commit comments

Comments
 (0)