Skip to content

Commit 6176202

Browse files
authored
Merge pull request #19291 from github/redsun82/rust-pick-edition
Rust: pick correct edition for the files
2 parents 53c4b29 + c9cff09 commit 6176202

29 files changed

+91
-65
lines changed

Diff for: rust/extractor/src/rust_analyzer.rs

+59-58
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use itertools::Itertools;
2-
use ra_ap_base_db::{EditionedFileId, RootQueryDb, SourceDatabase};
2+
use ra_ap_base_db::{EditionedFileId, FileText, RootQueryDb, SourceDatabase};
33
use ra_ap_hir::Semantics;
44
use ra_ap_ide_db::RootDatabase;
55
use ra_ap_load_cargo::{LoadCargoConfig, load_workspace_at};
66
use ra_ap_paths::{AbsPath, Utf8PathBuf};
77
use ra_ap_project_model::ProjectManifest;
88
use ra_ap_project_model::{CargoConfig, ManifestPath};
99
use ra_ap_span::Edition;
10-
use ra_ap_span::EditionedFileId as SpanEditionedFileId;
1110
use ra_ap_span::TextRange;
1211
use ra_ap_span::TextSize;
1312
use ra_ap_syntax::SourceFile;
@@ -54,7 +53,6 @@ impl<'a> RustAnalyzer<'a> {
5453
) -> Option<(RootDatabase, Vfs)> {
5554
let progress = |t| (trace!("progress: {}", t));
5655
let manifest = project.manifest_path();
57-
5856
match load_workspace_at(manifest.as_ref(), config, load_config, &progress) {
5957
Ok((db, vfs, _macro_server)) => Some((db, vfs)),
6058
Err(err) => {
@@ -66,67 +64,70 @@ impl<'a> RustAnalyzer<'a> {
6664
pub fn new(vfs: &'a Vfs, semantics: &'a Semantics<'a, RootDatabase>) -> Self {
6765
RustAnalyzer::WithSemantics { vfs, semantics }
6866
}
69-
pub fn parse(&self, path: &Path) -> ParseResult {
70-
let no_semantics_reason;
67+
fn get_file_data(
68+
&self,
69+
path: &Path,
70+
) -> Result<(&Semantics<RootDatabase>, EditionedFileId, FileText), &str> {
7171
match self {
72+
RustAnalyzer::WithoutSemantics { reason } => Err(reason),
7273
RustAnalyzer::WithSemantics { vfs, semantics } => {
73-
if let Some(file_id) = path_to_file_id(path, vfs) {
74-
if let Ok(input) = std::panic::catch_unwind(|| semantics.db.file_text(file_id))
75-
{
76-
let file_id = EditionedFileId::new(
77-
semantics.db,
78-
SpanEditionedFileId::current_edition(file_id),
79-
);
80-
let source_file = semantics.parse(file_id);
81-
let errors = semantics
82-
.db
83-
.parse_errors(file_id)
84-
.into_iter()
85-
.flat_map(|x| x.to_vec())
86-
.collect();
87-
88-
return ParseResult {
89-
ast: source_file,
90-
text: input.text(semantics.db),
91-
errors,
92-
semantics_info: Ok(FileSemanticInformation { file_id, semantics }),
93-
};
94-
}
95-
debug!(
96-
"No text available for file_id '{:?}', falling back to loading file '{}' from disk.",
97-
file_id,
98-
path.to_string_lossy()
99-
);
100-
no_semantics_reason = "no text available for the file in the project";
101-
} else {
102-
no_semantics_reason = "file not found in project";
103-
}
104-
}
105-
RustAnalyzer::WithoutSemantics { reason } => {
106-
no_semantics_reason = reason;
74+
let file_id = path_to_file_id(path, vfs).ok_or("file not found in project")?;
75+
let input = std::panic::catch_unwind(|| semantics.db.file_text(file_id))
76+
.or(Err("no text available for the file in the project"))?;
77+
let editioned_file_id = semantics
78+
.attach_first_edition(file_id)
79+
.ok_or("failed to determine rust edition")?;
80+
Ok((
81+
semantics,
82+
EditionedFileId::new(semantics.db, editioned_file_id),
83+
input,
84+
))
10785
}
10886
}
109-
let mut errors = Vec::new();
110-
let input = match std::fs::read(path) {
111-
Ok(data) => data,
112-
Err(e) => {
113-
errors.push(SyntaxError::new(
114-
format!("Could not read {}: {}", path.to_string_lossy(), e),
115-
TextRange::empty(TextSize::default()),
116-
));
117-
vec![]
87+
}
88+
89+
pub fn parse(&self, path: &Path) -> ParseResult {
90+
match self.get_file_data(path) {
91+
Ok((semantics, file_id, input)) => {
92+
let source_file = semantics.parse(file_id);
93+
let errors = semantics
94+
.db
95+
.parse_errors(file_id)
96+
.into_iter()
97+
.flat_map(|x| x.to_vec())
98+
.collect();
99+
100+
ParseResult {
101+
ast: source_file,
102+
text: input.text(semantics.db),
103+
errors,
104+
semantics_info: Ok(FileSemanticInformation { file_id, semantics }),
105+
}
118106
}
119-
};
120-
let (input, err) = from_utf8_lossy(&input);
107+
Err(reason) => {
108+
let mut errors = Vec::new();
109+
let input = match std::fs::read(path) {
110+
Ok(data) => data,
111+
Err(e) => {
112+
errors.push(SyntaxError::new(
113+
format!("Could not read {}: {}", path.to_string_lossy(), e),
114+
TextRange::empty(TextSize::default()),
115+
));
116+
vec![]
117+
}
118+
};
119+
let (input, err) = from_utf8_lossy(&input);
121120

122-
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
123-
errors.extend(parse.errors());
124-
errors.extend(err);
125-
ParseResult {
126-
ast: parse.tree(),
127-
text: input.as_ref().into(),
128-
errors,
129-
semantics_info: Err(no_semantics_reason),
121+
let parse = ra_ap_syntax::ast::SourceFile::parse(&input, Edition::CURRENT);
122+
errors.extend(parse.errors());
123+
errors.extend(err);
124+
ParseResult {
125+
ast: parse.tree(),
126+
text: input.as_ref().into(),
127+
errors,
128+
semantics_info: Err(reason),
129+
}
130+
}
130131
}
131132
}
132133
}

Diff for: rust/ql/integration-tests/conftest.py

+29-3
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,55 @@
22
import json
33
import commands
44
import pathlib
5+
import tomllib
6+
7+
8+
@pytest.fixture(params=[2018, 2021, 2024])
9+
def rust_edition(request):
10+
return request.param
511

612

713
@pytest.fixture
8-
def cargo(cwd):
9-
assert (cwd / "Cargo.toml").exists()
14+
def cargo(cwd, rust_edition):
15+
manifest_file = cwd / "Cargo.toml"
16+
assert manifest_file.exists()
1017
(cwd / "rust-project.json").unlink(missing_ok=True)
1118

19+
def update(file):
20+
contents = file.read_text()
21+
m = tomllib.loads(contents)
22+
if 'package' in m:
23+
# tomllib does not support writing, and we don't want to use further dependencies
24+
# so we just do a dumb search and replace
25+
contents = contents.replace(f'edition = "{m["package"]["edition"]}"', f'edition = "{rust_edition}"')
26+
file.write_text(contents)
27+
if 'members' in m.get('workspace', ()):
28+
for member in m['workspace']['members']:
29+
update(file.parent / member / "Cargo.toml")
30+
31+
update(manifest_file)
32+
33+
1234
@pytest.fixture(scope="session")
1335
def rust_sysroot_src() -> str:
1436
rust_sysroot = pathlib.Path(commands.run("rustc --print sysroot", _capture=True))
1537
ret = rust_sysroot.joinpath("lib", "rustlib", "src", "rust", "library")
1638
assert ret.exists()
1739
return str(ret)
1840

41+
1942
@pytest.fixture
20-
def rust_project(cwd, rust_sysroot_src):
43+
def rust_project(cwd, rust_sysroot_src, rust_edition):
2144
project_file = cwd / "rust-project.json"
2245
assert project_file.exists()
2346
project = json.loads(project_file.read_text())
2447
project["sysroot_src"] = rust_sysroot_src
48+
for c in project["crates"]:
49+
c["edition"] = str(rust_edition)
2550
project_file.write_text(json.dumps(project, indent=4))
2651
(cwd / "Cargo.toml").unlink(missing_ok=True)
2752

53+
2854
@pytest.fixture
2955
def rust_check_diagnostics(check_diagnostics):
3056
check_diagnostics.redact += [

Diff for: rust/ql/integration-tests/hello-project/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
[package]
33
name = "hello-cargo"
44
version = "0.1.0"
5-
edition = "2021"
5+
edition = "2021" # replaced in test
66

77
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "exe"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2021" # replaced in test
55

66
[dependencies]
77
lib = { path = "../lib" }
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lib"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2021" # replaced in test
55

66
[dependencies]

Diff for: rust/ql/integration-tests/hello-[workspace]/test_workspace.py renamed to rust/ql/integration-tests/hello-workspace/test_workspace.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
22

3-
43
@pytest.mark.ql_test("steps.ql", expected=".cargo.expected")
54
@pytest.mark.ql_test("summary.qlref", expected=".cargo.expected")
65
def test_cargo(codeql, rust, cargo, check_source_archive, rust_check_diagnostics):

0 commit comments

Comments
 (0)