Skip to main content

oak_perl/lsp/
mod.rs

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/// Hover provider implementation for Perl.
16#[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/// Language service implementation for Perl.
33///
34/// This service provides LSP features like hover, completion, and diagnostics
35/// for the Perl language, utilizing the VFS for file management.
36#[cfg(feature = "lsp")]
37pub struct PerlLanguageService<V: Vfs> {
38    /// Virtual file system.
39    vfs: V,
40    /// Workspace manager.
41    workspace: oak_lsp::workspace::WorkspaceManager,
42    /// Hover provider.
43    hover_provider: PerlHoverProvider,
44}
45impl<V: Vfs> PerlLanguageService<V> {
46    /// Creates a new `PerlLanguageService` with the given VFS.
47    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            // TODO: Implement proper caching of parsed trees in LanguageService
64            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}