|
| 1 | +pub mod db; |
1 | 2 | pub mod diagnostics;
|
2 |
| - |
3 |
| -use std::path; |
4 |
| - |
5 |
| -use codespan_reporting::term::{ |
6 |
| - self, |
7 |
| - termcolor::{BufferWriter, ColorChoice}, |
8 |
| -}; |
9 |
| -use common::{ |
10 |
| - diagnostics::CompleteDiagnostic, |
11 |
| - impl_db_traits, |
12 |
| - indexmap::IndexSet, |
13 |
| - input::{IngotKind, Version}, |
14 |
| - InputDb, InputFile, InputIngot, |
15 |
| -}; |
16 |
| -pub use diagnostics::CsDbWrapper; |
17 |
| -use hir::{ |
18 |
| - analysis_pass::AnalysisPassManager, diagnostics::DiagnosticVoucher, hir_def::TopLevelMod, |
19 |
| - lower::map_file_to_mod, HirDb, LowerHirDb, ParsingPass, SpannedHirDb, |
20 |
| -}; |
21 |
| -use hir_analysis::{ |
22 |
| - name_resolution::{DefConflictAnalysisPass, ImportAnalysisPass, PathAnalysisPass}, |
23 |
| - ty::{ |
24 |
| - AdtDefAnalysisPass, BodyAnalysisPass, FuncAnalysisPass, ImplAnalysisPass, |
25 |
| - ImplTraitAnalysisPass, TraitAnalysisPass, TypeAliasAnalysisPass, |
26 |
| - }, |
27 |
| - HirAnalysisDb, |
28 |
| -}; |
29 |
| - |
30 |
| -use crate::diagnostics::ToCsDiag; |
31 |
| - |
32 |
| -#[salsa::db] |
33 |
| -pub trait DriverDb: |
34 |
| - salsa::Database + HirAnalysisDb + HirDb + LowerHirDb + SpannedHirDb + InputDb |
35 |
| -{ |
36 |
| - fn as_driver_db(&self) -> &dyn DriverDb; |
37 |
| -} |
38 |
| - |
39 |
| -#[derive(Default, Clone)] |
40 |
| -#[salsa::db] |
41 |
| -pub struct DriverDataBase { |
42 |
| - storage: salsa::Storage<Self>, |
43 |
| -} |
44 |
| -impl_db_traits!( |
45 |
| - DriverDataBase, |
46 |
| - InputDb, |
47 |
| - HirDb, |
48 |
| - LowerHirDb, |
49 |
| - SpannedHirDb, |
50 |
| - HirAnalysisDb, |
51 |
| - DriverDb |
52 |
| -); |
53 |
| - |
54 |
| -impl DriverDataBase { |
55 |
| - // TODO: An temporary implementation for ui testing. |
56 |
| - pub fn run_on_top_mod<'db>(&'db self, top_mod: TopLevelMod<'db>) -> DiagnosticsCollection<'db> { |
57 |
| - self.run_on_file_with_pass_manager(top_mod, initialize_analysis_pass) |
58 |
| - } |
59 |
| - |
60 |
| - pub fn run_on_file_with_pass_manager<'db, F>( |
61 |
| - &'db self, |
62 |
| - top_mod: TopLevelMod<'db>, |
63 |
| - pm_builder: F, |
64 |
| - ) -> DiagnosticsCollection<'db> |
65 |
| - where |
66 |
| - F: FnOnce(&'db DriverDataBase) -> AnalysisPassManager<'db>, |
67 |
| - { |
68 |
| - let mut pass_manager = pm_builder(self); |
69 |
| - DiagnosticsCollection(pass_manager.run_on_module(top_mod)) |
70 |
| - } |
71 |
| - |
72 |
| - pub fn standalone(&mut self, file_path: &path::Path, source: &str) -> (InputIngot, InputFile) { |
73 |
| - let kind = IngotKind::StandAlone; |
74 |
| - |
75 |
| - // We set the ingot version to 0.0.0 for stand-alone file. |
76 |
| - let version = Version::new(0, 0, 0); |
77 |
| - let root_file = file_path; |
78 |
| - let ingot = InputIngot::new( |
79 |
| - self, |
80 |
| - file_path.parent().unwrap().as_os_str().to_str().unwrap(), |
81 |
| - kind, |
82 |
| - version, |
83 |
| - IndexSet::new(), |
84 |
| - ); |
85 |
| - |
86 |
| - let file_name = root_file.file_name().unwrap().to_str().unwrap(); |
87 |
| - let input_file = InputFile::new(self, file_name.into(), source.to_string()); |
88 |
| - ingot.set_root_file(self, input_file); |
89 |
| - ingot.set_files(self, [input_file].into_iter().collect()); |
90 |
| - (ingot, input_file) |
91 |
| - } |
92 |
| - |
93 |
| - pub fn top_mod(&self, ingot: InputIngot, input: InputFile) -> TopLevelMod { |
94 |
| - map_file_to_mod(self, ingot, input) |
95 |
| - } |
96 |
| -} |
97 |
| - |
98 |
| -pub struct DiagnosticsCollection<'db>(Vec<Box<dyn DiagnosticVoucher<'db> + 'db>>); |
99 |
| -impl<'db> DiagnosticsCollection<'db> { |
100 |
| - pub fn emit(&self, db: &'db DriverDataBase) { |
101 |
| - let writer = BufferWriter::stderr(ColorChoice::Auto); |
102 |
| - let mut buffer = writer.buffer(); |
103 |
| - let config = term::Config::default(); |
104 |
| - |
105 |
| - for diag in self.finalize(db) { |
106 |
| - term::emit(&mut buffer, &config, &CsDbWrapper(db), &diag.to_cs(db)).unwrap(); |
| 3 | +pub mod files; |
| 4 | +use camino::Utf8PathBuf; |
| 5 | +pub use db::{DriverDataBase, DriverDb}; |
| 6 | + |
| 7 | +use clap::{Parser, Subcommand}; |
| 8 | +use hir::hir_def::TopLevelMod; |
| 9 | + |
| 10 | +pub fn run(opts: &Options) { |
| 11 | + match &opts.command { |
| 12 | + Command::Build => eprintln!("`fe build` doesn't work at the moment"), |
| 13 | + Command::Check { path } => { |
| 14 | + if !path.exists() { |
| 15 | + eprintln!("file '{}' does not exist", path); |
| 16 | + std::process::exit(2); |
| 17 | + } |
| 18 | + let source = std::fs::read_to_string(path).unwrap(); |
| 19 | + |
| 20 | + let mut db = DriverDataBase::default(); |
| 21 | + let (ingot, file) = db.standalone(path, &source); |
| 22 | + let top_mod = db.top_mod(ingot, file); |
| 23 | + let diags = db.run_on_top_mod(top_mod); |
| 24 | + diags.emit(&db); |
107 | 25 | }
|
108 |
| - |
109 |
| - eprintln!("{}", std::str::from_utf8(buffer.as_slice()).unwrap()); |
| 26 | + Command::New => eprintln!("`fe new` doesn't work at the moment"), |
110 | 27 | }
|
| 28 | +} |
111 | 29 |
|
112 |
| - /// Format the accumulated diagnostics to a string. |
113 |
| - pub fn format_diags(&self, db: &'db DriverDataBase) -> String { |
114 |
| - let writer = BufferWriter::stderr(ColorChoice::Never); |
115 |
| - let mut buffer = writer.buffer(); |
116 |
| - let config = term::Config::default(); |
117 |
| - |
118 |
| - for diag in self.finalize(db) { |
119 |
| - term::emit(&mut buffer, &config, &CsDbWrapper(db), &diag.to_cs(db)).unwrap(); |
120 |
| - } |
121 |
| - |
122 |
| - std::str::from_utf8(buffer.as_slice()).unwrap().to_string() |
123 |
| - } |
| 30 | +#[derive(Debug, Clone, Parser)] |
| 31 | +#[command(version, about, long_about = None)] |
| 32 | +pub struct Options { |
| 33 | + #[command(subcommand)] |
| 34 | + pub command: Command, |
| 35 | +} |
124 | 36 |
|
125 |
| - fn finalize(&self, db: &'db DriverDataBase) -> Vec<CompleteDiagnostic> { |
126 |
| - let mut diags: Vec<_> = self.0.iter().map(|d| d.to_complete(db)).collect(); |
127 |
| - diags.sort_by(|lhs, rhs| match lhs.error_code.cmp(&rhs.error_code) { |
128 |
| - std::cmp::Ordering::Equal => lhs.primary_span().cmp(&rhs.primary_span()), |
129 |
| - ord => ord, |
130 |
| - }); |
131 |
| - diags |
132 |
| - } |
| 37 | +#[derive(Debug, Clone, Subcommand)] |
| 38 | +pub enum Command { |
| 39 | + Build, |
| 40 | + Check { |
| 41 | + // #[clap(default_value_t = find_project_root().unwrap_or(Utf8PathBuf::from(".")))] |
| 42 | + path: Utf8PathBuf, |
| 43 | + }, |
| 44 | + New, |
133 | 45 | }
|
134 | 46 |
|
135 |
| -fn initialize_analysis_pass(db: &DriverDataBase) -> AnalysisPassManager<'_> { |
136 |
| - let mut pass_manager = AnalysisPassManager::new(); |
137 |
| - pass_manager.add_module_pass(Box::new(ParsingPass::new(db))); |
138 |
| - pass_manager.add_module_pass(Box::new(DefConflictAnalysisPass::new(db))); |
139 |
| - pass_manager.add_module_pass(Box::new(ImportAnalysisPass::new(db))); |
140 |
| - pass_manager.add_module_pass(Box::new(PathAnalysisPass::new(db))); |
141 |
| - pass_manager.add_module_pass(Box::new(AdtDefAnalysisPass::new(db))); |
142 |
| - pass_manager.add_module_pass(Box::new(TypeAliasAnalysisPass::new(db))); |
143 |
| - pass_manager.add_module_pass(Box::new(TraitAnalysisPass::new(db))); |
144 |
| - pass_manager.add_module_pass(Box::new(ImplAnalysisPass::new(db))); |
145 |
| - pass_manager.add_module_pass(Box::new(ImplTraitAnalysisPass::new(db))); |
146 |
| - pass_manager.add_module_pass(Box::new(FuncAnalysisPass::new(db))); |
147 |
| - pass_manager.add_module_pass(Box::new(BodyAnalysisPass::new(db))); |
148 |
| - pass_manager |
| 47 | +fn _dump_scope_graph(db: &DriverDataBase, top_mod: TopLevelMod) -> String { |
| 48 | + let mut s = vec![]; |
| 49 | + top_mod.scope_graph(db).write_as_dot(db, &mut s).unwrap(); |
| 50 | + String::from_utf8(s).unwrap() |
149 | 51 | }
|
0 commit comments