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

feat: Flat config support in Linter (refs #13481) #15185

Merged
merged 37 commits into from Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a9da57b
Update: Flat config support in Linter (refs #13481)
nzakas Oct 18, 2021
a29a557
Update lib/linter/linter.js
nzakas Oct 19, 2021
38c0d16
Update lib/linter/linter.js
nzakas Oct 19, 2021
f2a7458
Clean up FlatConfigArray detection
nzakas Oct 19, 2021
66cf8a3
Add back FlatConfigArray import
nzakas Oct 19, 2021
dfdd4fa
More flat config tests passing; originals failing
nzakas Oct 20, 2021
531be0c
Finish languageOptions features
nzakas Oct 21, 2021
e3e9367
Make sure to recognize RuleTester-wrapped Espree
nzakas Oct 25, 2021
4ffbc2e
Move globals into local file
nzakas Oct 25, 2021
3bc4832
Normalize ecmaVersion to year on context.languageOptions
nzakas Oct 25, 2021
8076425
Clean up ecmaVersion normalization
nzakas Oct 26, 2021
a20e642
Revert parserOptions.ecmaVersion behavior to original
nzakas Oct 29, 2021
cee5632
Add more tests
nzakas Oct 29, 2021
ac3f270
Update defaults for flat config (refs #14588)
nzakas Oct 29, 2021
7a03b48
More tests passing
nzakas Nov 3, 2021
e948144
Fix wrong ecmaVersion conversion
nzakas Nov 3, 2021
703e590
Duplicated all tests for FlatConfig
nzakas Nov 9, 2021
360c2d7
Finish languageOptions tests
nzakas Nov 10, 2021
aaab04e
Settings tests working
nzakas Nov 10, 2021
f25b139
Rule context tests working
nzakas Nov 10, 2021
f6ea3f7
Options tests working
nzakas Nov 10, 2021
c0a1eb4
Directives tests working
nzakas Nov 11, 2021
f6b1207
reportUnusedDisableDirectives tests working
nzakas Nov 11, 2021
90c3214
All original tests passing
nzakas Nov 12, 2021
7130a27
Add test to verify lazy loading of rules (fixes #14862)
nzakas Nov 12, 2021
165e59b
Fix failing tests
nzakas Nov 12, 2021
2536a6b
Fix failing browser test
nzakas Nov 12, 2021
e0e1618
Fix ecmaVersion edge cases
nzakas Nov 23, 2021
240f0ad
Switch globalReturn to false if sourceType is module
nzakas Nov 23, 2021
a351eec
Update Espree and eslint-scope to support sourceType:commonjs
nzakas Nov 24, 2021
4cd44a4
Update lib/linter/linter.js
nzakas Nov 26, 2021
8cffdc8
Update lib/linter/linter.js
nzakas Nov 26, 2021
2c2e5d7
Fix processors functionality
nzakas Nov 29, 2021
d40a473
Update lib/shared/types.js
nzakas Dec 4, 2021
78237f2
Update tests/lib/linter/linter.js
nzakas Dec 4, 2021
b042303
Update tests/lib/linter/linter.js
nzakas Dec 4, 2021
9ad40d0
Update lib/linter/linter.js
nzakas Dec 4, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
144 changes: 144 additions & 0 deletions conf/globals.js
@@ -0,0 +1,144 @@
/**
* @fileoverview Globals for ecmaVersion/sourceType
* @author Nicholas C. Zakas
Copy link
Member Author

@nzakas nzakas Oct 26, 2021

Choose a reason for hiding this comment

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

Moved globals here since the list is much smaller without environments, allowing us to update more easily and also support ES3 correctly (right now we still add JSON when ecmaVersion is 3.

*/

"use strict";

//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------

const commonjs = {
exports: true,
global: false,
module: false,
require: false
};

const es3 = {
Array: false,
Boolean: false,
constructor: false,
Date: false,
decodeURI: false,
decodeURIComponent: false,
encodeURI: false,
encodeURIComponent: false,
Error: false,
escape: false,
eval: false,
EvalError: false,
Function: false,
hasOwnProperty: false,
Infinity: false,
isFinite: false,
isNaN: false,
isPrototypeOf: false,
Math: false,
NaN: false,
Number: false,
Object: false,
parseFloat: false,
parseInt: false,
propertyIsEnumerable: false,
RangeError: false,
ReferenceError: false,
RegExp: false,
String: false,
SyntaxError: false,
toLocaleString: false,
toString: false,
TypeError: false,
undefined: false,
unescape: false,
URIError: false,
valueOf: false
};

const es5 = {
...es3,
JSON: false
};

const es2015 = {
...es5,
ArrayBuffer: false,
DataView: false,
Float32Array: false,
Float64Array: false,
Int16Array: false,
Int32Array: false,
Int8Array: false,
Map: false,
Promise: false,
Proxy: false,
Reflect: false,
Set: false,
Symbol: false,
Uint16Array: false,
Uint32Array: false,
Uint8Array: false,
Uint8ClampedArray: false,
WeakMap: false,
WeakSet: false
};

// no new globals in ES2016
const es2016 = {
...es2015
};

const es2017 = {
...es2016,
Atomics: false,
SharedArrayBuffer: false
};

// no new globals in ES2018
const es2018 = {
...es2017
};

// no new globals in ES2019
const es2019 = {
...es2018
};

const es2020 = {
...es2019,
BigInt: false,
BigInt64Array: false,
BigUint64Array: false,
globalThis: false
};

const es2021 = {
...es2020,
AggregateError: false,
FinalizationRegistry: false,
WeakRef: false
};

const es2022 = {
...es2021
};


//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

module.exports = {
commonjs,
es3,
es5,
es2015,
es2016,
es2017,
es2018,
es2019,
es2020,
es2021,
es2022
};
9 changes: 9 additions & 0 deletions karma.conf.js
Expand Up @@ -16,6 +16,15 @@ module.exports = function(config) {
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: "",

// next three sections allow console.log to work
client: {
captureConsole: true
},

browserConsoleLogOptions: {
terminal: true,
level: "log"
},

/*
* frameworks to use
Expand Down
13 changes: 11 additions & 2 deletions lib/config/default-config.js
Expand Up @@ -26,7 +26,7 @@ exports.defaultConfig = [

/*
* Because we try to delay loading rules until absolutely
* necessary, a proxy allows us to hook into the lazy-loading
* necessary, a proxy allows us to hook into the lazy-loading
* aspect of the rules map while still keeping all of the
* relevant configuration inside of the config array.
*/
Expand All @@ -46,7 +46,16 @@ exports.defaultConfig = [
".git/**"
],
languageOptions: {
parser: "@/espree"
ecmaVersion: "latest",
sourceType: "module",
parser: "@/espree",
parserOptions: {}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Updating the defaults as briefly discussed in #14588. I think it makes sense to assume people will be using ESM and always want the latest ecmaVersion.

},
{
files: ["**/*.cjs"],
languageOptions: {
sourceType: "commonjs"
Copy link
Member Author

Choose a reason for hiding this comment

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

For .cjs files, I think it makes sense to opt them into "commonjs" sourceType.

}
}
];
4 changes: 2 additions & 2 deletions lib/config/flat-config-array.js
Expand Up @@ -52,13 +52,13 @@ class FlatConfigArray extends ConfigArray {
* @param {{basePath: string, baseConfig: FlatConfig}} options The options
* to use for the config array instance.
*/
constructor(configs, { basePath, baseConfig = defaultConfig }) {
constructor(configs, { basePath, baseConfig = defaultConfig } = {}) {
super(configs, {
basePath,
schema: flatConfigSchema
});

this.unshift(baseConfig);
this.unshift(...baseConfig);
}

/* eslint-disable class-methods-use-this -- Desired as instance method */
Expand Down
67 changes: 67 additions & 0 deletions lib/config/flat-config-helpers.js
@@ -0,0 +1,67 @@
/**
* @fileoverview Shared functions to work with configs.
* @author Nicholas C. Zakas
*/

"use strict";

//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------

/**
* Parses a ruleId into its plugin and rule parts.
* @param {string} ruleId The rule ID to parse.
* @returns {{pluginName:string,ruleName:string}} The plugin and rule
* parts of the ruleId;
*/
function parseRuleId(ruleId) {
let pluginName, ruleName;

// distinguish between core rules and plugin rules
if (ruleId.includes("/")) {
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
ruleName = ruleId.slice(pluginName.length + 1);
} else {
pluginName = "@";
ruleName = ruleId;
}

return {
pluginName,
ruleName
};
}

/**
* Retrieves a rule instance from a given config based on the ruleId.
* @param {string} ruleId The rule ID to look for.
* @param {FlatConfig} config The config to search.
* @returns {import("../shared/types").Rule|undefined} The rule if found
* or undefined if not.
*/
function getRuleFromConfig(ruleId, config) {

const { pluginName, ruleName } = parseRuleId(ruleId);

const plugin = config.plugins && config.plugins[pluginName];
let rule = plugin && plugin.rules && plugin.rules[ruleName];

// normalize function rules into objects
if (rule && typeof rule === "function") {
rule = {
create: rule
};
}

return rule;
}

//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

module.exports = {
parseRuleId,
getRuleFromConfig
};
21 changes: 13 additions & 8 deletions lib/config/flat-config-schema.js
Expand Up @@ -195,13 +195,6 @@ function assertIsObjectOrString(value) {
// Low-Level Schemas
//-----------------------------------------------------------------------------


/** @type {ObjectPropertySchema} */
const numberSchema = {
merge: "replace",
validate: "number"
};

/** @type {ObjectPropertySchema} */
const booleanSchema = {
merge: "replace",
Expand Down Expand Up @@ -415,6 +408,18 @@ const rulesSchema = {
}
};

/** @type {ObjectPropertySchema} */
const ecmaVersionSchema = {
merge: "replace",
validate(value) {
if (typeof value === "number" || value === "latest") {
return;
}

throw new TypeError("Expected a number or \"latest\".");
}
};

/** @type {ObjectPropertySchema} */
const sourceTypeSchema = {
merge: "replace",
Expand All @@ -439,7 +444,7 @@ exports.flatConfigSchema = {
},
languageOptions: {
schema: {
ecmaVersion: numberSchema,
ecmaVersion: ecmaVersionSchema,
sourceType: sourceTypeSchema,
globals: globalsSchema,
parser: parserSchema,
Expand Down