[7.x] [eslint] merge custom rules into a single plugin (#33733) (#33758)

Backports the following commits to 7.x:
 - [eslint] merge custom rules into a single plugin  (#33733)
This commit is contained in:
Spencer 2019-03-22 18:53:45 -07:00 committed by GitHub
parent 5f4a4ce8ba
commit f09e17e76c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 196 additions and 191 deletions

View file

@ -18,7 +18,6 @@ bower_components
/src/core/lib/kbn_internal_native_observable
/packages/*/target
/packages/eslint-config-kibana
/packages/eslint-plugin-kibana-custom
/packages/kbn-es-query/src/kuery/ast/kuery.js
/packages/kbn-es-query/src/kuery/ast/legacy_kuery.js
/packages/kbn-pm/dist

View file

@ -34,6 +34,7 @@ const ELASTIC_LICENSE_HEADER = `
module.exports = {
extends: ['@elastic/eslint-config-kibana', '@elastic/eslint-config-kibana/jest'],
plugins: ['@kbn/eslint-plugin-eslint'],
settings: {
'import/resolver': {
@ -55,7 +56,7 @@ module.exports = {
{
files: [
'.eslintrc.js',
'packages/eslint-plugin-kibana-custom/**/*',
'packages/kbn-eslint-plugin-eslint/**/*',
'packages/kbn-config-schema/**/*',
'packages/kbn-pm/**/*',
'packages/kbn-es/**/*',
@ -87,7 +88,7 @@ module.exports = {
{
files: ['x-pack/test/functional/apps/**/*', 'x-pack/plugins/apm/**/*'],
rules: {
'kibana-custom/no-default-export': 'off',
'@kbn/eslint/no-default-export': 'off',
'import/no-named-as-default': 'off',
},
},
@ -242,7 +243,7 @@ module.exports = {
'packages/kbn-plugin-generator/**/*',
'packages/kbn-plugin-helpers/**/*',
'packages/kbn-eslint-import-resolver-kibana/**/*',
'packages/kbn-eslint-plugin-license-header/**/*',
'packages/kbn-eslint-plugin-eslint/**/*',
'x-pack/gulpfile.js',
'x-pack/dev-tools/mocha/setup_mocha.js',
'x-pack/scripts/*',
@ -267,15 +268,14 @@ module.exports = {
*/
{
files: ['**/*.js'],
plugins: ['@kbn/eslint-plugin-license-header'],
rules: {
'@kbn/license-header/require-license-header': [
'@kbn/eslint/require-license-header': [
'error',
{
license: APACHE_2_0_LICENSE_HEADER,
},
],
'@kbn/license-header/disallow-license-headers': [
'@kbn/eslint/disallow-license-headers': [
'error',
{
licenses: [ELASTIC_LICENSE_HEADER],
@ -289,15 +289,14 @@ module.exports = {
*/
{
files: ['x-pack/**/*.js'],
plugins: ['@kbn/eslint-plugin-license-header'],
rules: {
'@kbn/license-header/require-license-header': [
'@kbn/eslint/require-license-header': [
'error',
{
license: ELASTIC_LICENSE_HEADER,
},
],
'@kbn/license-header/disallow-license-headers': [
'@kbn/eslint/disallow-license-headers': [
'error',
{
licenses: [APACHE_2_0_LICENSE_HEADER],

View file

@ -251,11 +251,10 @@
"@babel/parser": "^7.3.4",
"@babel/types": "^7.3.4",
"@elastic/eslint-config-kibana": "0.15.0",
"@elastic/eslint-plugin-kibana-custom": "1.1.0",
"@elastic/makelogs": "^4.4.0",
"@kbn/es": "1.0.0",
"@kbn/eslint-import-resolver-kibana": "2.0.0",
"@kbn/eslint-plugin-license-header": "1.0.0",
"@kbn/eslint-plugin-eslint": "1.0.0",
"@kbn/plugin-generator": "1.0.0",
"@kbn/test": "1.0.0",
"@octokit/rest": "^15.10.0",

View file

@ -1,14 +0,0 @@
module.exports = {
rules: {
'no-default-export': {
meta: {
schema: []
},
create: context => ({
ExportDefaultDeclaration: (node) => {
context.report(node, 'Default exports not allowed.');
}
})
}
}
};

View file

@ -1,10 +0,0 @@
{
"name": "@elastic/eslint-plugin-kibana-custom",
"version": "1.1.0",
"license": "Apache-2.0",
"description": "Custom ESLint rules for Kibana",
"repository": {
"type": "git",
"url": "https://github.com/elastic/kibana/tree/master/packages/%40elastic/eslint-plugin-kibana-custom"
}
}

View file

@ -21,5 +21,6 @@ module.exports = {
rules: {
'require-license-header': require('./rules/require_license_header'),
'disallow-license-headers': require('./rules/disallow_license_headers'),
'no-default-export': require('./rules/no_default_export'),
},
};

View file

@ -31,14 +31,14 @@ exports.normalizeWhitespace = function normalizeWhitespace(string) {
return string.replace(/\s+/g, ' ');
};
exports.init = function (context, program, initStep) {
exports.init = function(context, program, initStep) {
try {
return initStep();
} catch (error) {
if (error.failedAssertion) {
context.report({
node: program,
message: error.message
message: error.message,
});
} else {
throw error;

View file

@ -1,5 +1,5 @@
{
"name": "@kbn/eslint-plugin-license-header",
"name": "@kbn/eslint-plugin-eslint",
"version": "1.0.0",
"private": true,
"license": "Apache-2.0",

View file

@ -21,15 +21,14 @@ const { RuleTester } = require('eslint');
const rule = require('../disallow_license_headers');
const dedent = require('dedent');
const RULE_NAME = '@kbn/license-header/disallow-license-headers';
const ruleTester = new RuleTester({
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2015
}
ecmaVersion: 2015,
},
});
ruleTester.run(RULE_NAME, rule, {
ruleTester.run('@kbn/eslint/disallow-license-headers', rule, {
valid: [
{
code: dedent`
@ -38,11 +37,11 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
'// license'
]
}],
options: [
{
licenses: ['// license'],
},
],
},
{
code: dedent`
@ -51,12 +50,12 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
'/* license */',
]
}],
}
options: [
{
licenses: ['/* license */'],
},
],
},
],
invalid: [
@ -70,8 +69,8 @@ ruleTester.run(RULE_NAME, rule, {
errors: [
{
message: '"licenses" option is required',
}
]
},
],
},
// license cannot contain multiple block comments
@ -80,16 +79,16 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
'/* one *//* two */'
]
}],
options: [
{
licenses: ['/* one *//* two */'],
},
],
errors: [
{
message: '"licenses[0]" option must only include a single comment',
}
]
},
],
},
// license cannot contain multiple line comments
@ -98,16 +97,16 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
`// one\n// two`
]
}],
options: [
{
licenses: [`// one\n// two`],
},
],
errors: [
{
message: '"licenses[0]" option must only include a single comment',
}
]
},
],
},
// license cannot contain expressions
@ -116,20 +115,22 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
'// old license',
dedent`
options: [
{
licenses: [
'// old license',
dedent`
/* license */
console.log('hello world');
`
]
}],
`,
],
},
],
errors: [
{
message: '"licenses[1]" option must only include a single comment',
}
]
},
],
},
// license is not a single comment
@ -138,18 +139,16 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [{
licenses: [
'// old license',
'// older license',
`console.log('hello world');`
]
}],
options: [
{
licenses: ['// old license', '// older license', `console.log('hello world');`],
},
],
errors: [
{
message: '"licenses[2]" option must only include a single comment',
}
]
},
],
},
]
],
});

