Giter VIP home page Giter VIP logo

rslint's Introduction

RSLint

A fast, customizable, and easy to use JavaScript and TypeScript linter

build status Documentation Status

⚠️ RSLint is in early development and should not be used in production, expect bugs! πŸ›

Installation

Through Cargo

$ cargo install rslint_cli
$ rslint --help

Prebuilt Binaries

We publish prebuilt binaries for Windows, Linux, and MacOS for every release which you can find here.

Build From Source

$ git clone https://github.com/rslint/rslint.git
$ cd rslint
$ cargo run --release -- --help

Usage

To use the linter simply pass files to lint to the CLI:

$ echo "let a = foo.hasOwnProperty('bar');" > foo.js
$ rslint ./foo.js
error[no-prototype-builtins]: do not access the object property `hasOwnProperty` directly from `foo`
  β”Œβ”€ ./foo.js:1:9
  β”‚
1 β”‚ let a = foo.hasOwnProperty('bar');
  β”‚         ^^^^^^^^^^^^^^^^^^^^^^^^^
  β”‚
help: get the function from the prototype of `Object` and call it
  β”‚
1 β”‚ let a = Object.prototype.hasOwnProperty.call(foo, 'bar');
  β”‚         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  β”‚
  ╧ note: the method may be shadowed and cause random bugs and denial of service vulnerabilities

Outcome: 1 fail, 0 warn, 0 success

help: for more information about the errors try the explain command: `rslint explain <rules>`

The RSLint CLI works without a configuration file and will select recommended non-stylistic rules to run.

Features

Speed. RSLint uses parallelism to utilize multiple threads to speed up linting on top of being compiled to native code.

Low memory footprint. RSLint's syntax tree utilizes interning and other ways of drastically reducing memory usage while linting.

Sensible defaults. The CLI assumes recommended non-stylistic rules if no configuration file is specified and ignores directories such as node_modules.

Error recovery. RSLint's custom parser can recover from syntax errors and produce a usable syntax tree even when whole parts of a statement are missing. Allowing accurate on-the-fly linting as you type.

No confusing options. ECMAScript version for the parser does not have to be configured, the parser assumes latest syntax and assumes scripts for *.js and modules for *.mjs.

Native TypeScript support. *.ts files are automatically linted, no configuration for different parsers or rules is required.

Rule groups. Rules are grouped by scope for ease of configuration, understanding, and a cleaner file structure for the project.

Understandable errors. Each error emitted by the linter points out the area in the source code in an understandable and clean manner as well as contains labels, notes, and suggestions to explain how to fix each issue. There is also an alternative formatter similar to ESLint's formatter available using the -F flag or the formatter key in the config.

Strongly typed rule configuration. RSLint ships a JSON schema and links it for rslintrc.json to provide autocompletion for the config file in Visual Studio Code. The JSON Schema describes rule config options in full, allowing easy configuration. Moreover, RSLint's language server protocol implementation provides autocompletion for rslintrc.toml files too.

Powerful directives. Directives (commands through comments) use a parser based around the internal JavaScript lexer with instructions, allowing us to provide:

  • Autocompletion for directives such as // rslint-ignore no-empty in the language server protocol.
  • Hover support for directives to offer information on a command on hover.
  • Understandable errors for incorrect directives.

Standalone. RSLint is compiled to a single standalone binary, it does not require Node, v8, or any other runtime. RSLint can run on any platform which can be targeted by LLVM.

Powerful autofix. Automatic fixes for some errors are provided and can be applied through the --fix flag or actions in the IDE. Fixes can even be applied if the file contains syntax errors through the --dirty flag.

Built-in documentation. RSLint contains rule documentation in its binary, allowing it to show documentation in the terminal through the explain subcommand, e.g. rslint explain no-empty, for-direction.

Internal Features

Clean and clear project layout. The RSLint project is laid out in a monorepo and each crate has a distinct job, each crate can be used in other Rust projects and each crate has good documentation and a good API.

Easy rule declaration. Rules are declared using a declare_lint! macro. The macro accepts doc comments, a struct name, the group name, a rule code, and configuration options. The macro generates a struct definition and a Rule implementation and processes the doc comments into the documentation for the struct as well as into a static string used in the docs() method on each rule. Everything is concise and kept in one place.

Full fidelity syntax tree. Unlike ESTree, RSLint's custom syntax tree retains:

  • All whitespace
  • All comments
  • All tokens

Allowing it to have powerful analysis without having to rely on separate structures such as ESLint's SourceCode.

Untyped Syntax Tree. RSLint's syntax tree is made of untyped nodes and untyped tokens at the low level, this allows for powerful, efficient traversal through the tree, e.g. if_stmt.cons()?.child_with_ast::<SwitchStmt>().

Easy APIs. RSLint uses easy to use builders for its complex errors, as well as builders for autofix. Everything is laid out to minimize the effort required to implement rules.

Performance

The benchmarks can be found in the benchmarks directory. You can run them on your machine using deno run -A --quiet benchmarks/bench.ts. They are also run on CI and you can see the latest results if you click on the latest GitHub Actions run.

Project RSLint eslint
engine262 (~42k LOC JavaScript) 414ms 46.9s
Oak (~11k LOC TypeScript) 53ms 399ms

(These benchmarks are run on AMD Ryzen 7 2700x, 8 Cores at 3.9MHz)

License

This project is Licensed under the MIT license.

rslint's People

Contributors

1011x avatar antleblanc avatar await-ovo avatar bartlomieju avatar charmander avatar chrisvariety avatar dependabot[bot] avatar ematipico avatar finn-orsini avatar herringtondarkholme avatar htgazurex1212 avatar jamiebuilds avatar kixiron avatar magurotuna avatar nicholas-baron avatar quriosapien avatar rdambrosio016 avatar rickbutton avatar sburris0 avatar silvanshade avatar stupremee avatar swatinem avatar tatekennington avatar thecp avatar yamadayuki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rslint's Issues

"\u{200" yields an unterminated string literal error

I tried this code:

{
  "\u{200"
}

