microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/language_service/src/completion/openqasm.rs
100lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use std::iter::once; |
| 5 | |
| 6 | use crate::{ |
| 7 | Compilation, |
| 8 | completion::{AstContext, Fields, Globals, collect_path_segments}, |
| 9 | protocol::{CompletionItemKind, CompletionList}, |
| 10 | }; |
| 11 | |
| 12 | use super::{Completion, Locals, into_completion_list}; |
| 13 | |
| 14 | pub(super) fn completions( |
| 15 | compilation: &Compilation, |
| 16 | source_contents: &str, |
| 17 | cursor_offset: u32, |
| 18 | ) -> CompletionList { |
| 19 | let expected_words_at_cursor = |
| 20 | qsc::qasm::completion::possible_words_at_offset_in_source(source_contents, cursor_offset); |
| 21 | |
| 22 | // Now that we have the information from the parser about what kinds of |
| 23 | // words are expected, gather the actual words (identifiers, keywords, etc) for each kind. |
| 24 | |
| 25 | // Keywords and other hardcoded words |
| 26 | let hardcoded_completions = collect_hardcoded_words(expected_words_at_cursor); |
| 27 | |
| 28 | // The tricky bit: locals, names we need to gather from the compilation. |
| 29 | let name_completions = collect_names_qasm(expected_words_at_cursor, cursor_offset, compilation); |
| 30 | |
| 31 | // We have all the data, put everything into a completion list. |
| 32 | into_completion_list(once(hardcoded_completions).chain(name_completions)) |
| 33 | } |
| 34 | |
| 35 | #[allow(clippy::items_after_statements)] |
| 36 | fn collect_hardcoded_words( |
| 37 | expected: qsc::qasm::completion::word_kinds::WordKinds, |
| 38 | ) -> Vec<Completion> { |
| 39 | let mut completions = Vec::new(); |
| 40 | for word_kind in expected.iter_hardcoded_ident_kinds() { |
| 41 | match word_kind { |
| 42 | qsc::qasm::completion::word_kinds::HardcodedIdentKind::Annotation => { |
| 43 | completions.extend([Completion::new( |
| 44 | "SimulatableIntrinsic".to_string(), |
| 45 | CompletionItemKind::Interface, |
| 46 | )]); |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | for keyword in expected.iter_keywords() { |
| 52 | completions.push(Completion::new( |
| 53 | keyword.to_string(), |
| 54 | CompletionItemKind::Keyword, |
| 55 | )); |
| 56 | } |
| 57 | |
| 58 | completions |
| 59 | } |
| 60 | |
| 61 | #[allow(clippy::items_after_statements)] |
| 62 | fn collect_paths( |
| 63 | expected: qsc::qasm::completion::word_kinds::PathKind, |
| 64 | locals_at_cursor: &Locals, |
| 65 | ) -> Vec<Vec<Completion>> { |
| 66 | let mut locals_and_builtins = Vec::new(); |
| 67 | match expected { |
| 68 | qsc::qasm::completion::word_kinds::PathKind::Expr => { |
| 69 | locals_and_builtins.push(locals_at_cursor.expr_names()); |
| 70 | } |
| 71 | } |
| 72 | locals_and_builtins |
| 73 | } |
| 74 | |
| 75 | #[allow(clippy::items_after_statements)] |
| 76 | fn collect_names_qasm( |
| 77 | expected: qsc::qasm::completion::word_kinds::WordKinds, |
| 78 | cursor_offset: u32, |
| 79 | compilation: &Compilation, |
| 80 | ) -> Vec<Vec<Completion>> { |
| 81 | let mut groups = Vec::new(); |
| 82 | use qsc::qasm::completion::word_kinds::NameKind; |
| 83 | for name_kind in expected.iter_name_kinds() { |
| 84 | match name_kind { |
| 85 | NameKind::Path(path_kind) => { |
| 86 | let locals = Locals::new(cursor_offset, compilation); |
| 87 | groups.extend(collect_paths(path_kind, &locals)); |
| 88 | } |
| 89 | NameKind::PathSegment => { |
| 90 | let globals = Globals::init(cursor_offset, compilation); |
| 91 | let ast_context = |
| 92 | AstContext::init(cursor_offset, &compilation.user_unit().ast.package); |
| 93 | let fields = Fields::new(compilation, &ast_context); |
| 94 | |
| 95 | groups.extend(collect_path_segments(&ast_context, &globals, &fields)); |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | groups |
| 100 | } |
| 101 | |