Compare commits
	
		
			3 Commits
		
	
	
		
			nightly-v2
			...
			jtran/requ
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7b46656c0f | |||
| 6c79b15adf | |||
| b45aa89d16 | 
| @ -15,7 +15,7 @@ close(sketch_group: SketchGroup, tag?: TagDeclarator) -> SketchGroup | ||||
| ### Examples | ||||
|  | ||||
| ```js | ||||
| startSketchOn('XZ') | ||||
| const exampleSketch = startSketchOn('XZ') | ||||
|   |> startProfileAt([0, 0], %) | ||||
|   |> line([10, 10], %) | ||||
|   |> line([10, 0], %) | ||||
|  | ||||
| @ -81459,7 +81459,7 @@ | ||||
|     "unpublished": false, | ||||
|     "deprecated": false, | ||||
|     "examples": [ | ||||
|       "startSketchOn('XZ')\n  |> startProfileAt([0, 0], %)\n  |> line([10, 10], %)\n  |> line([10, 0], %)\n  |> close(%)\n  |> extrude(10, %)", | ||||
|       "const exampleSketch = startSketchOn('XZ')\n  |> startProfileAt([0, 0], %)\n  |> line([10, 10], %)\n  |> line([10, 0], %)\n  |> close(%)\n  |> extrude(10, %)", | ||||
|       "const exampleSketch = startSketchOn('-XZ')\n  |> startProfileAt([0, 0], %)\n  |> line([10, 0], %)\n  |> line([0, 10], %)\n  |> close(%)\n\nconst example = extrude(10, exampleSketch)" | ||||
|     ] | ||||
|   }, | ||||
|  | ||||
| @ -3994,7 +3994,7 @@ mod tests { | ||||
|   |> startProfileAt([0.0000000000, 5.0000000000], %) | ||||
|     |> line([0.4900857016, -0.0240763666], %) | ||||
|  | ||||
| startSketchOn('XY') | ||||
| let s1 = startSketchOn('XY') | ||||
|   |> startProfileAt([0.0000000000, 5.0000000000], %) | ||||
|     |> line([0.4900857016, -0.0240763666], %) | ||||
|  | ||||
| @ -4025,7 +4025,7 @@ ghi("things") | ||||
|         assert_eq!(folding_ranges[1].end_line, 254); | ||||
|         assert_eq!( | ||||
|             folding_ranges[1].collapsed_text, | ||||
|             Some("startSketchOn('XY')".to_string()) | ||||
|             Some("let s1 = startSketchOn('XY')".to_string()) | ||||
|         ); | ||||
|         assert_eq!(folding_ranges[2].start_line, 390); | ||||
|         assert_eq!(folding_ranges[2].end_line, 403); | ||||
| @ -5264,7 +5264,7 @@ fn ghi = (part001) => { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_recast_trailing_comma() { | ||||
|         let some_program_string = r#"startSketchOn('XY') | ||||
|         let some_program_string = r#"let s = startSketchOn('XY') | ||||
|   |> startProfileAt([0, 0], %) | ||||
|   |> arc({ | ||||
|     radius: 1, | ||||
| @ -5278,7 +5278,7 @@ fn ghi = (part001) => { | ||||
|         let recasted = program.recast(&Default::default(), 0); | ||||
|         assert_eq!( | ||||
|             recasted, | ||||
|             r#"startSketchOn('XY') | ||||
|             r#"let s = startSketchOn('XY') | ||||
|   |> startProfileAt([0, 0], %) | ||||
|   |> arc({ | ||||
|        radius: 1, | ||||
| @ -5858,7 +5858,7 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#; | ||||
|  | ||||
|     #[tokio::test(flavor = "multi_thread")] | ||||
|     async fn test_parse_tag_named_std_lib() { | ||||
|         let some_program_string = r#"startSketchOn('XY') | ||||
|         let some_program_string = r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 0], %) | ||||
|     |> line([5, 5], %, $xLine) | ||||
| "#; | ||||
| @ -5869,13 +5869,13 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#; | ||||
|         assert!(result.is_err()); | ||||
|         assert_eq!( | ||||
|             result.unwrap_err().to_string(), | ||||
|             r#"syntax: KclErrorDetails { source_ranges: [SourceRange([76, 82])], message: "Cannot assign a tag to a reserved keyword: xLine" }"# | ||||
|             r#"syntax: KclErrorDetails { source_ranges: [SourceRange([84, 90])], message: "Cannot assign a tag to a reserved keyword: xLine" }"# | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[tokio::test(flavor = "multi_thread")] | ||||
|     async fn test_parse_empty_tag() { | ||||
|         let some_program_string = r#"startSketchOn('XY') | ||||
|         let some_program_string = r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 0], %) | ||||
|     |> line([5, 5], %, $) | ||||
| "#; | ||||
| @ -5886,13 +5886,13 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#; | ||||
|         assert!(result.is_err()); | ||||
|         assert_eq!( | ||||
|             result.unwrap_err().to_string(), | ||||
|             r#"syntax: KclErrorDetails { source_ranges: [SourceRange([57, 59])], message: "Unexpected token" }"# | ||||
|             r#"syntax: KclErrorDetails { source_ranges: [SourceRange([65, 67])], message: "Unexpected token" }"# | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[tokio::test(flavor = "multi_thread")] | ||||
|     async fn test_parse_digest() { | ||||
|         let prog1_string = r#"startSketchOn('XY') | ||||
|         let prog1_string = r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 0], %) | ||||
|     |> line([5, 5], %) | ||||
| "#; | ||||
| @ -5900,7 +5900,7 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#; | ||||
|         let prog1_parser = crate::parser::Parser::new(prog1_tokens); | ||||
|         let prog1_digest = prog1_parser.ast().unwrap().compute_digest(); | ||||
|  | ||||
|         let prog2_string = r#"startSketchOn('XY') | ||||
|         let prog2_string = r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 2], %) | ||||
|     |> line([5, 5], %) | ||||
| "#; | ||||
| @ -5910,7 +5910,7 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#; | ||||
|  | ||||
|         assert!(prog1_digest != prog2_digest); | ||||
|  | ||||
|         let prog3_string = r#"startSketchOn('XY') | ||||
|         let prog3_string = r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 0], %) | ||||
|     |> line([5, 5], %) | ||||
| "#; | ||||
|  | ||||
| @ -2086,6 +2086,20 @@ const newVar = myVar + 1"#; | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[tokio::test(flavor = "multi_thread")] | ||||
|     async fn test_execute_top_level_pipe_without_variable() { | ||||
|         let ast = r#"startSketchOn('XY') | ||||
|   |> startProfileAt([0, 0], %) | ||||
|   |> lineTo([2, 2], %, $yo) | ||||
| "#; | ||||
|         let result = parse_execute(ast).await; | ||||
|         assert!(result.is_err()); | ||||
|         assert_eq!( | ||||
|             result.unwrap_err().to_string(), | ||||
|             r#"syntax: KclErrorDetails { source_ranges: [SourceRange([0, 78])], message: "A top-level pipe expression must be assigned to a new variable declaration" }"#.to_owned() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[tokio::test(flavor = "multi_thread")] | ||||
|     async fn test_execute_angled_line_that_intersects() { | ||||
|         let ast_fn = |offset: &str| -> String { | ||||
|  | ||||
| @ -1354,7 +1354,7 @@ async fn test_kcl_lsp_formatting() { | ||||
|                 uri: "file:///test.kcl".try_into().unwrap(), | ||||
|                 language_id: "kcl".to_string(), | ||||
|                 version: 1, | ||||
|                 text: r#"startSketchOn('XY') | ||||
|                 text: r#"let s = startSketchOn('XY') | ||||
|                     |> startProfileAt([0,0], %)"# | ||||
|                     .to_string(), | ||||
|             }, | ||||
| @ -1385,7 +1385,7 @@ async fn test_kcl_lsp_formatting() { | ||||
|     assert_eq!(formatting.len(), 1); | ||||
|     assert_eq!( | ||||
|         formatting[0].new_text, | ||||
|         r#"startSketchOn('XY') | ||||
|         r#"let s = startSketchOn('XY') | ||||
|     |> startProfileAt([0, 0], %)"# | ||||
|     ); | ||||
| } | ||||
| @ -2901,7 +2901,7 @@ async fn test_kcl_lsp_folding() { | ||||
|                 uri: "file:///test.kcl".try_into().unwrap(), | ||||
|                 language_id: "kcl".to_string(), | ||||
|                 version: 1, | ||||
|                 text: r#"startSketchOn('XY') | ||||
|                 text: r#"let s = startSketchOn('XY') | ||||
|                     |> startProfileAt([0,0], %)"# | ||||
|                     .to_string(), | ||||
|             }, | ||||
| @ -2926,12 +2926,12 @@ async fn test_kcl_lsp_folding() { | ||||
|     assert_eq!( | ||||
|         folding.first().unwrap().clone(), | ||||
|         tower_lsp::lsp_types::FoldingRange { | ||||
|             start_line: 19, | ||||
|             start_line: 27, | ||||
|             start_character: None, | ||||
|             end_line: 67, | ||||
|             end_line: 75, | ||||
|             end_character: None, | ||||
|             kind: Some(tower_lsp::lsp_types::FoldingRangeKind::Region), | ||||
|             collapsed_text: Some("startSketchOn('XY')".to_string()) | ||||
|             collapsed_text: Some("let s = startSketchOn('XY')".to_string()) | ||||
|         } | ||||
|     ); | ||||
| } | ||||
|  | ||||
| @ -50,6 +50,37 @@ fn program(i: TokenSlice) -> PResult<Program> { | ||||
|     // Once this is merged and stable, consider changing this as I think it's more accurate | ||||
|     // without the -1. | ||||
|     out.end -= 1; | ||||
|  | ||||
|     // Prevent top-level pipe expressions without a variable declaration, giving | ||||
|     // a good error message that will help users fix their code.  This is a | ||||
|     // band-aid until we can use the artifact graph. | ||||
|     let source_ranges = out | ||||
|         .body | ||||
|         .iter() | ||||
|         .filter_map(|item| { | ||||
|             if let BodyItem::ExpressionStatement(ExpressionStatement { | ||||
|                 expression: Value::PipeExpression(_), | ||||
|                 start, | ||||
|                 end, | ||||
|                 .. | ||||
|             }) = item | ||||
|             { | ||||
|                 Some(SourceRange([*start, *end])) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         }) | ||||
|         .collect::<Vec<_>>(); | ||||
|     if !source_ranges.is_empty() { | ||||
|         return Err(ErrMode::Cut( | ||||
|             KclError::Syntax(KclErrorDetails { | ||||
|                 source_ranges, | ||||
|                 message: "A top-level pipe expression must be assigned to a new variable declaration".to_owned(), | ||||
|             }) | ||||
|             .into(), | ||||
|         )); | ||||
|     } | ||||
|  | ||||
|     Ok(out) | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -1395,7 +1395,7 @@ pub async fn close(args: Args) -> Result<MemoryItem, KclError> { | ||||
| /// Close the current sketch. | ||||
| /// | ||||
| /// ```no_run | ||||
| /// startSketchOn('XZ') | ||||
| /// const exampleSketch = startSketchOn('XZ') | ||||
| ///    |> startProfileAt([0, 0], %) | ||||
| ///    |> line([10, 10], %) | ||||
| ///    |> line([10, 0], %) | ||||
|  | ||||
| @ -484,7 +484,7 @@ const part = roundedRectangle([0, 0], 20, 20, 4) | ||||
|  | ||||
| #[tokio::test(flavor = "multi_thread")] | ||||
| async fn kcl_test_top_level_expression() { | ||||
|     let code = r#"startSketchOn('XY') |> circle([0,0], 22, %) |> extrude(14, %)"#; | ||||
|     let code = r#"let c1 = startSketchOn('XY') |> circle([0,0], 22, %) |> extrude(14, %)"#; | ||||
|  | ||||
|     let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap(); | ||||
|     assert_out("top_level_expression", &result); | ||||
| @ -2117,7 +2117,7 @@ async fn kcl_test_extrude_custom_plane() { | ||||
|  | ||||
| #[tokio::test(flavor = "multi_thread")] | ||||
| async fn kcl_test_arc_error_same_start_end() { | ||||
|     let code = r#"startSketchOn('XY') | ||||
|     let code = r#"let x = startSketchOn('XY') | ||||
|   |> startProfileAt([10, 0], %) | ||||
|   |> arc({ | ||||
|        angle_start: 180, | ||||
| @ -2137,7 +2137,7 @@ async fn kcl_test_arc_error_same_start_end() { | ||||
|     assert!(result.is_err()); | ||||
|     assert_eq!( | ||||
|         result.err().unwrap().to_string(), | ||||
|         r#"type: KclErrorDetails { source_ranges: [SourceRange([57, 140])], message: "Arc start and end angles must be different" }"# | ||||
|         r#"type: KclErrorDetails { source_ranges: [SourceRange([65, 148])], message: "Arc start and end angles must be different" }"# | ||||
|     ); | ||||
| } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	