Automatic fixing of deprecations and use non-quoted default planes by default (#5902)

* Automatic fixing of deprecations and use non-quoted default planes by default

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Nick Cameron
2025-03-21 22:39:12 +13:00
committed by GitHub
parent 06b35b76ff
commit e8feb0309b
235 changed files with 1227 additions and 1097 deletions

View File

@ -25,6 +25,13 @@ impl LiteralValue {
suffix: NumericSuffix::None,
}
}
pub fn string_value(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
}
impl fmt::Display for LiteralValue {

View File

@ -2192,8 +2192,13 @@ impl Node<Identifier> {
/// Get the constraint level for this identifier.
/// Identifier are always fully constrained.
pub fn get_constraint_level(&self) -> ConstraintLevel {
ConstraintLevel::Full {
source_ranges: vec![self.into()],
match &*self.name {
"XY" | "XZ" | "YZ" => ConstraintLevel::None {
source_ranges: vec![self.into()],
},
_ => ConstraintLevel::Full {
source_ranges: vec![self.into()],
},
}
}
}
@ -3484,11 +3489,11 @@ mod tests {
#[test]
fn test_get_lsp_folding_ranges() {
let code = r#"const part001 = startSketchOn('XY')
let code = r#"const part001 = startSketchOn(XY)
|> startProfileAt([0.0000000000, 5.0000000000], %)
|> line([0.4900857016, -0.0240763666], %)
startSketchOn('XY')
startSketchOn(XY)
|> startProfileAt([0.0000000000, 5.0000000000], %)
|> line([0.4900857016, -0.0240763666], %)
@ -3507,20 +3512,17 @@ ghi("things")
let program = crate::parsing::top_level_parse(code).unwrap();
let folding_ranges = program.get_lsp_folding_ranges();
assert_eq!(folding_ranges.len(), 3);
assert_eq!(folding_ranges[0].start_line, 29);
assert_eq!(folding_ranges[0].end_line, 134);
assert_eq!(folding_ranges[0].start_line, 27);
assert_eq!(folding_ranges[0].end_line, 132);
assert_eq!(
folding_ranges[0].collapsed_text,
Some("part001 = startSketchOn('XY')".to_string())
Some("part001 = startSketchOn(XY)".to_string())
);
assert_eq!(folding_ranges[1].start_line, 155);
assert_eq!(folding_ranges[1].end_line, 254);
assert_eq!(
folding_ranges[1].collapsed_text,
Some("startSketchOn('XY')".to_string())
);
assert_eq!(folding_ranges[2].start_line, 384);
assert_eq!(folding_ranges[2].end_line, 403);
assert_eq!(folding_ranges[1].start_line, 151);
assert_eq!(folding_ranges[1].end_line, 250);
assert_eq!(folding_ranges[1].collapsed_text, Some("startSketchOn(XY)".to_string()));
assert_eq!(folding_ranges[2].start_line, 380);
assert_eq!(folding_ranges[2].end_line, 399);
assert_eq!(folding_ranges[2].collapsed_text, Some("fn ghi(x) {".to_string()));
}
@ -3986,7 +3988,7 @@ const cylinder = startSketchOn('-XZ')
async fn test_parse_get_meta_settings_inch() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_some());
@ -4002,7 +4004,7 @@ startSketchOn('XY')"#;
async fn test_parse_get_meta_settings_inch_to_mm() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_some());
@ -4033,14 +4035,14 @@ startSketchOn('XY')"#;
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
startSketchOn(XY)
"#
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_get_meta_settings_nothing_to_mm() {
let some_program_string = r#"startSketchOn('XY')"#;
let some_program_string = r#"startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_none());
@ -4065,7 +4067,7 @@ startSketchOn('XY')
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
startSketchOn(XY)
"#
);
}

View File