View file

@ -21,15 +21,14 @@ const { RuleTester } = require('eslint');
const rule = require('../require_license_header');
const dedent = require('dedent');
const RULE_NAME = '@kbn/license-header/require-license-header';
const ruleTester = new RuleTester({
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2015
}
ecmaVersion: 2015,
},
});
ruleTester.run(RULE_NAME, rule, {
ruleTester.run('@kbn/eslint/require-license-header', rule, {
valid: [
{
code: dedent`
@ -48,7 +47,7 @@ ruleTester.run(RULE_NAME, rule, {
`,
options: [{ license: '// license' }],
}
},
],
invalid: [
@ -62,8 +61,8 @@ ruleTester.run(RULE_NAME, rule, {
errors: [
{
message: '"license" option is required',
}
]
},
],
},
// content cannot contain multiple block comments
@ -72,14 +71,12 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [
{ license: '/* one *//* two */' }
],
options: [{ license: '/* one *//* two */' }],
errors: [
{
message: '"license" option must only include a single comment',
}
]
},
],
},
// content cannot contain multiple line comments
@ -88,14 +85,12 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [
{ license: `// one\n// two` }
],
options: [{ license: `// one\n// two` }],
errors: [
{
message: '"license" option must only include a single comment',
}
]
},
],
},
// content cannot contain expressions
@ -109,14 +104,14 @@ ruleTester.run(RULE_NAME, rule, {
license: dedent`
/* license */
console.log('hello world');
`
}
`,
},
],
errors: [
{
message: '"license" option must only include a single comment',
}
]
},
],
},
// content is not a single comment
@ -125,14 +120,12 @@ ruleTester.run(RULE_NAME, rule, {
console.log('foo')
`,
options: [
{ license: `console.log('hello world');` }
],
options: [{ license: `console.log('hello world');` }],
errors: [
{
message: '"license" option must only include a single comment',
}
]
},
],
},
// missing license header
@ -145,19 +138,21 @@ ruleTester.run(RULE_NAME, rule, {
errors: [
{
message: 'File must start with a license header',
}
},
],
output: dedent`
/* license */
console.log('foo')
`
`,
},
// strips newlines before the license comment
{
code: '\n\n' + dedent`
code:
'\n\n' +
dedent`
/* license */
console.log('foo')
@ -167,14 +162,14 @@ ruleTester.run(RULE_NAME, rule, {
errors: [
{
message: 'License header must be at the very beginning of the file',
}
},
],
output: dedent`
/* license */
console.log('foo')
`
`,
},
// moves license header before other nodes if necessary
@ -189,7 +184,7 @@ ruleTester.run(RULE_NAME, rule, {
errors: [
{
message: 'License header must be at the very beginning of the file',
}
},
],
output: dedent`
@ -198,7 +193,7 @@ ruleTester.run(RULE_NAME, rule, {
/* not license */
console.log('foo')
`
`,
},
]
],
});

View file

@ -24,18 +24,20 @@ const { assert, normalizeWhitespace, init } = require('../lib');
module.exports = {
meta: {
fixable: 'code',
schema: [{
type: 'object',
properties: {
licenses: {
type: 'array',
items: {
type: 'string'
}
schema: [
{
type: 'object',
properties: {
licenses: {
type: 'array',
items: {
type: 'string',
},
},
},
additionalProperties: false,
},
additionalProperties: false,
}]
],
},
create: context => {
return {
@ -49,8 +51,14 @@ module.exports = {
return licenses.map((license, i) => {
const parsed = babelEslint.parse(license);
assert(!parsed.body.length, `"licenses[${i}]" option must only include a single comment`);
assert(parsed.comments.length === 1, `"licenses[${i}]" option must only include a single comment`);
assert(
!parsed.body.length,
`"licenses[${i}]" option must only include a single comment`
);
assert(
parsed.comments.length === 1,
`"licenses[${i}]" option must only include a single comment`
);
return normalizeWhitespace(parsed.comments[0].value);
});
@ -69,10 +77,10 @@ module.exports = {
message: 'This license header is not allowed in this file.',
fix(fixer) {
return fixer.remove(node);
}
},
});
});
},
};
}
},
};

View file

@ -0,0 +1,29 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
module.exports = {
meta: {
schema: [],
},
create: context => ({
ExportDefaultDeclaration: node => {
context.report(node, 'Default exports not allowed.');
},
}),
};

View file

@ -28,20 +28,22 @@ function isHashbang(text) {
module.exports = {
meta: {
fixable: 'code',
schema: [{
type: 'object',
properties: {
license: {
type: 'string',
schema: [
{
type: 'object',
properties: {
license: {
type: 'string',
},
},
additionalProperties: false,
},
additionalProperties: false,
}]
],
},
create: context => {
return {
Program(program) {
const license = init(context, program, function () {
const license = init(context, program, function() {
const options = context.options[0] || {};
const license = options.license;
@ -49,11 +51,14 @@ module.exports = {
const parsed = babelEslint.parse(license);
assert(!parsed.body.length, '"license" option must only include a single comment');
assert(parsed.comments.length === 1, '"license" option must only include a single comment');
assert(
parsed.comments.length === 1,
'"license" option must only include a single comment'
);
return {
source: license,
nodeValue: normalizeWhitespace(parsed.comments[0].value)
nodeValue: normalizeWhitespace(parsed.comments[0].value),
};
});
@ -62,9 +67,9 @@ module.exports = {
}
const sourceCode = context.getSourceCode();
const comment = sourceCode.getAllComments().find(node => (
normalizeWhitespace(node.value) === license.nodeValue
));
const comment = sourceCode
.getAllComments()
.find(node => normalizeWhitespace(node.value) === license.nodeValue);
// no licence comment
if (!comment) {
@ -72,7 +77,7 @@ module.exports = {
message: 'File must start with a license header',
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: sourceCode.lines[0].length - 1 }
end: { line: 1, column: sourceCode.lines[0].length - 1 },
},
fix(fixer) {
if (isHashbang(sourceCode.lines[0])) {
@ -80,13 +85,15 @@ module.exports = {
}
return fixer.replaceTextRange([0, 0], license.source + '\n\n');
}
},
});
return;
}
// ensure there is nothing before the comment
const sourceBeforeNode = sourceCode.getText().slice(0, sourceCode.getIndexFromLoc(comment.loc.start));
const sourceBeforeNode = sourceCode
.getText()
.slice(0, sourceCode.getIndexFromLoc(comment.loc.start));
if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) {
context.report({
node: comment,
@ -103,10 +110,10 @@ module.exports = {
fixer.remove(comment),
fixer.replaceTextRange([0, 0], license.source + '\n\n'),
];
}
},
});
}
},
};
}
},
};

View file

@ -1,7 +1,3 @@
plugins: [
'@elastic/eslint-plugin-kibana-custom'
]
rules:
no-console: 2
'@elastic/kibana-custom/no-default-export': error
'@kbn/eslint/no-default-export': error

View file

@ -17,7 +17,7 @@
* under the License.
*/
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function HitSortFnFactory() {
/**
* Creates a sort function that will resort hits based on the value

View file

@ -43,7 +43,7 @@ const formatIds = [
'static_lookup'
];
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default describe('conformance', function () {
const getConfig = (...args) => config.get(...args);

View file

@ -1,6 +1,3 @@
plugins: [
'@elastic/eslint-plugin-kibana-custom'
]
rules:
no-console: 2
'@elastic/kibana-custom/no-default-export': error
'@kbn/eslint/no-default-export': error

View file

@ -17,7 +17,7 @@
* under the License.
*/
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (leaf) {
// walk up the branch for each parent
function walk(item, memo) {

View file

@ -22,7 +22,7 @@ import { VisProvider } from '../../vis';
import { aggTypes } from '..';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function AggParamWriterHelper(Private) {
const Vis = Private(VisProvider);
const stubbedLogstashIndexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);

View file

@ -22,7 +22,7 @@ import expect from 'expect.js';
import { BaseParamType } from '../../param_types/base';
import { JsonParamType } from '../../param_types/json';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default describe('JSON', function () {
const paramName = 'json_test';
let aggParam;

View file

@ -22,7 +22,7 @@ import expect from 'expect.js';
import { BaseParamType } from '../../param_types/base';
import { StringParamType } from '../../param_types/string';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default describe('String', function () {
const paramName = 'json_test';
let aggParam;

View file

@ -46,7 +46,7 @@ function ParamClassStub(parent, body) {
* @param {PrivateLoader} Private - The private module loader, inject by passing this function to ngMock.inject()
* @return {undefined}
*/
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function stubParamClasses(Private) {
const BaseAggParam = Private.stub(
BaseParamType,

View file

@ -20,7 +20,7 @@
import { clone, get } from 'lodash';
import { resolve } from 'url';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (chrome, internals) {
if (get(internals, 'app.navLink.url')) {

View file

@ -17,7 +17,7 @@
* under the License.
*/
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (chrome, internals) {
/**

View file

@ -19,5 +19,5 @@
import { chrome } from './chrome';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default chrome;

View file

@ -59,7 +59,7 @@ function displayBanner() {
}, 15000);
}
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (opts) {
opts = opts || {};
const whenMissingRedirectTo = opts.whenMissingRedirectTo || null;

View file

@ -19,7 +19,7 @@
import testSubjSelector from '@kbn/test-subj-selector';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function bindToJquery($) {
/**

View file

@ -19,5 +19,5 @@
import { uiRoutes } from './routes';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default uiRoutes;

View file

@ -23,7 +23,7 @@ import { wrapRouteWithPrep } from './wrap_route_with_prep';
import { RouteSetupManager } from './route_setup_manager';
import { parsePathToBreadcrumbs } from './breadcrumbs';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function RouteManager() {
const self = this;
const setup = new RouteSetupManager();

View file

@ -30,7 +30,7 @@ function isIntegerInRange(integer: number, min: number, max: number) {
);
}
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
// tslint:disable:no-default-export
export default class Ipv4Address {
private value: number;

View file

@ -20,7 +20,7 @@
import angular from 'angular';
import _ from 'lodash';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function MappingSetupService() {
const mappingSetup = this;

View file

@ -19,7 +19,7 @@
import chrome from '../chrome';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function AggConfigResult(aggConfig, parent, value, key, filters) {
this.key = key;
this.value = value;

View file

@ -19,5 +19,5 @@
import { VislibProvider } from './vislib';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default VislibProvider;

View file

@ -19,7 +19,7 @@
import d3 from 'd3';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function ChartSplitFactory() {
/*

View file

@ -19,7 +19,7 @@
import d3 from 'd3';
// eslint-disable-next-line @elastic/kibana-custom/no-default-export
// eslint-disable-next-line @kbn/eslint/no-default-export
export default function ChartTitleSplitFactory() {
/*

View file

@ -1,4 +1,4 @@
/* eslint-disable @kbn/license-header/require-license-header */
/* eslint-disable @kbn/eslint/require-license-header */
/**
* @notice

View file

@ -1,4 +1,4 @@
/* eslint-disable @kbn/license-header/require-license-header */
/* eslint-disable @kbn/eslint/require-license-header */
/**
* @notice

View file

@ -1,4 +1,4 @@
/* eslint-disable @kbn/license-header/require-license-header */
/* eslint-disable @kbn/eslint/require-license-header */
// This function was extracted from angular v1.3

View file

@ -1,4 +1,4 @@
/* eslint-disable @kbn/license-header/require-license-header */
/* eslint-disable @kbn/eslint/require-license-header */
/**
* @notice
*

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
/* eslint-disable kibana-custom/no-default-export */
/* eslint-disable @kbn/eslint/no-default-export */
import { resolve } from 'path';