Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add eslint package to handle linting #37417

Merged
merged 67 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
11c88a6
create: feature flag for eslint migration
ayushpahwa Sep 25, 2024
8c4ad0f
update: enum for linter engines
ayushpahwa Sep 25, 2024
8cc1c36
update: refactored if check logic
ayushpahwa Sep 25, 2024
35c9441
update: remove const from enum declaration
ayushpahwa Sep 25, 2024
3ff9c9e
create: type added for lint length
ayushpahwa Sep 25, 2024
77ef464
update: logic added to skip lint length calculation
ayushpahwa Sep 25, 2024
bba3989
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Sep 28, 2024
5c3c434
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Sep 28, 2024
7ab0717
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Sep 30, 2024
5579787
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Sep 30, 2024
1298a8f
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Oct 9, 2024
206db12
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Oct 9, 2024
9e1a65b
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Oct 14, 2024
d84b7b1
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Oct 14, 2024
64d4272
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Nov 6, 2024
40b0c85
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Nov 11, 2024
34b638b
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Nov 11, 2024
18afebc
update: sync with release
ayushpahwa Nov 11, 2024
a03edc2
update: refactor var name
ayushpahwa Nov 11, 2024
23649ca
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Nov 11, 2024
03e97dd
Merge branch 'release' into feat/eslint/feature-flag
ayushpahwa Nov 12, 2024
254f465
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Nov 12, 2024
00d8519
update: refactored variable name
ayushpahwa Nov 12, 2024
43b4ef2
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Nov 12, 2024
ac773e1
update: refactor var name
ayushpahwa Nov 12, 2024
7c35991
Merge branch 'feat/eslint/feature-flag' into feat/eslint/lint-length-…
ayushpahwa Nov 12, 2024
0919825
Merge branch 'release' into feat/eslint/lint-length-processing
ayushpahwa Nov 14, 2024
b6d23a7
Merge branch 'release' into feat/eslint/lint-length-processing
ayushpahwa Nov 18, 2024
924ceb0
update: add tests for lint length change
ayushpahwa Nov 18, 2024
afe552b
update: fix lint issue
ayushpahwa Nov 18, 2024
fc035b4
create: new package for eslint
ayushpahwa Nov 18, 2024
c4df9f1
update: config update based on lintertype used
ayushpahwa Nov 18, 2024
3c8ef15
update: pass the current lintertype to options conflig
ayushpahwa Nov 18, 2024
7452c8c
update: helper methods for eslint
ayushpahwa Nov 18, 2024
b63e371
update: lock file
ayushpahwa Nov 18, 2024
b3600f3
update: lint length if engine is eslint
ayushpahwa Nov 18, 2024
9653d47
update: source of linter
ayushpahwa Nov 18, 2024
0f6078a
update: constants for linter
ayushpahwa Nov 18, 2024
a13751f
update: add polyfill for missing method
ayushpahwa Nov 18, 2024
36e7f16
update: force the lint test to be run for both jshint and eslint
ayushpahwa Nov 18, 2024
b263be4
update: refactor function passing for jest test
ayushpahwa Nov 18, 2024
987d809
update: pass mocked function for test
ayushpahwa Nov 18, 2024
8df7584
update: comment added for clarity
ayushpahwa Nov 18, 2024
7da61e7
Merge branch 'release' into feat/eslint/lint-length-processing
ayushpahwa Nov 19, 2024
6b07590
Merge branch 'feat/eslint/lint-length-processing' into feat/eslint/es…
ayushpahwa Nov 19, 2024
550dd08
Merge branch 'release' into feat/eslint/eslint-package
ayushpahwa Nov 20, 2024
8996a3a
Merge branch 'release' into feat/eslint/eslint-package
ayushpahwa Nov 21, 2024
418b990
update: WIP tests for each rule config
ayushpahwa Nov 21, 2024
6ea9f12
update: add tests for curl
ayushpahwa Nov 21, 2024
40f57f7
update: moved unused vars to warn state
ayushpahwa Nov 21, 2024
073ad50
update: new tests for config rules
ayushpahwa Nov 21, 2024
7fb4717
update: add tests for asi and boss rule config
ayushpahwa Nov 21, 2024
1291da0
udpate: add tests for no semicolons
ayushpahwa Nov 21, 2024
e72081e
update: add test for boss rule
ayushpahwa Nov 21, 2024
74951dc
update: add tests for eval rule
ayushpahwa Nov 21, 2024
2ab43e4
update: add tests for funcscope and dotnotation
ayushpahwa Nov 21, 2024
983fa65
update: add tests for expr rule config
ayushpahwa Nov 21, 2024
23543c3
update: fix test for funcscope
ayushpahwa Nov 21, 2024
22e7cc8
Merge branch 'release' into feat/eslint/eslint-package
ayushpahwa Nov 21, 2024
9ea70c6
update: add indirect eval tests
ayushpahwa Nov 21, 2024
a347807
update: remove redundant code
ayushpahwa Nov 21, 2024
7df7f53
update: add polyfil for jest tests
ayushpahwa Nov 21, 2024
32ea12a
update: acorn walk package
ayushpahwa Nov 21, 2024
81bc617
update: yarn lock for package upgrade
ayushpahwa Nov 21, 2024
518c411
update: remove unused type skip commetns
ayushpahwa Nov 21, 2024
7fd76f3
Merge branch 'chore/fix-acorn-version' into feat/eslint/eslint-package
ayushpahwa Nov 21, 2024
579e477
Merge branch 'release' into feat/eslint/eslint-package
ayushpahwa Nov 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"deep-diff": "^1.0.2",
"downloadjs": "^1.4.7",
"echarts": "^5.4.2",
"eslint-linter-browserify": "^9.15.0",
ayushpahwa marked this conversation as resolved.
Show resolved Hide resolved
"fast-deep-equal": "^3.1.3",
"fast-sort": "^3.4.0",
"fastdom": "^1.0.11",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,10 @@ export const getLintAnnotations = (
// Jshint counts \t as two characters and codemirror counts it as 1.
// So we need to subtract number of tabs to get accurate position.
// This is not needed for custom lint errors, since they are not generated by JSHint
// ESLint doesn't have this issue and hence we are skipping if lint is generated via eslint
const tabs =
error.code && error.code in CUSTOM_LINT_ERRORS
(error.code && error.code in CUSTOM_LINT_ERRORS) ||
(lintLength && lintLength > 0)
? 0
: lineContent.slice(0, currentCh).match(/\t/g)?.length || 0;
const from = {
Expand Down
100 changes: 74 additions & 26 deletions app/client/src/plugins/Linting/constants.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,85 @@
import { ECMA_VERSION } from "@shared/ast";
import type { LintOptions } from "jshint";
import isEntityFunction from "./utils/isEntityFunction";
import type { Linter } from "eslint-linter-browserify";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ayushpahwa Where have we defined the flag that enables ESLint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

he feature flag was added in a previous PR. Let me share all the PRs with you
PR1: #36543
PR2: #36548

Now we are on PR3, the current PR to add the eslint package

Next planned PRs
4) Add custom rules for floating promises
5) Remove jshint and related feature flags


