Skip to content

Commit

Permalink
Merge pull request #17849 from github/aibaars/single-semantics
Browse files Browse the repository at this point in the history
Rust: try to speed things up a bit
  • Loading branch information
redsun82 authored Nov 4, 2024
2 parents 662a824 + 0e511d6 commit bde517f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 48 deletions.
22 changes: 14 additions & 8 deletions rust/extractor/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use anyhow::Context;
use archive::Archiver;
use log::info;
use ra_ap_hir::Semantics;
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_project_model::ProjectManifest;
use rust_analyzer::{ParseResult, RustAnalyzer};
Expand All @@ -17,7 +18,7 @@ mod translate;
pub mod trap;

fn extract(
rust_analyzer: &mut rust_analyzer::RustAnalyzer,
rust_analyzer: &rust_analyzer::RustAnalyzer,
archiver: &Archiver,
traps: &trap::TrapFileProvider,
file: &std::path::Path,
Expand All @@ -29,7 +30,6 @@ fn extract(
text,
errors,
file_id,
semantics,
} = rust_analyzer.parse(file);
let line_index = LineIndex::new(text.as_ref());
let display_path = file.to_string_lossy();
Expand All @@ -45,7 +45,7 @@ fn extract(
label,
line_index,
file_id,
semantics,
file_id.and(rust_analyzer.semantics()),
);

for err in errors {
Expand Down Expand Up @@ -116,14 +116,20 @@ fn main() -> anyhow::Result<()> {
if files.is_empty() {
break;
}
let mut rust_analyzer = RustAnalyzer::new(manifest, &cfg.scratch_dir);
for file in files {
extract(&mut rust_analyzer, &archiver, &traps, file);
if let Some((ref db, ref vfs)) = RustAnalyzer::load_workspace(manifest, &cfg.scratch_dir) {
let semantics = Semantics::new(db);
let rust_analyzer = RustAnalyzer::new(vfs, semantics);
for file in files {
extract(&rust_analyzer, &archiver, &traps, file);
}
} else {
for file in files {
extract(&RustAnalyzer::WithoutSemantics, &archiver, &traps, file);
}
}
}
let mut rust_analyzer = RustAnalyzer::WithoutDatabase();
for file in other_files {
extract(&mut rust_analyzer, &archiver, &traps, file);
extract(&RustAnalyzer::WithoutSemantics, &archiver, &traps, file);
}

Ok(())
Expand Down
94 changes: 56 additions & 38 deletions rust/extractor/src/rust_analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use itertools::Itertools;
use log::{debug, info};
use ra_ap_base_db::SourceDatabase;
use ra_ap_base_db::SourceDatabaseFileInputExt;
use ra_ap_hir::Semantics;
use ra_ap_ide_db::RootDatabase;
use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
Expand All @@ -21,19 +20,24 @@ use ra_ap_vfs::VfsPath;
use std::borrow::Cow;
use std::path::{Path, PathBuf};
use triomphe::Arc;
pub enum RustAnalyzer {
WithDatabase { db: RootDatabase, vfs: Vfs },
WithoutDatabase(),
pub enum RustAnalyzer<'a> {
WithSemantics {
vfs: &'a Vfs,
semantics: Semantics<'a, RootDatabase>,
},
WithoutSemantics,
}
pub struct ParseResult<'a> {
pub struct ParseResult {
pub ast: SourceFile,
pub text: Arc<str>,
pub errors: Vec<SyntaxError>,
pub file_id: Option<EditionedFileId>,
pub semantics: Option<Semantics<'a, RootDatabase>>,
}
impl RustAnalyzer {
pub fn new(project: &ProjectManifest, scratch_dir: &Path) -> Self {
impl<'a> RustAnalyzer<'a> {
pub fn load_workspace(
project: &ProjectManifest,
scratch_dir: &Path,
) -> Option<(RootDatabase, Vfs)> {
let config = CargoConfig {
sysroot: Some(RustLibSource::Discover),
target_dir: ra_ap_paths::Utf8PathBuf::from_path_buf(scratch_dir.to_path_buf())
Expand All @@ -50,14 +54,55 @@ impl RustAnalyzer {
let manifest = project.manifest_path();

match load_workspace_at(manifest.as_ref(), &config, &load_config, &progress) {
Ok((db, vfs, _macro_server)) => RustAnalyzer::WithDatabase { db, vfs },
Ok((db, vfs, _macro_server)) => Some((db, vfs)),
Err(err) => {
log::error!("failed to load workspace for {}: {}", manifest, err);
RustAnalyzer::WithoutDatabase()
None
}
}
}
pub fn parse(&mut self, path: &Path) -> ParseResult<'_> {
pub fn new(vfs: &'a Vfs, semantics: Semantics<'a, RootDatabase>) -> Self {
RustAnalyzer::WithSemantics { vfs, semantics }
}
pub fn semantics(&'a self) -> Option<&'a Semantics<'a, RootDatabase>> {
match self {
RustAnalyzer::WithSemantics { vfs: _, semantics } => Some(semantics),
RustAnalyzer::WithoutSemantics => None,
}
}
pub fn parse(&self, path: &Path) -> ParseResult {
if let RustAnalyzer::WithSemantics { vfs, semantics } = self {
if let Some(file_id) = Utf8PathBuf::from_path_buf(path.to_path_buf())
.ok()
.and_then(|x| AbsPathBuf::try_from(x).ok())
.map(VfsPath::from)
.and_then(|x| vfs.file_id(&x))
{
if let Ok(input) = std::panic::catch_unwind(|| semantics.db.file_text(file_id)) {
let file_id = EditionedFileId::current_edition(file_id);
let source_file = semantics.parse(file_id);
let errors = semantics
.db
.parse_errors(file_id)
.into_iter()
.flat_map(|x| x.to_vec())
.collect();

return ParseResult {
ast: source_file,
text: input,
errors,
file_id: Some(file_id),
};
} else {
log::debug!(
"No text available for file_id '{:?}', falling back to loading file '{}' from disk.",
file_id,
path.to_string_lossy()
)
}
}
}
let mut errors = Vec::new();
let input = match std::fs::read(path) {
Ok(data) => data,
Expand All @@ -71,32 +116,6 @@ impl RustAnalyzer {
};
let (input, err) = from_utf8_lossy(&input);

if let RustAnalyzer::WithDatabase { vfs, db } = self {
if let Some(file_id) = Utf8PathBuf::from_path_buf(path.to_path_buf())
.ok()
.and_then(|x| AbsPathBuf::try_from(x).ok())
.map(VfsPath::from)
.and_then(|x| vfs.file_id(&x))
{
db.set_file_text(file_id, &input);
let semantics = Semantics::new(db);

let file_id = EditionedFileId::current_edition(file_id);
let source_file = semantics.parse(file_id);
errors.extend(
db.parse_errors(file_id)
.into_iter()
.flat_map(|x| x.to_vec()),
);
return ParseResult {
ast: source_file,
text: input.as_ref().into(),
errors,
file_id: Some(file_id),
semantics: Some(semantics),
};
}
}
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
errors.extend(parse.errors());
errors.extend(err);
Expand All @@ -105,7 +124,6 @@ impl RustAnalyzer {
text: input.as_ref().into(),
errors,
file_id: None,
semantics: None,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions rust/extractor/src/translate/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct Translator<'a> {
label: trap::Label,
line_index: LineIndex,
file_id: Option<EditionedFileId>,
pub semantics: Option<Semantics<'a, RootDatabase>>,
pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
}

impl<'a> Translator<'a> {
Expand All @@ -65,7 +65,7 @@ impl<'a> Translator<'a> {
label: trap::Label,
line_index: LineIndex,
file_id: Option<EditionedFileId>,
semantics: Option<Semantics<'a, RootDatabase>>,
semantics: Option<&'a Semantics<'a, RootDatabase>>,
) -> Translator<'a> {
Translator {
trap,
Expand Down

0 comments on commit bde517f

Please sign in to comment.