microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
source/language_service/src/code_action/wrap_in_array/tests.rs
158lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use crate::{ |
| 5 | code_action, |
| 6 | test_utils::{compile_project_with_markers_no_cursor, whole_document_range}, |
| 7 | }; |
| 8 | use qsc::line_column::Encoding; |
| 9 | |
| 10 | fn get_wrap_in_array_actions(source: &str) -> Vec<crate::protocol::CodeAction> { |
| 11 | let (compilation, _targets) = |
| 12 | compile_project_with_markers_no_cursor(&[("<source>", source)], false); |
| 13 | let range = whole_document_range(source); |
| 14 | let actions = code_action::get_code_actions(&compilation, "<source>", range, Encoding::Utf8); |
| 15 | actions |
| 16 | .into_iter() |
| 17 | .filter(|a| a.title == "Convert to single-element array") |
| 18 | .collect() |
| 19 | } |
| 20 | |
| 21 | #[test] |
| 22 | fn single_arg_qubit_to_qubit_array() { |
| 23 | let source = "namespace A { |
| 24 | operation Foo(qs: Qubit[]) : Unit is Adj { |
| 25 | use q = Qubit(); |
| 26 | Foo(q); |
| 27 | } |
| 28 | } |
| 29 | "; |
| 30 | let actions = get_wrap_in_array_actions(source); |
| 31 | assert_eq!(actions.len(), 1, "Expected 1 action, got: {actions:?}"); |
| 32 | let action = &actions[0]; |
| 33 | let edit = action.edit.as_ref().expect("expected edit"); |
| 34 | let (_, text_edits) = &edit.changes[0]; |
| 35 | assert_eq!(text_edits.len(), 2); |
| 36 | assert_eq!(text_edits[0].new_text, "["); |
| 37 | assert_eq!(text_edits[1].new_text, "]"); |
| 38 | } |
| 39 | |
| 40 | #[test] |
| 41 | fn multi_arg_second_param_is_array() { |
| 42 | let source = "namespace A { |
| 43 | operation Bar(x: Int, qs: Qubit[]) : Unit { |
| 44 | use q = Qubit(); |
| 45 | Bar(1, q); |
| 46 | } |
| 47 | } |
| 48 | "; |
| 49 | let actions = get_wrap_in_array_actions(source); |
| 50 | assert_eq!(actions.len(), 1, "Expected 1 action, got: {actions:?}"); |
| 51 | let action = &actions[0]; |
| 52 | let edit = action.edit.as_ref().expect("expected edit"); |
| 53 | let (_, text_edits) = &edit.changes[0]; |
| 54 | assert_eq!(text_edits.len(), 2); |
| 55 | assert_eq!(text_edits[0].new_text, "["); |
| 56 | assert_eq!(text_edits[1].new_text, "]"); |
| 57 | } |
| 58 | |
| 59 | #[test] |
| 60 | fn no_action_when_types_already_match() { |
| 61 | let source = "namespace A { |
| 62 | operation Foo(qs: Qubit[]) : Unit is Adj { |
| 63 | use q = Qubit(); |
| 64 | Foo([q]); |
| 65 | } |
| 66 | } |
| 67 | "; |
| 68 | let actions = get_wrap_in_array_actions(source); |
| 69 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 70 | } |
| 71 | |
| 72 | #[test] |
| 73 | fn no_action_for_unrelated_mismatch() { |
| 74 | // Int passed where String expected - should NOT offer wrap in array. |
| 75 | let source = "namespace A { |
| 76 | function Foo(s: String) : Unit {} |
| 77 | function Bar() : Unit { |
| 78 | Foo(42); |
| 79 | } |
| 80 | } |
| 81 | "; |
| 82 | let actions = get_wrap_in_array_actions(source); |
| 83 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 84 | } |
| 85 | |
| 86 | #[test] |
| 87 | fn no_action_for_tuple_to_tuple_array() { |
| 88 | // (Qubit, Qubit) passed where (Qubit, Qubit)[] expected - not a primitive type. |
| 89 | let source = "namespace A { |
| 90 | operation Foo(qs: (Qubit, Qubit)[]) : Unit {} |
| 91 | operation Bar() : Unit { |
| 92 | use (q1, q2) = (Qubit(), Qubit()); |
| 93 | Foo((q1, q2)); |
| 94 | } |
| 95 | } |
| 96 | "; |
| 97 | let actions = get_wrap_in_array_actions(source); |
| 98 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 99 | } |
| 100 | |
| 101 | #[test] |
| 102 | fn no_action_for_array_to_nested_array() { |
| 103 | // Qubit[] passed where Qubit[][] expected - the expression type is Qubit[] (not |
| 104 | // a primitive), so the code action should not be offered. |
| 105 | let source = "namespace A { |
| 106 | operation Foo(qs: Qubit[][]) : Unit {} |
| 107 | operation Bar(qs: Qubit[]) : Unit { |
| 108 | Foo(qs); |
| 109 | } |
| 110 | } |
| 111 | "; |
| 112 | let actions = get_wrap_in_array_actions(source); |
| 113 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 114 | } |
| 115 | |
| 116 | #[test] |
| 117 | fn no_action_for_arrow_to_arrow_array() { |
| 118 | // An operation value passed where ((Qubit) => Unit)[] expected - not a primitive type. |
| 119 | let source = "namespace A { |
| 120 | operation MyOp(q: Qubit) : Unit {} |
| 121 | operation Foo(ops: ((Qubit) => Unit)[]) : Unit {} |
| 122 | operation Bar() : Unit { |
| 123 | Foo(MyOp); |
| 124 | } |
| 125 | } |
| 126 | "; |
| 127 | let actions = get_wrap_in_array_actions(source); |
| 128 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 129 | } |
| 130 | |
| 131 | #[test] |
| 132 | fn no_action_for_param_to_param_array() { |
| 133 | // A generic type parameter passed where 'T[] expected - not a primitive type. |
| 134 | let source = "namespace A { |
| 135 | operation Foo<'T>(ts: 'T[]) : Unit {} |
| 136 | operation Bar<'T>(x: 'T) : Unit { |
| 137 | Foo(x); |
| 138 | } |
| 139 | } |
| 140 | "; |
| 141 | let actions = get_wrap_in_array_actions(source); |
| 142 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 143 | } |
| 144 | |
| 145 | #[test] |
| 146 | fn no_action_for_udt_to_udt_array() { |
| 147 | // A UDT value passed where MyType[] expected - not a primitive type. |
| 148 | let source = "namespace A { |
| 149 | newtype MyType = Int; |
| 150 | function Foo(xs: MyType[]) : Unit {} |
| 151 | function Bar(x: MyType) : Unit { |
| 152 | Foo(x); |
| 153 | } |
| 154 | } |
| 155 | "; |
| 156 | let actions = get_wrap_in_array_actions(source); |
| 157 | assert!(actions.is_empty(), "Expected no actions, got: {actions:?}"); |
| 158 | } |
| 159 | |