Skip to main content
We welcome contributions to EmmyLua Analyzer! This guide will help you get started with contributing to the project.

Getting Started

Before contributing, please:
  1. Read through the building guide to set up your development environment
  2. Familiarize yourself with the architecture of the project
  3. Check existing issues and pull requests

Development Workflow

1

Fork and clone

Fork the repository and clone your fork:
git clone https://github.com/YOUR_USERNAME/emmylua-analyzer-rust.git
cd emmylua-analyzer-rust
2

Create a branch

Create a feature branch for your changes:
git checkout -b feature/my-new-feature
3

Make your changes

Implement your feature or bug fix. Make sure to:
  • Follow the coding standards
  • Add tests for new functionality
  • Update documentation as needed
4

Run tests and checks

Before committing, ensure all tests pass and code is properly formatted:
# Format code
cargo fmt --all

# Run linter
cargo clippy --all-targets --all-features

# Run tests
cargo test

# Run pre-commit hooks
pre-commit run --all
5

Commit your changes

Commit your changes with a clear, descriptive message:
git add .
git commit -m "Add feature: description of your changes"
6

Push and create PR

Push your branch and create a pull request:
git push origin feature/my-new-feature
Then open a pull request on GitHub with a clear description of your changes.

Testing

EmmyLua Analyzer uses the standard Rust testing harness along with assert macros from googletest-rust.

Running Tests

# Run all tests
cargo test

# Run tests for a specific crate
cargo test -p emmylua_parser
cargo test -p emmylua_code_analysis
cargo test -p emmylua_ls

Writing Tests

The project uses googletest-rust for assertions. Here are the key concepts:

Basic Test Structure

Use #[gtest] annotation for test functions:
use googletest::prelude::*;

#[gtest]
fn test_example() {
    assert_that!(2 * 2, eq(4));
}

Assert Macros

Checks a condition and panics on error:
assert_that!(2 * 2, eq(4));
Prefer assert_that!(x, eq(y)) over assert_eq! because it generates better error messages with diffs.
Checks a condition, marks the test as failed on error, but continues execution:
// Both expectations will be evaluated and reported:
expect_that!(2 * 2, ne(4));
expect_that!(3 * 3, ne(9));
This is useful when testing multiple cases in a single test function.
Checks a condition and returns a googletest::Result:
verify_that!(value, eq(expected))?;

OrFail Extension

The OrFail::or_fail extension converts Optional and Result to googletest::Result and adds location information:
let value = some_optional.or_fail()?;
The project provides a wrapper called check! for this pattern.

Testing Requirements

When contributing:
  • Add tests for new features: All new functionality should include appropriate tests
  • Maintain existing tests: Don’t break existing tests without good reason
  • Test edge cases: Consider boundary conditions and error cases
  • Use descriptive test names: Test names should clearly indicate what they’re testing

Code Style and Formatting

EmmyLua Analyzer uses automated tools to maintain consistent code style.

rustfmt

rustfmt formats all Rust code. Run it before committing:
cargo fmt --all
The project uses the default rustfmt configuration.

pre-commit

pre-commit fixes common issues in all text files, including:
  • Trailing whitespace
  • Missing newlines at end of files
  • Broken symlinks
  • Large files accidentally committed
1

Install pre-commit

Install the pre-commit tool:
# Using pip
pip install pre-commit

# Or using Homebrew (macOS)
brew install pre-commit
2

Run manually

Run pre-commit checks on all files:
pre-commit run --all
3

Install git hook (optional)

Configure pre-commit to run automatically before each commit:
pre-commit install
Note: This is optional - CI will catch any issues even if you don’t install the hook.

Clippy

The project uses Clippy for linting with workspace-level configuration. Review the lints before committing:
cargo clippy --all-targets --all-features
The workspace defines allowed lints for parser and language server-specific patterns. See Cargo.toml for details.

Coding Standards

General Guidelines

  • Write idiomatic Rust: Follow Rust best practices and conventions
  • Document public APIs: Add doc comments for public functions, types, and modules
  • Handle errors properly: Use Result types and provide meaningful error messages
  • Avoid unsafe code: Only use unsafe when absolutely necessary and document why

Project-Specific Patterns

The workspace lint configuration allows certain patterns common in parser and LSP projects:
  • Module inception: Acceptable for AST/syntax organization
  • Enum variant names: Repetition is allowed for syntax tree clarity
  • High complexity: Domain-specific logic may have higher cognitive complexity
  • Many arguments: Builder patterns and comprehensive APIs may need many parameters
See Cargo.toml workspace lints for the complete list.

Pull Request Process

Before Submitting

PR Description

Your pull request should include:
  • Clear title: Summarize the change in one line
  • Description: Explain what changes you made and why
  • Related issues: Link to any related issues
  • Testing: Describe how you tested your changes
  • Breaking changes: Note any breaking changes and migration steps

Review Process

After submitting your PR:
  1. CI checks: Automated checks will run on your PR
  2. Code review: Maintainers will review your code
  3. Feedback: Address any requested changes
  4. Approval: Once approved, your PR will be merged

Project Structure

EmmyLua Analyzer is organized as a Cargo workspace with multiple crates:
CrateDescription
emmylua_parserCore Lua parser for maximum efficiency and accuracy
emmylua_parser_descMarkdown/RST highlighting in comments
emmylua_code_analysisSemantic analysis engine with type inference
emmylua_lsLanguage Server Protocol implementation
emmylua_doc_cliDocumentation generator
emmylua_checkStatic analysis tool
emmylua_code_styleCode formatting and style
emmylua_diagnostic_macroDiagnostic generation macros
schema_to_emmyluaSchema conversion utilities
See the architecture guide for detailed information about each component.

Getting Help

If you need assistance:

Next Steps

Build from Source

Set up your development environment

Architecture

Understand the codebase structure

Build docs developers (and LLMs) love