114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
"""This module provides tools for analyzing a project."""
|
|
|
|
import json
|
|
import logging
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
|
|
from dss.analyze.base import ProjectAnalysis
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
# Path to the node.js parser script.
|
|
# This assumes the script is located in the same directory as this file.
|
|
parser_script_path = Path(__file__).parent / "parser.js"
|
|
|
|
|
|
def analyze_project(
|
|
path: str,
|
|
output_graph: bool = False,
|
|
prune: bool = False,
|
|
visualize: bool = False,
|
|
) -> ProjectAnalysis:
|
|
"""
|
|
Analyzes a project, including all its components and their dependencies.
|
|
|
|
Args:
|
|
path: The path to the project to analyze.
|
|
output_graph: Whether to output the dependency graph.
|
|
prune: Whether to prune the dependency graph.
|
|
visualize: Whether to visualize the dependency graph.
|
|
|
|
Returns:
|
|
A ProjectAnalysis object containing the analysis results.
|
|
"""
|
|
project_path = Path(path).resolve()
|
|
log.info(f"Analyzing project at {project_path}...")
|
|
|
|
# Get all component files in the project.
|
|
component_files = list(project_path.glob("**/*.js")) + list(project_path.glob("**/*.jsx"))
|
|
|
|
# For each component file, get its AST.
|
|
for file_path in component_files:
|
|
if file_path.is_file():
|
|
# Call the external node.js parser
|
|
result = subprocess.run(
|
|
["node", str(parser_script_path), file_path],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
# The AST is now in result.stdout as a JSON string.
|
|
ast = json.loads(result.stdout)
|
|
# TODO: Do something with the AST.
|
|
|
|
# TODO: Populate the ProjectAnalysis object with the analysis results.
|
|
analysis = ProjectAnalysis(
|
|
project_name=project_path.name,
|
|
project_path=str(project_path),
|
|
total_files=len(component_files),
|
|
components={},
|
|
)
|
|
log.info(f"Analysis complete for {project_path.name}.")
|
|
return analysis
|
|
|
|
|
|
def export_project_context(analysis: ProjectAnalysis, output_path: str):
|
|
"""
|
|
Exports the project context to a JSON file.
|
|
"""
|
|
log.info(f"Exporting project context to {output_path}...")
|
|
with open(output_path, "w") as f:
|
|
json.dump(analysis.dict(), f, indent=2)
|
|
log.info("Export complete.")
|
|
|
|
|
|
def get_ast(file_path: str) -> Dict:
|
|
"""
|
|
Gets the AST of a file using a node.js parser.
|
|
"""
|
|
log.info(f"Getting AST for {file_path}...")
|
|
result = subprocess.run(
|
|
["node", str(parser_script_path), file_path],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
log.info("AST retrieved.")
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def main():
|
|
"""
|
|
Main function for the project analyzer.
|
|
"""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="Analyze a project.")
|
|
parser.add_argument("path", help="The path to the project to analyze.")
|
|
parser.add_argument("--output-graph", action="store_true", help="Output the dependency graph.")
|
|
parser.add_argument("--prune", action="store_true", help="Prune the dependency graph.")
|
|
parser.add_argument("--visualize", action="store_true", help="Visualize the dependency graph.")
|
|
parser.add_argument("--export-context", help="Export the project context to a JSON file.")
|
|
args = parser.parse_args()
|
|
|
|
analysis = analyze_project(args.path, args.output_graph, args.prune, args.visualize)
|
|
|
|
if args.export_context:
|
|
export_project_context(analysis, args.export_context)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|