Skip to content

Commit

Permalink
feat(deno-lint): implment webpack loader and cli
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Aug 18, 2020
1 parent 9e1c24a commit 59454e2
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 20 deletions.
4 changes: 3 additions & 1 deletion packages/deno-lint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ edition = "2018"
crate-type = ["cdylib"]

[dependencies]
deno_lint = "0.1"
deno_lint = "0.1.22"
ignore = "0.4"
napi = { version = "0.4" }
napi-derive = { version = "0.4" }
serde = "1"
serde_json = "1"
termcolor = "1.1"

[target.'cfg(all(unix, not(target_env = "musl")))'.dependencies]
Expand Down
85 changes: 84 additions & 1 deletion packages/deno-lint/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,93 @@
# `@node-rs/deno-lint`

![](https://github.com/napi-rs/node-rs/workflows/CI/badge.svg)
![](https://img.shields.io/npm/dm/@node-rs/deno-lint.svg?sanitize=true)

> deno_lint nodejs binding
## Performance

### Hardware info

```
Model Name: MacBook Pro
Model Identifier: MacBookPro15,1
Processor Name: 6-Core Intel Core i9
Processor Speed: 2.9 GHz
Number of Processors: 1
Total Number of Cores: 6
L2 Cache (per Core): 256 KB
L3 Cache: 12 MB
Hyper-Threading Technology: Enabled
Memory: 32 GB
```

### Benchmark

```
@node-rs/deno-lint x 885 ops/sec ±1.26% (92 runs sampled)
eslint x 118 ops/sec ±4.97% (78 runs sampled)
Lint benchmark bench suite: Fastest is @node-rs/deno-lint
```

## Usage

```ts
import { lint } from 'deno-lint'
import { lint } from '@node-rs/deno-lint'

lint(filepath, source, enableAllRules)
```

## webpack-loader

```js
// webpack.config.js

module.exports = {
module: {
rules: [
{
enforce: 'pre',
test: /\.(t|j)s?$/,
loader: '@node-rs/deno-lint/webpack-loader',
exclude: [/node_modules/],
},
],
},
}
```

### Options

You can pass denolint options using standard webpack loader options.

#### `enableAllRules`

- Type: `Boolean`
- Default: `false`

Whether to enable all rules. If false, `denolint` will enable all recommend rules.

#### `failOnError`

- Type: `Boolean`
- Default: `false`

Will cause the module build to fail if there are any errors, if option is set to `true`.

#### `quiet`

- Type: `Boolean`
- Default: `false`

Emit nothing even if there were errors happened.

## `denolint` cli

### usage

`npx denolint`

### `--all`, `-a`

Enable all rules flag, if not present, denolint will run with recommend rules.
4 changes: 3 additions & 1 deletion packages/deno-lint/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

const { binding } = require('@node-rs/deno-lint')

const hasError = binding.denolint(__dirname)
const enableAllRules = process.argv.includes('--all') || process.argv.includes('-a')

const hasError = binding.denolint(__dirname, enableAllRules)

if (hasError) {
process.exit(1)
Expand Down
22 changes: 17 additions & 5 deletions packages/deno-lint/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,30 @@ let binding

try {
binding = loadBinding(__dirname, 'deno-lint')
} catch (e) {
// eslint-disable-next-line no-empty
} catch (e) {}

if (!binding) {
const platformName = platform()
try {
binding = require(`@node-rs/deno-lint-${platform()}`)
binding = require(`@node-rs/deno-lint-${platformName}`)
} catch (e) {
throw new TypeError('Not compatible with your platform. Error message: ' + e.message)
if (platformName === 'linux') {
try {
binding = require('@node-rs/deno-lint-linux-musl')
} catch (e) {
throw new TypeError('Error loading native addon: ' + e.message)
}
} else {
throw new TypeError('Not compatible with your platform. Error message: ' + e.message)
}
}
}

module.exports = {
binding,
lint: function lint(filename, sourcecode) {
lint: function lint(path, sourcecode, allRules = false) {
const source = Buffer.isBuffer(sourcecode) ? sourcecode : Buffer.from(sourcecode)
return binding.lint(filename, source)
return binding.lint(path, source, allRules)
},
}
3 changes: 3 additions & 0 deletions packages/deno-lint/npm/musl/READEME.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `@node-rs/deno-lint-linux-musl`

This is the Linux 64-bit `musl` binary for `@node-rs/deno-lint`.
24 changes: 24 additions & 0 deletions packages/deno-lint/npm/musl/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@node-rs/deno-lint-linux-musl",
"version": "0.0.0",
"description": "Deno lint binding for NodeJS",
"keywords": ["Deno", "Lint", "ESLint", "node-rs", "napi", "N-API", "Rust", "napi-rs"],
"author": "LongYinan <lynweklm@gmail.com>",
"homepage": "https://github.com/napi-rs/node-rs",
"license": "MIT",
"main": "deno-lint.musl.node",
"files": ["deno-lint.musl.node"],
"os": ["linux"],
"cpu": ["x64"],
"engines": {
"node": ">= 8.9"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/napi-rs/node-rs.git"
}
}
8 changes: 6 additions & 2 deletions packages/deno-lint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"denolint": "./bin.js"
},
"typings": "index.d.ts",
"files": ["index.js", "index.d.ts", "bin.js", "LICENSE"],
"files": ["index.js", "index.d.ts", "bin.js", "webpack-loader.js", "LICENSE"],
"os": ["darwin", "linux", "win32"],
"cpu": ["x64"],
"engines": {
Expand All @@ -36,6 +36,10 @@
"url": "https://github.com/napi-rs/node-rs/issues"
},
"dependencies": {
"@node-rs/helper": "^0.2.1"
"@node-rs/helper": "^0.2.1",
"loader-utils": "^2.0.0"
},
"devDependencies": {
"@types/webpack": "^4.41.21"
}
}
1 change: 1 addition & 0 deletions packages/deno-lint/platforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = ['win32', 'darwin', 'linux']
5 changes: 2 additions & 3 deletions packages/deno-lint/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ const { execSync } = require('child_process')
const fs = require('fs')
const path = require('path')

const platforms = require('../../scripts/platforms')

const { version } = require('./package.json')
const platforms = require('./platforms')
const updatePackageJson = require('./update-package')

updatePackageJson(path.join(__dirname, 'package.json'), {
Expand All @@ -14,7 +13,7 @@ updatePackageJson(path.join(__dirname, 'package.json'), {
}, {}),
})

for (const name of platforms) {
for (const name of [...platforms, 'musl']) {
const pkgDir = path.join(__dirname, 'npm', name)
const filename = `deno-lint.${name}.node`
const bindingFile = fs.readFileSync(path.join(__dirname, `bindings-${name}`, filename))
Expand Down
31 changes: 24 additions & 7 deletions packages/deno-lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ extern crate napi;
#[macro_use]
extern crate napi_derive;

use napi::JsBoolean;
use std::env;
use std::fmt;
use std::fs;
Expand All @@ -12,10 +11,12 @@ use std::str;

use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::linter::LinterBuilder;
use deno_lint::rules::{get_all_rules, get_recommended_rules};
use deno_lint::swc_util::get_default_ts_config;
use ignore::overrides::OverrideBuilder;
use ignore::types::TypesBuilder;
use ignore::WalkBuilder;
use napi::{CallContext, Error, JsBuffer, JsObject, JsString, Module, Result, Status};
use napi::{CallContext, Error, JsBoolean, JsBuffer, JsObject, JsString, Module, Result, Status};
use termcolor::Color::{Ansi256, Red};
use termcolor::{Ansi, ColorSpec, WriteColor};

Expand Down Expand Up @@ -114,11 +115,19 @@ fn init(js_module: &mut Module) -> Result<()> {
Ok(())
}

#[js_function(2)]
#[js_function(3)]
fn lint(ctx: CallContext) -> Result<JsObject> {
let file_name = ctx.get::<JsString>(0)?;
let source_code = ctx.get::<JsBuffer>(1)?;
let mut linter = LinterBuilder::default().build();
let all_rules = ctx.get::<JsBoolean>(2)?;
let mut linter = LinterBuilder::default()
.rules(if all_rules.get_value()? {
get_all_rules()
} else {
get_recommended_rules()
})
.syntax(get_default_ts_config())
.build();

let source_string = str::from_utf8(&source_code).map_err(|e| Error {
status: Status::StringExpected,
Expand Down Expand Up @@ -148,9 +157,10 @@ fn lint(ctx: CallContext) -> Result<JsObject> {
Ok(result)
}

#[js_function(1)]
#[js_function(2)]
fn lint_command(ctx: CallContext) -> Result<JsBoolean> {
let __dirname = ctx.get::<JsString>(0)?;
let enable_all_rules = ctx.get::<JsBoolean>(1)?.get_value()?;
let mut has_error = false;
let cwd = env::current_dir().map_err(|e| {
Error::new(
Expand Down Expand Up @@ -210,7 +220,14 @@ fn lint_command(ctx: CallContext) -> Result<JsBoolean> {
if !p.is_dir() {
let file_content = fs::read_to_string(&p)
.map_err(|e| Error::from_reason(format!("Read file {:?} failed: {}", p, e)))?;
let mut linter = LinterBuilder::default().build();
let mut linter = LinterBuilder::default()
.rules(if enable_all_rules {
get_all_rules()
} else {
get_recommended_rules()
})
.syntax(get_default_ts_config())
.build();
let file_diagnostics = linter
.lint(
(&p.to_str())
Expand All @@ -227,7 +244,7 @@ fn lint_command(ctx: CallContext) -> Result<JsBoolean> {
})?;
for diagnostic in file_diagnostics {
has_error = true;
println!("{:?}", diagnostic);
println!("{}", format_diagnostic(&diagnostic));
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions packages/deno-lint/webpack-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { getOptions } = require('loader-utils')

const { lint } = require('./index')

module.exports = function denoLintLoader(source, sm) {
const callback = this.async()
const options = getOptions(this)
const diagnostics = lint(this.resourcePath, source, options.enableAllRules)

if (this.resourcePath.endsWith('diff-size.ts')) {
this.emitWarning(`${this.resourcePath}, ${diagnostics.length}`)
}

const hasError = diagnostics.length

if (!hasError) {
callback(null, source, sm)
return
}

if (options.failOnError) {
callback(new Error('Lint error'), source, sm)
return
}

if (!options.quiet) {
for (const diagnostic of diagnostics) {
this.emitError(diagnostic)
}
}

callback(null, source, sm)
}

0 comments on commit 59454e2

Please sign in to comment.