Skip to content

Commit 4e9a355

Browse files
committed
Fix _related_source_files
1 parent bae159e commit 4e9a355

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

onlinejudge_verify/languages/rust.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def _list_dependencies_by_crate(path: pathlib.Path, *, basedir: pathlib.Path, ca
6363
metadata = _cargo_metadata(cwd=path.parent)
6464

6565
# First, collects source files in the same crate.
66-
common_result = set(_source_files_in_same_targets(path, _related_source_files(metadata)))
66+
common_result = set(_source_files_in_same_targets(path, _related_source_files(basedir, metadata)))
6767

6868
main_package_and_target = _find_target(metadata, path)
6969
if not main_package_and_target:
@@ -132,14 +132,15 @@ def from_dep_kind(cls, kind: str):
132132
continue
133133
depended_target = next(filter(_is_lib_or_proc_macro, depended_package['targets']), None)
134134
if depended_target:
135-
related_source_files = _related_source_files(_cargo_metadata_by_manifest_path(pathlib.Path(depended_package["manifest_path"])))
135+
related_source_files = _related_source_files(basedir, _cargo_metadata_by_manifest_path(pathlib.Path(depended_package["manifest_path"])))
136136
ret |= _source_files_in_same_targets(pathlib.Path(depended_target['src_path']), related_source_files)
137137
return sorted(ret)
138138

139139

140-
def _related_source_files(metadata: Dict[str, Any]) -> Dict[pathlib.Path, FrozenSet[pathlib.Path]]:
140+
def _related_source_files(basedir: pathlib.Path, metadata: Dict[str, Any]) -> Dict[pathlib.Path, FrozenSet[pathlib.Path]]:
141141
"""Collects all of the `.rs` files recognized by a workspace.
142142
143+
:param basedir: A parameter from `Language.list_dependencies`.
143144
:param metadata: Output of `cargo metadata`
144145
:returns: A (main source file) → (other related files) map
145146
"""
@@ -159,24 +160,36 @@ def _related_source_files(metadata: Dict[str, Any]) -> Dict[pathlib.Path, Frozen
159160

160161
targets_in_workspace = itertools.chain.from_iterable(p['targets'] for p in metadata['packages'] if p['id'] in metadata['workspace_members'])
161162
for target in targets_in_workspace:
162-
# Finds a **latest** `.d` file that contains a line in the following format, and parses the line.
163+
# Finds the **latest** "dep-info" file that contains a line in the following format, and parses the line.
163164
#
164165
# ```
165-
# <absolute path to the `.d` file itself>: <relative path to the root source file> <relative/aboslute paths to the other related files>...
166+
# <relative/absolute path to the `.d` file itself>: <relative/absolute path to the root source file> <relative/aboslute paths to the other related files>...
166167
# ```
167-
d_file_paths = sorted(
168+
#
169+
# - https://github.com/rust-lang/cargo/blob/rust-1.49.0/src/cargo/core/compiler/fingerprint.rs#L1979-L1997
170+
# - https://github.com/rust-lang/cargo/blob/rust-1.49.0/src/cargo/core/compiler/fingerprint.rs#L1824-L1830
171+
dep_info_paths = sorted(
168172
pathlib.Path(metadata['target_directory'], 'debug', 'deps').glob(f'{target["name"].replace("-", "_")}-*.d'),
169173
key=lambda p: p.stat().st_mtime_ns,
170174
reverse=True,
171175
)
172-
for d_file_path in d_file_paths:
173-
with open(d_file_path) as d_file:
174-
d_file_content = d_file.read()
175-
for line in d_file_content.splitlines():
176-
words = line.split(':')
177-
if len(words) == 2 and pathlib.Path(words[0]) == d_file_path:
178-
# Ignores paths like `/dev/null` or `/usr/share/foo/bar` (if any).
179-
paths = [pathlib.Path(metadata['workspace_root'], s) for s in words[1].split() if not pathlib.Path(s).is_absolute()]
176+
for dep_info_path in dep_info_paths:
177+
with open(dep_info_path) as file:
178+
dep_info = file.read()
179+
for line in dep_info.splitlines():
180+
ss = line.split(': ')
181+
if len(ss) == 2 and pathlib.Path(metadata['workspace_root'], ss[0]) == dep_info_path:
182+
paths = []
183+
it = iter(ss[1].split())
184+
for s in it:
185+
while s.endswith('\\'):
186+
s = s.rstrip('\\')
187+
s += ' '
188+
s += next(it)
189+
path = pathlib.Path(metadata['workspace_root'], s)
190+
# Ignores paths like `/dev/null` or `/usr/share/foo/bar` (if any).
191+
if any(path.parts[:i + 1] == basedir.parts for i, _ in enumerate(path.parts)):
192+
paths.append(path)
180193
if paths[:1] == [pathlib.Path(target['src_path'])]:
181194
ret[paths[0]] = frozenset(paths[1:])
182195
break

tests/test_rust.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,9 @@ def test_mono_crate(self) -> None:
7676
pub mod b;
7777
pub mod c;
7878
""").encode(),
79-
pathlib.Path('src', 'a.rs'): textwrap.dedent("""\
80-
pub struct A;
81-
""").encode(),
82-
pathlib.Path('src', 'b.rs'): textwrap.dedent("""\
83-
pub struct B;
84-
""").encode(),
85-
pathlib.Path('src', 'c.rs'): textwrap.dedent("""\
86-
pub struct C;
87-
""").encode(),
79+
pathlib.Path('src', 'a.rs'): b'',
80+
pathlib.Path('src', 'b.rs'): b'',
81+
pathlib.Path('src', 'c.rs'): b'',
8882
}
8983

9084
with tests.utils.load_files_pathlib(files) as tempdir:

0 commit comments

Comments
 (0)