Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to the project.
-
Be respectful and constructive
-
Welcome newcomers and help them get started
-
Focus on what is best for the community
-
Show empathy towards other community members
-
Fork the repository
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/universal-language-connector.git -
Add upstream remote:
git remote add upstream https://github.com/universal-connector/universal-language-connector.git -
Create a branch:
git checkout -b feature/your-feature-name
-
Rust 1.75+ (install via rustup)
-
Node.js 18+ (for VS Code client development)
-
Docker/Podman (optional, for container testing)
# Install development tools
make setup
# Build the project
make build
# Run tests
make test
# Start development server
make dev-
All logic in server - Clients are thin wrappers (<100 LOC)
-
LSP 3.17 strict compliance - No custom extensions without justification
-
Performance targets - <100ms response, <50MB memory, <500ms startup
-
Server-first thinking - When in doubt, implement in the server
Server: - Rust with tokio (async runtime) - tower-lsp (LSP implementation) - axum (HTTP API) - dashmap (concurrent document storage)
Clients: - Language-specific LSP client libraries - Minimal code, maximum delegation to server
-
LSP Handler (
server/src/lsp.rs) - Language Server Protocol implementation -
HTTP API (
server/src/http.rs) - REST endpoints -
WebSocket (
server/src/websocket.rs) - Real-time updates -
Conversion Core (
server/src/core.rs) - Document format conversion -
Document Store (
server/src/document_store.rs) - Concurrent document management
-
Update your fork:
git fetch upstream git rebase upstream/main
-
Make your changes:
-
Write code following style guidelines
-
Add tests for new functionality
-
Update documentation
-
-
Test your changes:
make test make lint make fmt -
Commit your changes:
git add . git commit -m "feat: add new conversion format"
Follow Conventional Commits:
<type>(<scope>): <description> [optional body] [optional footer]
Types: - feat: New feature - fix: Bug fix - docs:
Documentation changes - style: Code style changes (formatting, etc.)
- refactor: Code refactoring - test: Adding or updating tests -
chore: Maintenance tasks
Examples:
feat(core): add YAML conversion support fix(lsp): handle UTF-16 position correctly docs(api): update WebSocket examples
# All tests
make test
# Specific test file
cd server && cargo test --test core_tests
# With output
cd server && cargo test -- --nocapture
# Integration tests
make test-integrationUnit tests (same file as code):
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_conversion() {
// Test code here
}
}Integration tests (server/tests/):
#[tokio::test]
async fn test_http_endpoint() {
// Test code here
}-
Push to your fork:
git push origin feature/your-feature-name
-
Create Pull Request:
-
Go to GitHub and create a PR from your fork
-
Fill in the PR template
-
Link related issues
-
-
PR Requirements:
-
All tests must pass
-
Code must be formatted (
make fmt) -
Linter must pass (
make lint) -
Documentation updated if needed
-
At least one review approval
-
-
After Approval:
-
Squash commits if requested
-
Rebase on main if needed
-
Maintainers will merge
-
Follow standard Rust conventions:
// Use rustfmt
cargo fmt
// Pass clippy
cargo clippy -- -D warnings
// Naming
const MAX_SIZE: usize = 100;
fn convert_document() {}
struct DocumentStore {}
// Error handling
fn process() -> Result<Output, Error> {
// Use ? operator
let data = fetch_data()?;
Ok(process_data(data))
}
// Documentation
/// Converts a document between formats.
///
/// # Arguments
/// * `request` - Conversion request with content and formats
///
/// # Returns
/// Converted content or error
pub fn convert(request: ConversionRequest) -> Result<ConversionResponse> {
// Implementation
}For client code:
// Use consistent formatting
// Prefer async/await over callbacks
// Document public APIs
/**
* Converts the current document to HTML
*/
async function convertToHtml(): Promise<void> {
// Implementation
}-
Add parser dependency to
server/Cargo.toml -
Implement converter in
server/src/core.rs -
Add tests in
server/tests/core_tests.rs -
Update documentation in
docs/API.md -
Add examples to
examples/conversions/
Example:
// In core.rs
pub enum Format {
Markdown,
Html,
Json,
Yaml, // New format
}
impl ConversionCore {
fn markdown_to_yaml(markdown: &str) -> Result<String> {
// Implementation
}
}-
Create directory:
clients/<editor-name>/ -
Implement LSP client using editor’s native API
-
Keep under 100 LOC
-
Add README with installation instructions
-
Test end-to-end with real editor
Template structure:
clients/myeditor/ ├── plugin.ext # Main plugin file (<100 LOC) ├── README.md # Installation guide └── package.json/config # Package metadata (if applicable)
-
Define route in
server/src/http.rs -
Add handler function
-
Add tests in
server/tests/http_api_tests.rs -
Update API docs in
docs/API.md
Example:
async fn new_endpoint(
State(state): State<Arc<ServerState>>,
Json(payload): Json<Request>,
) -> Result<Json<Response>, ApiError> {
// Implementation
}
// In create_router()
.route("/api/new-endpoint", post(new_endpoint))-
Implement method in
server/src/lsp.rs -
Update capabilities in
initialize() -
Add tests in
server/tests/lsp_compliance.rs -
Document in
docs/API.md
Example:
#[tower_lsp::async_trait]
impl LanguageServer for UniversalConnectorBackend {
async fn new_method(&self, params: Params) -> LspResult<Response> {
// Implementation
}
}Always consider performance:
-
Use async/await for I/O operations
-
Avoid blocking operations on main thread
-
Use
dashmapfor concurrent access -
Profile changes with
cargo bench -
Target <100ms response times
Update documentation for:
-
New features
-
API changes
-
Configuration options
-
Breaking changes
Documentation locations: - API: docs/API.md - Architecture:
docs/ARCHITECTURE.md - User guide: README.md - Code comments:
Inline documentation
-
Issues: GitHub Issues
-
Discussions: GitHub Discussions
-
Documentation: See
docs/directory