Linter experiment: TypeScript no-floating-promises via inter-process communication · oxc-project/oxc · Discussion #2855 (original) (raw)
Summary
I had a look through tsserver protocol definitions (here) and source (here). I don't think TSServer API would be sufficient to implement type checker based lint rules. The only type related command I could see is typeDefinition, which returns the type definition at a given locaiton in a file, but this top-level information would not be sufficient for the lint rule. There is a chance we could resolve the type fully by recursively using go-to definition paired with type definition commands, but this does not seem practical.
There might be another option though: implement a TSServer like utility to give us access to type checker the way typescript-eslint does it.
Communication with TSServer
Communication with tsserver happens through stdin/stdout by writing and reading simple JSON messages. High level protocol description can be found here. And there is a simple example implemented in JS here. As part of looking into this I have implemented a simple POC in Rust, if you think it could be useful I can publish the repo.
The rest of documentation is in the form of comments in code. All the available commands are listed in protocol.ts and usually have a simple description atteched to the command arguments object. The corresponding implementation can be found in the session.ts. But looking through the code I did not see a way to access type checker API we need for lint rules.
Type checker API
The API used by typescript-eslint is the type checker that is part of the compiler API documented here. They directly import typescript and create required primitives to access the type checker. The relevant package containing the implementation is typescript-estree. There are some recently added experimental options to simplify this by relying more on typescript ProjectServices, but this mostly simplifies managing open files and projects, and still allows direct access to type checker. Relevant discussion with more details is here typescript-eslint/typescript-eslint#6575.
Alternative solution
Look into typescript-estree and build something similar in JS, importing typescript directly and exposing an API to load the project, open/close files and access the type checker. This seems doable, but calling methods over IPC might have too much overhead to make it sufficiently fast.
We might want to consider using JS code for anything to do with type checker. For example rules could have an associated JS file, that define functions that the rule could call through the IPC interface. The JS function would accept Typescript AST node as input, and perform all the necessary type checking logic on the JS side.
So with the no-floating-promises example, we would map the Rust AST node into TS one in Rust, and then call the isPromise function through the IPC for a TS node we just mapped. The isPromise would be implemented entirely in JS.