Skip to main content

Overview

Prisma Format (prisma-fmt) is a multi-purpose tool that provides:
  1. Schema formatting: Consistent, automatic formatting for Prisma schema files
  2. Language Server Protocol (LSP): Powers IDE features like autocomplete, hover, diagnostics, and more
  3. Schema linting: Warnings and suggestions for schema improvements
  4. Code actions: Quick fixes and refactoring suggestions
prisma-fmt is the bridge between your editor and the Prisma Schema Language. It’s what makes the Prisma VS Code extension and other editor integrations possible.

Architecture

Prisma Format is built on top of the PSL (Prisma Schema Language) parser and provides LSP-compliant features:

Formatting

Consistent schema formatting with configurable indentation

LSP Features

Autocomplete, hover info, diagnostics, references, and code actions

Validation

Real-time schema validation and error reporting

Quick Fixes

Automated solutions for common schema issues

Core Modules

The crate is organized into focused modules:
mod actions;                    // Referential actions
mod code_actions;               // LSP code actions (quick fixes)
mod format;                     // Schema formatting
mod get_config;                 // Configuration extraction
mod get_datamodel;             // Datamodel extraction
mod get_dmmf;                  // DMMF generation
mod hover;                     // Hover information
mod lint;                      // Schema linting
mod merge_schemas;             // Multi-file schema merging
mod native;                    // Native types information
mod preview;                   // Preview features
mod references;                // Find references
mod text_document_completion;  // Autocomplete
mod validate;                  // Schema validation

API Functions

Schema Formatting

Format Prisma schemas with consistent style:
pub fn format(datamodel: String, params: &str) -> String
Input:
  • datamodel: JSON-serialized SchemaFileInput (single or multiple files)
  • params: JSON-serialized DocumentFormattingParams (LSP standard)
Example:
{
  "textDocument": { "uri": "file:///path/to/schema.prisma" },
  "options": { "tabSize": 2, "insertSpaces": true }
}
Output: Formatted schema string
The formatter preserves comments and uses the configured tab size (typically 2 spaces for Prisma schemas).

Text Document Completion

Provides autocomplete suggestions:
pub fn text_document_completion(schema_files: String, params: &str) -> String
Completions provided for:
  • Model names
  • Field types
  • Attribute names (@id, @unique, @default, etc.)
  • Attribute arguments
  • Datasource providers
  • Generator providers
  • Relation field names
  • Enum values
Example completion scenarios:
model User {
  id Int @|  // Suggests: id, unique, default, map, etc.
}

datasource db {
  provider = "|"  // Suggests: postgresql, mysql, sqlite, sqlserver, mongodb
}

model Post {
  author |  // Suggests: User (from available models)
}

Hover Information

Provides contextual information on hover:
pub fn hover(schema_files: String, params: &str) -> String
Hover info includes:
  • Field type documentation
  • Attribute descriptions
  • Model relationship information
  • Native type mappings
  • Validation constraints

Code Actions

Suggests quick fixes and refactorings:
pub fn code_actions(schema_files: String, params: &str) -> String
Available code actions:

Block Actions

Add missing opposite relation fields, add @@map for naming conventions

Field Actions

Add missing relation arguments, fix relation field types

MongoDB Actions

Add @db.ObjectId for MongoDB IDs, fix composite type usage

Multi-Schema Actions

Add schema references for multi-schema setups

Relation Mode Actions

Add relation mode configuration, add missing indexes

Relation Actions

Fix broken relations, add relation names, add referential actions

Find References

Finds all references to a symbol:
pub fn references(schema_files: String, params: &str) -> String
Can find references for:
  • Model names (used in relations, @@map, etc.)
  • Enum names (used in field types)
  • Field names (used in relations, indexes)
  • Composite type names (MongoDB)

Schema Validation

Validates schema and returns errors:
pub fn validate(validate_params: String) -> Result<(), String>
Validation includes:
  • Syntax errors
  • Type errors
  • Relation errors
  • Constraint violations
  • Attribute validation
  • Database-specific validations
