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
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ jobs:
- run: rustup update stable && rustup default stable
- run: cargo build --verbose
- run: cargo test --verbose

wasm:
name: analysis lib - wasm32
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update stable && rustup default stable && rustup target add wasm32-unknown-unknown
- run: cargo build --no-default-features --target wasm32-unknown-unknown --verbose
45 changes: 26 additions & 19 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,39 @@ version = "0.1.0"
edition = "2021"
license = "GPL-3.0-only"

[lib]
name = "comline_language_server"
path = "src/lib.rs"

[[bin]]
name = "comline-lsp"
path = "src/main.rs"
required-features = ["server"]

[dependencies]
# LSP Infrastructure
tower-lsp = "0.20.0"
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# Comline Core Integration — by git rev, like the rest of the tree (the LSP
# links `comline-core` and is part of the GPL toolchain). Local iteration:
# uncomment the `[patch]` below onto a sibling `core` checkout.
comline-core = { git = "https://github.com/ComlineProject/core", rev = "50c17cc740676416e945582dd6e2547e8535ac03" }
rust-sitter = "0.4.5" # For parse error types

# Diagnostics & Error Reporting
ariadne = { version = "0.4.0", features = ["auto-color"] }
codespan-reporting = "0.11"
[features]
default = ["server"]
# The `tower-lsp` stdio server (the `comline-lsp` binary). With it off, only the
# analysis library builds — `parser` + `analysis` + `handlers`, over `lsp-types`
# and `comline-core` — and that compiles for `wasm32-unknown-unknown`. The
# Comline playground links the crate that way.
server = ["dep:tower-lsp", "dep:tokio", "dep:tracing-subscriber", "dep:dashmap"]

# Utilities
[dependencies]
# The analysis layer: pure `lsp-types` (serde only, wasm-safe), the parser, and
# `comline-core`. By git rev, like the rest of the tree — the LSP links
# `comline-core` and is part of the GPL toolchain. Local iteration: uncomment
# the `[patch]` below onto a sibling `core` checkout.
lsp-types = "0.94"
rust-sitter = "0.4.5"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
anyhow = "1.0"
dashmap = "5.5"
comline-core = { git = "https://github.com/ComlineProject/core", rev = "50c17cc740676416e945582dd6e2547e8535ac03" }

# `server`-only.
tower-lsp = { version = "0.20.0", optional = true }
tokio = { version = "1.35", features = ["full"], optional = true }
tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true }
dashmap = { version = "5.5", optional = true }

