Skip to content

Commit 4fc8d5c

Browse files
committed
refactoring tmc-langs-util
1 parent 74de9f5 commit 4fc8d5c

File tree

17 files changed

+370
-403
lines changed

17 files changed

+370
-403
lines changed

tmc-langs-core/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Used for communicating with the TMC server.

tmc-langs-core/src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ pub enum CoreError {
4949
#[error("Failed to find cache directory")]
5050
CacheDir,
5151

52-
#[error(transparent)]
53-
TmcLangs(#[from] tmc_langs_util::TmcError),
5452
#[error(transparent)]
5553
Response(#[from] response::ResponseError),
5654
#[error(transparent)]
5755
ResponseErrors(#[from] response::ResponseErrors),
5856
#[error(transparent)]
5957
WalkDir(#[from] walkdir::Error),
58+
#[error(transparent)]
59+
Tmc(#[from] tmc_langs_util::error::UtilError),
6060
}
6161

6262
impl From<TokenError> for CoreError {

tmc-langs-framework/src/domain.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
33
pub mod meta_syntax;
44

5-
use super::{Result, TmcError};
5+
use super::Result;
6+
use crate::io::file_util;
7+
68
use log::debug;
79
use schemars::JsonSchema;
810
use serde::{Deserialize, Serialize};
911
use std::collections::{HashMap, HashSet};
10-
use std::fs::File;
1112
use std::path::{Path, PathBuf};
1213

1314
/// A description of an exercise's test case.
@@ -157,7 +158,7 @@ impl TmcProjectYml {
157158
return Ok(Self::default());
158159
}
159160
debug!("reading .tmcproject.yml from {}", config_path.display());
160-
let file = File::open(&config_path).map_err(|e| TmcError::OpenFile(config_path, e))?;
161+
let file = file_util::open_file(&config_path)?;
161162
Ok(serde_yaml::from_reader(file)?)
162163
}
163164
}

tmc-langs-framework/src/domain/meta_syntax.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
//! Contains utilities for parsing text files, separating lines into
2-
//! strings, stubs and solutions so that they can be more easily filtered accordingly
1+
//! Contains utilities for parsing annotated exercise source files, separating lines into
2+
//! strings, stubs and solutions so that they can be more easily filtered later.
33
44
use crate::{Result, TmcError};
55
use lazy_static::lazy_static;
6-
use log::debug;
76
use regex::{Captures, Regex};
87
use std::io::{BufRead, BufReader, Read};
98

10-
// Meta syntaxes for each comment syntax
9+
// rules for finding comments in various languages
1110
lazy_static! {
1211
static ref META_SYNTAXES_C: [MetaSyntax; 2] = [
1312
MetaSyntax::new("//", None),
@@ -17,7 +16,7 @@ lazy_static! {
1716
static ref META_SYNTAXES_PY: [MetaSyntax; 1] = [MetaSyntax::new("#", None)];
1817
}
1918

20-
// Used to classify lines of code based on the annotations in the file
19+
/// Used to classify lines of code based on the annotations in the file.
2120
#[derive(Debug, PartialEq, Eq)]
2221
pub enum MetaString {
2322
String(String),
@@ -26,7 +25,6 @@ pub enum MetaString {
2625
}
2726

2827
impl MetaString {
29-
// Borrows the underlying line of text
3028
pub fn as_str(&self) -> &str {
3129
match self {
3230
Self::String(s) => &s,
@@ -36,7 +34,7 @@ impl MetaString {
3634
}
3735
}
3836

39-
// Contains the needed regexes for a given comment syntax
37+
/// Contains the needed regexes for a given comment syntax.
4038
#[derive(Debug)]
4139
struct MetaSyntax {
4240
solution_file: Regex,
@@ -48,11 +46,14 @@ struct MetaSyntax {
4846

4947
impl MetaSyntax {
5048
fn new(comment_start: &'static str, comment_end: Option<&'static str>) -> Self {
49+
// comment patterns
5150
let comment_start_pattern = format!("^(\\s*){}\\s*", comment_start);
5251
let comment_end_pattern = match comment_end {
5352
Some(s) => format!("(.*){}\\s*", s),
5453
None => "(.*)".to_string(),
5554
};
55+
56+
// annotation patterns
5657
let solution_file = Regex::new(&format!(
5758
"{}SOLUTION\\s+FILE{}",
5859
comment_start_pattern, comment_end_pattern
@@ -81,7 +82,7 @@ impl MetaSyntax {
8182
}
8283
}
8384

84-
/// Parses a given text file into an iterator of `MetaString`s
85+
/// Parses a given text file into an iterator of `MetaString`s.
8586
#[derive(Debug)]
8687
pub struct MetaSyntaxParser<B: BufRead> {
8788
meta_syntaxes: &'static [MetaSyntax],
@@ -95,13 +96,14 @@ pub struct MetaSyntaxParser<B: BufRead> {
9596
impl<R: Read> MetaSyntaxParser<BufReader<R>> {
9697
pub fn new(target: R, target_extension: &str) -> Self {
9798
let reader = BufReader::new(target);
98-
// Assigns each supported file extension with the proper comment syntax
99+
// assigns each supported file extension with the proper comment syntax
99100
let meta_syntaxes: &[MetaSyntax] = match target_extension {
100101
"java" | "c" | "cpp" | "h" | "hpp" | "js" | "css" | "rs" | "qml" => &*META_SYNTAXES_C,
101102
"xml" | "http" | "html" | "qrc" => &*META_SYNTAXES_HTML,
102103
"properties" | "py" | "R" | "pro" => &*META_SYNTAXES_PY,
103104
_ => &[],
104105
};
106+
105107
Self {
106108
meta_syntaxes,
107109
reader,
@@ -125,37 +127,39 @@ impl<B: BufRead> Iterator for MetaSyntaxParser<B> {
125127
for meta_syntax in self.meta_syntaxes {
126128
// check for stub
127129
if self.in_stub.is_none() && meta_syntax.stub_begin.is_match(&s) {
128-
debug!("stub start: '{}'", s);
130+
log::debug!("stub start: '{}'", s);
129131
// save the syntax that started the current stub
130132
self.in_stub = Some(meta_syntax);
131133
// remove stub start
132134
s = meta_syntax
133135
.stub_begin
134136
.replace(&s, |caps: &Captures| caps[1].to_string())
135137
.to_string();
136-
debug!("parsed: '{}'", s);
138+
log::debug!("parsed: '{}'", s);
137139
if s.trim().is_empty() {
138140
// only metadata, skip
139141
return self.next();
140142
}
141143
}
142144
// if the line matches stub_end and the saved syntax matches
143-
// the start of the current meta syntax
145+
// the start of the current meta syntax, return stub contents if any
144146
if meta_syntax.stub_end.is_match(&s)
145147
&& self.in_stub.map(|r| r.stub_begin.as_str())
146148
== Some(meta_syntax.stub_begin.as_str())
147149
{
148-
debug!("stub end: '{}'", s);
150+
log::debug!("stub end: '{}'", s);
149151
self.in_stub = None;
152+
// remove stub end
150153
s = meta_syntax
151154
.stub_end
152155
.replace(&s, |caps: &Captures| caps[1].to_string())
153156
.to_string();
154-
debug!("parsed: '{}'", s);
157+
log::debug!("parsed: '{}'", s);
155158
if s.trim().is_empty() {
156159
// only metadata, skip
157160
return self.next();
158161
}
162+
// return the stub contents
159163
return Some(Ok(MetaString::Stub(s)));
160164
}
161165

@@ -173,13 +177,13 @@ impl<B: BufRead> Iterator for MetaSyntaxParser<B> {
173177
// after processing the line with each meta syntax,
174178
// parse the current line accordingly
175179
if self.in_solution {
176-
debug!("solution: '{}'", s);
180+
log::debug!("solution: '{}'", s);
177181
Some(Ok(MetaString::Solution(s)))
178182
} else if self.in_stub.is_some() {
179-
debug!("stub: '{}'", s);
183+
log::debug!("stub: '{}'", s);
180184
Some(Ok(MetaString::Stub(s)))
181185
} else {
182-
debug!("string: '{}'", s);
186+
log::debug!("string: '{}'", s);
183187
Some(Ok(MetaString::String(s)))
184188
}
185189
}

tmc-langs-framework/src/error.rs

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,22 @@ use thiserror::Error;
77
#[derive(Error, Debug)]
88
pub enum TmcError {
99
// IO
10-
#[error("Failed to open file at {0}")]
11-
OpenFile(PathBuf, #[source] std::io::Error),
12-
#[error("Failed to create file at {0}")]
13-
CreateFile(PathBuf, #[source] std::io::Error),
14-
#[error("Failed to remove file at {0}")]
15-
RemoveFile(PathBuf, #[source] std::io::Error),
16-
#[error("Failed to create dir(s) at {0}")]
17-
CreateDir(PathBuf, #[source] std::io::Error),
18-
#[error("Failed to remove dir at {0}")]
19-
RemoveDir(PathBuf, #[source] std::io::Error),
20-
#[error("Failed to create temporary directory")]
21-
TempDir(#[source] std::io::Error),
22-
#[error("Failed to rename {0} to {1}")]
23-
Rename(PathBuf, PathBuf, #[source] std::io::Error),
24-
#[error("Failed to write to {0}")]
25-
Write(PathBuf, #[source] std::io::Error),
26-
#[error("Failed to read zip archive at {0}")]
10+
#[error("File IO error")]
11+
FileIo(#[from] FileIo),
12+
#[error("{0} exists and is not a directory")]
13+
UnexpectedFile(PathBuf),
14+
15+
#[error("Failed to read file inside zip archive with path {0}")]
2716
ZipRead(PathBuf, #[source] std::io::Error),
17+
#[error("Failed to write file at {0} to zip archive")]
18+
ZipWrite(PathBuf, #[source] std::io::Error),
19+
2820
#[error("Error appending to tar")]
2921
TarAppend(#[source] std::io::Error),
3022
#[error("Error finishing tar")]
3123
TarFinish(#[source] std::io::Error),
3224
#[error("Failed to read line")]
3325
ReadLine(#[source] std::io::Error),
34-
#[error("Failed to copy file from {0} to {1}")]
35-
FileCopy(PathBuf, PathBuf, #[source] std::io::Error),
36-
#[error("Failed to open file at {0}")]
37-
FileOpen(PathBuf, #[source] std::io::Error),
38-
#[error("Failed to read file at {0}")]
39-
FileRead(PathBuf, #[source] std::io::Error),
4026
#[error("Failed to canonicalize path {0}")]
4127
Canonicalize(PathBuf, #[source] std::io::Error),
4228
#[error("Error occurred in a child process")]
@@ -80,10 +66,53 @@ pub enum TmcError {
8066
}
8167

8268
// == Collection of errors likely to be useful in multiple plugins which can be special cased without needing a plugin's specific error type ==
69+
/// An error caused by a failed attempt to execute an external command.
8370
#[derive(Error, Debug)]
8471
#[error("The executable for \"{name}\" could not be found ({path}). Please make sure you have installed it correctly.")]
8572
pub struct CommandNotFound {
8673
pub name: &'static str,
8774
pub path: PathBuf,
8875
pub source: std::io::Error,
8976
}
77+
78+
#[derive(Error, Debug)]
79+
pub enum FileIo {
80+
#[error("Failed to open file at {0}")]
81+
FileOpen(PathBuf, #[source] std::io::Error),
82+
#[error("Failed to read file at {0}")]
83+
FileRead(PathBuf, #[source] std::io::Error),
84+
#[error("Failed to write file at {0}")]
85+
FileWrite(PathBuf, #[source] std::io::Error),
86+
#[error("Failed to create file at {0}")]
87+
FileCreate(PathBuf, #[source] std::io::Error),
88+
#[error("Failed to remove file at {0}")]
89+
FileRemove(PathBuf, #[source] std::io::Error),
90+
#[error("Failed to copy file from {from} to {to}")]
91+
FileCopy {
92+
from: PathBuf,
93+
to: PathBuf,
94+
source: std::io::Error,
95+
},
96+
#[error("Failed to move file from {from} to {to}")]
97+
FileMove {
98+
from: PathBuf,
99+
to: PathBuf,
100+
source: std::io::Error,
101+
},
102+
103+
#[error("Failed to open directory at {0}")]
104+
DirOpen(PathBuf, #[source] std::io::Error),
105+
#[error("Failed to read directory at {0}")]
106+
DirRead(PathBuf, #[source] std::io::Error),
107+
#[error("Failed to create directory at {0}")]
108+
DirCreate(PathBuf, #[source] std::io::Error),
109+
#[error("Failed to remove directory at {0}")]
110+
DirRemove(PathBuf, #[source] std::io::Error),
111+
112+
#[error("Failed to rename file {from} to {to}")]
113+
Rename {
114+
from: PathBuf,
115+
to: PathBuf,
116+
source: std::io::Error,
117+
},
118+
}

0 commit comments

Comments
 (0)