mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
186 lines
5.4 KiB
Rust
186 lines
5.4 KiB
Rust
//! Editor providers: implement [`Providers`] and register with
|
|
//! `register_plugin!(T, providers)`, then declare the kinds and languages in
|
|
//! `plugin.toml`:
|
|
//!
|
|
//! ```toml
|
|
//! [[contributes.providers]]
|
|
//! kinds = ["completion", "definition"] # also inline-completion, code-actions, line-markers
|
|
//! languages = ["xml"]
|
|
//! ```
|
|
//!
|
|
//! They run on the editing path: answer within ~50 ms (later results are
|
|
//! dropped; at 500 ms the call is interrupted). Inline completion may take
|
|
//! longer (it may use the network) but is cancelled when the user types on.
|
|
|
|
use crate::types::{Location, Position, Range, TextEdit};
|
|
|
|
/// The document a request is about.
|
|
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
|
pub struct Document {
|
|
pub path: String,
|
|
pub language: String,
|
|
pub version: u64,
|
|
pub text: String,
|
|
}
|
|
|
|
/// Icon and sort group of a completion item.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
#[non_exhaustive]
|
|
pub enum CompletionKind {
|
|
Text,
|
|
Method,
|
|
Function,
|
|
Constructor,
|
|
Field,
|
|
Variable,
|
|
Class,
|
|
Interface,
|
|
Module,
|
|
Property,
|
|
Unit,
|
|
Value,
|
|
Enum,
|
|
Keyword,
|
|
Snippet,
|
|
Color,
|
|
File,
|
|
Reference,
|
|
Folder,
|
|
EnumMember,
|
|
Constant,
|
|
Struct,
|
|
Event,
|
|
Operator,
|
|
TypeParameter,
|
|
}
|
|
|
|
impl CompletionKind {
|
|
/// The name the plugin API uses (`completion-item.kind`).
|
|
pub fn as_str(self) -> &'static str {
|
|
match self {
|
|
Self::Text => "text",
|
|
Self::Method => "method",
|
|
Self::Function => "function",
|
|
Self::Constructor => "constructor",
|
|
Self::Field => "field",
|
|
Self::Variable => "variable",
|
|
Self::Class => "class",
|
|
Self::Interface => "interface",
|
|
Self::Module => "module",
|
|
Self::Property => "property",
|
|
Self::Unit => "unit",
|
|
Self::Value => "value",
|
|
Self::Enum => "enum",
|
|
Self::Keyword => "keyword",
|
|
Self::Snippet => "snippet",
|
|
Self::Color => "color",
|
|
Self::File => "file",
|
|
Self::Reference => "reference",
|
|
Self::Folder => "folder",
|
|
Self::EnumMember => "enum-member",
|
|
Self::Constant => "constant",
|
|
Self::Struct => "struct",
|
|
Self::Event => "event",
|
|
Self::Operator => "operator",
|
|
Self::TypeParameter => "type-parameter",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct CompletionItem {
|
|
pub label: String,
|
|
pub detail: Option<String>,
|
|
pub kind: Option<CompletionKind>,
|
|
/// With `snippet`, tab stops and placeholders (`$1`, `${1:name}`, `$0`).
|
|
pub insert_text: String,
|
|
pub snippet: bool,
|
|
/// Replaced on accept; `None`: the word at the caret.
|
|
pub replace: Option<Range>,
|
|
pub sort_text: Option<String>,
|
|
/// Matched against what was typed instead of `label`.
|
|
pub filter_text: Option<String>,
|
|
/// Markdown.
|
|
pub documentation: Option<String>,
|
|
/// Applied with the item elsewhere in the document (an import).
|
|
pub additional_edits: Vec<TextEdit>,
|
|
}
|
|
|
|
impl CompletionItem {
|
|
pub fn new(label: &str, kind: CompletionKind) -> Self {
|
|
Self {
|
|
label: label.into(),
|
|
detail: None,
|
|
kind: Some(kind),
|
|
insert_text: label.into(),
|
|
snippet: false,
|
|
replace: None,
|
|
sort_text: None,
|
|
filter_text: None,
|
|
documentation: None,
|
|
additional_edits: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct InlineSuggestion {
|
|
pub insert_text: String,
|
|
/// Replaced range; `None` inserts at the caret.
|
|
pub replace: Option<Range>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct CodeAction {
|
|
pub title: String,
|
|
/// `quickfix`, `refactor`, …
|
|
pub kind: Option<String>,
|
|
pub preferred: bool,
|
|
/// (absolute path, edits) per file.
|
|
pub edits: Vec<(String, Vec<TextEdit>)>,
|
|
/// The plugin's own reference: with it and no `edits`, the edits come
|
|
/// from [`Providers::resolve_code_action`] once the user picks the action.
|
|
pub data: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct LineMarker {
|
|
/// 0-based.
|
|
pub line: u32,
|
|
/// `navigate` (default), `implemented`, `implementing`, `run`.
|
|
pub icon: Option<String>,
|
|
pub tooltip: String,
|
|
/// Opened on click.
|
|
pub target: Option<Location>,
|
|
}
|
|
|
|
/// What a plugin provides in the editor. Only the kinds declared in
|
|
/// `plugin.toml` are ever called; the defaults return nothing.
|
|
pub trait Providers {
|
|
fn completion(&mut self, _doc: &Document, _at: Position, _trigger: Option<&str>) -> Vec<CompletionItem> {
|
|
Vec::new()
|
|
}
|
|
|
|
fn inline_completion(&mut self, _doc: &Document, _at: Position) -> Option<InlineSuggestion> {
|
|
None
|
|
}
|
|
|
|
fn code_actions(&mut self, _doc: &Document, _selection: Range) -> Vec<CodeAction> {
|
|
Vec::new()
|
|
}
|
|
|
|
/// The edits of an action [`Providers::code_actions`] returned with
|
|
/// `data`, when the user picks it (the command budget applies, not 50 ms).
|
|
fn resolve_code_action(&mut self, _doc: &Document, action: CodeAction) -> Result<CodeAction, crate::Error> {
|
|
Ok(action)
|
|
}
|
|
|
|
fn definition(&mut self, _doc: &Document, _at: Position) -> Vec<Location> {
|
|
Vec::new()
|
|
}
|
|
|
|
fn line_markers(&mut self, _doc: &Document) -> Vec<LineMarker> {
|
|
Vec::new()
|
|
}
|
|
}
|