(new) jinx-rust: A Rust Parser for Rust Tooling in Typescript

jinx-rust

jinx-rust is a Rust parser written in Typescript; it enables the development of Rust Tooling in Typescript.

Repository: GitHub - jinxdash/jinx-rust: A permissive Rust Parser for Rust Tooling written in Typescript

Example project using jinx-rust: Prettier Rust formatter

Usage

import { rs } from "jinx-rust";

const file = rs.parseFile("let leet: u32 = 1337;");

console.log(JSON.stringify(file));

{
  "type": "SourceFile",
  "program": {
    "type": "Program",
    "ast": [
      {
        "type": "LetVariableDeclaration",
        "pattern": { "type": "Identifier", "name": "leet" },
        "typeAnnotation": { "type": "Identifier", "name": "u32" },
        "expression": { "type": "Literal", "kind": 11, "value": "1337" }
      }
    ],
    "danglingAttributes": [],
    "comments": []
  }
}

A tolerant parser for better Rust Tooling

jinx-rust is unstrict by default and tolerates bad syntax:

  • Tokens:

    • Missing semicolons
    • Missing commas in some places
    • Whitespace within long tokens
    • Javascript-ey syntax, (currently just === and !==)
    • Unsyntactic parentheses (e.g. RangePattern bounds)
    • Closures with a returnType and a non-block expression
  • Nodes:

    • Unsyntactic Labels, Attributes and Doc Attributes
    • Arbitrary specifier order (e.g. unsafe pub fn ...)
    • Forbidden node types (e.g. patterns in const variables, expressions in top level)
    • Missing typeAnnotations

Why jinx-rust? And why in Typescript?

  • The case for Rust Tooling to split from rustc

    Tooling and compiler should only share the spec in common. Take the tripartite system in Javascript:

    • The spec TC39 ("legislative")
    • The core V8/JC/SM ("judicial")
    • The tooling Typescript ("executive")

    Through that lens, Rust is in a rather bleek shape:

    • No spec, the 1 implementation is the law
    • The core is rustc
    • The tooling is done on top of core, sometimes even arbitrarily within core's algorithms

    Building Rust Tooling on top of rustc is a mistake akin to building Typescript's editor integration on top of v8's Turbofan.

  • The case for Core and Tooling to use different Parsers and ASTs

    Both have drastically different needs, and attempting to serve both at the same time is grossly counterproductive.

    • Core needs a minimalistic, clear and no bs parser & AST that follows the syntax allowed in the spec by the dot and to the dot. Arbitrarily injecting lints in the core parser or bloating its data structure with CST is frankly out of scope and corrupts the entire language foundation.

    • Tooling needs a parser that is much more tolerant and flexible, it should be able to overlook or bend the spec syntax rules to best infer user's intent.

  • The case for writing Rust Tooling in Typescript

    Tooling requires a language with a structure that is much more flexible, dynamic and hackable to accomodate for the wide range and open-endedness of the solutions it seeks to provide. Rust is simply not the right pick for the job, Rust is not the right tool for every job damnit.

3 Likes

After spending the last couple weeks going through rust-analyzer's source code and architecture, I would respectfully like to disagree with this premise.

In particular, rust-analyzer's machinery for parsing the language and reasoning about its semantics (e.g. queries like "what is the type of x here?") is extremely elegant and powerful. It also ticks most of your boxes (tolerant of errors, not littered with diagnostic code, developed independently of rust-lang/rust, doesn't use rustc's internal code/algorithms, etc.).

A lot of what makes rust-analyzer easy to write code for is specific to Rust - for example, when writing assists you will be working on part of a potentially incomplete/broken AST. Features like ? let your tools deal with the fact that almost anything may be missing or broken without cluttering your code with if-statements (imagine the user is halfway through writing a statement and you want to make suggestions based on the incomplete input). The invert-if assist is a real-world example of this.

That said, you are 100% correct about Rust not always being the best tool for the job! For example, Rust is a bad choice for dynamic, cycle heavy applications like UIs... It's just that compiler-like tooling is one of Rust's strong points.

6 Likes

The fact that theres UIs built in C/C++ like imgui, qt, gtk, etc. tells me that language isnt really that big of a factor

1 Like

[...] Rust is a bad choice for dynamic, cycle heavy applications like UIs...

Agreed! That's why rust-analyzer only works statically on disk and falls apart as soon as you edit files

Umm... Are you sure you haven't accidentally misconfigured rust-analyzer? I've been writing Rust professionally for several years and that's not my experience at all.

Unless it changed recently? :thinking: I don't write Rust professionally so it's my mistake, but that was my experience with RA the last time I used it~

I've used rust-analyzer on projects with hundreds of files, it hasn't failed me yet. (What has failed me was my available memory, but that's doomed to be worse in a tool written in javascript.) And I believe that's been the experience of many users here as well.

rust-analyzer also provides autoformatting via rustfmt so I don't quite get the purpose of your prettier plugin for rust. Why would I install another (slower) toolchain when I can use the already installed, faster, better tooling ?

1 Like

Note also the swc project which is the inverse of this: rewriting the Typescript tooling in Rust, with extremely impressive results so far.

That said, having more implementations is not a bad idea, and I can see this being useful in some cases.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.