# Local iteration against a sibling `core` checkout — uncomment to build
# `comline-core` from the working tree instead of the pinned git rev.
Expand Down
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@ A Language Server Protocol (LSP) implementation for [Comline](https://github.com
- **Hover Information** - Rich tooltips showing full type definitions and signatures
- **Go to Definition** - Jump from type references to their declarations
- **Find References** - Locate all usages of a symbol (with include/exclude declaration option)
- **Auto-Completion** - Context-aware code suggestions:
- Keywords with snippets (`struct`, `enum`, `protocol`, `const`, `use`, `import`)
- Primitive types (i8-i64, u8-u64, f32/f64, string, bool)
- User-defined types (all structs, enums, protocols from current file)
- Context detection (type position, top-level, struct body)

### 🚧 Planned

- Find References - Locate all usages of a symbol
- Auto-Completion - Context-aware code completion
- Rename Symbol - Safe refactoring across files
- Code Formatting - Automatic code formatting
- Semantic Tokens - Enhanced syntax highlighting
- **Auto-Completion** - Context-aware code suggestions (keywords, primitives, user types)
- **Semantic Tokens** - Comline syntax highlighting from a shared lexer

### 🚧 Rougher / next

- Rename Symbol, Code Formatting, Signature Help, Code Actions — present but thin
- Cross-file `use` resolution (analysis is single-file today)
- AST-accurate spans (declaration ranges use a text-search heuristic)

## Library

The crate is also an **analysis library**. `--no-default-features` drops the
`server` feature (`tower-lsp`, `tokio`, the doc store, the `comline-lsp` bin),
leaving `parser` + `analysis` + `handlers` over `lsp-types` and `comline-core` —
which **builds for `wasm32-unknown-unknown`**. The Comline playground links it
that way so its browser editor runs the *same* diagnostics, hover, completion
and highlighting as the LSP.

## Installation

Expand Down
2 changes: 1 addition & 1 deletion src/analysis/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use comline_core::schema::idl::grammar::Document;
use comline_core::schema::ir::compiler::interpreter::incremental::IncrementalInterpreter;
use comline_core::schema::ir::compiler::Compile;
use comline_core::schema::ir::validation;
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
use lsp_types::{Diagnostic, DiagnosticSeverity};

/// Semantic diagnostics from `comline-core`'s validation pass — undefined type
/// references, duplicate declarations, and the like: the same checks
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use comline_core::schema::idl::grammar::{Declaration, Document};
use std::collections::HashMap;
use tower_lsp::lsp_types::{Location, Position, Range, SymbolKind, Url};
use lsp_types::{Location, Position, Range, SymbolKind, Url};

#[derive(Debug, Clone)]
pub struct Symbol {
Expand Down
16 changes: 8 additions & 8 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::document::DocumentStore;

//
use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::*;
use lsp_types::*;
use tower_lsp::{Client, LanguageServer};

pub struct Backend {
Expand Down Expand Up @@ -51,17 +51,17 @@ impl LanguageServer for Backend {
SemanticTokensServerCapabilities::SemanticTokensOptions(
SemanticTokensOptions {
legend: SemanticTokensLegend {
// Order must match the indices in
// `handlers::semantic_tokens` (`LEGEND_TYPES`).
token_types: vec![
SemanticTokenType::KEYWORD,
SemanticTokenType::TYPE,
SemanticTokenType::STRUCT,
SemanticTokenType::ENUM,
SemanticTokenType::INTERFACE,
SemanticTokenType::FUNCTION,
SemanticTokenType::VARIABLE,
SemanticTokenType::PROPERTY,
SemanticTokenType::STRING,
SemanticTokenType::COMMENT,
SemanticTokenType::NUMBER,
SemanticTokenType::DECORATOR,
],
token_modifiers: vec![SemanticTokenModifier::DECLARATION],
token_modifiers: vec![],
},
range: Some(false),
full: Some(SemanticTokensFullOptions::Bool(true)),
Expand Down
2 changes: 1 addition & 1 deletion src/document.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use dashmap::DashMap;
use std::sync::Arc;
use tower_lsp::lsp_types::Url;
use lsp_types::Url;

/// Represents a document in the workspace
#[derive(Debug, Clone)]
Expand Down
8 changes: 4 additions & 4 deletions src/handlers/code_actions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Code actions handler - provides quick fixes and refactorings

use tower_lsp::lsp_types::{CodeActionOrCommand, CodeActionParams, Url};
use lsp_types::{CodeActionOrCommand, CodeActionParams, Url};

/// Get code actions for a given range
pub fn get_code_actions(
Expand Down Expand Up @@ -28,9 +28,9 @@ mod tests {
let source = "struct User {}";
let uri = Url::parse("file:///test.ids").unwrap();
let params = CodeActionParams {
text_document: tower_lsp::lsp_types::TextDocumentIdentifier { uri: uri.clone() },
range: tower_lsp::lsp_types::Range::default(),
context: tower_lsp::lsp_types::CodeActionContext {
text_document: lsp_types::TextDocumentIdentifier { uri: uri.clone() },
range: lsp_types::Range::default(),
context: lsp_types::CodeActionContext {
diagnostics: vec![],
only: None,
trigger_kind: None,
Expand Down
16 changes: 8 additions & 8 deletions src/handlers/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::analysis::symbols;
use crate::parser;
use crate::util::position_to_offset;
use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, Position, Url};
use lsp_types::{CompletionItem, CompletionItemKind, Position, Url};

/// Get completion suggestions at a position
pub fn get_completions(source: &str, uri: &Url, position: Position) -> Vec<CompletionItem> {
Expand Down Expand Up @@ -113,31 +113,31 @@ fn get_keyword_completions() -> Vec<CompletionItem> {
kind: Some(CompletionItemKind::KEYWORD),
detail: Some("Define a structure".to_string()),
insert_text: Some("struct $1 {\n\t$0\n}".to_string()),
insert_text_format: Some(tower_lsp::lsp_types::InsertTextFormat::SNIPPET),
insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET),
..Default::default()
},
CompletionItem {
label: "enum".to_string(),
kind: Some(CompletionItemKind::KEYWORD),
detail: Some("Define an enumeration".to_string()),
insert_text: Some("enum $1 {\n\t$0\n}".to_string()),
insert_text_format: Some(tower_lsp::lsp_types::InsertTextFormat::SNIPPET),
insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET),
..Default::default()
},
CompletionItem {
label: "protocol".to_string(),
kind: Some(CompletionItemKind::KEYWORD),
detail: Some("Define a protocol".to_string()),
insert_text: Some("protocol $1 {\n\t$0\n}".to_string()),
insert_text_format: Some(tower_lsp::lsp_types::InsertTextFormat::SNIPPET),
insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET),
..Default::default()
},
CompletionItem {
label: "const".to_string(),
kind: Some(CompletionItemKind::KEYWORD),
detail: Some("Define a constant".to_string()),
insert_text: Some("const $1: $2 = $0".to_string()),
insert_text_format: Some(tower_lsp::lsp_types::InsertTextFormat::SNIPPET),
insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET),
..Default::default()
},
CompletionItem {
Expand Down Expand Up @@ -250,9 +250,9 @@ fn get_type_completions(symbol_table: &symbols::SymbolTable) -> Vec<CompletionIt
.iter()
.map(|symbol| {
let kind = match symbol.kind {
tower_lsp::lsp_types::SymbolKind::STRUCT => CompletionItemKind::STRUCT,
tower_lsp::lsp_types::SymbolKind::ENUM => CompletionItemKind::ENUM,
tower_lsp::lsp_types::SymbolKind::INTERFACE => CompletionItemKind::INTERFACE,
lsp_types::SymbolKind::STRUCT => CompletionItemKind::STRUCT,
lsp_types::SymbolKind::ENUM => CompletionItemKind::ENUM,
lsp_types::SymbolKind::INTERFACE => CompletionItemKind::INTERFACE,
_ => CompletionItemKind::CLASS,
};

Expand Down
2 changes: 1 addition & 1 deletion src/handlers/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::analysis::symbols;
use crate::parser;
use crate::util::position_to_offset;
use tower_lsp::lsp_types::{GotoDefinitionResponse, Position, Url};
use lsp_types::{GotoDefinitionResponse, Position, Url};

/// Find the definition of a symbol at a position
pub fn find_definition(source: &str, uri: &Url, position: Position) -> Option<GotoDefinitionResponse> {
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/formatting.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Formatting handler - formats Comline code

use tower_lsp::lsp_types::{Position, Range, TextEdit};
use lsp_types::{Position, Range, TextEdit};

/// Format an entire document
pub fn format_document(source: &str) -> Vec<TextEdit> {
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::analysis::symbols;
use crate::parser;
use crate::util::position_to_offset;
use comline_core::schema::idl::grammar::{Declaration, Type};
use tower_lsp::lsp_types::{Hover, HoverContents, MarkedString, Position, Url};
use lsp_types::{Hover, HoverContents, MarkedString, Position, Url};

/// Get hover information at a position
pub fn get_hover_info(source: &str, uri: &Url, position: Position) -> Option<Hover> {
Expand Down Expand Up @@ -41,7 +41,7 @@ pub fn get_hover_info(source: &str, uri: &Url, position: Position) -> Option<Hov

/// Create hover for a symbol (struct, enum, protocol, const)
fn create_symbol_hover(symbol: &symbols::Symbol, document: &comline_core::schema::idl::grammar::Document) -> Hover {
use tower_lsp::lsp_types::SymbolKind;
use lsp_types::SymbolKind;

let mut contents = vec![];

Expand Down
2 changes: 1 addition & 1 deletion src/handlers/references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::analysis::symbols;
use crate::parser;
use crate::util::{byte_range_to_lsp_range, position_to_offset};
use comline_core::schema::idl::grammar::{Declaration, Type};
use tower_lsp::lsp_types::{Location, Position, Url};
use lsp_types::{Location, Position, Url};

/// Find all references to a symbol at a position
pub fn find_references(
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::analysis::symbols;
use crate::parser;
use crate::util::position_to_offset;
use std::collections::HashMap;
use tower_lsp::lsp_types::{Position, TextEdit, Url, WorkspaceEdit};
use lsp_types::{Position, TextEdit, Url, WorkspaceEdit};

/// Rename a symbol at a position to a new name
pub fn rename_symbol(
Expand Down
Loading
Loading