1#![doc = include_str!("readme.md")]
2pub mod formatter;
3#[cfg(feature = "oak-highlight")]
4pub mod highlighter;
5
6use crate::{PerlLanguage, parser::element_type::PerlElementType};
7use core::range::Range;
8use oak_core::tree::RedNode;
9#[cfg(feature = "lsp")]
10use {
11 oak_hover::{Hover as ProviderHover, HoverProvider},
12 oak_lsp::{service::LanguageService, types::Hover as LspHover},
13 oak_vfs::Vfs,
14};
15#[cfg(feature = "lsp")]
17pub struct PerlHoverProvider;
18#[cfg(feature = "lsp")]
19impl HoverProvider<PerlLanguage> for PerlHoverProvider {
20 fn hover(&self, node: &RedNode<PerlLanguage>, _range: Range<usize>) -> Option<ProviderHover> {
21 let kind = node.green.kind;
22 let contents = match kind {
23 PerlElementType::SubroutineDeclaration => "### Perl Subroutine\nA named block of code that can be called.",
24 PerlElementType::PackageDeclaration => "### Perl Package\nDefines a namespace for the code.",
25 PerlElementType::VariableDeclaration => "### Perl Variable\nA variable declared with `my`, `our`, or `local`.",
26 PerlElementType::IfStatement => "### If Statement\nConditional execution block.",
27 _ => return None,
28 };
29 Some(ProviderHover { contents: contents.to_string(), range: Some(node.span()) })
30 }
31}
32#[cfg(feature = "lsp")]
37pub struct PerlLanguageService<V: Vfs> {
38 vfs: V,
40 workspace: oak_lsp::workspace::WorkspaceManager,
42 hover_provider: PerlHoverProvider,
44}
45impl<V: Vfs> PerlLanguageService<V> {
46 pub fn new(vfs: V) -> Self {
48 Self { vfs, workspace: oak_lsp::workspace::WorkspaceManager::default(), hover_provider: PerlHoverProvider }
49 }
50}
51impl<V: Vfs + Send + Sync + 'static + oak_vfs::WritableVfs> LanguageService for PerlLanguageService<V> {
52 type Lang = PerlLanguage;
53 type Vfs = V;
54 fn vfs(&self) -> &Self::Vfs {
55 &self.vfs
56 }
57 fn workspace(&self) -> &oak_lsp::workspace::WorkspaceManager {
58 &self.workspace
59 }
60 fn get_root(&self, uri: &str) -> impl futures::Future<Output = Option<RedNode<'_, PerlLanguage>>> + Send + '_ {
61 let _source = self.get_source(uri);
62 async move {
63 None
65 }
66 }
67 fn hover(&self, uri: &str, range: Range<usize>) -> impl futures::Future<Output = Option<LspHover>> + Send + '_ {
68 let uri = uri.to_string();
69 async move { self.with_root(&uri, |root| self.hover_provider.hover(&root, range).map(|h| LspHover { contents: h.contents, range: h.range })).await.flatten() }
70 }
71 fn completion(&self, _uri: &str, _offset: usize) -> impl futures::Future<Output = Vec<oak_lsp::types::CompletionItem>> + Send + '_ {
72 async move { vec![] }
73 }
74}