Skip to main content

lisette_syntax/program/
file.rs

1use std::collections::HashMap;
2use std::hash::BuildHasher;
3
4use ecow::EcoString;
5
6use crate::ast::{Expression, ImportAlias, Span};
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct File {
10    pub id: u32,
11    pub module_id: String,
12    /// Stable bare filename (e.g. `greet.lis`); identity key for caching and
13    /// LSP path reconstruction.
14    pub name: String,
15    /// Cwd-relative path for diagnostics and `--debug` directives; equals
16    /// `name` for synthetic/test loaders that have no notion of cwd.
17    pub display_path: String,
18    pub source: String,
19    pub items: Vec<Expression>,
20}
21
22#[derive(Debug, Clone, PartialEq)]
23pub struct FileImport {
24    pub name: EcoString,
25    pub name_span: Span,
26    pub alias: Option<ImportAlias>,
27    pub span: Span,
28}
29
30impl FileImport {
31    pub fn effective_alias<S: BuildHasher>(
32        &self,
33        go_package_names: &HashMap<String, String, S>,
34    ) -> Option<String> {
35        match &self.alias {
36            Some(ImportAlias::Named(name, _)) => Some(name.to_string()),
37            Some(ImportAlias::Blank(_)) => None,
38            None => {
39                if let Some(pkg_name) = go_package_names.get(self.name.as_str()) {
40                    return Some(pkg_name.clone());
41                }
42                Some(
43                    self.name
44                        .strip_prefix("go:")
45                        .unwrap_or(&self.name)
46                        .split('/')
47                        .next_back()
48                        .unwrap_or(&self.name)
49                        .to_string(),
50                )
51            }
52        }
53    }
54}
55
56impl File {
57    pub fn new(
58        module_id: &str,
59        name: &str,
60        display_path: &str,
61        source: &str,
62        items: Vec<Expression>,
63        id: u32,
64    ) -> Self {
65        File {
66            id,
67            module_id: module_id.to_string(),
68            name: name.to_string(),
69            display_path: display_path.to_string(),
70            source: source.to_string(),
71            items,
72        }
73    }
74
75    pub fn new_cached(
76        module_id: &str,
77        name: &str,
78        display_path: &str,
79        source: &str,
80        id: u32,
81    ) -> Self {
82        Self {
83            id,
84            module_id: module_id.to_string(),
85            name: name.to_string(),
86            display_path: display_path.to_string(),
87            source: source.to_string(),
88            items: vec![],
89        }
90    }
91
92    pub fn is_d_lis(&self) -> bool {
93        self.name.ends_with(".d.lis")
94    }
95
96    pub fn is_lis(&self) -> bool {
97        !self.is_d_lis()
98    }
99
100    pub fn imports(&self) -> Vec<FileImport> {
101        self.items
102            .iter()
103            .filter_map(|item| match item {
104                Expression::ModuleImport {
105                    name,
106                    name_span,
107                    alias,
108                    span,
109                } => Some(FileImport {
110                    name: name.clone(),
111                    name_span: *name_span,
112                    alias: alias.clone(),
113                    span: *span,
114                }),
115                _ => None,
116            })
117            .collect()
118    }
119
120    pub fn go_filename(&self) -> String {
121        std::path::Path::new(&self.name)
122            .with_extension("go")
123            .display()
124            .to_string()
125    }
126}