export enum LINTER_TYPE {
"JSHINT" = "JSHint",
"ESLINT" = "ESLint",
}

export const lintOptions = (globalData: Record<string, boolean>) =>
({
indent: 2,
esversion: ECMA_VERSION,
eqeqeq: false, // Not necessary to use ===
curly: false, // Blocks can be added without {}, eg if (x) return true
freeze: true, // Overriding inbuilt classes like Array is not allowed
undef: true, // Undefined variables should be reported as error
forin: false, // Doesn't require filtering for..in loops with obj.hasOwnProperty()
noempty: false, // Empty blocks are allowed
strict: false, // We won't force strict mode
unused: "strict", // Unused variables are not allowed
asi: true, // Tolerate Automatic Semicolon Insertion (no semicolons)
boss: true, // Tolerate assignments where comparisons would be expected
evil: false, // Use of eval not allowed
funcscope: true, // Tolerate variable definition inside control statements
sub: true, // Don't force dot notation
expr: true, // suppresses warnings about the use of expressions where normally you would expect to see assignments or function calls
// environments
browser: false,
worker: true,
mocha: false,
// global values
globals: globalData,
loopfunc: true,
}) as LintOptions;
export const lintOptions = (
globalData: Record<string, boolean>,
linterType: LINTER_TYPE = LINTER_TYPE.JSHINT,
) => {
if (linterType === LINTER_TYPE.JSHINT) {
return {
indent: 2,
esversion: ECMA_VERSION,
eqeqeq: false, // Not necessary to use ===
curly: false, // Blocks can be added without {}, eg if (x) return true
freeze: true, // Overriding inbuilt classes like Array is not allowed
undef: true, // Undefined variables should be reported as error
forin: false, // Doesn't require filtering for..in loops with obj.hasOwnProperty()
noempty: false, // Empty blocks are allowed
strict: false, // We won't force strict mode
unused: "strict", // Unused variables are not allowed
asi: true, // Tolerate Automatic Semicolon Insertion (no semicolons)
boss: true, // Tolerate assignments where comparisons would be expected
evil: false, // Use of eval not allowed
funcscope: true, // Tolerate variable definition inside control statements
sub: true, // Don't force dot notation
expr: true, // suppresses warnings about the use of expressions where normally you would expect to see assignments or function calls
// environments
browser: false,
worker: true,
mocha: false,
// global values
globals: globalData,
loopfunc: true,
} as LintOptions;
} else {
const eslintGlobals: Record<string, "writable" | "readonly"> = {
setTimeout: "readonly",
clearTimeout: "readonly",
console: "readonly",
};

for (const key in globalData) {
if (globalData.hasOwnProperty(key)) {
eslintGlobals[key] = "readonly";
}
Comment on lines +48 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use Object.prototype.hasOwnProperty.call() for safer property checks

Accessing hasOwnProperty directly on globalData can lead to unexpected behavior if globalData has its own hasOwnProperty property. It's safer to use Object.prototype.hasOwnProperty.call(globalData, key).

Apply this diff to fix the issue:

- if (globalData.hasOwnProperty(key)) {
+ if (Object.prototype.hasOwnProperty.call(globalData, key)) {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome

[error] 49-49: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)

}
Comment on lines +48 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use Object.hasOwn() for safer property checks

The direct use of hasOwnProperty is unsafe. Use Object.hasOwn() for better safety.

Apply this fix:

- if (globalData.hasOwnProperty(key)) {
+ if (Object.hasOwn(globalData, key)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const key in globalData) {
if (globalData.hasOwnProperty(key)) {
eslintGlobals[key] = "readonly";
}
}
for (const key in globalData) {
if (Object.hasOwn(globalData, key)) {
eslintGlobals[key] = "readonly";
}
}
🧰 Tools
🪛 Biome

[error] 49-49: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)


return {
languageOptions: {
ecmaVersion: ECMA_VERSION,
globals: eslintGlobals,
sourceType: "script",
},
rules: {
eqeqeq: "off",
curly: "off",
"no-extend-native": "error",
"no-undef": "error",
"guard-for-in": "off",
"no-empty": "off",
strict: "off",
"no-unused-vars": [
"warn",
{ vars: "all", args: "all", ignoreRestSiblings: false },
],
"no-cond-assign": "off",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we made sure that these rules correspond to what was in JSHint? This is important so as not to spoil the user experience.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked these manually but it makes sense to add tests for these all, let me update.

"no-eval": "error",
"block-scoped-var": "off",
"dot-notation": "off",
"no-unused-expressions": "off",
"no-loop-func": "off",
},
} as Linter.Config;
}
};

export const JS_OBJECT_START_STATEMENT = "export default";
export const INVALID_JSOBJECT_START_STATEMENT = `JSObject must start with '${JS_OBJECT_START_STATEMENT}'`;
export const INVALID_JSOBJECT_START_STATEMENT_ERROR_CODE =
Expand All @@ -43,6 +90,7 @@ export const IDENTIFIER_NOT_DEFINED_LINT_ERROR_CODE = "W117";
// For these error types, we want to show a warning
// All messages can be found here => https://github.com/jshint/jshint/blob/2.9.5/src/messages.js
export const WARNING_LINT_ERRORS = {
"no-unused-vars": "'{a}' is assigned a value but never used.",
W098: "'{a}' is defined but never used.",
W014: "Misleading line break before '{a}'; readers may interpret this as an expression boundary.",
ASYNC_FUNCTION_BOUND_TO_SYNC_FIELD:
Expand Down
Loading
Loading