From 4a2a75bb34fd80e226b7a04cb5c1a8f3a7fd7f53 Mon Sep 17 00:00:00 2001 From: Ashwin P Chandran Date: Tue, 16 Nov 2021 16:04:34 -0800 Subject: [PATCH] [LIC] Allows the simplified header for new files (#936) * [LIC] Allows the simplified header for new files Signed-off-by: Ashwin Pc * Updates licence variable names Signed-off-by: Ashwin Pc Co-authored-by: Ashwin Pc --- .eslintrc.js | 27 ++++-- .../rules/__tests__/require_license_header.js | 88 ++++++++++++++++--- .../rules/require_license_header.js | 53 ++++++----- 3 files changed, 126 insertions(+), 42 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0920c552629b..63ea02147000 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -30,7 +30,20 @@ * GitHub history for details. */ -const NEW_OSS_HEADER = ` +/** + * For new files created by OpenSearch Contributers + */ +const OSD_HEADER = ` +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +`; + +/** + * For files that modify or use code with an exsting OSS header + */ +const OSS_HEADER = ` /* * SPDX-License-Identifier: Apache-2.0 * @@ -151,7 +164,7 @@ module.exports = { '@osd/eslint/require-license-header': [ 'error', { - license: NEW_OSS_HEADER, + licenses: [OSD_HEADER, OSS_HEADER], }, ], '@osd/eslint/disallow-license-headers': [ @@ -187,7 +200,7 @@ module.exports = { '@osd/eslint/require-license-header': [ 'error', { - license: SAFER_LODASH_SET_LODASH_HEADER, + licenses: [SAFER_LODASH_SET_LODASH_HEADER], }, ], '@osd/eslint/disallow-license-headers': [ @@ -209,14 +222,14 @@ module.exports = { '@osd/eslint/require-license-header': [ 'error', { - license: SAFER_LODASH_SET_HEADER, + licenses: [SAFER_LODASH_SET_HEADER], }, ], '@osd/eslint/disallow-license-headers': [ 'error', { licenses: [ - NEW_OSS_HEADER, + OSS_HEADER, ELASTIC_LICENSE_HEADER, APACHE_2_0_LICENSE_HEADER, SAFER_LODASH_SET_LODASH_HEADER, @@ -233,14 +246,14 @@ module.exports = { '@osd/eslint/require-license-header': [ 'error', { - license: SAFER_LODASH_SET_DEFINITELYTYPED_HEADER, + licenses: [SAFER_LODASH_SET_DEFINITELYTYPED_HEADER], }, ], '@osd/eslint/disallow-license-headers': [ 'error', { licenses: [ - NEW_OSS_HEADER, + OSS_HEADER, ELASTIC_LICENSE_HEADER, APACHE_2_0_LICENSE_HEADER, SAFER_LODASH_SET_HEADER, diff --git a/packages/osd-eslint-plugin-eslint/rules/__tests__/require_license_header.js b/packages/osd-eslint-plugin-eslint/rules/__tests__/require_license_header.js index 5f654e42ca00..9df30dd71d96 100644 --- a/packages/osd-eslint-plugin-eslint/rules/__tests__/require_license_header.js +++ b/packages/osd-eslint-plugin-eslint/rules/__tests__/require_license_header.js @@ -50,7 +50,7 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '/* license */' }], + options: [{ licenses: ['/* license */'] }], }, { code: dedent` @@ -59,7 +59,17 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '// license' }], + options: [{ licenses: ['// license'] }], + }, + // multiple valid licenses + { + code: dedent` + /* license 2 */ + + console.log('foo') + `, + + options: [{ licenses: ['/* license 1 */', '/* license 2 */'] }], }, ], @@ -73,7 +83,7 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { options: [], errors: [ { - message: '"license" option is required', + message: '"licenses" option is required', }, ], }, @@ -84,10 +94,10 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '/* one *//* two */' }], + options: [{ licenses: ['/* one *//* two */'] }], errors: [ { - message: '"license" option must only include a single comment', + message: '"licenses[0]" option must only include a single comment', }, ], }, @@ -98,10 +108,10 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: `// one\n// two` }], + options: [{ licenses: [`// one\n// two`] }], errors: [ { - message: '"license" option must only include a single comment', + message: '"licenses[0]" option must only include a single comment', }, ], }, @@ -114,15 +124,17 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { options: [ { - license: dedent` + licenses: [ + dedent` /* license */ console.log('hello world'); `, + ], }, ], errors: [ { - message: '"license" option must only include a single comment', + message: '"licenses[0]" option must only include a single comment', }, ], }, @@ -133,10 +145,10 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: `console.log('hello world');` }], + options: [{ licenses: [`console.log('hello world');`] }], errors: [ { - message: '"license" option must only include a single comment', + message: '"licenses[0]" option must only include a single comment', }, ], }, @@ -147,7 +159,7 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '/* license */' }], + options: [{ licenses: ['/* license */'] }], errors: [ { message: 'File must start with a license header', @@ -171,7 +183,7 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '/* license */' }], + options: [{ licenses: ['/* license */'] }], errors: [ { message: 'License header must be at the very beginning of the file', @@ -193,7 +205,7 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, - options: [{ license: '/* license */' }], + options: [{ licenses: ['/* license */'] }], errors: [ { message: 'License header must be at the very beginning of the file', @@ -208,5 +220,53 @@ ruleTester.run('@osd/eslint/require-license-header', rule, { console.log('foo') `, }, + + // atleast one of multiple licenses must be present + { + code: dedent` + /* not license */ + /* also not license */ + console.log('foo') + `, + + options: [{ licenses: ['/* license 1 */', '/* license 2 */'] }], + errors: [ + { + message: 'File must start with a license header', + }, + ], + + output: dedent` + /* license 1 */ + + /* not license */ + /* also not license */ + console.log('foo') + `, + }, + + // atleast one of multiple licenses must be present at the top of the file + { + code: dedent` + /* not license */ + /* license 2 */ + console.log('foo') + `, + + options: [{ licenses: ['/* license 1 */', '/* license 2 */'] }], + errors: [ + { + message: 'License header must be at the very beginning of the file', + }, + ], + + output: dedent` + /* license 2 */ + + /* not license */ + + console.log('foo') + `, + }, ], }); diff --git a/packages/osd-eslint-plugin-eslint/rules/require_license_header.js b/packages/osd-eslint-plugin-eslint/rules/require_license_header.js index d0ea88318353..ee8e56d5d606 100644 --- a/packages/osd-eslint-plugin-eslint/rules/require_license_header.js +++ b/packages/osd-eslint-plugin-eslint/rules/require_license_header.js @@ -45,8 +45,11 @@ module.exports = { { type: 'object', properties: { - license: { - type: 'string', + licenses: { + type: 'array', + items: { + type: 'string', + }, }, }, additionalProperties: false, @@ -56,33 +59,38 @@ module.exports = { create: (context) => { return { Program(program) { - const license = init(context, program, function () { + const licenses = init(context, program, function () { const options = context.options[0] || {}; - const license = options.license; + const licenses = options.licenses; - assert(!!license, '"license" option is required'); + assert(!!licenses, '"licenses" option is required'); - 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' - ); + 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` + ); - return { - source: license, - nodeValue: normalizeWhitespace(parsed.comments[0].value), - }; + return { + source: license, + nodeValue: normalizeWhitespace(parsed.comments[0].value), + }; + }); }); - if (!license) { - return; - } + if (!licenses || !licenses.length) return; const sourceCode = context.getSourceCode(); const comment = sourceCode .getAllComments() - .find((node) => normalizeWhitespace(node.value) === license.nodeValue); + .find((node) => + licenses.map((license) => license.nodeValue).includes(normalizeWhitespace(node.value)) + ); // no licence comment if (!comment) { @@ -97,13 +105,16 @@ module.exports = { return undefined; } - return fixer.replaceTextRange([0, 0], license.source + '\n\n'); + return fixer.replaceTextRange([0, 0], licenses[0].source + '\n\n'); }, }); return; } // ensure there is nothing before the comment + const currentLicense = licenses.find( + (license) => normalizeWhitespace(comment.value) === license.nodeValue + ); const sourceBeforeNode = sourceCode .getText() .slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); @@ -121,7 +132,7 @@ module.exports = { // if removing whitespace is not possible return [ fixer.remove(comment), - fixer.replaceTextRange([0, 0], license.source + '\n\n'), + fixer.replaceTextRange([0, 0], currentLicense.source + '\n\n'), ]; }, });