Skip to content

Commit

Permalink
Ensure paths are consistently canonicalized. Closes #115
Browse files Browse the repository at this point in the history
  • Loading branch information
kraigher committed Nov 13, 2023
1 parent d1c7e07 commit 77a2b54
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 42 deletions.
33 changes: 4 additions & 29 deletions vhdl_lang/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,6 @@ impl LibraryConfig {
/// Only include files that exists
/// Files that do not exist produce a warning message
pub fn file_names(&self, messages: &mut dyn MessageHandler) -> Vec<PathBuf> {
fn as_abspath(file_path: &Path) -> Result<PathBuf, Message> {
match dunce::canonicalize(file_path) {
Ok(file_path) => Ok(file_path),
Err(err) => Err(Message::error(format!(
"Could not create absolute path {}: {:?}",
file_path.to_string_lossy(),
err
))),
}
}

let mut result = Vec::new();
for pattern in self.patterns.iter() {
let stripped_pattern = if cfg!(windows) {
Expand All @@ -53,17 +42,10 @@ impl LibraryConfig {
};

if is_literal(stripped_pattern) {
let file_path = Path::new(pattern);
let file_path = Path::new(pattern).to_owned();

if file_path.exists() {
match as_abspath(file_path) {
Ok(abs_path) => {
result.push(abs_path);
}
Err(msg) => {
messages.push(msg);
}
};
result.push(file_path);
} else {
messages.push(Message::warning(format! {"File {pattern} does not exist"}));
}
Expand All @@ -76,14 +58,7 @@ impl LibraryConfig {
empty_pattern = false;
match file_path_or_error {
Ok(file_path) => {
match as_abspath(&file_path) {
Ok(abs_path) => {
result.push(abs_path);
}
Err(msg) => {
messages.push(msg);
}
};
result.push(file_path);
}
Err(err) => {
messages.push(Message::error(err.to_string()));
Expand Down Expand Up @@ -329,7 +304,7 @@ mod tests {
}

fn assert_files_eq(got: &[PathBuf], expected: &[PathBuf]) {
assert_eq!(got, abspaths(expected).as_slice());
assert_eq!(abspaths(got), abspaths(expected));
}

#[test]
Expand Down
43 changes: 41 additions & 2 deletions vhdl_lang/src/data/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use std::path::{Path, PathBuf};
use std::sync::Arc;

struct FileId {
name: PathBuf,
name: FilePath,
/// Hash value of `self.name`.
hash: u64,
}
Expand All @@ -26,7 +26,7 @@ impl FileId {
fn new(name: &Path) -> FileId {
let hash = hash(name);
Self {
name: name.to_owned(),
name: FilePath::new(name),
hash,
}
}
Expand Down Expand Up @@ -93,6 +93,10 @@ impl UniqueSource {
fn file_name(&self) -> &Path {
self.file_id.name.as_ref()
}

fn file_path(&self) -> &FilePath {
&self.file_id.name
}
}

/// A thread-safe reference to a source file.
Expand Down Expand Up @@ -160,6 +164,10 @@ impl Source {
self.source.file_name()
}

pub(crate) fn file_path(&self) -> &FilePath {
self.source.file_path()
}

pub fn pos(&self, start: Position, end: Position) -> SrcPos {
SrcPos {
source: self.clone(),
Expand Down Expand Up @@ -578,6 +586,37 @@ impl<T: HasSrcPos> HasSource for T {
}
}

/// A wrapper arround a PathBuf that ensures the path is canoninicalized
#[derive(PartialEq, Eq, Hash, Clone)]
pub(crate) struct FilePath {
path: PathBuf,
}

impl std::ops::Deref for FilePath {
type Target = Path;
fn deref(&self) -> &Self::Target {
&self.path
}
}

impl FilePath {
pub fn new(path: &Path) -> Self {
let path = match dunce::canonicalize(path) {
Ok(path) => path,
Err(err) => {
eprintln!(
"Could not create absolute path {}: {:?}",
path.to_string_lossy(),
err
);
path.to_owned()
}
};

Self { path }
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
24 changes: 13 additions & 11 deletions vhdl_lang/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ use crate::syntax::VHDLParser;
use crate::{data::*, EntHierarchy, EntityId};
use fnv::{FnvHashMap, FnvHashSet};
use std::collections::hash_map::Entry;
use std::path::{Path, PathBuf};
use std::path::Path;

pub struct Project {
parser: VHDLParser,
config: Config,
root: DesignRoot,
files: FnvHashMap<PathBuf, SourceFile>,
files: FnvHashMap<FilePath, SourceFile>,
empty_libraries: FnvHashSet<Symbol>,
lint: Option<UnusedDeclarationsLinter>,
}
Expand Down Expand Up @@ -90,8 +90,8 @@ impl Project {
&mut self,
config: &Config,
messages: &mut dyn MessageHandler,
) -> FnvHashMap<PathBuf, FnvHashSet<Symbol>> {
let mut files: FnvHashMap<PathBuf, FnvHashSet<Symbol>> = FnvHashMap::default();
) -> FnvHashMap<FilePath, FnvHashSet<Symbol>> {
let mut files: FnvHashMap<FilePath, FnvHashSet<Symbol>> = FnvHashMap::default();
self.empty_libraries.clear();

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

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

fn parse_and_add_files(
&mut self,
files_to_parse: FnvHashMap<PathBuf, FnvHashSet<Symbol>>,
files_to_parse: FnvHashMap<FilePath, FnvHashSet<Symbol>>,
messages: &mut dyn MessageHandler,
) {
use rayon::prelude::*;
Expand All @@ -151,7 +151,7 @@ impl Project {
};

self.files.insert(
source.file_name().to_owned(),
FilePath::new(source.file_name()),
SourceFile {
source,
library_names,
Expand All @@ -163,7 +163,7 @@ impl Project {
}

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

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

pub fn update_source(&mut self, source: &Source) {
let mut source_file = {
if let Some(mut source_file) = self.files.remove(source.file_name()) {
if let Some(mut source_file) = self.files.remove(source.file_path()) {
// File is already part of the project
for library_name in source_file.library_names.iter() {
self.root.remove_source(library_name.clone(), source);
Expand Down Expand Up @@ -208,7 +210,7 @@ impl Project {
.parser
.parse_design_source(source, &mut source_file.parser_diagnostics);
self.files
.insert(source.file_name().to_owned(), source_file);
.insert(source.file_path().to_owned(), source_file);
}

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

0 comments on commit 77a2b54

Please sign in to comment.