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
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ rustc-hash = "2.1.1"

# local
# we have to make the versions explicit otherwise `cargo publish` won't work
squawk-fmt = { path = "./crates/squawk_fmt", version = "2.63.0" }
squawk-github = { path = "./crates/squawk_github", version = "2.63.0" }
squawk-ide = { path = "./crates/squawk_ide", version = "2.63.0" }
squawk-lexer = { path = "./crates/squawk_lexer", version = "2.63.0" }
Expand Down
1 change: 1 addition & 0 deletions crates/squawk_fmt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ squawk-line-index.workspace = true
rowan.workspace = true
clap.workspace = true
anyhow.workspace = true
annotate-snippets.workspace = true

[dev-dependencies]
insta.workspace = true
Expand Down
30 changes: 16 additions & 14 deletions crates/squawk_fmt/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22951,25 +22951,13 @@ fn build_target<'a>(target: ast::Target) -> Option<Doc<'a>> {
Some(doc)
}

pub fn fmt(text: &str) -> Result<String> {
let line_ending = find_newline(text)
.map(|(_, ending)| ending)
.unwrap_or_default();

pub fn fmt(source_file: &ast::SourceFile, line_ending: LineEnding) -> Result<String> {
let line_break = match line_ending {
LineEnding::Cr => LineBreak::Cr,
LineEnding::CrLf => LineBreak::Crlf,
LineEnding::Lf => LineBreak::Lf,
};

let parse = ast::SourceFile::parse(text);
let file = parse.tree();
debug_assert_eq!(
parse.errors(),
vec![],
"should bail out when there's parse errors"
);
let doc = build_source_file(&file);
let doc = build_source_file(source_file);

Ok(print(
&doc,
Expand All @@ -22979,3 +22967,17 @@ pub fn fmt(text: &str) -> Result<String> {
},
))
}

pub fn fmt_str(text: &str) -> Result<String> {
let line_ending = find_newline(text)
.map(|(_, ending)| ending)
.unwrap_or_default();
let parse = ast::SourceFile::parse(text);
let errors = parse.errors();
if !errors.is_empty() {
let messages = errors.iter().map(ToString::to_string).join("\n");
anyhow::bail!(messages);
}

fmt(&parse.tree(), line_ending)
}
2 changes: 1 addition & 1 deletion crates/squawk_fmt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
mod fmt;

pub use fmt::fmt;
pub use fmt::{fmt, fmt_str};
42 changes: 35 additions & 7 deletions crates/squawk_fmt/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::io::{self, Read};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::process::ExitCode;

use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle};
use anyhow::Result;
use clap::Parser;
use squawk_syntax::SourceFile;

#[derive(Parser)]
#[command(name = "squawk-fmt")]
Expand All @@ -11,18 +14,43 @@ struct Cli {
file: Option<PathBuf>,
}

