Skip to main content
EmmyLua Analyzer is built as a modular Rust workspace with multiple specialized crates working together to provide comprehensive Lua language support.

Workspace Structure

The project uses Cargo’s workspace feature to organize related crates:
[workspace]
resolver = "2"
members = [
    "crates/*",
    "tools/*",
]
This structure enables:
  • Shared dependencies: Common dependencies are defined once in the workspace
  • Unified builds: All crates can be built together
  • Consistent versioning: Workspace-wide lint and dependency management
  • Modular development: Each crate has a focused responsibility

Core Crates

The workspace is organized into several specialized crates:

emmylua_parser

Foundational Lua parser built for efficiency and accuracy

emmylua_code_analysis

Semantic analysis engine with type inference and cross-reference resolution

emmylua_ls

Language Server Protocol implementation for IDE integration

emmylua_parser_desc

Markdown/RST syntax highlighting in Lua comments

Additional Crates

Documentation GeneratorProfessional documentation generator that creates beautiful, searchable API documentation from Lua code and EmmyLua annotations.
  • Parses EmmyLua annotations
  • Generates HTML documentation
  • Creates searchable API references
  • Supports multiple documentation formats
Static AnalyzerComprehensive static analysis tool for code quality assurance:
  • Performs static code analysis
  • Detects potential bugs and issues
  • Enforces coding standards
  • Generates diagnostic reports
Code FormatterCode formatting and style enforcement:
  • Implements Lua code formatting rules
  • Integrates with external formatters
  • Provides style configuration options
Diagnostic MacrosProcedural macros for diagnostic generation:
  • Simplifies diagnostic creation
  • Provides consistent error formatting
  • Enables internationalization support
Schema ConversionUtilities for converting schemas to EmmyLua annotations:
  • Converts JSON schemas
  • Generates type definitions
  • Supports various schema formats

Parser Architecture

The emmylua_parser crate is the foundation of the entire analyzer, built using the Rowan library for lossless syntax tree representation.

Key Components

Lexer

The lexer (src/lexer/) tokenizes Lua source code:
  • Lua lexer: Tokenizes standard Lua syntax
  • Doc lexer: Handles EmmyLua annotation comments
  • Lexer config: Configurable lexing behavior for different Lua versions
// Lexer supports multiple Lua versions
// Lua 5.1, 5.2, 5.3, 5.4, 5.5, and LuaJIT

Grammar

The grammar modules (src/grammar/) define parsing rules:
  • Lua grammar: Core Lua syntax (expressions, statements)
  • Doc grammar: EmmyLua annotation syntax (tags, types)
  • Recursive descent parser: Hand-written for maximum control and error recovery

Syntax Kinds

The src/kind/ module defines all syntax node types:
  • Token kinds: Keywords, operators, literals
  • Syntax kinds: AST node types
  • Language levels: Lua version-specific features
  • Operators: Operator precedence and associativity

Design Principles

Lossless Parsing

Preserves all source information including whitespace and comments for accurate formatting

Error Recovery

Continues parsing after errors to provide diagnostics for the entire file

Incremental Parsing

Supports efficient re-parsing of modified code

Version Support

Handles multiple Lua versions (5.1-5.5, LuaJIT)

Code Analysis Pipeline

The emmylua_code_analysis crate provides deep semantic understanding of Lua code.

Architecture Layers

Key Subsystems

Compilation (src/compilation/)

Manages the compilation process:
  • Analyzer: Orchestrates analysis phases
  • File management: Tracks source files and their states
  • Incremental compilation: Re-analyzes only changed files

Database Index (src/db_index/)

Maintains indexed information about the codebase:
  • Declarations: Function, class, and variable declarations
  • References: Symbol usage and cross-references
  • Types: Type definitions and relationships
  • Signatures: Function signatures and parameters
  • Members: Class and table members
  • Modules: Module structure and exports
  • Globals: Global variable tracking
  • Dependencies: Module dependency graph

Semantic Analysis (src/semantic/)

Provides deep code understanding:
  • Type inference (infer/): Deduces types from code context
  • Reference resolution (reference/): Finds symbol definitions
  • Member resolution (member/): Resolves table and class members
  • Generic support (generic/): Handles generic types
  • Type checking (type_check/): Validates type compatibility
  • Overload resolution (overload_resolve/): Selects correct function overload
  • Visibility (visibility/): Enforces access modifiers

Diagnostics (src/diagnostic/)

Generates error and warning messages:
  • Checkers: Implements various diagnostic checks
  • Internationalization: Multi-language diagnostic messages
  • Severity levels: Errors, warnings, hints

Virtual File System (src/vfs/)

Abstracts file system access:
  • File reading: Handles various encodings
  • File watching: Detects file changes
  • URI handling: Converts between file paths and URIs

Configuration (src/config/)

Manages analyzer configuration:
  • Workspace config: Project-wide settings
  • Lua loader: Configures Lua module resolution
  • Flatten config: Merges configuration sources

LSP Server Design

The emmylua_ls crate implements the Language Server Protocol for IDE integration.

Server Architecture

Core Components

Server (src/server/)

Manages the LSP connection:
  • Communication: Stdio or TCP transport
  • Message handling: Request/response lifecycle
  • Capabilities: Declares supported LSP features

Context (src/context/)

Maintains server state:
  • Workspace state: Open files, configuration
  • Analysis context: Links to code analysis
  • Document tracking: Synchronizes file changes

Handlers (src/handlers/)

Implements LSP features, each in its own module:

Handler Pattern

Each handler follows a consistent pattern:
// 1. Extract parameters from LSP request
// 2. Access analysis context
// 3. Query semantic information
// 4. Format response according to LSP spec
// 5. Return result to client

Data Flow

Here’s how data flows through the system:
1

Source code input

Editor sends file content to LSP server
2

Parsing

emmylua_parser creates a lossless syntax tree
3

Compilation

emmylua_code_analysis processes the syntax tree and builds indices
4

Semantic analysis

Type inference, reference resolution, and diagnostics are performed
5

LSP handling

emmylua_ls handlers query the analysis results
6

Response

Results are formatted according to LSP and sent to the editor

Performance Optimizations

EmmyLua Analyzer is designed for high performance:

Incremental Compilation

  • Fine-grained tracking: Only re-analyzes changed files
  • Dependency graph: Propagates changes to dependent files
  • Caching: Memoizes expensive computations

Memory Efficiency

  • String interning: Reduces memory for repeated strings
  • Arena allocation: Efficient memory management for syntax trees
  • Lazy evaluation: Defers expensive computations until needed

Concurrent Processing

  • Tokio runtime: Asynchronous I/O and task scheduling
  • Parallel analysis: Analyzes independent files concurrently
  • Lock-free structures: Minimizes contention in multi-threaded code

Extension Points

The architecture supports extensibility:

Adding New LSP Features

  1. Create a new handler module in emmylua_ls/src/handlers/
  2. Implement the LSP request/notification handler
  3. Query emmylua_code_analysis for semantic information
  4. Format and return the LSP response

Adding New Diagnostics

  1. Create a checker in emmylua_code_analysis/src/diagnostic/checker/
  2. Implement the diagnostic logic
  3. Register the checker in the diagnostic system

Supporting New Lua Features

  1. Update emmylua_parser grammar and syntax kinds
  2. Extend emmylua_code_analysis semantic analysis
  3. Update LSP handlers to expose the new functionality

Next Steps

Build from Source

Set up your development environment

Contributing

Learn how to contribute to the project

Build docs developers (and LLMs) love