@ -146,6 +146,32 @@ impl From<KclError> for ParseResult {
}
}
const STR_DEPRECATIONS: [(&str, &str); 6] = [
("XY", "XY"),
("XZ", "XZ"),
("YZ", "YZ"),
("-XY", "-XY"),
("-XZ", "-XZ"),
("-YZ", "-YZ"),
];
const FN_DEPRECATIONS: [(&str, &str); 3] = [("pi", "PI"), ("e", "E"), ("tau", "TAU")];
const CONST_DEPRECATIONS: [(&str, &str); 0] = [];
#[derive(Clone, Copy)]
pub enum DeprecationKind {
String,
Function,
Const,
}
pub fn deprecation(s: &str, kind: DeprecationKind) -> Option<&'static str> {
match kind {
DeprecationKind::String => STR_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
DeprecationKind::Function => FN_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
DeprecationKind::Const => CONST_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
}
}
#[cfg(test)]
mod tests {
macro_rules! parse_and_lex {

View File

@ -15,6 +15,7 @@ use winnow::{
use super::{
ast::types::{Ascription, ImportPath, LabelledExpression},
token::{NumericSuffix, RESERVED_WORDS},
DeprecationKind,
};
use crate::{
docs::StdLibFn,
@ -477,7 +478,8 @@ fn string_literal(i: &mut TokenSlice) -> PResult<Node<Literal>> {
})
.context(expected("string literal (like \"myPart\""))
.parse_next(i)?;
Ok(Node::new(
let result = Node::new(
Literal {
value,
raw: token.value.clone(),
@ -486,7 +488,32 @@ fn string_literal(i: &mut TokenSlice) -> PResult<Node<Literal>> {
token.start,
token.end,
token.module_id,
))
);
if let Some(suggestion) = super::deprecation(result.value.string_value().unwrap(), DeprecationKind::String) {
ParseContext::warn(
CompilationError::err(
result.as_source_range(),
format!(
"Using `\"{}\"` is deprecated, prefer using `{}`.",
result.value.string_value().unwrap(),
suggestion
),
)
.with_suggestion(
format!(
"Replace `\"{}\"` with `{}`",
result.value.string_value().unwrap(),
suggestion
),
suggestion,
None,
Tag::Deprecated,
),
);
}
Ok(result)
}
/// Parse a KCL literal number, with no - sign.
@ -2315,6 +2342,21 @@ fn nameable_identifier(i: &mut TokenSlice) -> PResult<Node<Identifier>> {
));
}
if let Some(suggestion) = super::deprecation(&result.name, DeprecationKind::Const) {
ParseContext::warn(
CompilationError::err(
result.as_source_range(),
format!("Using `{}` is deprecated, prefer using `{}`.", result.name, suggestion),
)
.with_suggestion(
format!("Replace `{}` with `{}`", result.name, suggestion),
suggestion,
None,
Tag::Deprecated,
),
);
}
Ok(result)
}
@ -3016,7 +3058,7 @@ fn fn_call(i: &mut TokenSlice) -> PResult<Node<CallExpression>> {
}
let end = preceded(opt(whitespace), close_paren).parse_next(i)?.end;
Ok(Node::new_node(
let result = Node::new_node(
fn_name.start,
end,
fn_name.module_id,
@ -3025,7 +3067,27 @@ fn fn_call(i: &mut TokenSlice) -> PResult<Node<CallExpression>> {
arguments: args,
digest: None,
},
))
);
if let Some(suggestion) = super::deprecation(&result.callee.name, DeprecationKind::Function) {
ParseContext::warn(
CompilationError::err(
result.as_source_range(),
format!(
"Calling `{}` is deprecated, prefer using `{}`.",
result.callee.name, suggestion
),
)
.with_suggestion(
format!("Replace `{}` with `{}`", result.callee.name, suggestion),
suggestion,
None,
Tag::Deprecated,
),
);
}
Ok(result)
}
fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
@ -3097,7 +3159,7 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
non_code_nodes,
..Default::default()
};
Ok(Node::new_node(
let result = Node::new_node(
fn_name.start,
end,
fn_name.module_id,
@ -3108,7 +3170,27 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
digest: None,
non_code_meta,
},
))
);
if let Some(suggestion) = super::deprecation(&result.callee.name, DeprecationKind::Function) {
ParseContext::warn(
CompilationError::err(
result.as_source_range(),
format!(
"Calling `{}` is deprecated, prefer using `{}`.",
result.callee.name, suggestion
),
)
.with_suggestion(
format!("Replace `{}` with `{}`", result.callee.name, suggestion),
suggestion,
None,
Tag::Deprecated,
),
);
}
Ok(result)
}
#[cfg(test)]
@ -3326,7 +3408,7 @@ mySk1 = startSketchOn(XY)
#[test]
fn inline_comment_pipe_expression() {
let test_input = r#"a('XY')
let test_input = r#"a(XY)
|> b(%)
|> c(%) // inline-comment
|> d(%)"#;

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 6,
"end": 106,
"end": 104,
"id": {
"commentStart": 6,
"end": 14,
@ -22,12 +22,11 @@ expression: actual
"arguments": [
{
"commentStart": 31,
"end": 35,
"raw": "'XY'",
"end": 33,
"name": "XY",
"start": 31,
"type": "Literal",
"type": "Literal",
"value": "XY"
"type": "Identifier",
"type": "Identifier"
}
],
"callee": {
@ -38,7 +37,7 @@ expression: actual
"type": "Identifier"
},
"commentStart": 17,
"end": 36,
"end": 34,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
@ -48,20 +47,20 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 51,
"end": 57,
"commentStart": 49,
"end": 55,
"name": "center",
"start": 51,
"start": 49,
"type": "Identifier"
},
"arg": {
"commentStart": 59,
"commentStart": 57,
"elements": [
{
"commentStart": 60,
"end": 61,
"commentStart": 58,
"end": 59,
"raw": "0",
"start": 60,
"start": 58,
"type": "Literal",
"type": "Literal",
"value": {
@ -70,10 +69,10 @@ expression: actual
}
},
{
"commentStart": 63,
"end": 64,
"commentStart": 61,
"end": 62,
"raw": "0",
"start": 63,
"start": 61,
"type": "Literal",
"type": "Literal",
"value": {
@ -82,8 +81,8 @@ expression: actual
}
}
],
"end": 65,
"start": 59,
"end": 63,
"start": 57,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
@ -91,17 +90,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 67,
"end": 73,
"commentStart": 65,
"end": 71,
"name": "radius",
"start": 67,
"start": 65,
"type": "Identifier"
},
"arg": {
"commentStart": 75,
"end": 77,
"commentStart": 73,
"end": 75,
"raw": "22",
"start": 75,
"start": 73,
"type": "Literal",
"type": "Literal",
"value": {
@ -112,15 +111,15 @@ expression: actual
}
],
"callee": {
"commentStart": 44,
"end": 50,
"commentStart": 42,
"end": 48,
"name": "circle",
"start": 44,
"start": 42,
"type": "Identifier"
},
"commentStart": 44,
"end": 78,
"start": 44,
"commentStart": 42,
"end": 76,
"start": 42,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
@ -130,17 +129,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 94,
"end": 100,
"commentStart": 92,
"end": 98,
"name": "length",
"start": 94,
"start": 92,
"type": "Identifier"
},
"arg": {
"commentStart": 103,
"end": 105,
"commentStart": 101,
"end": 103,
"raw": "14",
"start": 103,
"start": 101,
"type": "Literal",
"type": "Literal",
"value": {
@ -151,22 +150,22 @@ expression: actual
}
],
"callee": {
"commentStart": 86,
"end": 93,
"commentStart": 84,
"end": 91,
"name": "extrude",
"start": 86,
"start": 84,
"type": "Identifier"
},
"commentStart": 86,
"end": 106,
"start": 86,
"commentStart": 84,
"end": 104,
"start": 84,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 17,
"end": 106,
"end": 104,
"start": 17,
"type": "PipeExpression",
"type": "PipeExpression"
@ -174,7 +173,7 @@ expression: actual
"start": 6,
"type": "VariableDeclarator"
},
"end": 106,
"end": 104,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -182,6 +181,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 107,
"end": 105,
"start": 0
}