Skills

Psl Ast Layers

How to use the PSL syntax tree layers (green tree, red tree, strongly-typed AST...

Install

npx skills add prisma/orm --skill psl-ast-layers -g -a claude-code -y
Repository
prisma/orm47.7k
Category
Business
Updated
4d ago
License
Apache-2.0
Context cost
Mediumabout 2,163 tokens
Runs scripts
No, instructions only

What it does

How to use the PSL syntax tree layers (green tree, red tree, strongly-typed AST classes) correctly. Use for any PSL-related work: PSL interpreters (contract-psl), helpers inside the psl-parser package, the language server, formatters, or anything else that consumes `parse()` output from @internal/psl-parser.

PSL AST Layers

The PSL parser (packages/1-framework/2-authoring/psl-parser) produces a three-layer syntax tree. Each layer has exactly one job, pick the right one and the code stays lossless, typed, and cheap.

LayerTypesJobUse in consumer code?
Green treeGreenNode, GreenToken (syntax/green.ts)Immutable, position-independent storage. Foundation only.Never
Red treeSyntaxNode, SyntaxToken (syntax/red.ts, syntax/navigation.ts)Navigation with offsets and parents: findAncestor(), tokenAtOffset(), nextToken/prevToken, nonTriviaSibling()Navigation outside the current node
Typed ASTModelDeclarationAst, FieldDeclarationAst, … (syntax/ast/)Structural information about a known node via getters (name(), fields(), lbrace(), value())Default choice

Everything is exported from @internal/psl-parser/syntax. parse(source) returns { document: DocumentAst, diagnostics, sourceFile }, you start in the typed layer.

Choosing a layer

  1. You know what the node is (you hold a ModelDeclarationAst, a FieldAttributeAst, …) and want its parts → call the typed getters. Never dig through children yourself.

  2. You need to move outward or sideways (find the enclosing model, the previous declaration, the token after the cursor) → use the red tree's navigation helpers, then immediately re-enter the typed layer with a static cast:

    // enclosing model (tests the node itself first, then walks ancestors)
    const model = node.syntax.findAncestor(ModelDeclarationAst.cast);
    
    // enclosing model OR composite type, combine casts with any(…)
    const owner = node.syntax.findAncestor(
      any(ModelDeclarationAst.cast, CompositeTypeDeclarationAst.cast),
    );
    

    Sideways and token-level movement all have dedicated helpers, do not hand-roll the walks:

Read the whole SKILL.md on GitHub

More in Business