|
1 | 1 | #![feature(rustc_private)]
|
2 | 2 |
|
| 3 | +extern crate rustc_ast; |
| 4 | +extern crate rustc_ast_pretty; |
| 5 | +extern crate rustc_data_structures; |
3 | 6 | extern crate rustc_driver;
|
4 | 7 | extern crate rustc_error_codes;
|
5 | 8 | extern crate rustc_errors;
|
6 | 9 | extern crate rustc_hash;
|
7 | 10 | extern crate rustc_hir;
|
8 | 11 | extern crate rustc_interface;
|
| 12 | +extern crate rustc_middle; |
9 | 13 | extern crate rustc_session;
|
10 | 14 | extern crate rustc_span;
|
11 | 15 |
|
12 |
| -use std::{path, process, str, sync::Arc}; |
| 16 | +use std::io; |
| 17 | +use std::path::Path; |
13 | 18 |
|
14 |
| -use rustc_errors::registry; |
15 |
| -use rustc_hash::FxHashMap; |
16 |
| -use rustc_session::config; |
| 19 | +use rustc_ast_pretty::pprust::item_to_string; |
| 20 | +use rustc_data_structures::sync::Lrc; |
| 21 | +use rustc_driver::{Compilation, RunCompiler}; |
| 22 | +use rustc_interface::interface::Compiler; |
| 23 | +use rustc_middle::ty::TyCtxt; |
17 | 24 |
|
| 25 | +struct MyFileLoader; |
| 26 | + |
| 27 | +impl rustc_span::source_map::FileLoader for MyFileLoader { |
| 28 | + fn file_exists(&self, path: &Path) -> bool { |
| 29 | + path == Path::new("main.rs") |
| 30 | + } |
| 31 | + |
| 32 | + fn read_file(&self, path: &Path) -> io::Result<String> { |
| 33 | + if path == Path::new("main.rs") { |
| 34 | + Ok(r#" |
18 | 35 | fn main() {
|
19 |
| - let out = process::Command::new("rustc") |
20 |
| - .arg("--print=sysroot") |
21 |
| - .current_dir(".") |
22 |
| - .output() |
23 |
| - .unwrap(); |
24 |
| - let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); |
25 |
| - let config = rustc_interface::Config { |
26 |
| - // Command line options |
27 |
| - opts: config::Options { |
28 |
| - maybe_sysroot: Some(path::PathBuf::from(sysroot)), |
29 |
| - ..config::Options::default() |
30 |
| - }, |
31 |
| - // cfg! configuration in addition to the default ones |
32 |
| - crate_cfg: Vec::new(), // FxHashSet<(String, Option<String>)> |
33 |
| - crate_check_cfg: Vec::new(), // CheckCfg |
34 |
| - input: config::Input::Str { |
35 |
| - name: rustc_span::FileName::Custom("main.rs".into()), |
36 |
| - input: r#" |
37 |
| -static HELLO: &str = "Hello, world!"; |
38 |
| -fn main() { |
39 |
| - println!("{HELLO}"); |
| 36 | + let message = "Hello, World!"; |
| 37 | + println!("{message}"); |
40 | 38 | }
|
41 | 39 | "#
|
42 |
| - .into(), |
43 |
| - }, |
44 |
| - output_dir: None, // Option<PathBuf> |
45 |
| - output_file: None, // Option<PathBuf> |
46 |
| - file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>> |
47 |
| - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, |
48 |
| - lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level> |
49 |
| - // This is a callback from the driver that is called when [`ParseSess`] is created. |
50 |
| - psess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>> |
51 |
| - // This is a callback from the driver that is called when we're registering lints; |
52 |
| - // it is called during plugin registration when we have the LintStore in a non-shared state. |
53 |
| - // |
54 |
| - // Note that if you find a Some here you probably want to call that function in the new |
55 |
| - // function being registered. |
56 |
| - register_lints: None, // Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> |
57 |
| - // This is a callback from the driver that is called just after we have populated |
58 |
| - // the list of queries. |
59 |
| - // |
60 |
| - // The second parameter is local providers and the third parameter is external providers. |
61 |
| - override_queries: None, // Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)> |
62 |
| - // Registry of diagnostics codes. |
63 |
| - registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), |
64 |
| - make_codegen_backend: None, |
65 |
| - expanded_args: Vec::new(), |
66 |
| - ice_file: None, |
67 |
| - hash_untracked_state: None, |
68 |
| - using_internal_features: Arc::default(), |
69 |
| - }; |
70 |
| - rustc_interface::run_compiler(config, |compiler| { |
71 |
| - compiler.enter(|queries| { |
72 |
| - // Parse the program and print the syntax tree. |
73 |
| - let parse = queries.parse().unwrap().get_mut().clone(); |
74 |
| - println!("{parse:?}"); |
75 |
| - // Analyze the program and inspect the types of definitions. |
76 |
| - queries.global_ctxt().unwrap().enter(|tcx| { |
77 |
| - for id in tcx.hir().items() { |
78 |
| - let hir = tcx.hir(); |
79 |
| - let item = hir.item(id); |
80 |
| - match item.kind { |
81 |
| - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { |
82 |
| - let name = item.ident; |
83 |
| - let ty = tcx.type_of(item.hir_id().owner.def_id); |
84 |
| - println!("{name:?}:\t{ty:?}") |
85 |
| - } |
86 |
| - _ => (), |
87 |
| - } |
| 40 | + .to_string()) |
| 41 | + } else { |
| 42 | + Err(io::Error::other("oops")) |
| 43 | + } |
| 44 | + } |
| 45 | + |
| 46 | + fn read_binary_file(&self, _path: &Path) -> io::Result<Lrc<[u8]>> { |
| 47 | + Err(io::Error::other("oops")) |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +struct MyCallbacks; |
| 52 | + |
| 53 | +impl rustc_driver::Callbacks for MyCallbacks { |
| 54 | + fn after_crate_root_parsing( |
| 55 | + &mut self, |
| 56 | + _compiler: &Compiler, |
| 57 | + krate: &rustc_ast::Crate, |
| 58 | + ) -> Compilation { |
| 59 | + for item in &krate.items { |
| 60 | + println!("{}", item_to_string(&item)); |
| 61 | + } |
| 62 | + |
| 63 | + Compilation::Continue |
| 64 | + } |
| 65 | + |
| 66 | + fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { |
| 67 | + // Analyze the program and inspect the types of definitions. |
| 68 | + for id in tcx.hir().items() { |
| 69 | + let hir = tcx.hir(); |
| 70 | + let item = hir.item(id); |
| 71 | + match item.kind { |
| 72 | + rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { |
| 73 | + let name = item.ident; |
| 74 | + let ty = tcx.type_of(item.hir_id().owner.def_id); |
| 75 | + println!("{name:?}:\t{ty:?}") |
88 | 76 | }
|
89 |
| - }) |
90 |
| - }); |
91 |
| - }); |
| 77 | + _ => (), |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + Compilation::Stop |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +fn main() { |
| 86 | + match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) { |
| 87 | + mut compiler => { |
| 88 | + compiler.set_file_loader(Some(Box::new(MyFileLoader))); |
| 89 | + compiler.run(); |
| 90 | + } |
| 91 | + } |
92 | 92 | }
|
0 commit comments