Error format:
The `referentialIntegrity` and `relationMode` attributes cannot be 
used together. Please use only `relationMode` instead.
  -->  schema.prisma:5
   |
 4 |   relationMode         = "prisma"
 5 |   referentialIntegrity = "foreignKeys"
 6 | }
   |

Validation Error Count: 1

Configuration Extraction

Extracts datasource and generator configuration:
pub fn get_config(get_config_params: String) -> String
Input params:
interface GetConfigParams {
  prismaSchema: string;
  ignoreEnvVarErrors?: boolean;
  env?: { [key: string]: string };
  datasourceOverrides?: { [key: string]: string };
}
Output: JSON with datasources and generators

DMMF Generation

Generates Data Model Meta Format:
pub fn get_dmmf(get_dmmf_params: String) -> Result<String, String>
DMMF includes:
  • All models and their fields
  • All enums and their values
  • Relations and their properties
  • Unique constraints and indexes
  • Used for Prisma Client generation

Schema Merging

Merges multiple schema files:
pub fn merge_schemas(params: String) -> Result<String, String>
Useful for:
  • Multi-file schema support
  • Client generation from split schemas
  • Schema composition

Linting

Provides schema quality warnings:
pub fn lint(schema: String) -> String
Lint warnings include:
  • Naming convention violations
  • Missing indexes on foreign keys
  • Inefficient relation patterns
  • Deprecated syntax usage

LSP Context

Internal LSP operations use a shared context:
pub(crate) struct LSPContext<'a, T> {
    pub(crate) db: &'a ParserDatabase,
    pub(crate) config: &'a Configuration,
    pub(crate) initiating_file_id: FileId,
    pub(crate) params: &'a T,
}

impl<'a, T> LSPContext<'a, T> {
    pub(crate) fn datasource(&self) -> Option<&Datasource>;
    pub(crate) fn connector(&self) -> &'static dyn Connector;
    pub(crate) fn generator(&self) -> Option<&'a Generator>;
}
This context provides access to:
  • Parsed schema database
  • Configuration (datasources, generators)
  • Active file being edited
  • Database connector information

Code Actions in Detail

Block-Level Actions

Add missing opposite relation field:
// Before
model User {
  id    Int    @id
  posts Post[]
}

model Post {
  id Int @id
  // Missing: author User @relation(fields: [authorId], references: [id])
  // Missing: authorId Int
}

// After applying code action
model Post {
  id       Int  @id
  author   User @relation(fields: [authorId], references: [id])
  authorId Int
}

Field-Level Actions

Fix relation field types:
// Before (error: wrong type)
model Post {
  author String @relation(fields: [authorId], references: [id])
  authorId Int
}

// After code action
model Post {
  author User @relation(fields: [authorId], references: [id])
  authorId Int
}

MongoDB-Specific Actions

Add @db.ObjectId for MongoDB:
// Before
model User {
  id String @id @default(auto()) @map("_id")
}

// After code action
model User {
  id String @id @default(auto()) @map("_id") @db.ObjectId
}

Relation Mode Actions

Add missing indexes for Prisma relation mode:
datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

model Post {
  author   User @relation(fields: [authorId], references: [id])
  authorId Int  // Code action: add @@index([authorId])
}

// After applying action
model Post {
  author   User @relation(fields: [authorId], references: [id])
  authorId Int
  
  @@index([authorId])
}

Integration with Editors

VS Code

The Prisma VS Code extension uses prisma-fmt:
  • Runs as a language server process
  • Provides real-time diagnostics
  • Offers autocomplete and hover info
  • Enables code actions (quick fixes)
  • Handles formatting on save

Other Editors

Any editor with LSP support can use prisma-fmt:
  • Neovim: Via nvim-lspconfig
  • Emacs: Via lsp-mode
  • Sublime Text: Via LSP package
  • IntelliJ IDEA: Via Prisma plugin
