Skip to content

Commit 58d2c71

Browse files
committed
Rust: load files from disk ourselves
This avoids problems with files containing invalid utf-8 data, which may cause panic's like: ``` thread 'main' panicked at external/rules_rust~~_crate~ql~~r~r__ra_ap_salsa-0.0.232/src/input.rs:91:32: no value set for CompressedFileTextQuery(FileId(2429)) stack backtrace: 0: rust_begin_unwind at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5 1: core::panicking::panic_fmt at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14 2: <salsa::input::InputStorage<Q> as salsa::plumbing::QueryStorageOps<Q>>::fetch 3: <DB as ra_ap_base_db::SourceDatabase>::compressed_file_text::__shim 4: <ra_ap_base_db::FileTextQuery as salsa::plumbing::QueryFunction>::execute 5: salsa::Cycle::catch 6: salsa::derived_lru::slot::Slot<Q,MP>::execute 7: salsa::derived_lru::slot::Slot<Q,MP>::read 8: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch 9: <DB as ra_ap_base_db::SourceDatabase>::file_text::__shim 10: <DB as ra_ap_base_db::SourceDatabase>::file_text 11: <ra_ap_base_db::ParseQuery as salsa::plumbing::QueryFunction>::execute 12: salsa::Cycle::catch 13: salsa::derived_lru::slot::Slot<Q,MP>::execute 14: salsa::derived_lru::slot::Slot<Q,MP>::read 15: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch 16: <DB as ra_ap_base_db::SourceDatabase>::parse::__shim 17: <DB as ra_ap_base_db::SourceDatabase>::parse 18: ra_ap_hir::semantics::SemanticsImpl::parse 19: single_arch_extractor::main ```
1 parent f70f8a3 commit 58d2c71

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

rust/extractor/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod translate;
88
pub mod trap;
99

1010
fn extract(
11-
rust_analyzer: &rust_analyzer::RustAnalyzer,
11+
rust_analyzer: &mut rust_analyzer::RustAnalyzer,
1212
traps: &trap::TrapFileProvider,
1313
file: std::path::PathBuf,
1414
) -> anyhow::Result<()> {
@@ -49,7 +49,7 @@ fn main() -> anyhow::Result<()> {
4949
.module(module_path!())
5050
.verbosity(2 + cfg.verbose as usize)
5151
.init()?;
52-
let rust_analyzer = rust_analyzer::RustAnalyzer::new(&cfg)?;
52+
let mut rust_analyzer = rust_analyzer::RustAnalyzer::new(&cfg)?;
5353

5454
let traps = trap::TrapFileProvider::new(&cfg).context("failed to set up trap files")?;
5555
let archiver = archive::Archiver {
@@ -59,7 +59,7 @@ fn main() -> anyhow::Result<()> {
5959
let file = std::path::absolute(&file).unwrap_or(file);
6060
let file = std::fs::canonicalize(&file).unwrap_or(file);
6161
archiver.archive(&file);
62-
extract(&rust_analyzer, &traps, file)?;
62+
extract(&mut rust_analyzer, &traps, file)?;
6363
}
6464

6565
Ok(())

rust/extractor/src/rust_analyzer.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use anyhow::Context;
33
use itertools::Itertools;
44
use log::info;
55
use ra_ap_base_db::SourceDatabase;
6+
use ra_ap_base_db::SourceDatabaseFileInputExt;
67
use ra_ap_hir::Semantics;
78
use ra_ap_ide_db::RootDatabase;
89
use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
@@ -59,7 +60,7 @@ impl RustAnalyzer {
5960
Ok(RustAnalyzer { workspace })
6061
}
6162
pub fn parse(
62-
&self,
63+
&mut self,
6364
path: &PathBuf,
6465
) -> (
6566
SourceFile,
@@ -68,43 +69,52 @@ impl RustAnalyzer {
6869
Option<EditionedFileId>,
6970
Option<Semantics<'_, RootDatabase>>,
7071
) {
72+
let mut errors = Vec::new();
73+
let input = match std::fs::read(path) {
74+
Ok(data) => data,
75+
Err(e) => {
76+
errors.push(SyntaxError::new(
77+
format!("Could not read {}: {}", path.to_string_lossy(), e),
78+
TextRange::empty(TextSize::default()),
79+
));
80+
vec![]
81+
}
82+
};
83+
let (input, err) = from_utf8_lossy(&input);
84+
7185
let mut p = path.as_path();
7286
while let Some(parent) = p.parent() {
7387
p = parent;
74-
if let Some((vfs, db)) = self.workspace.get(parent) {
88+
if self.workspace.contains_key(parent) {
89+
let (vfs, db) = self.workspace.get_mut(parent).unwrap();
7590
if let Some(file_id) = Utf8PathBuf::from_path_buf(path.to_path_buf())
7691
.ok()
7792
.and_then(|x| AbsPathBuf::try_from(x).ok())
7893
.map(VfsPath::from)
7994
.and_then(|x| vfs.file_id(&x))
8095
{
96+
db.set_file_text(file_id, &input);
8197
let semi = Semantics::new(db);
82-
let file_id = EditionedFileId::current_edition(file_id);
8398

84-
return (
85-
semi.parse(file_id),
86-
db.file_text(file_id.into()),
99+
let file_id = EditionedFileId::current_edition(file_id);
100+
let source_file = semi.parse(file_id);
101+
errors.extend(
87102
db.parse_errors(file_id)
88-
.map(|x| x.to_vec())
89-
.unwrap_or_default(),
103+
.into_iter()
104+
.flat_map(|x| x.to_vec()),
105+
);
106+
return (
107+
source_file,
108+
input.as_ref().into(),
109+
errors,
90110
Some(file_id),
91111
Some(semi),
92112
);
113+
} else {
114+
break;
93115
}
94116
}
95117
}
96-
let mut errors = Vec::new();
97-
let input = match std::fs::read(path) {
98-
Ok(data) => data,
99-
Err(e) => {
100-
errors.push(SyntaxError::new(
101-
format!("Could not read {}: {}", path.to_string_lossy(), e),
102-
TextRange::empty(TextSize::default()),
103-
));
104-
vec![]
105-
}
106-
};
107-
let (input, err) = from_utf8_lossy(&input);
108118
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
109119
errors.extend(parse.errors());
110120
errors.extend(err);

0 commit comments

Comments
 (0)