Skip to content

Commit 77a2b54

Browse files
committed
Ensure paths are consistently canonicalized. Closes #115
1 parent d1c7e07 commit 77a2b54

File tree

3 files changed

+58
-42
lines changed

3 files changed

+58
-42
lines changed

vhdl_lang/src/config.rs

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,6 @@ impl LibraryConfig {
3333
/// Only include files that exists
3434
/// Files that do not exist produce a warning message
3535
pub fn file_names(&self, messages: &mut dyn MessageHandler) -> Vec<PathBuf> {
36-
fn as_abspath(file_path: &Path) -> Result<PathBuf, Message> {
37-
match dunce::canonicalize(file_path) {
38-
Ok(file_path) => Ok(file_path),
39-
Err(err) => Err(Message::error(format!(
40-
"Could not create absolute path {}: {:?}",
41-
file_path.to_string_lossy(),
42-
err
43-
))),
44-
}
45-
}
46-
4736
let mut result = Vec::new();
4837
for pattern in self.patterns.iter() {
4938
let stripped_pattern = if cfg!(windows) {
@@ -53,17 +42,10 @@ impl LibraryConfig {
5342
};
5443

5544
if is_literal(stripped_pattern) {
56-
let file_path = Path::new(pattern);
45+
let file_path = Path::new(pattern).to_owned();
5746

5847
if file_path.exists() {
59-
match as_abspath(file_path) {
60-
Ok(abs_path) => {
61-
result.push(abs_path);
62-
}
63-
Err(msg) => {
64-
messages.push(msg);
65-
}
66-
};
48+
result.push(file_path);
6749
} else {
6850
messages.push(Message::warning(format! {"File {pattern} does not exist"}));
6951
}
@@ -76,14 +58,7 @@ impl LibraryConfig {
7658
empty_pattern = false;
7759
match file_path_or_error {
7860
Ok(file_path) => {
79-
match as_abspath(&file_path) {
80-
Ok(abs_path) => {
81-
result.push(abs_path);
82-
}
83-
Err(msg) => {
84-
messages.push(msg);
85-
}
86-
};
61+
result.push(file_path);
8762
}
8863
Err(err) => {
8964
messages.push(Message::error(err.to_string()));
@@ -329,7 +304,7 @@ mod tests {
329304
}
330305

331306
fn assert_files_eq(got: &[PathBuf], expected: &[PathBuf]) {
332-
assert_eq!(got, abspaths(expected).as_slice());
307+
assert_eq!(abspaths(got), abspaths(expected));
333308
}
334309

335310
#[test]

vhdl_lang/src/data/source.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use std::path::{Path, PathBuf};
1717
use std::sync::Arc;
1818

1919
struct FileId {
20-
name: PathBuf,
20+
name: FilePath,
2121
/// Hash value of `self.name`.
2222
hash: u64,
2323
}
@@ -26,7 +26,7 @@ impl FileId {
2626
fn new(name: &Path) -> FileId {
2727
let hash = hash(name);
2828
Self {
29-
name: name.to_owned(),
29+
name: FilePath::new(name),
3030
hash,
3131
}
3232
}
@@ -93,6 +93,10 @@ impl UniqueSource {
9393
fn file_name(&self) -> &Path {
9494
self.file_id.name.as_ref()
9595
}
96+
97+
fn file_path(&self) -> &FilePath {
98+
&self.file_id.name
99+
}
96100
}
97101

98102
/// A thread-safe reference to a source file.
@@ -160,6 +164,10 @@ impl Source {
160164
self.source.file_name()
161165
}
162166

167+
pub(crate) fn file_path(&self) -> &FilePath {
168+
self.source.file_path()
169+
}
170+
163171
pub fn pos(&self, start: Position, end: Position) -> SrcPos {
164172
SrcPos {
165173
source: self.clone(),
@@ -578,6 +586,37 @@ impl<T: HasSrcPos> HasSource for T {
578586
}
579587
}
580588

589+
/// A wrapper arround a PathBuf that ensures the path is canoninicalized
590+
#[derive(PartialEq, Eq, Hash, Clone)]
591+
pub(crate) struct FilePath {
592+
path: PathBuf,
593+
}
594+
595+
impl std::ops::Deref for FilePath {
596+
type Target = Path;
597+
fn deref(&self) -> &Self::Target {
598+
&self.path
599+
}
600+
}
601+
602+
impl FilePath {
603+
pub fn new(path: &Path) -> Self {
604+
let path = match dunce::canonicalize(path) {
605+
Ok(path) => path,
606+
Err(err) => {
607+
eprintln!(
608+
"Could not create absolute path {}: {:?}",
609+
path.to_string_lossy(),
610+
err
611+
);
612+
path.to_owned()
613+
}
614+
};
615+
616+
Self { path }
617+
}
618+
}
619+
581620
#[cfg(test)]
582621
mod tests {
583622
use super::*;

vhdl_lang/src/project.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ use crate::syntax::VHDLParser;
1414
use crate::{data::*, EntHierarchy, EntityId};
1515
use fnv::{FnvHashMap, FnvHashSet};
1616
use std::collections::hash_map::Entry;
17-
use std::path::{Path, PathBuf};
17+
use std::path::Path;
1818

1919
pub struct Project {
2020
parser: VHDLParser,
2121
config: Config,
2222
root: DesignRoot,
23-
files: FnvHashMap<PathBuf, SourceFile>,
23+
files: FnvHashMap<FilePath, SourceFile>,
2424
empty_libraries: FnvHashSet<Symbol>,
2525
lint: Option<UnusedDeclarationsLinter>,
2626
}
@@ -90,8 +90,8 @@ impl Project {
9090
&mut self,
9191
config: &Config,
9292
messages: &mut dyn MessageHandler,
93-
) -> FnvHashMap<PathBuf, FnvHashSet<Symbol>> {
94-
let mut files: FnvHashMap<PathBuf, FnvHashSet<Symbol>> = FnvHashMap::default();
93+
) -> FnvHashMap<FilePath, FnvHashSet<Symbol>> {
94+
let mut files: FnvHashMap<FilePath, FnvHashSet<Symbol>> = FnvHashMap::default();
9595
self.empty_libraries.clear();
9696

9797
for library in config.iter_libraries() {
@@ -103,7 +103,7 @@ impl Project {
103103
for file_name in library.file_names(messages) {
104104
empty_library = false;
105105

106-
match files.entry(file_name.clone()) {
106+
match files.entry(FilePath::new(&file_name)) {
107107
Entry::Occupied(mut entry) => {
108108
entry.get_mut().insert(library_name.clone());
109109
}
@@ -124,7 +124,7 @@ impl Project {
124124

125125
fn parse_and_add_files(
126126
&mut self,
127-
files_to_parse: FnvHashMap<PathBuf, FnvHashSet<Symbol>>,
127+
files_to_parse: FnvHashMap<FilePath, FnvHashSet<Symbol>>,
128128
messages: &mut dyn MessageHandler,
129129
) {
130130
use rayon::prelude::*;
@@ -151,7 +151,7 @@ impl Project {
151151
};
152152

153153
self.files.insert(
154-
source.file_name().to_owned(),
154+
FilePath::new(source.file_name()),
155155
SourceFile {
156156
source,
157157
library_names,
@@ -163,7 +163,7 @@ impl Project {
163163
}
164164

165165
pub fn library_mapping_of(&self, source: &Source) -> Vec<Symbol> {
166-
let file = if let Some(file) = self.files.get(source.file_name()) {
166+
let file = if let Some(file) = self.files.get(source.file_path()) {
167167
file
168168
} else {
169169
return Vec::new();
@@ -174,12 +174,14 @@ impl Project {
174174
}
175175

176176
pub fn get_source(&self, file_name: &Path) -> Option<Source> {
177-
self.files.get(file_name).map(|file| file.source.clone())
177+
self.files
178+
.get(&FilePath::new(file_name))
179+
.map(|file| file.source.clone())
178180
}
179181

180182
pub fn update_source(&mut self, source: &Source) {
181183
let mut source_file = {
182-
if let Some(mut source_file) = self.files.remove(source.file_name()) {
184+
if let Some(mut source_file) = self.files.remove(source.file_path()) {
183185
// File is already part of the project
184186
for library_name in source_file.library_names.iter() {
185187
self.root.remove_source(library_name.clone(), source);
@@ -208,7 +210,7 @@ impl Project {
208210
.parser
209211
.parse_design_source(source, &mut source_file.parser_diagnostics);
210212
self.files
211-
.insert(source.file_name().to_owned(), source_file);
213+
.insert(source.file_path().to_owned(), source_file);
212214
}
213215

214216
pub fn analyse(&mut self) -> Vec<Diagnostic> {

0 commit comments

Comments
 (0)