Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
556 changes: 556 additions & 0 deletions crates/squawk_ide/src/folding_ranges.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/squawk_ide/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod db;
pub mod document_symbols;
pub mod expand_selection;
pub mod find_references;
pub mod folding_ranges;
mod generated;
pub mod goto_definition;
pub mod hover;
Expand Down
50 changes: 41 additions & 9 deletions crates/squawk_server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ use lsp_types::{
CodeAction, CodeActionKind, CodeActionOptions, CodeActionOrCommand, CodeActionParams,
CodeActionProviderCapability, CodeActionResponse, Command, CompletionOptions, CompletionParams,
CompletionResponse, Diagnostic, DidChangeTextDocumentParams, DidCloseTextDocumentParams,
DidOpenTextDocumentParams, DocumentSymbol, DocumentSymbolParams, GotoDefinitionParams,
GotoDefinitionResponse, Hover, HoverContents, HoverParams, HoverProviderCapability,
InitializeParams, InlayHint, InlayHintKind, InlayHintLabel, InlayHintLabelPart,
InlayHintParams, LanguageString, Location, MarkedString, OneOf, PublishDiagnosticsParams,
ReferenceParams, SelectionRangeParams, SelectionRangeProviderCapability, ServerCapabilities,
SymbolKind, TextDocumentSyncCapability, TextDocumentSyncKind, Url, WorkDoneProgressOptions,
WorkspaceEdit,
DidOpenTextDocumentParams, DocumentSymbol, DocumentSymbolParams, FoldingRange,
FoldingRangeProviderCapability, GotoDefinitionParams, GotoDefinitionResponse, Hover,
HoverContents, HoverParams, HoverProviderCapability, InitializeParams, InlayHint,
InlayHintKind, InlayHintLabel, InlayHintLabelPart, InlayHintParams, LanguageString, Location,
MarkedString, OneOf, PublishDiagnosticsParams, ReferenceParams, SelectionRangeParams,
SelectionRangeProviderCapability, ServerCapabilities, SymbolKind, TextDocumentSyncCapability,
TextDocumentSyncKind, Url, WorkDoneProgressOptions, WorkspaceEdit,
notification::{
DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, Notification as _,
PublishDiagnostics,
},
request::{
CodeActionRequest, Completion, DocumentSymbolRequest, GotoDefinition, HoverRequest,
InlayHintRequest, References, Request, SelectionRangeRequest,
CodeActionRequest, Completion, DocumentSymbolRequest, FoldingRangeRequest, GotoDefinition,
HoverRequest, InlayHintRequest, References, Request, SelectionRangeRequest,
},
};
use rowan::TextRange;
Expand All @@ -30,6 +30,7 @@ use squawk_ide::completion::completion;
use squawk_ide::db::{Database, File, line_index, parse};
use squawk_ide::document_symbols::{DocumentSymbolKind, document_symbols};
use squawk_ide::find_references::find_references;
use squawk_ide::folding_ranges::folding_ranges;
use squawk_ide::goto_definition::goto_definition;
use squawk_ide::hover::hover;
use squawk_ide::inlay_hints::inlay_hints;
Expand Down Expand Up @@ -119,6 +120,7 @@ pub fn run() -> Result<()> {
hover_provider: Some(HoverProviderCapability::Simple(true)),
inlay_hint_provider: Some(OneOf::Left(true)),
document_symbol_provider: Some(OneOf::Left(true)),
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
completion_provider: Some(CompletionOptions {
resolve_provider: Some(false),
trigger_characters: Some(vec![".".to_owned()]),
Expand Down Expand Up @@ -183,6 +185,9 @@ fn main_loop(connection: Connection, params: serde_json::Value) -> Result<()> {
DocumentSymbolRequest::METHOD => {
handle_document_symbol(&connection, req, &file_system)?;
}
FoldingRangeRequest::METHOD => {
handle_folding_range(&connection, req, &file_system)?;
}
Completion::METHOD => {
handle_completion(&connection, req, &file_system)?;
}
Expand Down Expand Up @@ -450,6 +455,33 @@ fn handle_document_symbol(
Ok(())
}

fn handle_folding_range(
connection: &Connection,
req: lsp_server::Request,
file_system: &impl FileSystem,
) -> Result<()> {
let params: lsp_types::FoldingRangeParams = serde_json::from_value(req.params)?;
let uri = params.text_document.uri;

let db = file_system.db();
let file = file_system.file(&uri).unwrap();
let line_idx = line_index(db, file);

let lsp_folds: Vec<FoldingRange> = folding_ranges(db, file)
.into_iter()
.map(|fold| lsp_utils::folding_range(&line_idx, fold))
.collect();

let resp = Response {
id: req.id,
result: Some(serde_json::to_value(&lsp_folds).unwrap()),
error: None,
};

connection.sender.send(Message::Response(resp))?;
Ok(())
}

fn handle_selection_range(
connection: &Connection,
req: lsp_server::Request,
Expand Down
23 changes: 22 additions & 1 deletion crates/squawk_server/src/lsp_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ use std::{collections::HashMap, ops::Range};

use line_index::{LineIndex, TextRange, TextSize};
use log::warn;
use lsp_types::{CodeAction, CodeActionKind, Url, WorkspaceEdit};
use lsp_types::{
CodeAction, CodeActionKind, FoldingRange, FoldingRangeKind as LspFoldingRangeKind, Url,
WorkspaceEdit,
};
use squawk_ide::code_actions::ActionKind;
use squawk_ide::folding_ranges::{Fold, FoldKind};

fn text_range(index: &LineIndex, range: lsp_types::Range) -> Option<TextRange> {
let start = offset(index, range.start)?;
Expand Down Expand Up @@ -143,6 +147,23 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang
)
}

pub(crate) fn folding_range(line_index: &LineIndex, fold: Fold) -> FoldingRange {
let start = line_index.line_col(fold.range.start());
let end = line_index.line_col(fold.range.end());
let kind = match fold.kind {
FoldKind::Comment => Some(LspFoldingRangeKind::Comment),
_ => Some(LspFoldingRangeKind::Region),
};
FoldingRange {
start_line: start.line,
start_character: Some(start.col),
end_line: end.line,
end_character: Some(end.col),
kind,
collapsed_text: None,
}
}

// base on rust-analyzer's
// see: https://github.com/rust-lang/rust-analyzer/blob/3816d0ae53c19fe75532a8b41d8c546d94246b53/crates/rust-analyzer/src/lsp/utils.rs#L168C1-L168C1
pub(crate) fn apply_incremental_changes(
Expand Down
1 change: 1 addition & 0 deletions crates/squawk_syntax/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod generated;
mod node_ext;
mod nodes;
mod support;
mod token_ext;
mod traits;

use std::marker::PhantomData;
Expand Down
25 changes: 25 additions & 0 deletions crates/squawk_syntax/src/ast/generated/tokens.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions crates/squawk_syntax/src/ast/token_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::ast::{self, AstToken};

impl ast::Whitespace {
pub fn spans_multiple_lines(&self) -> bool {
let text = self.text();
text.find('\n')
.is_some_and(|idx| text[idx + 1..].contains('\n'))
}
}

impl ast::Comment {
pub fn kind(&self) -> CommentKind {
CommentKind::from_text(self.text())
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CommentKind {
Line,
Block,
}

impl CommentKind {
const BY_PREFIX: [(&'static str, CommentKind); 3] = [
("/**/", CommentKind::Block),
("/*", CommentKind::Block),
("--", CommentKind::Line),
];
pub(crate) fn from_text(text: &str) -> CommentKind {
let &(_prefix, kind) = CommentKind::BY_PREFIX
.iter()
.find(|&(prefix, _kind)| text.starts_with(prefix))
.unwrap();
kind
}

pub fn is_line(self) -> bool {
self == CommentKind::Line
}

pub fn is_block(self) -> bool {
self == CommentKind::Block
}
}
1 change: 1 addition & 0 deletions crates/xtask/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ fn lower(grammar: &Grammar) -> AstSrc {
("Null", "NULL_KW"),
("String", "STRING"),
("Comment", "COMMENT"),
("Whitespace", "WHITESPACE"),
];
let mut res = AstSrc {
tokens,
Expand Down
Loading