@tishlang/tish 1.3.8 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/tish +0 -0
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish_lint/Cargo.toml +1 -0
- package/crates/tish_lint/src/bin/tish-lint.rs +141 -23
- package/crates/tish_lint/src/lib.rs +3 -1
- package/crates/tish_lsp/README.md +1 -1
- package/package.json +1 -8
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
package/bin/tish
CHANGED
|
Binary file
|
package/crates/tish/Cargo.toml
CHANGED
|
@@ -12,6 +12,7 @@ path = "src/bin/tish-lint.rs"
|
|
|
12
12
|
|
|
13
13
|
[dependencies]
|
|
14
14
|
clap = { version = "4.6.0", features = ["derive"] }
|
|
15
|
+
serde_json = "1.0"
|
|
15
16
|
walkdir = "2"
|
|
16
17
|
tishlang_ast = { path = "../tish_ast", version = ">=0.1" }
|
|
17
18
|
tishlang_parser = { path = "../tish_parser", version = ">=0.1" }
|
|
@@ -3,30 +3,54 @@
|
|
|
3
3
|
use std::fs;
|
|
4
4
|
use std::path::{Path, PathBuf};
|
|
5
5
|
|
|
6
|
-
use clap::Parser;
|
|
6
|
+
use clap::{Parser, ValueEnum};
|
|
7
|
+
use serde_json::json;
|
|
8
|
+
|
|
9
|
+
#[derive(Clone, Copy, Debug, ValueEnum)]
|
|
10
|
+
enum OutputFormat {
|
|
11
|
+
Text,
|
|
12
|
+
Sarif,
|
|
13
|
+
}
|
|
7
14
|
|
|
8
15
|
#[derive(Parser)]
|
|
9
16
|
#[command(name = "tish-lint")]
|
|
10
17
|
#[command(about = "AST-based linter for Tish")]
|
|
11
18
|
struct Cli {
|
|
19
|
+
/// Output format (SARIF 2.1.0 for code scanning integrations).
|
|
20
|
+
#[arg(long = "format", value_enum, default_value_t = OutputFormat::Text)]
|
|
21
|
+
output_format: OutputFormat,
|
|
22
|
+
|
|
12
23
|
#[arg(required = true)]
|
|
13
24
|
paths: Vec<String>,
|
|
14
25
|
}
|
|
15
26
|
|
|
27
|
+
#[derive(Debug)]
|
|
28
|
+
struct Issue {
|
|
29
|
+
path: PathBuf,
|
|
30
|
+
line: u32,
|
|
31
|
+
col: u32,
|
|
32
|
+
code: String,
|
|
33
|
+
message: String,
|
|
34
|
+
level: &'static str,
|
|
35
|
+
}
|
|
36
|
+
|
|
16
37
|
fn main() {
|
|
17
38
|
let cli = Cli::parse();
|
|
18
|
-
if let Err(e) = run(&cli.paths) {
|
|
39
|
+
if let Err(e) = run(&cli.paths, cli.output_format) {
|
|
19
40
|
eprintln!("{}", e);
|
|
20
41
|
std::process::exit(1);
|
|
21
42
|
}
|
|
22
43
|
}
|
|
23
44
|
|
|
24
|
-
fn
|
|
45
|
+
fn collect_files(paths: &[String]) -> Result<Vec<PathBuf>, String> {
|
|
25
46
|
let mut files: Vec<PathBuf> = Vec::new();
|
|
26
47
|
for p in paths {
|
|
27
48
|
let path = Path::new(p);
|
|
28
49
|
if path.is_dir() {
|
|
29
|
-
for e in walkdir::WalkDir::new(path)
|
|
50
|
+
for e in walkdir::WalkDir::new(path)
|
|
51
|
+
.into_iter()
|
|
52
|
+
.filter_map(|e| e.ok())
|
|
53
|
+
{
|
|
30
54
|
if e.path().extension().map(|x| x == "tish").unwrap_or(false) {
|
|
31
55
|
files.push(e.path().to_path_buf());
|
|
32
56
|
}
|
|
@@ -40,38 +64,132 @@ fn run(paths: &[String]) -> Result<(), String> {
|
|
|
40
64
|
if files.is_empty() {
|
|
41
65
|
return Err("No .tish files to lint".into());
|
|
42
66
|
}
|
|
43
|
-
|
|
67
|
+
Ok(files)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fn run(paths: &[String], format: OutputFormat) -> Result<(), String> {
|
|
71
|
+
let files = collect_files(paths)?;
|
|
72
|
+
let mut issues: Vec<Issue> = Vec::new();
|
|
44
73
|
for f in files {
|
|
45
74
|
let src = fs::read_to_string(&f).map_err(|e| format!("{}: {}", f.display(), e))?;
|
|
46
75
|
match tishlang_lint::lint_source(&src) {
|
|
47
76
|
Ok(diags) => {
|
|
48
77
|
for d in diags {
|
|
49
|
-
let
|
|
50
|
-
tishlang_lint::Severity::Error =>
|
|
51
|
-
errors += 1;
|
|
52
|
-
"error"
|
|
53
|
-
}
|
|
78
|
+
let level = match d.severity {
|
|
79
|
+
tishlang_lint::Severity::Error => "error",
|
|
54
80
|
tishlang_lint::Severity::Warning => "warning",
|
|
55
81
|
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
d.
|
|
60
|
-
d.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
);
|
|
82
|
+
issues.push(Issue {
|
|
83
|
+
path: f.clone(),
|
|
84
|
+
line: d.line,
|
|
85
|
+
col: d.col,
|
|
86
|
+
code: d.code.to_string(),
|
|
87
|
+
message: d.message,
|
|
88
|
+
level,
|
|
89
|
+
});
|
|
65
90
|
}
|
|
66
91
|
}
|
|
67
92
|
Err(e) => {
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
issues.push(Issue {
|
|
94
|
+
path: f.clone(),
|
|
95
|
+
line: 1,
|
|
96
|
+
col: 1,
|
|
97
|
+
code: "tish-parse-error".into(),
|
|
98
|
+
message: e,
|
|
99
|
+
level: "error",
|
|
100
|
+
});
|
|
70
101
|
}
|
|
71
102
|
}
|
|
72
103
|
}
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
|
|
105
|
+
let error_count = issues.iter().filter(|i| i.level == "error").count();
|
|
106
|
+
|
|
107
|
+
match format {
|
|
108
|
+
OutputFormat::Text => {
|
|
109
|
+
for i in &issues {
|
|
110
|
+
println!(
|
|
111
|
+
"{}:{}:{}: {} [{}] {}",
|
|
112
|
+
i.path.display(),
|
|
113
|
+
i.line,
|
|
114
|
+
i.col,
|
|
115
|
+
i.level,
|
|
116
|
+
i.code,
|
|
117
|
+
i.message
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
if error_count > 0 {
|
|
121
|
+
return Err(format!("{} issue(s)", error_count));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
OutputFormat::Sarif => {
|
|
125
|
+
print_sarif(&issues)?;
|
|
126
|
+
if error_count > 0 {
|
|
127
|
+
return Err(format!("{} issue(s)", error_count));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
75
130
|
}
|
|
131
|
+
|
|
132
|
+
Ok(())
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
fn print_sarif(issues: &[Issue]) -> Result<(), String> {
|
|
136
|
+
let rules: Vec<_> = tishlang_lint::RULES
|
|
137
|
+
.iter()
|
|
138
|
+
.map(|(id, desc)| {
|
|
139
|
+
json!({
|
|
140
|
+
"id": id,
|
|
141
|
+
"name": id,
|
|
142
|
+
"shortDescription": { "text": desc },
|
|
143
|
+
"helpUri": "https://tishlang.com/docs/reference/linting/"
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
.chain(std::iter::once(json!({
|
|
147
|
+
"id": "tish-parse-error",
|
|
148
|
+
"name": "tish-parse-error",
|
|
149
|
+
"shortDescription": { "text": "Source failed to parse as Tish." },
|
|
150
|
+
"helpUri": "https://tishlang.com/docs/language/overview/"
|
|
151
|
+
})))
|
|
152
|
+
.collect();
|
|
153
|
+
|
|
154
|
+
let results: Vec<_> = issues
|
|
155
|
+
.iter()
|
|
156
|
+
.map(|i| {
|
|
157
|
+
let uri = i.path.to_str().unwrap_or("unknown").replace('\\', "/");
|
|
158
|
+
json!({
|
|
159
|
+
"ruleId": i.code,
|
|
160
|
+
"level": i.level,
|
|
161
|
+
"message": { "text": i.message },
|
|
162
|
+
"locations": [{
|
|
163
|
+
"physicalLocation": {
|
|
164
|
+
"artifactLocation": { "uri": uri },
|
|
165
|
+
"region": {
|
|
166
|
+
"startLine": i.line,
|
|
167
|
+
"startColumn": i.col
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}]
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
.collect();
|
|
174
|
+
|
|
175
|
+
let doc = json!({
|
|
176
|
+
"version": "2.1.0",
|
|
177
|
+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
|
178
|
+
"runs": [{
|
|
179
|
+
"tool": {
|
|
180
|
+
"driver": {
|
|
181
|
+
"name": "tish-lint",
|
|
182
|
+
"informationUri": "https://tishlang.com/docs/reference/linting/",
|
|
183
|
+
"rules": rules
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"results": results
|
|
187
|
+
}]
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
println!(
|
|
191
|
+
"{}",
|
|
192
|
+
serde_json::to_string_pretty(&doc).map_err(|e| e.to_string())?
|
|
193
|
+
);
|
|
76
194
|
Ok(())
|
|
77
195
|
}
|
|
@@ -246,7 +246,9 @@ fn lint_expr(e: &Expr, out: &mut Vec<LintDiagnostic>) {
|
|
|
246
246
|
}
|
|
247
247
|
Expr::Await { operand, .. } => lint_expr(operand, out),
|
|
248
248
|
Expr::TypeOf { operand, .. } => lint_expr(operand, out),
|
|
249
|
-
Expr::JsxElement {
|
|
249
|
+
Expr::JsxElement {
|
|
250
|
+
props, children, ..
|
|
251
|
+
} => {
|
|
250
252
|
for pr in props {
|
|
251
253
|
match pr {
|
|
252
254
|
tishlang_ast::JsxProp::Attr { value, .. } => {
|
|
@@ -19,7 +19,7 @@ Binary: `target/release/tish-lsp` (stdio LSP).
|
|
|
19
19
|
|
|
20
20
|
## Client configuration
|
|
21
21
|
|
|
22
|
-
See the [Tish docs — Language server](https://tishlang.
|
|
22
|
+
See the [Tish docs — Language server](https://tishlang.com/docs/reference/language-server/) and [Editor setup](https://tishlang.com/docs/getting-started/editor/).
|
|
23
23
|
|
|
24
24
|
## Developing
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tishlang/tish",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Tish - minimal TS/JS-compatible language. Run, REPL, build to native or other targets.",
|
|
5
5
|
"license": "PIF",
|
|
6
6
|
"repository": {
|
|
@@ -29,13 +29,6 @@
|
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=22"
|
|
31
31
|
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
34
|
-
"@semantic-release/github": "^12.0.6",
|
|
35
|
-
"@semantic-release/npm": "^13.1.5",
|
|
36
|
-
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
37
|
-
"semantic-release": "^25.0.3"
|
|
38
|
-
},
|
|
39
32
|
"keywords": [
|
|
40
33
|
"tish",
|
|
41
34
|
"language",
|
|
Binary file
|
package/platform/darwin-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|
package/platform/linux-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|