syncable_cli/analyzer/context/
analysis.rs

1use crate::analyzer::{
2    AnalysisConfig, BuildScript, DetectedLanguage, DetectedTechnology, EntryPoint, EnvVar, Port,
3    ProjectType,
4};
5use crate::error::Result;
6use std::collections::{HashMap, HashSet};
7use std::path::Path;
8
9use super::file_analyzers::{docker, env, makefile};
10use super::language_analyzers::{go, javascript, jvm, python, rust};
11use super::microservices;
12use super::project_type;
13use super::tech_specific;
14
15/// Project context information
16pub struct ProjectContext {
17    pub entry_points: Vec<EntryPoint>,
18    pub ports: Vec<Port>,
19    pub environment_variables: Vec<EnvVar>,
20    pub project_type: ProjectType,
21    pub build_scripts: Vec<BuildScript>,
22}
23
24/// Analyzes project context including entry points, ports, and environment variables
25pub fn analyze_context(
26    project_root: &Path,
27    languages: &[DetectedLanguage],
28    technologies: &[DetectedTechnology],
29    config: &AnalysisConfig,
30) -> Result<ProjectContext> {
31    log::info!("Analyzing project context");
32
33    let mut entry_points = Vec::new();
34    let mut ports = HashSet::new();
35    let mut env_vars = HashMap::new();
36    let mut build_scripts = Vec::new();
37
38    // Analyze based on detected languages
39    for language in languages {
40        match language.name.as_str() {
41            "JavaScript" | "TypeScript" => {
42                javascript::analyze_node_project(
43                    project_root,
44                    &mut entry_points,
45                    &mut ports,
46                    &mut env_vars,
47                    &mut build_scripts,
48                    config,
49                )?;
50            }
51            "Python" => {
52                python::analyze_python_project(
53                    project_root,
54                    &mut entry_points,
55                    &mut ports,
56                    &mut env_vars,
57                    &mut build_scripts,
58                    config,
59                )?;
60            }
61            "Rust" => {
62                rust::analyze_rust_project(
63                    project_root,
64                    &mut entry_points,
65                    &mut ports,
66                    &mut env_vars,
67                    &mut build_scripts,
68                    config,
69                )?;
70            }
71            "Go" => {
72                go::analyze_go_project(
73                    project_root,
74                    &mut entry_points,
75                    &mut ports,
76                    &mut env_vars,
77                    &mut build_scripts,
78                    config,
79                )?;
80            }
81            "Java" | "Kotlin" => {
82                jvm::analyze_jvm_project(
83                    project_root,
84                    &mut ports,
85                    &mut env_vars,
86                    &mut build_scripts,
87                    config,
88                )?;
89            }
90            _ => {}
91        }
92    }
93
94    // Analyze common configuration files
95    docker::analyze_docker_files(project_root, &mut ports, &mut env_vars)?;
96    env::analyze_env_files(project_root, &mut env_vars)?;
97    makefile::analyze_makefile(project_root, &mut build_scripts)?;
98
99    // Technology-specific analysis
100    for technology in technologies {
101        tech_specific::analyze_technology_specifics(
102            technology,
103            project_root,
104            &mut entry_points,
105            &mut ports,
106        )?;
107    }
108
109    // Detect microservices structure
110    let microservices = microservices::detect_microservices_structure(project_root)?;
111
112    // Determine project type
113    let ports_vec: Vec<Port> = ports.iter().cloned().collect();
114    let project_type = project_type::determine_project_type_with_structure(
115        languages,
116        technologies,
117        &entry_points,
118        &ports_vec,
119        &microservices,
120    );
121
122    // Convert collections to vectors
123    let ports: Vec<Port> = ports.into_iter().collect();
124    let environment_variables: Vec<EnvVar> = env_vars
125        .into_iter()
126        .map(|(name, (default, required, desc))| EnvVar {
127            name,
128            default_value: default,
129            required,
130            description: desc,
131        })
132        .collect();
133
134    Ok(ProjectContext {
135        entry_points,
136        ports,
137        environment_variables,
138        project_type,
139        build_scripts,
140    })
141}