mirror of
https://github.com/github/codeql.git
synced 2026-04-20 06:24:03 +02:00
Rust: pick correct edition for the files
Previously we would unconditionally set the edition to the latest stable according to rust-analyzer (2021 at the moment). Now we ask rust-analyzer itself to pick the correct edition for the file.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use itertools::Itertools;
|
||||
use ra_ap_base_db::{EditionedFileId, RootQueryDb, SourceDatabase};
|
||||
use ra_ap_base_db::{EditionedFileId, FileText, RootQueryDb, SourceDatabase};
|
||||
use ra_ap_hir::Semantics;
|
||||
use ra_ap_ide_db::RootDatabase;
|
||||
use ra_ap_load_cargo::{LoadCargoConfig, load_workspace_at};
|
||||
@@ -7,7 +7,6 @@ use ra_ap_paths::{AbsPath, Utf8PathBuf};
|
||||
use ra_ap_project_model::ProjectManifest;
|
||||
use ra_ap_project_model::{CargoConfig, ManifestPath};
|
||||
use ra_ap_span::Edition;
|
||||
use ra_ap_span::EditionedFileId as SpanEditionedFileId;
|
||||
use ra_ap_span::TextRange;
|
||||
use ra_ap_span::TextSize;
|
||||
use ra_ap_syntax::SourceFile;
|
||||
@@ -54,7 +53,6 @@ impl<'a> RustAnalyzer<'a> {
|
||||
) -> Option<(RootDatabase, Vfs)> {
|
||||
let progress = |t| (trace!("progress: {}", t));
|
||||
let manifest = project.manifest_path();
|
||||
|
||||
match load_workspace_at(manifest.as_ref(), config, load_config, &progress) {
|
||||
Ok((db, vfs, _macro_server)) => Some((db, vfs)),
|
||||
Err(err) => {
|
||||
@@ -66,67 +64,70 @@ impl<'a> RustAnalyzer<'a> {
|
||||
pub fn new(vfs: &'a Vfs, semantics: &'a Semantics<'a, RootDatabase>) -> Self {
|
||||
RustAnalyzer::WithSemantics { vfs, semantics }
|
||||
}
|
||||
pub fn parse(&self, path: &Path) -> ParseResult {
|
||||
let no_semantics_reason;
|
||||
fn get_file_data(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Result<(&Semantics<RootDatabase>, EditionedFileId, FileText), &str> {
|
||||
match self {
|
||||
RustAnalyzer::WithoutSemantics { reason } => Err(reason),
|
||||
RustAnalyzer::WithSemantics { vfs, semantics } => {
|
||||
if let Some(file_id) = path_to_file_id(path, vfs) {
|
||||
if let Ok(input) = std::panic::catch_unwind(|| semantics.db.file_text(file_id))
|
||||
{
|
||||
let file_id = EditionedFileId::new(
|
||||
semantics.db,
|
||||
SpanEditionedFileId::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.text(semantics.db),
|
||||
errors,
|
||||
semantics_info: Ok(FileSemanticInformation { file_id, semantics }),
|
||||
};
|
||||
}
|
||||
debug!(
|
||||
"No text available for file_id '{:?}', falling back to loading file '{}' from disk.",
|
||||
file_id,
|
||||
path.to_string_lossy()
|
||||
);
|
||||
no_semantics_reason = "no text available for the file in the project";
|
||||
} else {
|
||||
no_semantics_reason = "file not found in project";
|
||||
}
|
||||
}
|
||||
RustAnalyzer::WithoutSemantics { reason } => {
|
||||
no_semantics_reason = reason;
|
||||
let file_id = path_to_file_id(path, vfs).ok_or("file not found in project")?;
|
||||
let input = std::panic::catch_unwind(|| semantics.db.file_text(file_id))
|
||||
.or(Err("no text available for the file in the project"))?;
|
||||
let editioned_file_id = semantics
|
||||
.attach_first_edition(file_id)
|
||||
.ok_or("failed to determine rust edition")?;
|
||||
Ok((
|
||||
semantics,
|
||||
EditionedFileId::new(semantics.db, editioned_file_id),
|
||||
input,
|
||||
))
|
||||
}
|
||||
}
|
||||
let mut errors = Vec::new();
|
||||
let input = match std::fs::read(path) {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
errors.push(SyntaxError::new(
|
||||
format!("Could not read {}: {}", path.to_string_lossy(), e),
|
||||
TextRange::empty(TextSize::default()),
|
||||
));
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
let (input, err) = from_utf8_lossy(&input);
|
||||
}
|
||||
|
||||
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
|
||||
errors.extend(parse.errors());
|
||||
errors.extend(err);
|
||||
ParseResult {
|
||||
ast: parse.tree(),
|
||||
text: input.as_ref().into(),
|
||||
errors,
|
||||
semantics_info: Err(no_semantics_reason),
|
||||
pub fn parse(&self, path: &Path) -> ParseResult {
|
||||
match self.get_file_data(path) {
|
||||
Ok((semantics, file_id, input)) => {
|
||||
let source_file = semantics.parse(file_id);
|
||||
let errors = semantics
|
||||
.db
|
||||
.parse_errors(file_id)
|
||||
.into_iter()
|
||||
.flat_map(|x| x.to_vec())
|
||||
.collect();
|
||||
|
||||
ParseResult {
|
||||
ast: source_file,
|
||||
text: input.text(semantics.db),
|
||||
errors,
|
||||
semantics_info: Ok(FileSemanticInformation { file_id, semantics }),
|
||||
}
|
||||
}
|
||||
Err(reason) => {
|
||||
let mut errors = Vec::new();
|
||||
let input = match std::fs::read(path) {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
errors.push(SyntaxError::new(
|
||||
format!("Could not read {}: {}", path.to_string_lossy(), e),
|
||||
TextRange::empty(TextSize::default()),
|
||||
));
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
let (input, err) = from_utf8_lossy(&input);
|
||||
|
||||
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
|
||||
errors.extend(parse.errors());
|
||||
errors.extend(err);
|
||||
ParseResult {
|
||||
ast: parse.tree(),
|
||||
text: input.as_ref().into(),
|
||||
errors,
|
||||
semantics_info: Err(reason),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user