npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

langium-visitor

v1.4.4

Published

A CLI tool to generate visitor classes for Langium grammars

Readme

Langium Visitor

A CLI tool to generate visitor classes for a Langium project. The generator will generate two different abstract visitors:

  • Visitor: A visitor that can visit all the nodes of the AST.
  • ValidationVisitor: A visitor enabling Langium validation.

Installation

npm install -D langium-visitor

Usage

Generate the visitor files

langium-visitor

Or modify the package.json file of your Langium project to add a script:

"scripts": {
  "langium:visitor": "langium-visitor"
}

To correctly work, the langium-visitor command must be run after the langium:generate command. Indeed, the langium-visitor command will use the generated "src/language/generated/grammar.ts" file to generate the visitor classes. The generated files will be placed in the "src/semantics" directory.

Plug the visitor files in your Langium project

To allow your Langium project to use the visitor files, you need to import them in your project as a module. For that, you need to add the following lines in your "src/language/-module.ts" file:

import { <LanguageName>AcceptWeaver } from '../semantics/<language-id>-accept-weaver.js';
import { <LanguageName>CustomVisitor } from './your/path/language-id-visitor.ts';
import { <LanguageName>CustomValidationVisitor } from './your/path/language-id-custom-validation-visitor.ts';
import { registerVisitorAsValidator } from '../semantics/<language-id>-visitor.js';

...

export type <LanguageName>AddedServices = {
    visitors: {
      <LanguageName>AcceptWeaver: <LanguageName>AcceptWeaver
      <LanguageName>CustomVisitor: <LanguageName>CustomVisitor
      <LanguageName>CustomValidationVisitor: <LanguageName>CustomValidationVisitor
    }
}

...

export const <LanguageName>Module: Module<<LanguageName>Services, PartialLangiumServices & <LanguageName>AddedServices> = {
    visitors: {
      <LanguageName>AcceptWeaver: (services) => new <LanguageName>AcceptWeaver(services)
      <LanguageName>CustomVisitor: () => new <LanguageName>CustomVisitor()
      <LanguageName>CustomValidationVisitor: () => new <LanguageName>CustomValidationVisitor()
    }
};

...

// On the create services function, just after "shared.ServiceRegistry.register(<LanguageName>);"
HelloWorld.HelloWorldAcceptWeaver; // This is to instantiate the accept weaver
registerVisitorAsValidator(HelloWorld.visitors.HelloWorldTypeChecker, HelloWorld); // This is to register the validation visitor to the validation registry of Langium

The instantiation and registration of the validation is done by the registerVisitorAsValidator function. For basic visitors, you have to do it manually by calling <LanguageName>Module.visitors.<LanguageName>CustomVisitor where you want to use the visitor.

Create a new concrete Visitor

To create a new concrete Visitor, you just need to create a new class that implements the Visitor interface or extends the ValidationVisitor abstract class. If the main goal of this visitor is to program dynamic semantics, it is recommended to place your concrete visitor in the src/cli directory to follow Langium's convention. The ValidationVisitor provides a protected validationAccept function that can be used to accept an ASTNode, as in the default Langium validator. An example can be found in the examples directory.

CLI Arguments

| Argument | Description | Default Value | Optional | | -------- | ----------- | ------------- | -------- | | --out <path> | The output directory for the generated files | src/semantics | Yes | | --grammar <path> | The path to the grammar file | output path specified in the Langium config file + /grammar.ts | Yes | | --ast <path> | The path to the AST file | output path specified in the Langium config file + /ast.ts | Yes | | --config <path> | The path to the Langium config file | langium-config.json | Yes |

How does this work?

The purpose of the accept-weaver is to dynamically add a new method accept to the Langium generated (concrete) types. The weaver is executed when each time a Langium document goes in "IndexedReferences" state, but use a cache to avoid reweaving the same AST nodes multiple times. However, this method only exists at runtime, so TypeScript will throw errors when trying to access it. To fix this, the generator also creates for each type a type with the same properties of its equivalent Langium type, but also with an accept method. The only other difference is that instead of containing/referencing other Langium's types, they contain/reference the equivalent types generated by the generator. These types are in the visitor file. So by casting a Langium type to its equivalent visitor type (duck-typing), we can statically access the accept method we woven earlier. Accept methods are not woven to abstract types. We consider any type that doesn't have properties and has subtypes to be an abstract type.