I expected this to happen: invalid unicode codepoint escape error

Instead this happened::

error: Unterminated string literal
  β”Œβ”€ tests\main.js:2:3
  β”‚
2 β”‚   "\u{200"
  β”‚   - String literal starts here
3 β”‚ }
  β”‚  ^ Input ends here

error[SyntaxError]: Expected a statement or declaration, but found none
  β”Œβ”€ tests\main.js:2:3
  β”‚
2 β”‚ β”Œ   "\u{200"
3 β”‚ β”‚ }
  β”‚ └─^ Expected a statement or declaration here

Meta

rslint -V: rslint 0.1.2

If building from source:
rustc --version --verbose:

rustc 1.48.0-nightly (f68e08933 2020-09-19)
binary: rustc
commit-hash: f68e08933d8f519a9655934fedebbc509661b219
commit-date: 2020-09-19
host: x86_64-pc-windows-msvc
release: 1.48.0-nightly
LLVM version: 11.0

Additional context
Add any other context about the problem here.

Consider switching from codespan-reporting to annotate-snippets

Motivation

Codespan-reporting is amazing in terms of its files interface, however, it has no middle-level representation, and this has proven to be very very limiting. RSLint could greatly greatly benefit from things such as multiline suggestions like rustc. I think for the future it would be beneficial to make an rslint_errors crate which uses annotate-snippets as a backend for rendering, or maybe fork annotate-snippets.

Switching

The change would greatly affect rslint_lexer because it relies on codespan's diagnostic builder, this should be easy to switch out though. Moreover, the file walker would not have to have codespan specific files stuff, it would only need a way of getting the source code for annotate-snippets. Perhaps we should make a Files trait in rslint_errors. Then it should be simple from there. However, diagnostic builders may not work well since rslint_errors cannot rely on rslint_parser since it would be a cyclic dep, therefore we cannot make a Span trait like rslint_core. So we need to either give up the Span trait or make a wrapper of the builder in rslint_core.

Medium-term roadmap

This issue is meant to serve as a roadmap for the next few months to coordinate and discuss what should be done first, as well as give some updates on things i am working on.

First off, the things i am actively working on:

  • Scope analysis, most of the code is done, i am fixing many bugs in it (it includes a var ref analyzer and complex hoisting/shadowing logic so its not the easiest thing to debug)
  • Autofix, the fixer interface is done, most of the application logic is done, existing rules that need autofix are not done, this depends on incremental reparsing
  • Incremental reparsing/relinting, it mostly works, i am however waiting to merge it to add tests and check for any bugs.

Another person also mentioned they made an LSP and a VSC extension for rslint on the rust discord to me, so that is exciting and i will be awaiting the PR for that.

The issue when it comes to deciding what to work on is the fact that i would like to hold off on making more rules until we have all the features that rules should have, which includes autofix. This is vital to the long term of the project, if we rush rules then we end up with buggy rules and a lot of work to do once we add more features for rules. It seems to me that deno_lint ended up suffering from this issue greatly, since they added a lot of rules really fast, which caused bugs to not be caught, see denoland/deno_lint#330, and now they must add documentation, options, and suggestions to every rule. This is why i would rather hold off on adding more.

I am undecided when it comes to order of features, i believe parser tests should be done relatively soon, since the parser is the heart of the linter.

