How can I use a custom tslint rule written in TypeScript with vscode-tslint without compiling to JS?
Asked Answered
C

3

6

I have a custom rule written for TSlint in TypeScript that I can run using ts-node in a script I'm using on my Linux VM:

#!/bin/bash
set -e
ROOT_DIR=$(dirname $(dirname $0))
cd $ROOT_DIR
find "$ROOT_DIR/src" -name "*.ts" -o -name "*.tsx" | xargs $(yarn bin)/ts-node $(yarn bin)/tslint

This enables tslint to run the TS rule directly without compiling first, and it does work.

The problem is that ms-vscode.vscode-typescript-tslint-plugin isn't picking up that rule even though it's explicitly enabled in the tsconfig.json rules. I am running VSCode on a separate machine with a Windows host, mounting the filesystem via Samba served from the Linux VM. Other rules in the file are being respected and shown for installed and built-in rules, like no-console, etc.

How can I get information about why the rule isn't being applied? Is there something I need to configure in the plugin to make this work?

Canalize answered 10/6, 2019 at 10:37 Comment(8)
github.com/microsoft/typescript-tslint-plugin/blob/master/src/…Cirro
I'm not quite sure what info I can glean from that file. Are you saying the runner needs to implement the parsing of the rule file in order to support TypeScript rules?Eleonoraeleonore
I'm saying vscode plugin might not behave the same as tslint CLI tool. To find out why, only way is to dive into its source code. ln:287 is where it kicks spin the linter. Some logs around that line can reveal more info.Cirro
OK, thanks for those pointers, I'll dig in and see how that goes!Eleonoraeleonore
Looks like the plugin just let tslint instance get configuration, and this is how tslint load rulesCirro
To sum up, it's just node's require. And since the plugin loads tslint as a dependency, the node instance where that tslint app runs in is the same as where vscode plugin runs, which is a child process spinned up by vscode/electron.Cirro
So solution will be to find a way to teach that particular node process's require method to understand .ts files.Cirro
haven't tested, but guessing from source code, put require('ts-node/register') at the beginning of your custom rule .ts file could solve the problem.Cirro
L
0

Unfortunately, this is not supported by VScode/vscode-typescript-tslint-plugin and doesn't seem to be in their agenda.

Here is a closed issue on their GitHub asking for this feature.

You can of course compile your rule to JS first, but it is not what you asked for.

Lamellicorn answered 25/6, 2019 at 7:41 Comment(2)
That repository relates to the deprecated version of tslint for VSCode, so I might file a request to see if there's a way to support it in this version. Thanks!Eleonoraeleonore
The official stance is that this is out of scope for support in the new extension as well, so I guess that answers the question.Eleonoraeleonore
O
0

Here's what I think might be related to the problem.

  • Let us name the rule file noImportsRule.ts. Rules are referenced in tslint.json with their kebab-cased identifier, so "no-imports": true would configure the rule.

  • Core rules cannot be overwritten with a custom implementation.

  • Custom rules can also take in options just like core rules (retrieved via this.getOptions())

  • As of TSLint v5.7.0 you no longer need to compile your custom rules before using them. You need to tell node.js how to load .ts files for example by using ts-node:

Important conventions:

  • Rule identifiers are always kebab-cased.
  • Rule files are always camel-cased (camelCasedRule.ts).
  • Rule files must contain the suffix Rule.
  • The exported class must always be named Rule and extend from Lint.Rules.AbstractRule

for all details

Oystercatcher answered 24/6, 2019 at 15:11 Comment(2)
Thanks for that info, but the rule works just fine with the CLI, as explained above. The problem I have is that the VS Code tslint extension doesn't load the rule in .ts form without compiling to JS.Eleonoraeleonore
i think compiling to js is interesting with your webpack babel or lint configuration. You should say that i dont want to expose as js in your config. Can you share your configurations?Oystercatcher
L
0

Unfortunately, this is not supported by VScode/vscode-typescript-tslint-plugin and doesn't seem to be in their agenda.

Here is a closed issue on their GitHub asking for this feature.

You can of course compile your rule to JS first, but it is not what you asked for.

Lamellicorn answered 25/6, 2019 at 7:41 Comment(2)
That repository relates to the deprecated version of tslint for VSCode, so I might file a request to see if there's a way to support it in this version. Thanks!Eleonoraeleonore
The official stance is that this is out of scope for support in the new extension as well, so I guess that answers the question.Eleonoraeleonore
C
0

The hack I develop goes like this:

  1. assume your custom rules lives under ./rules, the directory looks like:
rules/
  |- registerRule.js
  |- oneRule.ts
  |- twoRule.ts
  1. oneRule.ts and twoRule.ts are actual rules written in typescript, but registerRule.js is a "spy". The purpose of this spy rule is just to get itself picked-up by tslint instance and inject the ts-node/register into the node runtime.
// registerRule.js

require('ts-node/register')

const Lint = require('tslint')

class Rule extends Lint.Rules.AbstractRule {
  apply(sourceFile) {
    return []
  }
}

module.exports.Rule = Rule
  1. setup tslint.json
{
  "rulesDirectory": "./rules",
  "rules": {
    "register": true,
    "one": true,
    "two": true
  }
}

I've tested. This hack will teach the vscode tslint plugin to understand .ts custom rules.

Cirro answered 25/6, 2019 at 7:43 Comment(2)
I would like to avoid hacking in support for ts-node, since it could adversely affect the language server and cause all sorts of interop problems.Eleonoraeleonore
@KlemenSlavič IMO the it's under control. It only affect the behavior of require for any file with .ts ext, things other than that stay unaffectedCirro

© 2022 - 2024 — McMap. All rights reserved.