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