Here is a list of features i would like to get done in the next few months:

  • Test262 testing for rslint_parser and 90% compliance (i don't expect full compliance to be achieved soon, there are many weird productions not allowed in ecma2021) 100% seems achievable
  • Scope analysis (the driver for rules such as no-undef, no-unused, no-shadow, etc)
  • Autofix (#45)
  • Incremental relinting
  • RegEx parser (this will likely just be put into rslint_parser, ive experimented with this and it involves some weird sub-token logic which will be interesting)
  • Code Flow analysis (for rules such as no-unreachable)
  • basic LSP/VSC extension, this should be pretty simple and as i mentioned, someone might pr it soon πŸ‘€, then it just has to be adapted for incremental relinting
  • TypeScript parsing (unlikely to be done in the next few months)

Panic "byte index 3236 is not a char boundary" on latest available release and first run.

Code

Not relevant, needed code is below.

Meta

rslint -V: 0.2.1

Error Output

current_dir> rslint_cli-windows d:/projects/nodejs/someproject
The linter panicked unexpectedly. This is a bug.

We would appreciate a bug report: https://github.com/RDambrosio016/RSLint/issues/new?labels=ILE%2C+bug&template=internal-linter-error.md

Please include the following info:

message: byte index 3236 is not a char boundary; it is inside 'β„’' (bytes 3234..3237) of `
// Filesystem modules
import { existsSync } from "fs"; import { project, messages } from "../config.js";

// Creates random strings for re-importing
import { list, trim } from "./f.js";

// This is the command(singular) handler, which imports comma`[...]
location: crates\rslint_parser\src\lossless_tree_sink.rs:74:28

.eslintrc config compatibility

First: this is totally not ready to implement and should be delayed until we support most of (or even all) the rules eslint supports.

For a simple switch from eslint to RSLint, it would be awesome to be able to use
an .eslintrc.json (or others) for RSLint configuration. This should be really easy to implement I think.
Imo this should be provided using an extra argument but I'm open for other suggestions

Alternatives

We could provide a tool to convert an eslint config file, to an rslint one. This should be pretty easy too (at least for json, yaml).

Tracking issue for version 0.1

Just a brief list of things id like to add before 0.1:
Rules:

  • no-extra-boolean-cast - (#15) - finished
  • no-prototype-builtins - finished
  • no-setter-return (#9) - finished
  • no-sparse-arrays - finished
  • no-unexpected-multiline finished
  • use-isnan (#13) - finished
  • valid-typeof (#8) - finished

These are most of the eslint-reccomended rules for errors which dont rely on regex parsing, scope analysis, and code flow analysis, id like all those tools to be developed as individual analyzers instead of rushing them for rules.

Fixes:

  • rslint_parser::numbers::parse_js_num needs to account for legacy octal literals and needs tests - finished
  • no-inner-declaration wrongfully fails (#12) - finished

Misc:

  • Add a changelog to keep track of features and fixed bugs (starting from 0.1) - finished

@magurotuna if you'd like to do more in depth stuff with rules then working on any of these rules or fixes is a great start! πŸ˜„
although if you start work on a rule please put a comment saying which rule just so we don't accidentally work on the same things.

Linter Panic

I tried this code:

import Vector2D from 'core/engine/geometry/Vector2D';
import GraphPoint from 'core/plan/room-profile/editor/GraphPoint';
import { Wall } from 'core/plan/room-profile/editor/WallsHandler';
import { RoomProfileEvents } from 'core/plan/room-profile/RoomProfileEvents';
import { SelectedPoint } from 'core/plan/room-profile/editor/ui-modes/MovingMode/InteractableEntities/SelectedEntity';
import MovingMode from 'inject!core/plan/room-profile/editor/ui-modes/MovingMode/MovingMode';

I expected this to happen:
Get some lint diagnostics

Instead this happened:
The linter panicked unexpectedly. This is a bug.

Meta

rslint -V: rslint 0.2.1

If building from source:
rustc --version --verbose:

rustc 1.54.0 (a178d0322 2021-07-26)
binary: rustc
commit-hash: a178d0322ce20e33eac124758e837cbd80a6f633
commit-date: 2021-07-26
host: x86_64-apple-darwin
release: 1.54.0
LLVM version: 12.0.1

Additional context

message: byte index 5759 is not a char boundary; it is inside 'βŠ•' (bytes 5758..5761) of `import Vector2D from 'core/engine/geometry/Vector2D';
import GraphPoint from 'core/plan/room-profile/editor/GraphPoint';
import { Wall } from 'core/plan/room-profile/editor/WallsHandler';
import { RoomProfileEvents } from 'core/plan/room-profile/RoomProfil`[...]
location: /Users/hector.maddock-gree/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_parser-0.2.1/src/lossless_tree_sink.rs:74:28

Install Error on Apple Silicon

I ran cargo install rslint_cli on my M1 MBAir.

It failed because it uses x86 feature detection.

   Compiling rslint_core v0.2.2
error[E0658]: use of unstable library feature 'stdsimd'
   --> /Users/austin/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_core-0.2.2/src/groups/errors/no_irregular_whitespace.rs:175:16
    |
175 |             if std::is_x86_feature_detected!("avx2") {
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information

error:
        is_x86_feature_detected can only be used on x86 and x86_64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:

            #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                if is_x86_feature_detected(...) { ... }
            }

   --> /Users/austin/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_core-0.2.2/src/groups/errors/no_irregular_whitespace.rs:175:16
    |
175 |             if std::is_x86_feature_detected!("avx2") {
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this error originates in the macro `std::is_x86_feature_detected` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0425]: cannot find function `short_circuit_pass` in this scope
   --> /Users/austin/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_core-0.2.2/src/groups/errors/no_irregular_whitespace.rs:177:26
    |
177 |                 unsafe { short_circuit_pass(bytes) }
    |                          ^^^^^^^^^^^^^^^^^^ not found in this scope

error: aborting due to 3 previous errors

The linter panicked unexpectedly

hi! i saw your post on r/rust. i write a lot of typescript, but tried running this on some plain JS.

i ran it on this file and was told everything's good:

$ rslint_cli index.js

Outcome: 0 fail, 0 warn, 1 success

i wanted to run it on this project, but i ran into an unexpected panic.

$ rslint_cli 'src/*.js' 
error[]: The linter panicked unexpectedly. this is a bug.

We would appreciate a bug report: https://github.com/RDambrosio016/RSLint/issues/new?labels=ILE%2C+bug&template=internal-linter-error.md

note[]: Please include the following info: 

message: 
location: /Users/brandly/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_parser-0.1.2/src/parser.rs:158:9

i'm wrapping the glob in quotes because i'm on zsh, and it'll expand the glob otherwise e.g.:

$ rslint_cli src/*.js  
error: Found argument 'src/api.test.js' which wasn't expected, or isn't valid in this context

USAGE:
    rslint_cli [FLAGS] [files] [SUBCOMMAND]

For more information try --help

if i'm running this incorrectly, the feedback could be improved. otherwise, something might be broken.

thanks again. i'm looking forward to fast JS tooling.

no-inner-declarations wrongfully fails on exports after the first statement

I tried this code:

export const foo = [];
export function bar() {}

I expected this to happen: linting passes

Instead this happened::

error[no-inner-declarations]: move this function declaration to program's root
  β”Œβ”€ tests\main.mjs:2:8
  β”‚
2 β”‚ export function bar() {}
  β”‚        ^^^^^^^^^^^^^^^^^
  β”‚
  = help: move the declaration to the program root

Meta

rslint -V: rslint 0.1.0

If building from source:
rustc --version --verbose:

rustc 1.48.0-nightly (f68e08933 2020-09-19)
binary: rustc
commit-hash: f68e08933d8f519a9655934fedebbc509661b219
commit-date: 2020-09-19
host: x86_64-pc-windows-msvc
release: 1.48.0-nightly
LLVM version: 11.0

**If
Additional context
Add any other context about the problem here.

Panic on question dot in string

Code

$ cat test.js
`${x.a?.x}`

$ rslint_cli test.js
<panic output - see below>

Meta

rslint -V:

rslint 0.2.1

Error Output

The linter panicked unexpectedly. This is a bug.

We would appreciate a bug report: https://github.com/RDambrosio016/RSLint/issues/new?labels=ILE%2C+bug&template=internal-linter-error.md

Please include the following info: 

message: internal error: entered unreachable code: Anything not template chunk or dollarcurly should have been eaten by the lexer, but QUESTIONDOT was found
location: /home/{user}/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_parser-0.2.1/src/syntax/expr.rs:929:18

RSLint should exit with specific exit codes

For use in CI, it is helpful for rslint to define exit codes for each scenario. I propose the following, which is mostly inline with eslint except for -1:
-1: Linting was unsuccessful because of an internal error
0: Linting was successful and there are no errors (but there may be warnings)
1: Linting was successful and there is at least one error
2: Linting could not be done because of a config or CLI error (e.g. invalid glob pattern)

Refactor directive parsing to use a vector of instructions for a command parser

Most linters out there simply use regex or similar alternatives to parsing directives (commands through comments). RSLint uses a full parser which utilizes a wrapper over rslint_lexer. This has a couple of advantages:

  • More complex commands can be defined, like (soon) rslint-ignore foo, bar until eof
  • Directive errors just work seamlessly and with the expected ranges

This works fine and even better than current solutions most linters use. However, we can do much better, i propose a solution which would make parsing easier and would allow for automatic LSP hover and autocompletion with likely minimal effort.

Autocompletion issues

One of the best features i would like to implement in rslint's lsp is autocompletion for more things like directives, when you are typing rslint-ignore no- it should give you a list of rules to autocomplete along with their documentation. This is pretty much impossible when using a very simple regex or similar tool based approach, you need to first off know where the directives are, if the cursor is in the comment, etc. You need to also know exactly what was expected and what is expected next, for example, in that example you need to know a valid rule was expected. This approach does not work without a lot of brute force autocompletion work which is tedious and janky.

Naive solution

Instead of simply parsing token by token and throwing out the tokens, we could keep a list of components, like rule name, command name, etc. This should work, but the logic for autocompletion would likely need to be manually implemented across commands. Moreover, you don't solve the issue of manually having to push components.

Solution

Instead of manually parsing, lets make a makeshift parser generator to do the work for us. Each rule defines a list of instructions for the parser, and the parser consumes them, goes through them, and issues any errors for stuff that went wrong. For example, we can have instructions as such:

enum Instruction {
  CommandName(&'static str),
  RuleName,
  Literal(&'static str),
  Optional(Vec<Instruction>),
  Repetition(Box<Instruction>, &'static str),
  Either(Box<Instruction>, Box<Instruction>)
}

This means to define a complex command such as rslint-ignore which can take a list of rules and (soon) an "until" clause as such:
rslint-ignore no-await-in-loop, getter-return until eof
or
rslint-ignore getter-return until eof

We can trivially define a grammar for this command as such:

vec![
  CommandName("ignore"),
  Repetition(RuleName, ","),
  Optional(vec![
    Literal("until"),
    Either(Literal("eof"), Number)
  ])
]

Then the IgnoreCommand implementation can take in the produced components and spit out a final struct/enum

Autocompletion

So now that we have a formal description of what each command wants, the parser can throw errors which contain the instruction expected, such as saying it expected a RuleName. The lsp takes in this information and can give accurate autocompletion info by knowing the directive parsing errors which occured in the last document change.

Hover support

Another thing the LSP can automatically do if it knows the components that went into a directive is hover support. Every time we get a hover request we can go through the following:

  • Is the range inside a directive?
  • If so, what command and component is it part of?
  • If its part of a component, get the appropriate hover info for the component (e.g. for rules, its documentation, for command names a description of what they do)

Syntax highlighting

If we know all the components making up a directive, we can (potentially) apply our own syntax highlighting for each component using vsc's text decoration API. I don't think we can go through the LSP's coloring API because we just want to add stuff on top of existing coloring.

This overall is not the easiest thing to change, but it will be an amazing and unique thing to have in the LSP.

Discussion: ways of implementing autofix and issues

This issue is meant for housing any discussions and implementations of autofix. I believe we should implement autofix relatively soon, this way we won't have a huge burden to add autofix to every rule once there are way more rules. As far as i see it, there are two ways of doing autofix:

  • Purely text based (eslint)
  • AST transformation based (rome)

Purely text based has the issue of often not being very flexible (i personally disagree), and AST transformation based has the issue of not being flexible for minor text based fixes and needing AST serialization. Collectively autofix has fundamental issues which must be overcome:

  • All/Some rules need to be rerun after, i propose we add the ability to mark rules as fix-unsafe which will rerun only them, instead of needing all rules to rerun, which is expensive. This is absolutely required for stylistic rules, a fix cannot always conform to style and it should not either ways.

  • How do we choose what rule's fixes take precedence, if a rule wants to delete a node but another wants to change something in the node, which one do we trust?

Im not an expert in autofix so i would love some other ideas. RSLint's syntax again shines in this because it allows us to:

  • Incrementally reparse only the changed bits of code extremely fast and efficiently (linting is 60%+ parsing in RSLint's case), i am working on incremental reparsing but its not a top priority, but it will be widely used for vsc, file watching, and autofix.
  • Make changes on individual tokens or nodes and delegate them to a rewriter which converts them to text edits

I for one think text based is the way to go, it allows for a wider range of edits, it provides a familiar UI to people who have used ESLint, and rslint's immutable tree makes it a little bit more difficult to apply AST transformations, moreover, RSLint does not have a way to make new nodes without the parser and serialize them.

As for implementation, i believe we should add a field to RuleCtx which is fixer: Option<Fixer>, rules can make a new fixer (similar to ESLint) and add it, then the linter can simply collect the fixers and apply them. I also thought about making a new provided method on RuleCtx but ended up scrapping it because rules will 100% want to know about context when fixing, so making it a separate method would mean that some of the linting logic would have to be repeated, this is very very ugly and i would rather not do that.

I for one am not sure how to get over the issue of "which rule do we trust when it comes to a fix, do we trust the one who wants to change the node or the one who wants to delete it?". I also believe we should not try applying fixes if the parser returned errors, that can cause an absolute ton of confusing errors which i would rather not meddle in, error tolerance is great for linting but as soon as you try changing the AST produced (which is potentially semantically wrong) you end up with confusion.

Implement error rules from eslint/ECMAScript 6

RSLint does not distinguish between ecma versions (because caring about standard versions does not matter), therefore we should fit some of eslint's ES6 rules into the errors group, those which actually cause errors.
Ive compiled a list of the rules which can be implemented into errors currently:

  • constructor-super
  • no-confusing-arrow
  • no-dupe-class-members
  • no-duplicate-imports
  • no-new-symbol
  • no-this-before-super

Rules im not sure about including

  • no-class-assign (i think this should be included since its a potential error/mistake)
  • require-yield (maybe this one too since its most likely a mistake and a potential error)

If you are looking for things to contribute to, this is a great list!
If you have any other rules i missed or have opinions on the rules im not sure about feel free to mention them πŸ‘

Getter and Setter 'key' returns the wrong node

rslint/xtask/src/ast.rs

Lines 1179 to 1185 in 5d30f0e

struct Getter {
decorators: [TsDecorator],
/* get */
key: PropName,
parameters: ParameterList,
body: BlockStmt,
}

Looks like the name of a Getter or Setter is not defined in the AST, so the key method returns the node corresponding to the get or set keywords. Wouldn't it be better if it referred to the value name of the getter or setter?

I came across this issue in PR #82

pub fn key(&self) -> Option<PropName> { support::child(&self.syntax) }

`foo(a, b;` causes infinite recursion with regards to error recovery

foo(a, b; causes the parser to infinitely recurse when trying to recover.

i presume this is because b will be parsed as an expr, then args will loop back and expect a comma, it does not see one so it goes on, then it tries to parse ; as an expression. ; is in the EXPR_RECOVERY_SET therefore it does not bump over the token. This might require explicit recovery set handling because recovery on ; is very valuable but infinite recursion is unacceptable. A solution to this which does not mess with other recoveries will require a bit of thought.

Parser do not support field property

I tried this code:

class ClassWithInstanceField {
  instanceField = 'instance field'
}

class ClassWithStaticField {   
  static staticField = 'static field' 
}

I expected this to happen: Parse without errors

Instead this happened:: error[SyntaxError]: expected '(' but instead found =

Meta

rslint -V: rslint 0.1.2

If building from source:
rustc --version --verbose:

<version>

Additional context
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields

Add `if (foo == true)` to no-extra-boolean-cast or make it a separate rule

One pattern which ESLint does not seem to catch is

if (foo == true) { /* */ }

no-extra-boolean-cast does not catch it, id like to make no-extra-boolean-cast encompass this pattern too, but that makes the name kind of misleading, so i am not sure whether we should rename it, and rename it to what exactly. Maybe we should make this a new rule?

Publish binaries for release

Since most people that will use RSLint are going to be JavaScript / TypeScript developers, many of them will not have Rust installed. So it would be nice to add workflows to publish binaries for multiple platforms in every release and upload them to the specific GitHub release as an asset.

Test262 integration

Test262 is the official test suite for validating ECMAScript compatibility.
To confirm that rslint_parser can parse the whole (or most of) the ECMA-262 specification.

The integration of test262 will probably be a bit tricky because there is much work required to set it up to a custom
parser. I would suggest using a similar approach like boa,
to have an extra workspace member (e.g. rslint_tester) that will run the whole test suite against rslint_parser
and then report how much of the specification can be parsed and what failed to parse correctly.

This could also be run in CI workflow, to see a regression of the passing and failing tests.

Q*A request

Hi @RDambrosio016 ,

Would you be interested in a Q&A on RSLint? I am a news editor for infoq.com, which focuses on bringing the latest innovation to a core audience of tech leads, software architects and senior developers. You can see an example of Q&A here: https://www.infoq.com/news/2019/07/doom3-web-assembly-port/

Let me know if that sounds of interest to you. If that is the case, we can continue the conversation through regular email.

Congratulations in any case for pushing this through. I know the amount of motivation and effort it takes to brings an open-source project forward.

Kind regards,

Panic on uppercase numeric literals

I tried this code:

0XFF

I expected this to happen: 0XFF should be parsed as 255 / 0xFF

Instead this happened:: RSLint panicked

Meta

If building from source:
rustc --version --verbose:

rustc 1.46.0 (04488afe3 2020-08-24)
binary: rustc
commit-hash: 04488afe34512aa4c33566eb16d8c912a3ae04f9
commit-date: 2020-08-24
host: x86_64-unknown-linux-gnu
release: 1.46.0
LLVM version: 10.0

Additional context
I would like to fix the problem

The linter panicked unexpectedly

Code

// https://docs.cypress.io/api/introduction/api.html

Cypress.on('uncaught:exception', (err, runnable) => { // eslint-disable-line 
  if (err.message.includes('Android is not defined')) {
    return false
  }
  return true
})

Meta

rslint -V: rslint 0.2.1

if building from source:
rustc --version --verbose:

rustc 1.50.0 (cb75ad5db 2021-02-10)
binary: rustc
commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b
commit-date: 2021-02-10
host: x86_64-unknown-linux-gnu
release: 1.50.0

Error Output

The linter panicked unexpectedly. This is a bug.

We would appreciate a bug report: https://github.com/RDambrosio016/RSLint/issues/new?labels=ILE%2C+bug&template=internal-linter-error.md

Please include the following info: 

message: byte index 2540 is not a char boundary; it is inside 'Γ©' (bytes 2539..2541) of `// https://docs.cypress.io/api/introduction/api.html

Cypress.on('uncaught:exception', (err, runnable) => { // eslint-disable-line 
  if (err.message.includes('Android is not defined')) {
    return false
  }
  return true
})

describe('Mon Cube', () => {
`[...]
location: /home/jeff/.cargo/registry/src/github.com-1ecc6299db9ec823/rslint_parser-0.2.1/src/lossless_tree_sink.rs:74:28

Is there a way to configure 'ignored' directories list?

Hi, me again here.

I was experimenting with rslint, but after compiling TypeScript for js, rslint is trying to lint the dist directory too.

In the documentation, I was unable to find information on how to set the ignored directory list as .eslintignore in ESLint.

I would love it if I could open pull request, but I am still too new to rust (I practically only know how to print "hello world" out) and I will wait for a new version if there is no option to ignore it

Thanks for all

Extensibility/modular definitions of new rules

Hello, excellent project!

What plans (if any) do you have so far for allowing end users to define their own sets of rules? One of the key "wins" provided by ESLint is that users can define their own rules and integrate them simply by providing them at a conventional path and then referring to them with ESLint's config. We use this extensively at LinkedIn to provide app-specific guidance, for rules specific to that projectβ€”whether due to technical limitations or simply to keep things consistent.

rslint (appropriately, in my view) is taking a different approach to configuration than ESLint does, and it will by necessity take a different approach to extensibility since the mechanics for doing this kind of thing with a compiled language are very different than they are for an interpreted language like JS/Node.

Obvious candidates:

  • Don't let users supply their own definitions, other than by forking rslint. (I believe this represents the current state of affairs?) This is the simplest, but also the least flexible for users.

  • Define an API for consumers to be able to supply dynamic libraries as β€œplugins”, which can be looked up from a conventional location and executed at runtime. This would have the best combination of performance and dynamic lookup, and would also most closely align… but would also almost certainly run into issues in short order due to Rust's lack of ABI stability. It would also require end users to actually do that build and/or distribute the binaries they build in some way.

  • Define an API/blueprint for consumers to be able run as separate binaries, the same way that binaries can work alongside something like the way cargo, git, etc. do this. This would probably require some kind of IPC with serialization (JSON?). It would also require end users to actually do that build and/or distribute the binaries they build in some way.

  • Follow SWC’s lead and make this consumable via WASM, which would (if carefully implemented!) still likely provide an order-of-magnitude speedup. I suspect this is the easiest story for extensibility from the perspective of end users… but also would presumably have the worst performance and the most implementation challenges on rslint’s end.

Thanks!

Does rslint already support TypeScript?

Hi,

I was testing rslint to see the difference with my eyes, but when I run rslint ***.ts it is throwing error: No matching files found.

This confused me because the description of this repo was saying:

A (WIP) Extremely fast JavaScript and TypeScript linter and Rust crate

After that error, I tried to lint some javascript files and it seems that there is no error.

Is this a bug or I need to do some other steps to lint typescript files?

Thanks!

Add `rslint-pragma` to specify the source type of a file

I noticed this being talked about in a deno_lint issue, and i think it would work well (but sadly deno_lint cannot implement it efficiently since they would need a lossless lexer to run on the code first or parse the code twice). To get this to work for us we would simply have to refactor a couple of things:

  • Make the core runner first run rslint_parser::tokenize
  • Do some kind of preprocessing by going through each comment token and checking its source
  • If a source type is specified then get that, or get the default one (script for .js, module for .mjs)
  • Make a new rslint_parser::TokenSource
  • Spawn an appropriate parser with new_module or new
  • Use the appropriate parser function from the syntax::program module and get the parser events and process then with a new LosslessTreeSink (theres instructions here on how it works)

There would be no need to run through a proper directive parser, just check for rslint-pragma script and rslint-pragma module.

Get Diagnostic Line Number

So I was wondering if there way any way to get the line number of the error (which line the error occured in).

Nodejs shows you the error like so:
image

So i was wondering if there was any field in Diagnostic that gives you the line number.

rslint_cli's panic hook should lock stderr/stdout and exit the program after

rslint_cli's panic hook does not lock stderr/stdout, therefore if it panics at the same time from multiple threads things can get a little... messy. And the panic hook does not exit which is kind of odd, we should exit with a non-zero exit code, although i am not sure of what the standard exit code for "uh oh, stuff went really bad" is.

Change rule docs from using ```ignore to using a proc macro which invokes rslint_lexer

rustdoc does not have support for highlighting anything not rust, so currently we abuse rustdoc and use ignore instead of js. However, i realized we could simply make a proc macro and invoke rslint_lexer to produce html. The declare_lint macro can capture doc comments using a cursed macro i learned about, then it feeds it to a proc macro which produces html docs and then a #[doc = "html"] tag on the struct.

Switch from a Span trait to a Span struct

Currently rslint_core uses a span trait. This is great for supplying nodes or tokens or ranges, however, it is a bit limiting. I think to allow for more complex span logic we should make a Span struct and then impl From<T> for Span (although no specialization might make this a bit limiting). We can then have logic similar to rustc_errors with things like trim, between, contains, until, etc. This switch should be fairly simple, just add the struct, impl the right traits, and change impl Span to impl Into<Span>.

Tracking issue: ESLint recommended rules

Tracking issue for rules from eslint:recommended set.

  • constructor-super
  • for-direction
  • getter-return
  • no-async-promise-executor
  • no-case-declarations
  • no-class-assign (blocked on scope analysis)
  • no-compare-neg-zero
  • no-cond-assign
  • no-const-assign (blocked on scope analysis)
  • no-constant-condition
  • no-control-regex
  • no-debugger
  • no-delete-var
  • no-dupe-args
  • no-dupe-class-members
  • no-dupe-else-if
  • no-dupe-keys
  • no-duplicate-case
  • no-empty
  • no-empty-character-class
  • no-empty-pattern
  • no-ex-assign (blocked on scope analysis)
  • no-extra-boolean-cast
  • no-extra-semi
  • no-fallthrough (blocked on code flow analysis)
  • no-func-assign (blocked on scope analysis)
  • no-global-assign (blocked on scope analysis)
  • no-import-assign (blocked on scope analysis)
  • no-inner-declarations
  • no-invalid-regexp
  • no-irregular-whitespace
  • no-misleading-character-class
  • no-mixed-spaces-and-tabs
  • no-new-symbol
  • no-obj-calls
  • no-octal
  • no-prototype-builtins
  • no-redeclare (blocked on scope analysis)
  • no-regex-spaces
  • no-self-assign
  • no-setter-return
  • no-shadow-restriced-names
  • no-sparse-arrays
  • no-this-before-super
  • no-undef (blocked on scope analysis)
  • no-unexpected-multiline
  • no-unreachable (blocked on code flow analysis)
  • no-unsafe-finally
  • no-unsafe-negation
  • no-unused-labels
  • no-unused-vars (blocked on scope analysis)
  • no-useless-escape
  • no-with
  • require-yield
  • use-isnan
  • valid-typeof

Host docs with github-pages and mdbook

It would be great to have a primitive docs website to host dev guides, rule docs, and other things. Im thinking github-pages + mdbook is the easiest way to do it for now. All we need to do is add a book.toml and SUMMARY.md. Then we need to modify the docgen script to add the page to the summary (since i dont think mdbook has support for "just include everything in here"). And finally we just add a CI step to build and deploy to github pages.

Deadlock in rslint-lsp

I tried this code:

$ cat >generate.sh <<'EOF'
#!/bin/sh
printf 'Content-Length: 404\r\n\r\n{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"rootPath":"/home/strager/Projects/quicklint-js/tools/benchmark-lsp/.","rootUri":"file:///home/strager/Projects/quicklint-js/tools/benchmark-lsp","initializationOptions":{"unstable":false,"enable":true,"lint":true},"workspaceFolders":[{"uri":"file:///home/strager/Projects/quicklint-js/tools/benchmark-lsp","name":"benchmarks"}],"capabilities":{}}}'
printf 'Content-Length: 52\r\n\r\n{"jsonrpc":"2.0","method":"initialized","params":{}}'
for i in $(seq 0 999) ; do
  printf 'Content-Length: 207\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/strager/Projects/quicklint-js/tools/benchmark-lsp/test%03d.js","languageId":"javascript","version":0,"text":""}}}' "${i}"
done
EOF 
$ sh generate.sh | rslint-lsp

I expected this to happen: rslint-lsp responds to initialize, then optionally prints a bunch of empty textDocument/publishDiagnostics messages, then exits.

Instead this happened: rslint-lsp hangs.

Meta

$ rslint_cli -V 
rslint 0.2.1
$ git rev-parse HEAD
b7a4eeb69dc00fedfee81eaed3cf2ad36bcb2e2e
$ rustc --version --verbose
rustc 1.50.0-nightly (1c389ffef 2020-11-24)
binary: rustc
commit-hash: 1c389ffeff814726dec325f0f2b0c99107df2673
commit-date: 2020-11-24
host: x86_64-unknown-linux-gnu
release: 1.50.0-nightly

Additional context
I am writing benchmarks for LSP servers. RSLint often hangs when I run my benchmarks.

Benchmarks Against SWC?

Hi,

This looks like a really cool project and I am wondering if you have benchmarks of your parser against SWC.

Feature: add `rslint-ignore <rules> until <line>`

Currently rslint's ignore command is either scoped to the entire file or its scoped to the statement or declaration its on top of. This does not seem to be the norm apparently, i would like to keep scoping as it is and instead add a more explicit modifier to the ignore command as such:

ignoring an entire statement:

// rslint-ignore no-empty
if (foo) {}
else {} // no error

ignoring a block of code until another line:

// rslint-ignore no-empty until 5
{}
{}
{}
{}
{} // error

Perhaps we could also add rslint-ignore <rules> until eof? i really prefer an explicit command such as this over weird scoping you cannot make sense of, which is the case with eslint (in my opinion)

Mentoring instructions

To add this you will need to modify the directive parser which is found here, ignore commands are parsed here. What i would personally do is add two more variants to the commands enum called IgnoreRulesUntil(Vec<Box<dyn CstRule>>, Range<usize>) and IgnoreUntil(Range<usize>) where the ranges are start and end byte indices. You will need to cache the byte indices of line starts in the directive parser which is very easy, you can simply do it once when the directive parser is created, you can get the source code text through root_node.text().to_string(). To parse the actual directive you can simply peek the lexer to see if the next token's text is until and then further peek to see if its a number or eof. Then to enforce the directives you can simply add something to the place where rules are run, run through all of the directives, if any directive applies to the rule (ignoreUntil applies to all rules, IgnoreRulesUntil only applies if the rule is contained) then go through all of the diagnostics returned, if the first primary label of the diagnostic's range start is included in the directive's range then simply remove the diagnostic (Vec::retain can do this easily).

You will also need to update the docs here to document this.

Vendor regex_syntax into rslint_regex and change it to be ES2021 compliant

Following a discussion on discord, @bartlomieju, @magurotuna, and i have chosen to work on vendoring regex_syntax as a new crate in rslint, rslint_regex. regex_syntax is not compliant to ES2021 therefore some work on the parser needs to be done, furthermore, we don't need the HIR produced in the crate, so that can be tossed as well. We should also replace the Error enum with rslint_errors diagnostics to provide more context and make it easier to work with.

TODO

  • Vendor regex_syntax
  • Remove HIR
  • Replace Error with rslint_errors diagnostics
  • Make the parser ES2021 compliant

Curly brackets where parameters should be should be parsed as block statements not object expressions

For example:

function {}

and

class foo {
set {}
}

in both of these examples {} should not be parsed as an object pattern for the parameters, it should be parsed as a block statement since object patterns in parameters are exceedingly rare and it is much better to assume the user forgot the parameters. This can probably be done by keeping some state boolean which is switched on if formal_parameters does not see a ( and sees a {, then primary_expr simply checks that boolean

Shebangs should be parsed correctly

Shebang support is not a thing, which is incorrect. However, supporting shebangs is pretty easy, a SHEBANG token kind already exists, so all that needs to be done is add a handler for it in the lexer, the logic is already there in Lexer::strip_shebang, so just add something in the lookup table which checks #, then in the match simply match for the dispatch then peek for !, you must also check if the current position is 0. Then for the parser:

  • Add a field to Script and Module in xtask/src/ast.rs:
struct Script {
+    T![shebang],
     items: [Stmt],
  }

struct Module {
+    T![shebang],
     items: [ModuleItem],
}
  • regenerate the definitions with cargo xtask syntax
  • add a simple p.eat(T![shebang]); after let m = p.start(); in rslint_parser/src/syntax/program.rs in script and module
  • log the change in the rslint_lexer and rslint_parser changelogs, as well as add lexer tests for it

Permission errors should not panic

In RSLint we treat all panics as bugs, therefore permission errors in rslint_cli with regards to files should not panic, they should instead use lint_err or lint_warn. There are quite a few instances where we panic instead of throwing a lint error in rslint_cli.

rslint_parser does not allow eval methods on classes

I tried this code:

class Foo {
  eval() {}
}

I expected this to happen: linting passes

Instead this happened::

error[SyntaxError]: Illegal use of `eval` as an identifier in strict mode
  β”Œβ”€ tests\main.js:2:3
  β”‚
2 β”‚   eval() {}
  β”‚   ^^^^


Outcome: 1 fail, 0 warn, 0 success

Meta

rslint -V: rslint 0.1.0

If building from source:
rustc --version --verbose:

rustc 1.48.0-nightly (f68e08933 2020-09-19)
binary: rustc
commit-hash: f68e08933d8f519a9655934fedebbc509661b219
commit-date: 2020-09-19
host: x86_64-pc-windows-msvc
release: 1.48.0-nightly
LLVM version: 11.0

Additional context
This is caused by implicit strict mode in class bodies and the way method parses prop keys (the keys for method), although im not quite sure how to fix it currently since i have not looked into it deeply and have been working on much more major bugs in the parser

Markdown support

This is a pretty easy but useful feature, being able to lint markdown files. Implementing this should be quite easy, simply use a regex like

\`\`\`(?:js|javascript)\n([\s\S]*?)\n\`\`\`

Then add a variant to JsFileKind for markdown. Then you can extract each code block using the regex and the first capture group. Then run rules as you would using the src of each group and the same file id. And finally merge the results from each code block run by offsetting the range of each label by the offset of the block. There might be some wonky handling for non-Ok lint runs but overall it should be pretty easy.

rslint_parser panic

I tried this code:

// βŠ•

I expected this to happen:
The parser should not crash

Instead this happened::

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /Users/me/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/lossless_tree_sink.rs:103:74
stack backtrace:
   0: rust_begin_unwind
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/std/src/panicking.rs:515:5
   1: core::panicking::panic_fmt
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/panicking.rs:92:14
   2: core::panicking::panic
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/panicking.rs:50:5
   3: core::option::Option<T>::unwrap
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/option.rs:388:21
   4: <rslint_parser::lossless_tree_sink::LosslessTreeSink as rslint_parser::TreeSink>::start_node::{{closure}}::{{closure}}
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/lossless_tree_sink.rs:103:44
   5: core::option::Option<T>::unwrap_or_else
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/option.rs:429:21
   6: <rslint_parser::lossless_tree_sink::LosslessTreeSink as rslint_parser::TreeSink>::start_node::{{closure}}
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/lossless_tree_sink.rs:101:21
   7: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &mut F>::call_once
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/ops/function.rs:280:13
   8: core::option::Option<T>::map
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/option.rs:489:29
   9: <core::iter::adapters::map::Map<I,F> as core::iter::traits::double_ended::DoubleEndedIterator>::next_back
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/iter/adapters/map.rs:142:9
  10: <core::iter::adapters::rev::Rev<I> as core::iter::traits::iterator::Iterator>::next
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/iter/adapters/rev.rs:33:9
  11: <core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::next
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/iter/adapters/enumerate.rs:44:17
  12: core::iter::adapters::peekable::Peekable<I>::peek::{{closure}}
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/iter/adapters/peekable.rs:239:43
  13: core::option::Option<T>::get_or_insert_with
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/option.rs:935:26
  14: core::iter::adapters::peekable::Peekable<I>::peek
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/iter/adapters/peekable.rs:239:9
  15: rslint_parser::lossless_tree_sink::n_attached_trivias
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/lossless_tree_sink.rs:214:31
  16: <rslint_parser::lossless_tree_sink::LosslessTreeSink as rslint_parser::TreeSink>::start_node
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/lossless_tree_sink.rs:106:13
  17: rslint_parser::event::process
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/event.rs:103:21
  18: rslint_parser::parse::parse_with_syntax
             at /Users/hector.maddock-gree/.cargo/git/checkouts/rslint-1a0b90046db1b20c/f7cc15b/crates/rslint_parser/src/parse.rs:252:5
  19: code_style::main
             at ./crates/code-style/src/main.rs:62:42
  20: core::ops::function::FnOnce::call_once
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/ops/function.rs:227:5

Meta

rslint -V:

If building from source:
rustc --version --verbose:

rustc 1.56.0-nightly (371f3cd3f 2021-09-02)
binary: rustc
commit-hash: 371f3cd3fe523d0b398ed1db1620667c53ba7d02
commit-date: 2021-09-02
host: x86_64-apple-darwin
release: 1.56.0-nightly
LLVM version: 13.0.0

Additional context
I am using rslint_parser as a library in a tool I am writing and it failed to parse one of our files. After looking through the file for a while I noticed the above symbol in a comment. After removing it the parser succeeds.

I'm using a forked version of rslint, but I thought I'd raise an issue for this here anyway. I only created the fork a week or so ago anyway.

No await in loop is missing documentation

no-await-in-loop is missing documentation.

To add documentation, place doc comments inside of the declare_lint! call in the source, before the struct name, then use cargo docgen to generate appropriate user facing documentation. Js code blocks should use ignore instead of js, this is to have basic highlighting in rustdoc, however, we may change it in the future. The docgen will automatically change these to js. Moreover, make sure the docs have an initial one sentence description with two newlines (you can see other rule docs for an example).

Modify LSP server to use Rope instead of String

The LSP server Document type should be modified to use Rope (from ropey) for text storage rather than String. It looks like with the way things are currently set up, this might either require making changes to rslint_core::File or somehow separating things out to where only the server uses Rope.

[Docs]: How does this compare to eslint [features/ rules]?

Hey! This is pretty cool project! I was wondering how does it compare to eslint in terms of features, rules, runtimes etc?

I was trying to figure out if there is any way I can contribute and if there is roadmap of things that can be crowdsourced (like adding rules etc) I'd be happy to help!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.