fn main() -> Result<()> {
fn main() -> Result<ExitCode> {
let cli = Cli::parse();

let input = match cli.file {
Some(path) => std::fs::read_to_string(&path)?,
let (input, path) = match cli.file {
Some(path) => {
let input = std::fs::read_to_string(&path)?;
(input, path.display().to_string())
}
None => {
let mut buf = String::new();
io::stdin().read_to_string(&mut buf)?;
buf
(buf, "stdin".to_string())
}
};

print!("{}", squawk_fmt::fmt(&input)?);
Ok(())
let parse = SourceFile::parse(&input);
let errors = parse.errors();
if !errors.is_empty() {
let renderer = Renderer::styled().decor_style(DecorStyle::Unicode);
let stderr = io::stderr();
let mut stderr = stderr.lock();

for error in errors {
let snippet = Snippet::source(&input)
.path(&path)
.fold(true)
.annotation(AnnotationKind::Primary.span(error.range().into()));
let group = Level::ERROR
.primary_title(error.message())
.id("syntax-error")
.element(snippet);
writeln!(stderr, "{}", renderer.render(&[group]))?;
}

return Ok(ExitCode::FAILURE);
}

write!(io::stdout().lock(), "{}", squawk_fmt::fmt_str(&input)?)?;
Ok(ExitCode::SUCCESS)
}
4 changes: 2 additions & 2 deletions crates/squawk_fmt/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn fmt(fixture: Fixture<&str>) {
.and_then(|x| x.strip_suffix(".sql"))
.unwrap();

let formatted = squawk_fmt::fmt(content).unwrap();
let formatted = squawk_fmt::fmt_str(content).unwrap();

assert_no_dropped_tokens(content, &formatted);

Expand All @@ -42,7 +42,7 @@ fn fmt_with_line_ending(line_ending: &str) -> String {
]
.join(line_ending);

match squawk_fmt::fmt(&sql) {
match squawk_fmt::fmt_str(&sql) {
Ok(formatted) => {
assert_no_dropped_tokens(&sql, &formatted);
formatted.replace('\r', "<CR>")
Expand Down
1 change: 1 addition & 0 deletions crates/squawk_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ rowan.workspace = true
salsa.workspace = true
serde.workspace = true
serde_json.workspace = true
squawk-fmt.workspace = true
squawk-ide.workspace = true
squawk-lexer.workspace = true
squawk-linter.workspace = true
Expand Down
13 changes: 8 additions & 5 deletions crates/squawk_server/src/global_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ use url::Url;

use gen_lsp_types::{
CodeActionRequest, CompletionRequest, DefinitionRequest, DocumentDiagnosticRequest,
DocumentSymbolRequest, FoldingRangeRequest, HoverRequest, InlayHintRequest, ReferencesRequest,
SelectionRangeRequest, SemanticTokensRangeRequest, SemanticTokensRequest, ShutdownRequest,
DocumentFormattingRequest, DocumentSymbolRequest, FoldingRangeRequest, HoverRequest,
InlayHintRequest, ReferencesRequest, SelectionRangeRequest, SemanticTokensRangeRequest,
SemanticTokensRequest, ShutdownRequest,
};

use crate::dispatch::{NotificationDispatcher, RequestDispatcher};
use crate::handlers::{
SyntaxTreeRequest, TokensRequest, handle_cancel, handle_code_action, handle_completion,
handle_did_change, handle_did_close, handle_did_open, handle_document_diagnostic,
handle_document_symbol, handle_folding_range, handle_goto_definition, handle_hover,
handle_inlay_hints, handle_references, handle_selection_range, handle_semantic_tokens_full,
handle_semantic_tokens_range, handle_shutdown, handle_syntax_tree, handle_tokens,
handle_document_symbol, handle_folding_range, handle_formatting, handle_goto_definition,
handle_hover, handle_inlay_hints, handle_references, handle_selection_range,
handle_semantic_tokens_full, handle_semantic_tokens_range, handle_shutdown, handle_syntax_tree,
handle_tokens,
};

type ReqQueue = lsp_server::ReqQueue<(String, Instant), ()>;
Expand Down Expand Up @@ -242,6 +244,7 @@ impl GlobalState {
.on::<NO_RETRY, CodeActionRequest>(handle_code_action)
.on::<NO_RETRY, InlayHintRequest>(handle_inlay_hints)
.on::<RETRY, DocumentSymbolRequest>(handle_document_symbol)
.on::<NO_RETRY, DocumentFormattingRequest>(handle_formatting)
.on::<RETRY, FoldingRangeRequest>(handle_folding_range)
.on::<NO_RETRY, DocumentDiagnosticRequest>(handle_document_diagnostic)
.on::<NO_RETRY, SyntaxTreeRequest>(handle_syntax_tree)
Expand Down
2 changes: 2 additions & 0 deletions crates/squawk_server/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod completion;
mod diagnostic;
mod document_symbol;
mod folding_range;
mod formatting;
mod goto_definition;
mod hover;
mod inlay_hints;
Expand All @@ -19,6 +20,7 @@ pub(crate) use completion::handle_completion;
pub(crate) use diagnostic::handle_document_diagnostic;
pub(crate) use document_symbol::handle_document_symbol;
pub(crate) use folding_range::handle_folding_range;
pub(crate) use formatting::handle_formatting;
pub(crate) use goto_definition::handle_goto_definition;
pub(crate) use hover::handle_hover;
pub(crate) use inlay_hints::handle_inlay_hints;
Expand Down
37 changes: 37 additions & 0 deletions crates/squawk_server/src/handlers/formatting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use anyhow::Result;
use gen_lsp_types::{DocumentFormattingParams, TextEdit};
use rowan::{TextRange, TextSize};
use squawk_ide::db::{line_index, parse};
use squawk_line_index::find_newline;

use crate::global_state::Snapshot;
use crate::lsp_utils;

pub(crate) fn handle_formatting(
snapshot: &Snapshot,
params: DocumentFormattingParams,
) -> Result<Option<Vec<TextEdit>>> {
let db = snapshot.db();
let file = snapshot.file(&params.text_document.uri).unwrap();
let content = file.content(db);
let line_ending = find_newline(content)
.map(|(_, ending)| ending)
.unwrap_or_default();
let parse = parse(db, file);
if !parse.errors().is_empty() {
return Ok(Some(Vec::new()));
}
let formatted = squawk_fmt::fmt(&parse.tree(), line_ending)?;

if formatted == content.as_ref() {
return Ok(Some(Vec::new()));
}

let range = TextRange::new(TextSize::default(), TextSize::try_from(content.len())?);
let range = lsp_utils::range(&line_index(db, file), range);

Ok(Some(vec![TextEdit {
range,
new_text: formatted,
}]))
}
11 changes: 6 additions & 5 deletions crates/squawk_server/src/server.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use anyhow::Result;
use gen_lsp_types::{
CodeActionKind, CodeActionOptions, CodeActionProvider, CompletionOptions, DefinitionProvider,
DiagnosticOptions, DiagnosticProvider, DocumentSymbolProvider, FoldingRangeProvider, Full,
HoverProvider, InitializeParams, InlayHintProvider, ReferencesProvider, SelectionRangeProvider,
SemanticTokensLegend, SemanticTokensOptions, SemanticTokensOptionsRange,
SemanticTokensProvider, ServerCapabilities, TextDocumentSync, TextDocumentSyncKind,
WorkDoneProgressOptions,
DiagnosticOptions, DiagnosticProvider, DocumentFormattingProvider, DocumentSymbolProvider,
FoldingRangeProvider, Full, HoverProvider, InitializeParams, InlayHintProvider,
ReferencesProvider, SelectionRangeProvider, SemanticTokensLegend, SemanticTokensOptions,
SemanticTokensOptionsRange, SemanticTokensProvider, ServerCapabilities, TextDocumentSync,
TextDocumentSyncKind, WorkDoneProgressOptions,
};
use log::info;
use lsp_server::Connection;
Expand Down Expand Up @@ -47,6 +47,7 @@ pub fn run() -> Result<()> {
},
})),
document_symbol_provider: Some(DocumentSymbolProvider::Bool(true)),
document_formatting_provider: Some(DocumentFormattingProvider::Bool(true)),
folding_range_provider: Some(FoldingRangeProvider::Bool(true)),
completion_provider: Some(CompletionOptions {
resolve_provider: Some(false),
Expand Down
Loading