quick-lint / quick-lint-js

quick-lint-js finds bugs in JavaScript programs
https://quick-lint-js.com
GNU General Public License v3.0
1.54k stars 192 forks source link

Using quick-lint-js as library #594

Open coderaiser opened 2 years ago

coderaiser commented 2 years ago

Hi, thank you for such a great project!

I'm working on 🐊Putout code transformer, and as I see, quick-lint-js is compiled to wasm.

Would be amazing to have ability to use it's API to check what is wrong with a file that cannot be parsed :).

strager commented 2 years ago

Can you sketch an example JavaScript API which would be ideal for Putout?

coderaiser commented 2 years ago

Yes! I use such concept as second chance while parsing for things like type assertions.

For babel is very hard to parse code like this:

var foo: any;
var bar = <string> foo; // bar is now of type "string"

In typescript + jsx mode.

Also when await used without async, or in case of duplicate declaration parser just crashes with no useful information.

So if you don't use concept of ESTree-based AST, some kind of quickLint (or any other name like validate) will be great:

const quickLint = require('quick-lint-js');
const places = quickLint('() => await');
// returns
[{
    message: `'await' is only allowed in async functions`,
    position: [{
        line: 1,
        column: 1,
    }]
}];

This is the best possible way, but even just message will be much better, then Cannot read property 'buildError' of undefined πŸ˜„.

Also would be great to install it using npm.

Thank you!

strager commented 2 years ago

When reporting errors, how do you want quick-lint-js to count columns and lines? Is there a specific tool we should emulate?

Context: Different tools have different preferences. For example, VS Code internally counts β˜ƒ (U+2603) as one column but 🎸 (U+1F3B8) as two columns. Vim internally counts β˜ƒ as three columns. VS Code columns start at 0; Vim columns start at 1. JavaScript treats U+2028 and U+2029 as newlines, but VS Code and Vim don't.

coderaiser commented 2 years ago

The perfect way according to ESTree:

image

@babel/parser from https://astexplorer.net on such code:

const a = 'β˜ƒ'; const b = 1;

Shows location of VariableDeclaration b as:

{
    line: 1,
    column: 15
}

Same for such code:

const a = 'x'; const b = 1;

So one char is one column, columns starts from 0, lines starts from 1.

strager commented 2 years ago

Status update:

src/quick-lint-js/c-api.h is the closest thing to a library interface. We use it for the web port: https://quick-lint-js.com/demo/ It is not exposed publicly right now (i.e. we don't ship a .wasm file with this interface); the API is unstable.

If a consumer wants more customization options today, then the parse_and_lint function in src/quick-lint-js/fe/linter.h might work. This is what all editor plugins use (including c-api.h). This even less stable than c-api.h.