forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeps.rs
128 lines (123 loc) · 5.04 KB
/
deps.rs
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use super::build_types::*;
use super::is_dirty;
use super::packages;
use crate::helpers;
use ahash::AHashSet;
use rayon::prelude::*;
fn get_dep_modules(
ast_file: &str,
namespace: Option<String>,
package_modules: &AHashSet<String>,
valid_modules: &AHashSet<String>,
) -> AHashSet<String> {
let mut deps = AHashSet::new();
if let Ok(lines) = helpers::read_lines(ast_file.to_string()) {
// we skip the first line with is some null characters
// the following lines in the AST are the dependency modules
// we stop when we hit a line that starts with a "/", this is the path of the file.
// this is the point where the dependencies end and the actual AST starts
for line in lines.skip(1).flatten() {
let line = line.trim().to_string();
if line.starts_with('/') {
break;
} else if !line.is_empty() {
deps.insert(line);
}
}
} else {
panic!("Could not read file {}", ast_file);
}
return deps
.iter()
.map(|dep| {
let dep_first = dep.split('.').next().unwrap();
let dep_second = dep.split('.').nth(1);
match &namespace {
Some(namespace) => {
// if the module is in the own namespace, take the submodule -- so:
// if the module is TeamwalnutApp.MyModule inside of the namespace TeamwalnutApp
// we need the dependency to be MyModule in the same namespace
let dep = match dep_second {
Some(dep_second) if dep_first == namespace => dep_second,
_ => dep_first,
};
let namespaced_name = dep.to_owned() + "-" + namespace;
if package_modules.contains(&namespaced_name) || valid_modules.contains(&namespaced_name)
{
namespaced_name
} else {
dep.to_string()
}
}
None => dep_first.to_string(),
}
})
.filter(|dep| {
valid_modules.contains(dep)
&& match namespace.to_owned() {
Some(namespace) => !dep.eq(&namespace),
None => true,
}
})
.collect::<AHashSet<String>>();
}
pub fn get_deps(build_state: &mut BuildState, deleted_modules: &AHashSet<String>) {
let all_mod = &build_state.module_names.union(deleted_modules).cloned().collect();
build_state
.modules
.par_iter()
.map(|(module_name, module)| match &module.source_type {
SourceType::MlMap(_) => (module_name.to_string(), module.deps.to_owned()),
SourceType::SourceFile(source_file) => {
let package = build_state
.get_package(&module.package_name)
.expect("Package not found");
let ast_path = package.get_ast_path(&source_file.implementation.path);
if is_dirty(module) || !build_state.deps_initialized {
let mut deps = get_dep_modules(
&ast_path,
package.namespace.to_suffix(),
package.modules.as_ref().unwrap(),
all_mod,
);
match &source_file.interface {
Some(interface) => {
let iast_path = package.get_iast_path(&interface.path);
deps.extend(get_dep_modules(
&iast_path,
package.namespace.to_suffix(),
package.modules.as_ref().unwrap(),
all_mod,
))
}
None => (),
}
match &package.namespace {
packages::Namespace::NamespaceWithEntry { namespace: _, entry }
if entry == module_name =>
{
deps.insert(package.namespace.to_suffix().unwrap());
}
_ => (),
}
deps.remove(module_name);
(module_name.to_string(), deps)
} else {
(module_name.to_string(), module.deps.to_owned())
}
}
})
.collect::<Vec<(String, AHashSet<String>)>>()
.into_iter()
.for_each(|(module_name, deps)| {
if let Some(module) = build_state.modules.get_mut(&module_name) {
module.deps = deps.clone();
}
deps.iter().for_each(|dep_name| {
if let Some(module) = build_state.modules.get_mut(dep_name) {
module.dependents.insert(module_name.to_string());
}
});
});
build_state.deps_initialized = true;
}