use std::sync::Arc;
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range};
use crate::document::ast::ParsedDoc;
pub const PHP_LSP_SOURCE: &str = "php-lsp";
pub fn parse_document_no_diags(source: &str) -> ParsedDoc {
ParsedDoc::parse(Arc::from(source))
}
pub fn diagnostics_from_doc(doc: &ParsedDoc) -> Vec<Diagnostic> {
let sv = doc.view();
doc.errors
.iter()
.map(|e| {
let span = e.span();
let start = sv.position_of(span.start);
let end = if span.end > span.start {
sv.position_of(span.end)
} else {
let ch_width = sv.source()[span.start as usize..]
.chars()
.next()
.map(|c| c.len_utf16() as u32)
.unwrap_or(1);
Position {
line: start.line,
character: start.character + ch_width,
}
};
Diagnostic {
range: Range { start, end },
severity: Some(DiagnosticSeverity::ERROR),
source: Some(PHP_LSP_SOURCE.to_string()),
message: e.to_string(),
..Default::default()
}
})
.collect()
}
pub fn merge_file_diagnostics(
parse: Vec<Diagnostic>,
semantic: Vec<Diagnostic>,
) -> Vec<Diagnostic> {
let mut all = parse;
all.extend(semantic);
all
}
pub fn parse_document(source: &str) -> (ParsedDoc, Vec<Diagnostic>) {
let doc = parse_document_no_diags(source);
let diagnostics = diagnostics_from_doc(&doc);
(doc, diagnostics)
}