aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/autoload/class_map_generator.rs
blob: 9a3fc0a90d4fd0ce4df98d979bb4a24b6db410a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! ref: composer/src/Composer/Autoload/ClassMapGenerator.php

use indexmap::IndexMap;

use shirabe_external_packages::composer::class_map_generator::class_map_generator::ClassMapGenerator as ExternalClassMapGenerator;
use shirabe_external_packages::composer::class_map_generator::file_list::FileList;
use shirabe_php_shim::PhpMixed;

use crate::io::io_interface::IOInterface;

#[derive(Debug)]
pub struct ClassMapGenerator;

impl ClassMapGenerator {
    pub fn dump(dirs: Vec<String>, file: &str) -> anyhow::Result<()> {
        let mut maps: IndexMap<String, String> = IndexMap::new();
        for dir in dirs {
            maps.extend(ClassMapGenerator::create_map(
                PhpMixed::String(dir),
                None,
                None,
                None,
                None,
                &mut IndexMap::new(),
            )?);
        }
        let maps_php = PhpMixed::Array(
            maps.into_iter()
                .map(|(k, v)| (k, Box::new(PhpMixed::String(v))))
                .collect(),
        );
        std::fs::write(file, format!("<?php return {};", shirabe_php_shim::var_export(&maps_php, true)))?;
        Ok(())
    }

    pub fn create_map(
        path: PhpMixed,
        excluded: Option<String>,
        io: Option<Box<dyn IOInterface>>,
        namespace: Option<String>,
        autoload_type: Option<String>,
        scanned_files: &mut IndexMap<String, bool>,
    ) -> anyhow::Result<IndexMap<String, String>> {
        let generator = ExternalClassMapGenerator::new(vec!["php".to_string(), "inc".to_string(), "hh".to_string()]);
        let mut file_list = FileList::new();
        file_list.files = scanned_files.clone();
        generator.avoid_duplicate_scans(&file_list);

        generator.scan_paths(path, excluded.as_deref(), autoload_type.as_deref().unwrap_or("classmap"), namespace.as_deref())?;

        let class_map = generator.get_class_map();

        *scanned_files = file_list.files;

        if let Some(io) = &io {
            for msg in class_map.get_psr_violations() {
                io.write_error(&format!("<warning>{}</warning>", msg));
            }

            for (class, paths) in class_map.get_ambiguous_classes() {
                if paths.len() > 1 {
                    io.write_error(&format!(
                        "<warning>Warning: Ambiguous class resolution, \"{}\" was found {}x: in \"{}\" and \"{}\", the first will be used.</warning>",
                        class,
                        paths.len() + 1,
                        class_map.get_class_path(&class),
                        paths.join("\", \""),
                    ));
                } else {
                    io.write_error(&format!(
                        "<warning>Warning: Ambiguous class resolution, \"{}\" was found in both \"{}\" and \"{}\", the first will be used.</warning>",
                        class,
                        class_map.get_class_path(&class),
                        paths.join("\", \""),
                    ));
                }
            }
        }

        Ok(class_map.get_map())
    }
}