LSP server command:
prisma-fmt lsp

Testing

prisma-fmt uses snapshot testing extensively:
# Run all tests
cargo test -p prisma-fmt -F psl/all

# Update snapshots
UPDATE_EXPECT=1 cargo test -p prisma-fmt -F psl/all

# Run specific test
cargo test -p prisma-fmt validate::tests::validate_direct_url

Test Structure

Tests use expect! macros for snapshot testing:
#[test]
fn test_completion() {
    let schema = r#"
        model User {
            id Int @
        }
    "#;
    
    let completions = get_completions(schema, position);
    
    expect![[r#"
        [
            {"label": "id"},
            {"label": "unique"},
            {"label": "default"},
        ]
    "#]].assert_eq(&completions);
}
When changing diagnostics or completions, always run with UPDATE_EXPECT=1 to regenerate snapshots, then review the diffs carefully.

Preview Features

Get available preview features:
pub fn preview_features() -> String
Returns JSON with all preview features and their status (active, deprecated, etc.).

Native Types

Get native type information:
pub fn native_types(input: String) -> String
Returns available native types for the specified connector:
{
  "postgresql": [
    {"name": "SmallInt", "args": []},
    {"name": "Integer", "args": []},
    {"name": "BigInt", "args": []},
    {"name": "Decimal", "args": ["precision", "scale"]},
    {"name": "VarChar", "args": ["length"]},
    // ... more types
  ]
}

Referential Actions

Get available referential actions:
pub fn referential_actions(schema: String) -> String
Returns referential actions supported by the datasource:
{
  "onDelete": ["Cascade", "Restrict", "NoAction", "SetNull", "SetDefault"],
  "onUpdate": ["Cascade", "Restrict", "NoAction", "SetNull", "SetDefault"]
}

Binary Distribution

prisma-fmt is distributed as:
  1. Native binary: For CLI usage and local LSP servers
  2. WASM module: For browser-based tools and web editors

Building

# Native binary
cargo build -p prisma-fmt --release

# With specific features
cargo build -p prisma-fmt -F psl/all --release

WASM Build

See prisma-schema-wasm crate for browser-compatible builds.

Common Issues

CRLF Line Endings

Some test fixtures expect CRLF line endings (Windows-style). Don’t convert these to LF or tests will fail.
Example test:
#[test]
fn create_missing_block_composite_type_crlf() {
    // This test specifically checks CRLF handling
}

Snapshot Updates

After changing diagnostics:
  1. Run tests with UPDATE_EXPECT=1
  2. Review git diff carefully
  3. Ensure changes are intentional
  4. Commit updated snapshots

Feature Flags

Some tests require specific feature flags:
# All PSL features
cargo test -p prisma-fmt -F psl/all

# Without features (may fail)
cargo test -p prisma-fmt  # ❌ May not compile

Performance

The LSP implementation is designed for real-time performance:
  • Incremental parsing: Only re-parse changed portions
  • Caching: Parser database cached between requests
  • Async operations: Non-blocking LSP server
  • Efficient completion: O(1) lookup for most completions

Example Usage

Formatting via CLI

echo '{"tabSize": 2}' > format-params.json
prisma-fmt format < schema.prisma > formatted.prisma

Running as LSP Server

prisma-fmt lsp
The server communicates via stdin/stdout using JSON-RPC 2.0.

Validation

use serde_json::json;

let params = json!({
    "prismaSchema": schema_string,
});

let result = prisma_fmt::validate(params.to_string());

if let Err(errors) = result {
    eprintln!("Validation errors:\n{}", errors);
}

Source Code

Explore the prisma-fmt source code:
  • Main crate: prisma-fmt/
  • LSP implementation: prisma-fmt/src/
  • Code actions: prisma-fmt/src/code_actions/
  • Completions: prisma-fmt/src/text_document_completion.rs
  • Repository: prisma/prisma-engines

Build docs developers (and LLMs) love