microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/mac-intel-cryptography

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/language_service/src/code_action/auto_import/tests.rs

177lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::code_action;
5use crate::test_utils::{
6 compile_notebook_with_fake_stdlib, compile_project_with_markers_no_cursor,
7};
8use expect_test::{Expect, expect};
9use qsc::line_column::{Encoding, Position, Range};
10
11/// Returns a range that spans the entire source, so all diagnostics are considered relevant.
12fn whole_document_range(source: &str) -> Range {
13 let newline_count = u32::try_from(source.matches('\n').count()).expect("count fits");
14 let end = if newline_count == 0 {
15 Position {
16 line: 0,
17 column: u32::try_from(source.len()).expect("len fits"),
18 }
19 } else {
20 Position {
21 line: newline_count + 1,
22 column: 0,
23 }
24 };
25 Range {
26 start: Position { line: 0, column: 0 },
27 end,
28 }
29}
30
31/// Collects the titles of the auto-import code actions offered for `source`.
32fn import_action_titles(source: &str) -> Vec<String> {
33 let (compilation, _targets) =
34 compile_project_with_markers_no_cursor(&[("<source>", source)], true);
35 let range = whole_document_range(source);
36 let actions = code_action::get_code_actions(&compilation, "<source>", range, Encoding::Utf8);
37 actions
38 .into_iter()
39 .filter(|a| a.title.starts_with("Import "))
40 .map(|a| a.title)
41 .collect()
42}
43
44fn check_import_titles(source: &str, expect: &Expect) {
45 expect.assert_eq(&format!("{:#?}", import_action_titles(source)));
46}
47
48#[test]
49fn unresolved_term_offers_import() {
50 check_import_titles(
51 "namespace Test {
52 operation Main() : Unit {
53 Fake();
54 }
55 }",
56 &expect![[r#"
57 [
58 "Import FakeStdLib.Fake",
59 ]"#]],
60 );
61}
62
63#[test]
64fn unresolved_type_offers_import() {
65 check_import_titles(
66 "namespace Test {
67 operation Main(x : Udt) : Unit {}
68 }",
69 &expect![[r#"
70 [
71 "Import FakeStdLib.Udt",
72 ]"#]],
73 );
74}
75
76#[test]
77fn resolved_name_offers_no_import() {
78 check_import_titles(
79 "namespace Test {
80 open FakeStdLib;
81 operation Main() : Unit {
82 Fake();
83 }
84 }",
85 &expect![[r#"
86 []"#]],
87 );
88}
89
90#[test]
91fn qualified_unresolved_name_is_skipped() {
92 // v1 only handles unqualified names; a partial path like `Wrong.Fake` should not
93 // produce an auto-import quick fix.
94 check_import_titles(
95 "namespace Test {
96 operation Main() : Unit {
97 Wrong.Fake();
98 }
99 }",
100 &expect![[r#"
101 []"#]],
102 );
103}
104
105#[test]
106fn name_in_multiple_namespaces_offers_one_import_each() {
107 // The same unqualified name exists in two namespaces, neither of which is open,
108 // so a separate import action is offered for each (sorted by namespace name).
109 check_import_titles(
110 "namespace NsA {
111 operation Collide() : Unit {}
112 export Collide;
113 }
114 namespace NsB {
115 operation Collide() : Unit {}
116 export Collide;
117 }
118 namespace Test {
119 operation Main() : Unit {
120 Collide();
121 }
122 }",
123 &expect![[r#"
124 [
125 "Import NsA.Collide",
126 "Import NsB.Collide",
127 ]"#]],
128 );
129}
130
131#[test]
132fn import_edit_inserts_at_namespace_start() {
133 let source = "namespace Test {
134 operation Main() : Unit {
135 Fake();
136 }
137 }";
138 let (compilation, _targets) =
139 compile_project_with_markers_no_cursor(&[("<source>", source)], true);
140 let range = whole_document_range(source);
141 let actions = code_action::get_code_actions(&compilation, "<source>", range, Encoding::Utf8);
142 let action = actions
143 .iter()
144 .find(|a| a.title == "Import FakeStdLib.Fake")
145 .expect("expected an import action for Fake");
146
147 let edit = action.edit.as_ref().expect("expected an edit");
148 assert_eq!(edit.changes.len(), 1);
149 let (file, edits) = &edit.changes[0];
150 assert_eq!(file, "<source>");
151 assert_eq!(edits.len(), 1);
152 let text_edit = &edits[0];
153 // Insertion (zero-length range) before the first item in the namespace.
154 assert_eq!(text_edit.range.start, text_edit.range.end);
155 assert!(
156 text_edit.new_text.contains("import FakeStdLib.Fake;"),
157 "unexpected edit text: {:?}",
158 text_edit.new_text
159 );
160}
161
162#[test]
163fn notebook_unresolved_term_offers_import() {
164 let compilation = compile_notebook_with_fake_stdlib([("cell1", "Fake();")].into_iter());
165 let range = whole_document_range("Fake();");
166 let actions = code_action::get_code_actions(&compilation, "cell1", range, Encoding::Utf8);
167 let titles: Vec<String> = actions
168 .into_iter()
169 .filter(|a| a.title.starts_with("Import "))
170 .map(|a| a.title)
171 .collect();
172 expect![[r#"
173 [
174 "Import FakeStdLib.Fake",
175 ]"#]]
176 .assert_eq(&format!("{titles:#?}"));
177}
178