deno_lint icon indicating copy to clipboard operation
deno_lint copied to clipboard

Interoperate with Existing ESLint Rules and Configs

Open chances opened this issue 4 years ago • 7 comments

@axetroy If you say there are too many options, why build out a deno lint at all? That's only adding more options. We already have a linting tool for linting JavaScript and TypeScript and it is called eslint. I don't see a value in duplicating all that work again.

Unless a developer only writes backend code, they will still need to touch eslint.

If a parallel lint tool must be built (are there really not better ways to improve deno?) then it MUST be able to consume existing eslint rules. Otherwise people will waste their time reinventing the wheel, writing duplicate rules for deno and frontend code rather than application code.

Instead deno lint would be more useful as something like golangci-lint where it aggregates and calls other already written lint rules and linters. It provides a "default lint config" (via url import) with sane default but still extendable.

Originally posted by @brandonkal in https://github.com/denoland/deno/issues/1880#issuecomment-601616251

Emphasis added.

chances avatar Apr 08 '20 05:04 chances

What if deno lint worked for frontend code?

nayeemrmn avatar Apr 08 '20 10:04 nayeemrmn

My opinion is that linter should be fewer configurations (even 0)

The most popular eslint rules should be adopted, but no options are provided.

In the short term, this is very bad, because everyone's writing habits are different

But in the long term, it unifies the code style

As I think about deno fmt

We should not add some flags to set the code style, eg. whether use trailing commas, whether to use spaces or tabs. I think this is very bad.

People don’t have to discuss which one is the best style

axetroy avatar Apr 08 '20 12:04 axetroy

Code style is only limited by your project and your personal writing style as you said. But having no option to thinker with that options only removes value to an otherwise highly (though opinionated by default) customizable environment

As has been discussed before, Deno doesn't do magic, doesn't pick default files and prefers to allow customization even though its defaults will be highly influenced by products such as ESLint and Prettier

Soremwar avatar Apr 08 '20 12:04 Soremwar

I would suggest having the linting setup include only common problems only; perhaps extending eslint:recommended (which is common problems only), something like:

{
    "parserOptions": {
      "ecmaVersion": X
    },
    "extends": [
      "eslint:recommended"
    ]
}

trevordmiller avatar Apr 24 '20 20:04 trevordmiller

Discussed offline with @magurotuna, we agree this is highly desirable and will look into what are the prerequisites.

bartlomieju avatar Sep 23 '21 14:09 bartlomieju

Deno's linter doesn't provide alternatives for all the Eslint rules we've historically used, which is a deal-breaker for us switching to Deno.

We tried adding workarounds to Eslint to let it run in Deno files (see https://github.com/typescript-eslint/typescript-eslint/issues/5921), but it's overly complicated and kind-of outside the scope of Eslint. IMO it would really behoove Deno Lint to natively support Eslint rules, rather than Deno Lint trying to come up with its own replacements for Eslint rules.

AFAIK there are a few things that prevent Eslint from working with Deno:

Eslint can't resolve .ts extensions

That's easy to work around:

// ts-resolver.js
const ts = require(`typescript`);
const tsExtension = /\.ts$/;
module.exports = {
	resolveModuleNames: (
		moduleNames,
		containingFile,
		reusedNames,
		redirectedReference,
		options
	) => moduleNames.map((moduleName) =>
		ts.resolveModuleName(
			moduleName.replace(tsExtension, ``),
			containingFile,
			options,
			ts.sys
		).resolvedModule
	),
};
// .eslintrc.js
module.exports = {
	env: {
		node: true,
	},
	overrides: [
		{
			files: [`*.ts`],
			parser: `@typescript-eslint/parser`,
			parserOptions: {
				moduleResolver: __dirname + `/ts-resolver.js`,
			},
		},
	],
};

Eslint can't resolve Deno's remote dependencies

For example:

import { serve } from 'https://deno.land/[email protected]/http/server.ts';

The eslint-import-resolver-deno shows how to work around this, and it's not complicated. The package can also just be used wholesale:

const ts = require(`typescript`);
const denoResolver = require(`eslint-import-resolver-deno`);

const tsExtension = /\.ts$/;
module.exports = {
	resolveModuleNames: (
		moduleNames,
		containingFile,
		reusedNames,
		redirectedReference,
		options
	) => moduleNames.map((moduleName) => {
		if (moduleName.startsWith(`http`)) {
			const { found, path } = denoResolver.resolve(
				moduleName,
				containingFile,
				{
					importMap: __dirname + `/import-map.json`,
				}
			);
			if (found) {
				moduleName = path;
			}
		}
		return ts.resolveModuleName(
			moduleName.replace(tsExtension, ``),
			containingFile,
			options,
			ts.sys
		).resolvedModule;
	}),
};

Eslint doesn't "know" about Deno's global types

Despite the above workarounds to the module resolution issues, Eslint interprets anything reliant on a global Deno type as any.

If Eslint can be configured to know about Deno's global types, then it seems like Eslint could support Deno pretty easily. Maybe this in turn means that Deno Lint could support Eslint pretty easily?

RobertAKARobin avatar Nov 08 '22 18:11 RobertAKARobin

Update: Well, I'm getting there. I have ESlint itself apparently working. But I can't make the VSCode ESlint extension play nice with Deno imports.

RobertAKARobin avatar Dec 14 '22 18:12 RobertAKARobin